pax_global_header00006660000000000000000000000064142014700030014501gustar00rootroot0000000000000052 comment=cdf6a0d6228eef4df2a82a1483f016c11f4a6019 hugo-0.92.2/000077500000000000000000000000001420147000300125355ustar00rootroot00000000000000hugo-0.92.2/.circleci/000077500000000000000000000000001420147000300143705ustar00rootroot00000000000000hugo-0.92.2/.circleci/config.yml000066400000000000000000000022711420147000300163620ustar00rootroot00000000000000defaults: &defaults docker: - image: bepsays/ci-goreleaser:1.1700.600 environment: CGO_ENABLED: "0" version: 2 jobs: build: <<: *defaults steps: - checkout: path: hugo - run: command: | git clone git@github.com:gohugoio/hugoDocs.git cd hugo go mod download sleep 5 go mod verify - persist_to_workspace: root: . paths: . release: <<: *defaults steps: - attach_workspace: at: /root/project - run: command: | cd hugo git config --global user.email "bjorn.erik.pedersen+hugoreleaser@gmail.com" git config --global user.name "hugoreleaser" go run -tags release main.go release -r ${CIRCLE_BRANCH} workflows: version: 2 release: jobs: - build: filters: branches: only: /release-.*/ - hold: type: approval requires: - build - release: context: org-global requires: - hold hugo-0.92.2/.dockerignore000066400000000000000000000001011420147000300152010ustar00rootroot00000000000000*.md *.log *.txt .git .github .circleci docs examples Dockerfile hugo-0.92.2/.gitattributes000066400000000000000000000002401420147000300154240ustar00rootroot00000000000000# Text files have auto line endings * text=auto # Go source files always have LF line endings *.go text eol=lf # SVG files should not be modified *.svg -text hugo-0.92.2/.github/000077500000000000000000000000001420147000300140755ustar00rootroot00000000000000hugo-0.92.2/.github/ISSUE_TEMPLATE/000077500000000000000000000000001420147000300162605ustar00rootroot00000000000000hugo-0.92.2/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000005171420147000300207550ustar00rootroot00000000000000--- name: 'Bug report' labels: 'Bug, NeedsTriage' assignees: '' about: Create a report to help us improve --- ### What version of Hugo are you using (`hugo version`)?
$ hugo version

### Does this issue reproduce with the latest release? hugo-0.92.2/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000005511420147000300202510ustar00rootroot00000000000000blank_issues_enabled: false contact_links: - name: SUPPORT, ISSUES and TROUBLESHOOTING url: https://discourse.gohugo.io/ about: Please DO NOT use Github for support requests. Please visit https://discourse.gohugo.io for support! You will be helped much faster there. If you ignore this request your issue might be closed with a discourse label. hugo-0.92.2/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000004301420147000300220020ustar00rootroot00000000000000--- name: Proposal about: Propose a new feature for Hugo title: '' labels: 'Proposal, NeedsTriage' assignees: '' --- hugo-0.92.2/.github/SUPPORT.md000066400000000000000000000003121420147000300155670ustar00rootroot00000000000000### Asking Support Questions We have an active [discussion forum](https://discourse.gohugo.io) where users and developers can ask questions. Please don't use the GitHub issue tracker to ask questions. hugo-0.92.2/.github/dependabot.yml000066400000000000000000000003561420147000300167310ustar00rootroot00000000000000# See https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#package-ecosystem version: 2 updates: - package-ecosystem: "gomod" directory: "/" schedule: interval: "daily" hugo-0.92.2/.github/workflows/000077500000000000000000000000001420147000300161325ustar00rootroot00000000000000hugo-0.92.2/.github/workflows/stale.yml000066400000000000000000000044721420147000300177740ustar00rootroot00000000000000name: 'Close stale and lock closed issues and PRs' on: schedule: - cron: '30 1 * * *' jobs: stale: runs-on: ubuntu-latest steps: - uses: dessant/lock-threads@08e671be8ac8944d0e132aa71d0ae8ccfb347675 with: issue-inactive-days: 7 add-issue-labels: 'Outdated' issue-comment: > This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. pr-comment: > This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. - uses: actions/stale@04a1828bc18ada028d85a0252a47cd2963a91abe with: days-before-issue-stale: 600 days-before-pr-stale: 200 days-before-issue-close: -1 days-before-pr-close: -1 stale-issue-message: > This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help. If this is a **bug** and you can still reproduce this error on the master branch, please reply with all of the information you have about it in order to keep the issue open. If this is a **feature request**, and you feel that it is still relevant and valuable, please tell us why. This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions. stale-pr-message: This PR has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help. Please check https://github.com/gohugoio/hugo/blob/master/CONTRIBUTING.md#code-contribution and verify that this code contribution fits with the description. If yes, tell is in a comment. This PR will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions. stale-issue-label: 'Stale' exempt-issue-labels: 'Keep,Security' stale-pr-label: 'Stale' exempt-pr-labels: 'Keep,Security' hugo-0.92.2/.github/workflows/test.yml000066400000000000000000000065151420147000300176430ustar00rootroot00000000000000on: [push, pull_request] name: Test jobs: test: env: GOPROXY: https://proxy.golang.org GO111MODULE: on strategy: matrix: go-version: [1.16.x, 1.17.x] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - name: Install Go uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 with: go-version: ${{ matrix.go-version }} - name: Install Ruby uses: actions/setup-ruby@5f29a1cd8dfebf420691c4c9a0e832e2fae5a526 with: ruby-version: '2.7' - name: Install Python uses: actions/setup-python@3105fb18c05ddd93efea5f9e0bef7a03a6e9e7df with: python-version: '3.x' - name: Install Mage run: go get github.com/magefile/mage@07afc7d24f4d6d6442305d49552f04fbda5ccb3e - name: Install asciidoctor uses: reitzig/actions-asciidoctor@7570212ae20b63653481675fb1ff62d1073632b0 - name: Checkout code uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f - name: Install docutils run: | pip install docutils rst2html.py --version - if: matrix.os == 'ubuntu-latest' name: Install pandoc on Linux run: | sudo apt-get update -y sudo apt-get install -y pandoc - if: matrix.os == 'macos-latest' run: | brew install pandoc - if: matrix.os == 'windows-latest' run: | choco install pandoc - run: pandoc -v - if: matrix.os == 'ubuntu-latest' name: Install dart-sass-embedded Linux run: | curl -LJO https://github.com/sass/dart-sass-embedded/releases/download/1.0.0-beta.6/sass_embedded-1.0.0-beta.6-linux-x64.tar.gz; echo "04fc1e5e28d29a4585a701941b6dace56771d94bfbe7f9e4db28d24417ceeec3 sass_embedded-1.0.0-beta.6-linux-x64.tar.gz" | sha256sum -c; tar -xvf sass_embedded-1.0.0-beta.6-linux-x64.tar.gz; echo "$GITHUB_WORKSPACE/sass_embedded/" >> $GITHUB_PATH - if: matrix.os == 'macos-latest' name: Install dart-sass-embedded MacOS run: | curl -LJO https://github.com/sass/dart-sass-embedded/releases/download/1.0.0-beta.6/sass_embedded-1.0.0-beta.6-macos-x64.tar.gz; echo "b3b984675a9b04aa22f6f2302dda4191b507ac2ca124467db2dfe7e58e72fbad sass_embedded-1.0.0-beta.6-macos-x64.tar.gz" | shasum -a 256 -c; tar -xvf sass_embedded-1.0.0-beta.6-macos-x64.tar.gz; echo "$GITHUB_WORKSPACE/sass_embedded/" >> $GITHUB_PATH - if: matrix.os == 'windows-latest' name: Install dart-sass-embedded Windows run: | curl -LJO https://github.com/sass/dart-sass-embedded/releases/download/1.0.0-beta.6/sass_embedded-1.0.0-beta.6-windows-x64.zip; echo "6ae442129dbb3334bc21ef851261da6c0c1b560da790ca2e1350871d00ab816d sass_embedded-1.0.0-beta.6-windows-x64.zip" | sha256sum -c; unzip sass_embedded-1.0.0-beta.6-windows-x64.zip; echo "$env:GITHUB_WORKSPACE/sass_embedded/" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf-8 -Append - name: Test run: | mage -v test mage -v check; - name: Build Docs env: HUGO_BUILD_TAGS: extended HUGO_TIMEOUT: 31000 HUGO_IGNOREERRORS: error-remote-getjson HUGO_SERVICES_INSTAGRAM_ACCESSTOKEN: dummytoken run: | mage -v hugo ./hugo -s docs/ ./hugo --renderToMemory -s docs/ hugo-0.92.2/.gitignore000066400000000000000000000003601420147000300145240ustar00rootroot00000000000000/hugo docs/public* /.idea .vscode/* hugo.exe *.test *.prof nohup.out cover.out *.swp *.swo .DS_Store *~ vendor/*/ *.bench *.debug coverage*.out dock.sh GoBuilds dist hugolib/hugo_stats.json resources/sunset.jpg vendor .hugo_build.lock hugo-0.92.2/.gitmodules000066400000000000000000000000001420147000300147000ustar00rootroot00000000000000hugo-0.92.2/.mailmap000066400000000000000000000002421420147000300141540ustar00rootroot00000000000000spf13 Steve Francia bep Bjørn Erik Pedersen hugo-0.92.2/CONTRIBUTING.md000066400000000000000000000205101420147000300147640ustar00rootroot00000000000000# Contributing to Hugo We welcome contributions to Hugo of any kind including documentation, themes, organization, tutorials, blog posts, bug reports, issues, feature requests, feature implementations, pull requests, answering questions on the forum, helping to manage issues, etc. The Hugo community and maintainers are [very active](https://github.com/gohugoio/hugo/pulse/monthly) and helpful, and the project benefits greatly from this activity. We created a [step by step guide](https://gohugo.io/tutorials/how-to-contribute-to-hugo/) if you're unfamiliar with GitHub or contributing to open source projects in general. *Note that this repository only contains the actual source code of Hugo. For **only** documentation-related pull requests / issues please refer to the [hugoDocs](https://github.com/gohugoio/hugoDocs) repository.* *Changes to the codebase **and** related documentation, e.g. for a new feature, should still use a single pull request.* ## Table of Contents * [Asking Support Questions](#asking-support-questions) * [Reporting Issues](#reporting-issues) * [Submitting Patches](#submitting-patches) * [Code Contribution Guidelines](#code-contribution-guidelines) * [Git Commit Message Guidelines](#git-commit-message-guidelines) * [Fetching the Sources From GitHub](#fetching-the-sources-from-github) * [Building Hugo with Your Changes](#building-hugo-with-your-changes) ## Asking Support Questions We have an active [discussion forum](https://discourse.gohugo.io) where users and developers can ask questions. Please don't use the GitHub issue tracker to ask questions. ## Reporting Issues If you believe you have found a defect in Hugo or its documentation, use the GitHub issue tracker to report the problem to the Hugo maintainers. If you're not sure if it's a bug or not, start by asking in the [discussion forum](https://discourse.gohugo.io). When reporting the issue, please provide the version of Hugo in use (`hugo version`) and your operating system. - [Hugo Issues · gohugoio/hugo](https://github.com/gohugoio/hugo/issues) - [Hugo Documentation Issues · gohugoio/hugoDocs](https://github.com/gohugoio/hugoDocs/issues) - [Hugo Website Theme Issues · gohugoio/hugoThemesSite](https://github.com/gohugoio/hugoThemesSite/issues) ## Code Contribution Hugo has become a fully featured static site generator, so any new functionality must: * be useful to many. * fit naturally into _what Hugo does best._ * strive not to break existing sites. * close or update an open [Hugo issue](https://github.com/gohugoio/hugo/issues) If it is of some complexity, the contributor is expected to maintain and support the new feature in the future (answer questions on the forum, fix any bugs etc.). It is recommended to open up a discussion on the [Hugo Forum](https://discourse.gohugo.io/) to get feedback on your idea before you begin. Any non-trivial code change needs to update an open [issue](https://github.com/gohugoio/hugo/issues). A non-trivial code change without an issue reference with one of the labels `bug` or `enhancement` will not be merged. Note that we do not accept new features that require [CGO](https://github.com/golang/go/wiki/cgo). We have one exception to this rule which is LibSASS. **Bug fixes are, of course, always welcome.** ## Submitting Patches The Hugo project welcomes all contributors and contributions regardless of skill or experience level. If you are interested in helping with the project, we will help you with your contribution. ### Code Contribution Guidelines Because we want to create the best possible product for our users and the best contribution experience for our developers, we have a set of guidelines which ensure that all contributions are acceptable. The guidelines are not intended as a filter or barrier to participation. If you are unfamiliar with the contribution process, the Hugo team will help you and teach you how to bring your contribution in accordance with the guidelines. To make the contribution process as seamless as possible, we ask for the following: * Go ahead and fork the project and make your changes. We encourage pull requests to allow for review and discussion of code changes. * When you’re ready to create a pull request, be sure to: * Sign the [CLA](https://cla-assistant.io/gohugoio/hugo). * Have test cases for the new code. If you have questions about how to do this, please ask in your pull request. * Run `go fmt`. * Add documentation if you are adding new features or changing functionality. The docs site lives in `/docs`. * Squash your commits into a single commit. `git rebase -i`. It’s okay to force update your pull request with `git push -f`. * Ensure that `mage check` succeeds. [Travis CI](https://travis-ci.org/gohugoio/hugo) (Windows, Linux and macOS) will fail the build if `mage check` fails. * Follow the **Git Commit Message Guidelines** below. ### Git Commit Message Guidelines This [blog article](http://chris.beams.io/posts/git-commit/) is a good resource for learning how to write good commit messages, the most important part being that each commit message should have a title/subject in imperative mood starting with a capital letter and no trailing period: *"Return error on wrong use of the Paginator"*, **NOT** *"returning some error."* Also, if your commit references one or more GitHub issues, always end your commit message body with *See #1234* or *Fixes #1234*. Replace *1234* with the GitHub issue ID. The last example will close the issue when the commit is merged into *master*. Sometimes it makes sense to prefix the commit message with the package name (or docs folder) all lowercased ending with a colon. That is fine, but the rest of the rules above apply. So it is "tpl: Add emojify template func", not "tpl: add emojify template func.", and "docs: Document emoji", not "doc: document emoji." Please use a short and descriptive branch name, e.g. **NOT** "patch-1". It's very common but creates a naming conflict each time when a submission is pulled for a review. An example: ```text tpl: Add custom index function Add a custom index template function that deviates from the stdlib simply by not returning an "index out of range" error if an array, slice or string index is out of range. Instead, we just return nil values. This should help make the new default function more useful for Hugo users. Fixes #1949 ``` ### Fetching the Sources From GitHub Since Hugo 0.48, Hugo uses the Go Modules support built into Go 1.11 to build. The easiest is to clone Hugo in a directory outside of `GOPATH`, as in the following example: ```bash mkdir $HOME/src cd $HOME/src git clone https://github.com/gohugoio/hugo.git cd hugo go install ``` >Note: Some Go tools may not be fully updated to support Go Modules yet. One example would be LiteIDE. Follow [this workaround](https://github.com/visualfc/liteide/issues/986#issuecomment-428117702) for how to continue to work with Hugo below `GOPATH`. For some convenient build and test targets, you also will want to install Mage: ```bash go get github.com/magefile/mage ``` Now, to make a change to Hugo's source: 1. Create a new branch for your changes (the branch name is arbitrary): ```bash git checkout -b iss1234 ``` 1. After making your changes, commit them to your new branch: ```bash git commit -a -v ``` 1. Fork Hugo in GitHub. 1. Add your fork as a new remote (the remote name, "fork" in this example, is arbitrary): ```bash git remote add fork git@github.com:USERNAME/hugo.git ``` 1. Push the changes to your new remote: ```bash git push --set-upstream fork iss1234 ``` 1. You're now ready to submit a PR based upon the new branch in your forked repository. ### Building Hugo with Your Changes Hugo uses [mage](https://github.com/magefile/mage) to sync vendor dependencies, build Hugo, run the test suite and other things. You must run mage from the Hugo directory. ```bash cd $HOME/go/src/github.com/gohugoio/hugo ``` To build Hugo: ```bash mage hugo ``` To install hugo in `$HOME/go/bin`: ```bash mage install ``` To run the tests: ```bash mage hugoRace mage -v check ``` To list all available commands along with descriptions: ```bash mage -l ``` **Note:** From Hugo 0.43 we have added a build tag, `extended` that adds **SCSS support**. This needs a C compiler installed to build. You can enable this when building by: ```bash HUGO_BUILD_TAGS=extended mage install ```` hugo-0.92.2/Dockerfile000077500000000000000000000021021420147000300145250ustar00rootroot00000000000000# GitHub: https://github.com/gohugoio # Twitter: https://twitter.com/gohugoio # Website: https://gohugo.io/ FROM golang:1.16-alpine AS build # Optionally set HUGO_BUILD_TAGS to "extended" or "nodeploy" when building like so: # docker build --build-arg HUGO_BUILD_TAGS=extended . ARG HUGO_BUILD_TAGS ARG CGO=1 ENV CGO_ENABLED=${CGO} ENV GOOS=linux ENV GO111MODULE=on WORKDIR /go/src/github.com/gohugoio/hugo COPY . /go/src/github.com/gohugoio/hugo/ # gcc/g++ are required to build SASS libraries for extended version RUN apk update && \ apk add --no-cache gcc g++ musl-dev git && \ go get github.com/magefile/mage RUN mage hugo && mage install # --- FROM alpine:3.12 COPY --from=build /go/bin/hugo /usr/bin/hugo # libc6-compat & libstdc++ are required for extended SASS libraries # ca-certificates are required to fetch outside resources (like Twitter oEmbeds) RUN apk update && \ apk add --no-cache ca-certificates libc6-compat libstdc++ git VOLUME /site WORKDIR /site # Expose port for live server EXPOSE 1313 ENTRYPOINT ["hugo"] CMD ["--help"] hugo-0.92.2/LICENSE000066400000000000000000000261351420147000300135510ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. hugo-0.92.2/README.md000066400000000000000000000237501420147000300140230ustar00rootroot00000000000000Hugo A Fast and Flexible Static Site Generator built with love by [bep](https://github.com/bep), [spf13](http://spf13.com/) and [friends](https://github.com/gohugoio/hugo/graphs/contributors) in [Go][]. [Website](https://gohugo.io) | [Forum](https://discourse.gohugo.io) | [Documentation](https://gohugo.io/getting-started/) | [Installation Guide](https://gohugo.io/getting-started/installing/) | [Contribution Guide](CONTRIBUTING.md) | [Twitter](https://twitter.com/gohugoio) [![GoDoc](https://godoc.org/github.com/gohugoio/hugo?status.svg)](https://godoc.org/github.com/gohugoio/hugo) [![Tests on Linux, MacOS and Windows](https://github.com/gohugoio/hugo/workflows/Test/badge.svg)](https://github.com/gohugoio/hugo/actions?query=workflow%3ATest) [![Go Report Card](https://goreportcard.com/badge/github.com/gohugoio/hugo)](https://goreportcard.com/report/github.com/gohugoio/hugo) ## Overview Hugo is a static HTML and CSS website generator written in [Go][]. It is optimized for speed, ease of use, and configurability. Hugo takes a directory with content and templates and renders them into a full HTML website. Hugo relies on Markdown files with front matter for metadata, and you can run Hugo from any directory. This works well for shared hosts and other systems where you don’t have a privileged account. Hugo renders a typical website of moderate size in a fraction of a second. A good rule of thumb is that each piece of content renders in around 1 millisecond. Hugo is designed to work well for any kind of website including blogs, tumbles, and docs. #### Supported Architectures Currently, we provide pre-built Hugo binaries for Windows, Linux, FreeBSD, NetBSD, DragonFly BSD, OpenBSD, macOS (Darwin), and [Android](https://gist.github.com/bep/a0d8a26cf6b4f8bc992729b8e50b480b) for x64, i386 and ARM architectures. Hugo may also be compiled from source wherever the Go compiler tool chain can run, e.g. for other operating systems including Plan 9 and Solaris. **Complete documentation is available at [Hugo Documentation](https://gohugo.io/getting-started/).** ## Choose How to Install If you want to use Hugo as your site generator, simply install the Hugo binaries. The Hugo binaries have no external dependencies. To contribute to the Hugo source code or documentation, you should [fork the Hugo GitHub project](https://github.com/gohugoio/hugo#fork-destination-box) and clone it to your local machine. Finally, you can install the Hugo source code with `go`, build the binaries yourself, and run Hugo that way. Building the binaries is an easy task for an experienced `go` getter. ### Install Hugo as Your Site Generator (Binary Install) Use the [installation instructions in the Hugo documentation](https://gohugo.io/getting-started/installing/). ### Build and Install the Binaries from Source (Advanced Install) #### Prerequisite Tools * [Git](https://git-scm.com/) * [Go (we test it with the last 2 major versions; but note that Hugo 0.81.0 only builds with >= Go 1.16.)](https://golang.org/dl/) #### Fetch from GitHub Since Hugo 0.48, Hugo uses the Go Modules support built into Go 1.11 to build. The easiest is to clone Hugo in a directory outside of `GOPATH`, as in the following example: ```bash mkdir $HOME/src cd $HOME/src git clone https://github.com/gohugoio/hugo.git cd hugo go install ``` **If you are a Windows user, substitute the `$HOME` environment variable above with `%USERPROFILE%`.** If you want to compile with Sass/SCSS support use `--tags extended` and make sure `CGO_ENABLED=1` is set in your go environment. If you don't want to have CGO enabled, you may use the following command to temporarily enable CGO only for hugo compilation: ```bash CGO_ENABLED=1 go install --tags extended ``` ## The Hugo Documentation The Hugo documentation now lives in its own repository, see https://github.com/gohugoio/hugoDocs. But we do keep a version of that documentation as a `git subtree` in this repository. To build the sub folder `/docs` as a Hugo site, you need to clone this repo: ```bash git clone git@github.com:gohugoio/hugo.git ``` ## Contributing to Hugo For a complete guide to contributing to Hugo, see the [Contribution Guide](CONTRIBUTING.md). We welcome contributions to Hugo of any kind including documentation, themes, organization, tutorials, blog posts, bug reports, issues, feature requests, feature implementations, pull requests, answering questions on the forum, helping to manage issues, etc. The Hugo community and maintainers are [very active](https://github.com/gohugoio/hugo/pulse/monthly) and helpful, and the project benefits greatly from this activity. ### Asking Support Questions We have an active [discussion forum](https://discourse.gohugo.io) where users and developers can ask questions. Please don't use the GitHub issue tracker to ask questions. ### Reporting Issues If you believe you have found a defect in Hugo or its documentation, use the GitHub issue tracker to report the problem to the Hugo maintainers. If you're not sure if it's a bug or not, start by asking in the [discussion forum](https://discourse.gohugo.io). When reporting the issue, please provide the version of Hugo in use (`hugo version`). ### Submitting Patches The Hugo project welcomes all contributors and contributions regardless of skill or experience level. If you are interested in helping with the project, we will help you with your contribution. Hugo is a very active project with many contributions happening daily. We want to create the best possible product for our users and the best contribution experience for our developers, we have a set of guidelines which ensure that all contributions are acceptable. The guidelines are not intended as a filter or barrier to participation. If you are unfamiliar with the contribution process, the Hugo team will help you and teach you how to bring your contribution in accordance with the guidelines. For a complete guide to contributing code to Hugo, see the [Contribution Guide](CONTRIBUTING.md). [Go]: https://golang.org/ [Hugo Documentation]: https://gohugo.io/overview/introduction/ ## Dependencies Hugo stands on the shoulder of many great open source libraries. If you run `hugo env -v` you will get a complete and up to date list. In Hugo 0.89.0 that list is, in lexical order: ``` cloud.google.com/go/storage="v1.10.0" cloud.google.com/go="v0.87.0" github.com/Azure/azure-pipeline-go="v0.2.2" github.com/Azure/azure-storage-blob-go="v0.9.0" github.com/BurntSushi/locker="v0.0.0-20171006230638-a6e239ea1c69" github.com/BurntSushi/toml="v0.3.1" github.com/PuerkitoBio/purell="v1.1.1" github.com/PuerkitoBio/urlesc="v0.0.0-20170810143723-de5bf2ad4578" github.com/alecthomas/chroma="v0.9.4" github.com/armon/go-radix="v1.0.0" github.com/aws/aws-sdk-go="v1.41.14" github.com/bep/debounce="v1.2.0" github.com/bep/gitmap="v1.1.2" github.com/bep/godartsass="v0.12.0" github.com/bep/golibsass="v1.0.0" github.com/bep/gowebp="v0.1.0" github.com/bep/tmc="v0.5.1" github.com/cli/safeexec="v1.0.0" github.com/cpuguy83/go-md2man/v2="v2.0.0" github.com/disintegration/gift="v1.2.1" github.com/dlclark/regexp2="v1.4.0" github.com/dustin/go-humanize="v1.0.0" github.com/evanw/esbuild="v0.13.12" github.com/fsnotify/fsnotify="v1.5.1" github.com/getkin/kin-openapi="v0.80.0" github.com/ghodss/yaml="v1.0.0" github.com/go-openapi/jsonpointer="v0.19.5" github.com/go-openapi/swag="v0.19.5" github.com/gobuffalo/flect="v0.2.3" github.com/gobwas/glob="v0.2.3" github.com/gohugoio/go-i18n/v2="v2.1.3-0.20210430103248-4c28c89f8013" github.com/gohugoio/locales="v0.14.0" github.com/gohugoio/localescompressed="v0.14.0" github.com/golang/groupcache="v0.0.0-20200121045136-8c9f03a8e57e" github.com/golang/protobuf="v1.5.2" github.com/google/go-cmp="v0.5.6" github.com/google/uuid="v1.1.2" github.com/google/wire="v0.4.0" github.com/googleapis/gax-go/v2="v2.0.5" github.com/googleapis/gax-go="v2.0.2+incompatible" github.com/gorilla/websocket="v1.4.2" github.com/inconshreveable/mousetrap="v1.0.0" github.com/jdkato/prose="v1.2.1" github.com/jmespath/go-jmespath="v0.4.0" github.com/kyokomi/emoji/v2="v2.2.8" github.com/mailru/easyjson="v0.0.0-20190626092158-b2ccc519800e" github.com/mattn/go-ieproxy="v0.0.1" github.com/mattn/go-isatty="v0.0.14" github.com/mattn/go-runewidth="v0.0.9" github.com/miekg/mmark="v1.3.6" github.com/mitchellh/hashstructure="v1.1.0" github.com/mitchellh/mapstructure="v1.4.2" github.com/muesli/smartcrop="v0.3.0" github.com/niklasfasching/go-org="v1.5.0" github.com/olekukonko/tablewriter="v0.0.5" github.com/pelletier/go-toml/v2="v2.0.0-beta.3.0.20210727221244-fa0796069526" github.com/pkg/errors="v0.9.1" github.com/rogpeppe/go-internal="v1.8.0" github.com/russross/blackfriday/v2="v2.0.1" github.com/russross/blackfriday="v1.5.3-0.20200218234912-41c5fccfd6f6" github.com/rwcarlsen/goexif="v0.0.0-20190401172101-9e8deecbddbd" github.com/sanity-io/litter="v1.5.1" github.com/sass/libsass="3.6.5" github.com/shurcooL/sanitized_anchor_name="v1.0.0" github.com/spf13/afero="v1.6.0" github.com/spf13/cast="v1.4.1" github.com/spf13/cobra="v1.2.1" github.com/spf13/fsync="v0.9.0" github.com/spf13/jwalterweatherman="v1.1.0" github.com/spf13/pflag="v1.0.5" github.com/tdewolff/minify/v2="v2.9.22" github.com/tdewolff/parse/v2="v2.5.21" github.com/webmproject/libwebp="v1.2.0" github.com/yuin/goldmark-highlighting="v0.0.0-20200307114337-60d527fdb691" github.com/yuin/goldmark="v1.4.2" go.opencensus.io="v0.23.0" gocloud.dev="v0.20.0" golang.org/x/image="v0.0.0-20210220032944-ac19c3e999fb" golang.org/x/net="v0.0.0-20210614182718-04defd469f4e" golang.org/x/oauth2="v0.0.0-20210628180205-a41e5a781914" golang.org/x/sync="v0.0.0-20210220032951-036812b2e83c" golang.org/x/sys="v0.0.0-20210908233432-aa78b53d3365" golang.org/x/text="v0.3.7" golang.org/x/xerrors="v0.0.0-20200804184101-5ec99f83aff1" google.golang.org/api="v0.51.0" google.golang.org/genproto="v0.0.0-20210716133855-ce7ef5c701ea" google.golang.org/grpc="v1.39.0" google.golang.org/protobuf="v1.27.1" gopkg.in/yaml.v2="v2.4.0" ``` hugo-0.92.2/SECURITY.md000066400000000000000000000007051420147000300143300ustar00rootroot00000000000000## Security Policy ### Reporting a Vulnerability Please report (suspected) security vulnerabilities to **[bjorn.erik.pedersen@gmail.com](mailto:bjorn.erik.pedersen@gmail.com)**. You will receive a response from us within 48 hours. If we can confirm the issue, we will release a patch as soon as possible depending on the complexity of the issue but historically within days. Also see [Hugo's Security Model](https://gohugo.io/about/security-model/). hugo-0.92.2/bench.sh000077500000000000000000000015331420147000300141550ustar00rootroot00000000000000#!/usr/bin/env bash # allow user to override go executable by running as GOEXE=xxx make ... GOEXE="${GOEXE-go}" # Convenience script to # - For a given branch # - Run benchmark tests for a given package # - Do the same for master # - then compare the two runs with benchcmp benchFilter=".*" if (( $# < 2 )); then echo "USAGE: ./bench.sh (and (regexp, optional))" exit 1 fi if [ $# -eq 3 ]; then benchFilter=$3 fi BRANCH=$1 PACKAGE=$2 git checkout $BRANCH "${GOEXE}" test -test.run=NONE -bench="$benchFilter" -test.benchmem=true ./$PACKAGE > /tmp/bench-$PACKAGE-$BRANCH.txt git checkout master "${GOEXE}" test -test.run=NONE -bench="$benchFilter" -test.benchmem=true ./$PACKAGE > /tmp/bench-$PACKAGE-master.txt benchcmp /tmp/bench-$PACKAGE-master.txt /tmp/bench-$PACKAGE-$BRANCH.txt hugo-0.92.2/benchSite.sh000077500000000000000000000010211420147000300147720ustar00rootroot00000000000000#!/bin/bash # allow user to override go executable by running as GOEXE=xxx make ... GOEXE="${GOEXE-go}" # Send in a regexp matching the benchmarks you want to run, i.e. './benchSite.sh "YAML"'. # Note the quotes, which will be needed for more complex expressions. # The above will run all variations, but only for front matter YAML. echo "Running with BenchmarkSiteBuilding/${1}" "${GOEXE}" test -run="NONE" -bench="BenchmarkSiteBuilding/${1}" -test.benchmem=true ./hugolib -memprofile mem.prof -count 3 -cpuprofile cpu.prof hugo-0.92.2/benchbep.sh000077500000000000000000000001061420147000300146370ustar00rootroot00000000000000gobench -package=./hugolib -bench="BenchmarkSiteNew/Deep_content_tree"hugo-0.92.2/bepdock.sh000077500000000000000000000001651420147000300145050ustar00rootroot00000000000000docker run --rm --mount type=bind,source="$(pwd)",target=/hugo -w /hugo -i -t bepsays/ci-goreleaser:1.11-2 /bin/bashhugo-0.92.2/bufferpool/000077500000000000000000000000001420147000300147005ustar00rootroot00000000000000hugo-0.92.2/bufferpool/bufpool.go000066400000000000000000000021241420147000300166740ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package bufferpool provides a pool of bytes buffers. package bufferpool import ( "bytes" "sync" ) var bufferPool = &sync.Pool{ New: func() interface{} { return &bytes.Buffer{} }, } // GetBuffer returns a buffer from the pool. func GetBuffer() (buf *bytes.Buffer) { return bufferPool.Get().(*bytes.Buffer) } // PutBuffer returns a buffer to the pool. // The buffer is reset before it is put back into circulation. func PutBuffer(buf *bytes.Buffer) { buf.Reset() bufferPool.Put(buf) } hugo-0.92.2/bufferpool/bufpool_test.go000066400000000000000000000016251420147000300177400ustar00rootroot00000000000000// Copyright 2016-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package bufferpool import ( "testing" qt "github.com/frankban/quicktest" ) func TestBufferPool(t *testing.T) { c := qt.New(t) buff := GetBuffer() buff.WriteString("do be do be do") c.Assert(buff.String(), qt.Equals, "do be do be do") PutBuffer(buff) c.Assert(buff.Len(), qt.Equals, 0) } hugo-0.92.2/cache/000077500000000000000000000000001420147000300136005ustar00rootroot00000000000000hugo-0.92.2/cache/filecache/000077500000000000000000000000001420147000300155035ustar00rootroot00000000000000hugo-0.92.2/cache/filecache/filecache.go000066400000000000000000000202551420147000300177410ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package filecache import ( "bytes" "errors" "io" "io/ioutil" "os" "path/filepath" "strings" "sync" "time" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/helpers" "github.com/BurntSushi/locker" "github.com/spf13/afero" ) // ErrFatal can be used to signal an unrecoverable error. var ErrFatal = errors.New("fatal filecache error") const ( filecacheRootDirname = "filecache" ) // Cache caches a set of files in a directory. This is usually a file on // disk, but since this is backed by an Afero file system, it can be anything. type Cache struct { Fs afero.Fs // Max age for items in this cache. Negative duration means forever, // 0 is effectively turning this cache off. maxAge time.Duration // When set, we just remove this entire root directory on expiration. pruneAllRootDir string nlocker *lockTracker } type lockTracker struct { seenMu sync.RWMutex seen map[string]struct{} *locker.Locker } // Lock tracks the ids in use. We use this information to do garbage collection // after a Hugo build. func (l *lockTracker) Lock(id string) { l.seenMu.RLock() if _, seen := l.seen[id]; !seen { l.seenMu.RUnlock() l.seenMu.Lock() l.seen[id] = struct{}{} l.seenMu.Unlock() } else { l.seenMu.RUnlock() } l.Locker.Lock(id) } // ItemInfo contains info about a cached file. type ItemInfo struct { // This is the file's name relative to the cache's filesystem. Name string } // NewCache creates a new file cache with the given filesystem and max age. func NewCache(fs afero.Fs, maxAge time.Duration, pruneAllRootDir string) *Cache { return &Cache{ Fs: fs, nlocker: &lockTracker{Locker: locker.NewLocker(), seen: make(map[string]struct{})}, maxAge: maxAge, pruneAllRootDir: pruneAllRootDir, } } // lockedFile is a file with a lock that is released on Close. type lockedFile struct { afero.File unlock func() } func (l *lockedFile) Close() error { defer l.unlock() return l.File.Close() } // WriteCloser returns a transactional writer into the cache. // It's important that it's closed when done. func (c *Cache) WriteCloser(id string) (ItemInfo, io.WriteCloser, error) { id = cleanID(id) c.nlocker.Lock(id) info := ItemInfo{Name: id} f, err := helpers.OpenFileForWriting(c.Fs, id) if err != nil { c.nlocker.Unlock(id) return info, nil, err } return info, &lockedFile{ File: f, unlock: func() { c.nlocker.Unlock(id) }, }, nil } // ReadOrCreate tries to lookup the file in cache. // If found, it is passed to read and then closed. // If not found a new file is created and passed to create, which should close // it when done. func (c *Cache) ReadOrCreate(id string, read func(info ItemInfo, r io.ReadSeeker) error, create func(info ItemInfo, w io.WriteCloser) error) (info ItemInfo, err error) { id = cleanID(id) c.nlocker.Lock(id) defer c.nlocker.Unlock(id) info = ItemInfo{Name: id} if r := c.getOrRemove(id); r != nil { err = read(info, r) defer r.Close() if err == nil || err == ErrFatal { // See https://github.com/gohugoio/hugo/issues/6401 // To recover from file corruption we handle read errors // as the cache item was not found. // Any file permission issue will also fail in the next step. return } } f, err := helpers.OpenFileForWriting(c.Fs, id) if err != nil { return } err = create(info, f) return } // GetOrCreate tries to get the file with the given id from cache. If not found or expired, create will // be invoked and the result cached. // This method is protected by a named lock using the given id as identifier. func (c *Cache) GetOrCreate(id string, create func() (io.ReadCloser, error)) (ItemInfo, io.ReadCloser, error) { id = cleanID(id) c.nlocker.Lock(id) defer c.nlocker.Unlock(id) info := ItemInfo{Name: id} if r := c.getOrRemove(id); r != nil { return info, r, nil } var ( r io.ReadCloser err error ) r, err = create() if err != nil { return info, nil, err } if c.maxAge == 0 { // No caching. return info, hugio.ToReadCloser(r), nil } var buff bytes.Buffer return info, hugio.ToReadCloser(&buff), afero.WriteReader(c.Fs, id, io.TeeReader(r, &buff)) } // GetOrCreateBytes is the same as GetOrCreate, but produces a byte slice. func (c *Cache) GetOrCreateBytes(id string, create func() ([]byte, error)) (ItemInfo, []byte, error) { id = cleanID(id) c.nlocker.Lock(id) defer c.nlocker.Unlock(id) info := ItemInfo{Name: id} if r := c.getOrRemove(id); r != nil { defer r.Close() b, err := ioutil.ReadAll(r) return info, b, err } var ( b []byte err error ) b, err = create() if err != nil { return info, nil, err } if c.maxAge == 0 { return info, b, nil } if err := afero.WriteReader(c.Fs, id, bytes.NewReader(b)); err != nil { return info, nil, err } return info, b, nil } // GetBytes gets the file content with the given id from the cache, nil if none found. func (c *Cache) GetBytes(id string) (ItemInfo, []byte, error) { id = cleanID(id) c.nlocker.Lock(id) defer c.nlocker.Unlock(id) info := ItemInfo{Name: id} if r := c.getOrRemove(id); r != nil { defer r.Close() b, err := ioutil.ReadAll(r) return info, b, err } return info, nil, nil } // Get gets the file with the given id from the cahce, nil if none found. func (c *Cache) Get(id string) (ItemInfo, io.ReadCloser, error) { id = cleanID(id) c.nlocker.Lock(id) defer c.nlocker.Unlock(id) info := ItemInfo{Name: id} r := c.getOrRemove(id) return info, r, nil } // getOrRemove gets the file with the given id. If it's expired, it will // be removed. func (c *Cache) getOrRemove(id string) hugio.ReadSeekCloser { if c.maxAge == 0 { // No caching. return nil } if c.maxAge > 0 { fi, err := c.Fs.Stat(id) if err != nil { return nil } if c.isExpired(fi.ModTime()) { c.Fs.Remove(id) return nil } } f, err := c.Fs.Open(id) if err != nil { return nil } return f } func (c *Cache) isExpired(modTime time.Time) bool { if c.maxAge < 0 { return false } return c.maxAge == 0 || time.Since(modTime) > c.maxAge } // For testing func (c *Cache) getString(id string) string { id = cleanID(id) c.nlocker.Lock(id) defer c.nlocker.Unlock(id) f, err := c.Fs.Open(id) if err != nil { return "" } defer f.Close() b, _ := ioutil.ReadAll(f) return string(b) } // Caches is a named set of caches. type Caches map[string]*Cache // Get gets a named cache, nil if none found. func (f Caches) Get(name string) *Cache { return f[strings.ToLower(name)] } // NewCaches creates a new set of file caches from the given // configuration. func NewCaches(p *helpers.PathSpec) (Caches, error) { var dcfg Configs if c, ok := p.Cfg.Get("filecacheConfigs").(Configs); ok { dcfg = c } else { var err error dcfg, err = DecodeConfig(p.Fs.Source, p.Cfg) if err != nil { return nil, err } } fs := p.Fs.Source m := make(Caches) for k, v := range dcfg { var cfs afero.Fs if v.isResourceDir { cfs = p.BaseFs.ResourcesCache } else { cfs = fs } if cfs == nil { // TODO(bep) we still have some places that do not initialize the // full dependencies of a site, e.g. the import Jekyll command. // That command does not need these caches, so let us just continue // for now. continue } baseDir := v.Dir if err := cfs.MkdirAll(baseDir, 0777); err != nil && !os.IsExist(err) { return nil, err } bfs := afero.NewBasePathFs(cfs, baseDir) var pruneAllRootDir string if k == cacheKeyModules { pruneAllRootDir = "pkg" } m[k] = NewCache(bfs, v.MaxAge, pruneAllRootDir) } return m, nil } func cleanID(name string) string { return strings.TrimPrefix(filepath.Clean(name), helpers.FilePathSeparator) } hugo-0.92.2/cache/filecache/filecache_config.go000066400000000000000000000140331420147000300212630ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package filecache import ( "path" "path/filepath" "strings" "time" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/helpers" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/spf13/afero" ) const ( cachesConfigKey = "caches" resourcesGenDir = ":resourceDir/_gen" cacheDirProject = ":cacheDir/:project" ) var defaultCacheConfig = Config{ MaxAge: -1, // Never expire Dir: cacheDirProject, } const ( cacheKeyGetJSON = "getjson" cacheKeyGetCSV = "getcsv" cacheKeyImages = "images" cacheKeyAssets = "assets" cacheKeyModules = "modules" cacheKeyGetResource = "getresource" ) type Configs map[string]Config func (c Configs) CacheDirModules() string { return c[cacheKeyModules].Dir } var defaultCacheConfigs = Configs{ cacheKeyModules: { MaxAge: -1, Dir: ":cacheDir/modules", }, cacheKeyGetJSON: defaultCacheConfig, cacheKeyGetCSV: defaultCacheConfig, cacheKeyImages: { MaxAge: -1, Dir: resourcesGenDir, }, cacheKeyAssets: { MaxAge: -1, Dir: resourcesGenDir, }, cacheKeyGetResource: Config{ MaxAge: -1, // Never expire Dir: cacheDirProject, }, } type Config struct { // Max age of cache entries in this cache. Any items older than this will // be removed and not returned from the cache. // a negative value means forever, 0 means cache is disabled. MaxAge time.Duration // The directory where files are stored. Dir string // Will resources/_gen will get its own composite filesystem that // also checks any theme. isResourceDir bool } // GetJSONCache gets the file cache for getJSON. func (f Caches) GetJSONCache() *Cache { return f[cacheKeyGetJSON] } // GetCSVCache gets the file cache for getCSV. func (f Caches) GetCSVCache() *Cache { return f[cacheKeyGetCSV] } // ImageCache gets the file cache for processed images. func (f Caches) ImageCache() *Cache { return f[cacheKeyImages] } // ModulesCache gets the file cache for Hugo Modules. func (f Caches) ModulesCache() *Cache { return f[cacheKeyModules] } // AssetsCache gets the file cache for assets (processed resources, SCSS etc.). func (f Caches) AssetsCache() *Cache { return f[cacheKeyAssets] } // GetResourceCache gets the file cache for remote resources. func (f Caches) GetResourceCache() *Cache { return f[cacheKeyGetResource] } func DecodeConfig(fs afero.Fs, cfg config.Provider) (Configs, error) { c := make(Configs) valid := make(map[string]bool) // Add defaults for k, v := range defaultCacheConfigs { c[k] = v valid[k] = true } m := cfg.GetStringMap(cachesConfigKey) _, isOsFs := fs.(*afero.OsFs) for k, v := range m { if _, ok := v.(maps.Params); !ok { continue } cc := defaultCacheConfig dc := &mapstructure.DecoderConfig{ Result: &cc, DecodeHook: mapstructure.StringToTimeDurationHookFunc(), WeaklyTypedInput: true, } decoder, err := mapstructure.NewDecoder(dc) if err != nil { return c, err } if err := decoder.Decode(v); err != nil { return nil, errors.Wrap(err, "failed to decode filecache config") } if cc.Dir == "" { return c, errors.New("must provide cache Dir") } name := strings.ToLower(k) if !valid[name] { return nil, errors.Errorf("%q is not a valid cache name", name) } c[name] = cc } // This is a very old flag in Hugo, but we need to respect it. disabled := cfg.GetBool("ignoreCache") for k, v := range c { dir := filepath.ToSlash(filepath.Clean(v.Dir)) hadSlash := strings.HasPrefix(dir, "/") parts := strings.Split(dir, "/") for i, part := range parts { if strings.HasPrefix(part, ":") { resolved, isResource, err := resolveDirPlaceholder(fs, cfg, part) if err != nil { return c, err } if isResource { v.isResourceDir = true } parts[i] = resolved } } dir = path.Join(parts...) if hadSlash { dir = "/" + dir } v.Dir = filepath.Clean(filepath.FromSlash(dir)) if !v.isResourceDir { if isOsFs && !filepath.IsAbs(v.Dir) { return c, errors.Errorf("%q must resolve to an absolute directory", v.Dir) } // Avoid cache in root, e.g. / (Unix) or c:\ (Windows) if len(strings.TrimPrefix(v.Dir, filepath.VolumeName(v.Dir))) == 1 { return c, errors.Errorf("%q is a root folder and not allowed as cache dir", v.Dir) } } if !strings.HasPrefix(v.Dir, "_gen") { // We do cache eviction (file removes) and since the user can set // his/hers own cache directory, we really want to make sure // we do not delete any files that do not belong to this cache. // We do add the cache name as the root, but this is an extra safe // guard. We skip the files inside /resources/_gen/ because // that would be breaking. v.Dir = filepath.Join(v.Dir, filecacheRootDirname, k) } else { v.Dir = filepath.Join(v.Dir, k) } if disabled { v.MaxAge = 0 } c[k] = v } return c, nil } // Resolves :resourceDir => /myproject/resources etc., :cacheDir => ... func resolveDirPlaceholder(fs afero.Fs, cfg config.Provider, placeholder string) (cacheDir string, isResource bool, err error) { workingDir := cfg.GetString("workingDir") switch strings.ToLower(placeholder) { case ":resourcedir": return "", true, nil case ":cachedir": d, err := helpers.GetCacheDir(fs, cfg) return d, false, err case ":project": return filepath.Base(workingDir), false, nil } return "", false, errors.Errorf("%q is not a valid placeholder (valid values are :cacheDir or :resourceDir)", placeholder) } hugo-0.92.2/cache/filecache/filecache_config_test.go000066400000000000000000000106631420147000300223270ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package filecache import ( "path/filepath" "runtime" "strings" "testing" "time" "github.com/spf13/afero" "github.com/gohugoio/hugo/config" qt "github.com/frankban/quicktest" ) func TestDecodeConfig(t *testing.T) { t.Parallel() c := qt.New(t) configStr := ` resourceDir = "myresources" contentDir = "content" dataDir = "data" i18nDir = "i18n" layoutDir = "layouts" assetDir = "assets" archetypeDir = "archetypes" [caches] [caches.getJSON] maxAge = "10m" dir = "/path/to/c1" [caches.getCSV] maxAge = "11h" dir = "/path/to/c2" [caches.images] dir = "/path/to/c3" [caches.getResource] dir = "/path/to/c4" ` cfg, err := config.FromConfigString(configStr, "toml") c.Assert(err, qt.IsNil) fs := afero.NewMemMapFs() decoded, err := DecodeConfig(fs, cfg) c.Assert(err, qt.IsNil) c.Assert(len(decoded), qt.Equals, 6) c2 := decoded["getcsv"] c.Assert(c2.MaxAge.String(), qt.Equals, "11h0m0s") c.Assert(c2.Dir, qt.Equals, filepath.FromSlash("/path/to/c2/filecache/getcsv")) c3 := decoded["images"] c.Assert(c3.MaxAge, qt.Equals, time.Duration(-1)) c.Assert(c3.Dir, qt.Equals, filepath.FromSlash("/path/to/c3/filecache/images")) c4 := decoded["getresource"] c.Assert(c4.MaxAge, qt.Equals, time.Duration(-1)) c.Assert(c4.Dir, qt.Equals, filepath.FromSlash("/path/to/c4/filecache/getresource")) } func TestDecodeConfigIgnoreCache(t *testing.T) { t.Parallel() c := qt.New(t) configStr := ` resourceDir = "myresources" contentDir = "content" dataDir = "data" i18nDir = "i18n" layoutDir = "layouts" assetDir = "assets" archeTypedir = "archetypes" ignoreCache = true [caches] [caches.getJSON] maxAge = 1234 dir = "/path/to/c1" [caches.getCSV] maxAge = 3456 dir = "/path/to/c2" [caches.images] dir = "/path/to/c3" [caches.getResource] dir = "/path/to/c4" ` cfg, err := config.FromConfigString(configStr, "toml") c.Assert(err, qt.IsNil) fs := afero.NewMemMapFs() decoded, err := DecodeConfig(fs, cfg) c.Assert(err, qt.IsNil) c.Assert(len(decoded), qt.Equals, 6) for _, v := range decoded { c.Assert(v.MaxAge, qt.Equals, time.Duration(0)) } } func TestDecodeConfigDefault(t *testing.T) { c := qt.New(t) cfg := newTestConfig() if runtime.GOOS == "windows" { cfg.Set("resourceDir", "c:\\cache\\resources") cfg.Set("cacheDir", "c:\\cache\\thecache") } else { cfg.Set("resourceDir", "/cache/resources") cfg.Set("cacheDir", "/cache/thecache") } fs := afero.NewMemMapFs() decoded, err := DecodeConfig(fs, cfg) c.Assert(err, qt.IsNil) c.Assert(len(decoded), qt.Equals, 6) imgConfig := decoded[cacheKeyImages] jsonConfig := decoded[cacheKeyGetJSON] if runtime.GOOS == "windows" { c.Assert(imgConfig.Dir, qt.Equals, filepath.FromSlash("_gen/images")) } else { c.Assert(imgConfig.Dir, qt.Equals, "_gen/images") c.Assert(jsonConfig.Dir, qt.Equals, "/cache/thecache/hugoproject/filecache/getjson") } c.Assert(imgConfig.isResourceDir, qt.Equals, true) c.Assert(jsonConfig.isResourceDir, qt.Equals, false) } func TestDecodeConfigInvalidDir(t *testing.T) { t.Parallel() c := qt.New(t) configStr := ` resourceDir = "myresources" contentDir = "content" dataDir = "data" i18nDir = "i18n" layoutDir = "layouts" assetDir = "assets" archeTypedir = "archetypes" [caches] [caches.getJSON] maxAge = "10m" dir = "/" ` if runtime.GOOS == "windows" { configStr = strings.Replace(configStr, "/", "c:\\\\", 1) } cfg, err := config.FromConfigString(configStr, "toml") c.Assert(err, qt.IsNil) fs := afero.NewMemMapFs() _, err = DecodeConfig(fs, cfg) c.Assert(err, qt.Not(qt.IsNil)) } func newTestConfig() config.Provider { cfg := config.New() cfg.Set("workingDir", filepath.FromSlash("/my/cool/hugoproject")) cfg.Set("contentDir", "content") cfg.Set("dataDir", "data") cfg.Set("resourceDir", "resources") cfg.Set("i18nDir", "i18n") cfg.Set("layoutDir", "layouts") cfg.Set("archetypeDir", "archetypes") cfg.Set("assetDir", "assets") return cfg } hugo-0.92.2/cache/filecache/filecache_pruner.go000066400000000000000000000053061420147000300213340ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package filecache import ( "io" "os" "github.com/gohugoio/hugo/hugofs" "github.com/pkg/errors" "github.com/spf13/afero" ) // Prune removes expired and unused items from this cache. // The last one requires a full build so the cache usage can be tracked. // Note that we operate directly on the filesystem here, so this is not // thread safe. func (c Caches) Prune() (int, error) { counter := 0 for k, cache := range c { count, err := cache.Prune(false) counter += count if err != nil { if os.IsNotExist(err) { continue } return counter, errors.Wrapf(err, "failed to prune cache %q", k) } } return counter, nil } // Prune removes expired and unused items from this cache. // If force is set, everything will be removed not considering expiry time. func (c *Cache) Prune(force bool) (int, error) { if c.pruneAllRootDir != "" { return c.pruneRootDir(force) } counter := 0 err := afero.Walk(c.Fs, "", func(name string, info os.FileInfo, err error) error { if info == nil { return nil } name = cleanID(name) if info.IsDir() { f, err := c.Fs.Open(name) if err != nil { // This cache dir may not exist. return nil } defer f.Close() _, err = f.Readdirnames(1) if err == io.EOF { // Empty dir. err = c.Fs.Remove(name) } if err != nil && !os.IsNotExist(err) { return err } return nil } shouldRemove := force || c.isExpired(info.ModTime()) if !shouldRemove && len(c.nlocker.seen) > 0 { // Remove it if it's not been touched/used in the last build. _, seen := c.nlocker.seen[name] shouldRemove = !seen } if shouldRemove { err := c.Fs.Remove(name) if err == nil { counter++ } if err != nil && !os.IsNotExist(err) { return err } } return nil }) return counter, err } func (c *Cache) pruneRootDir(force bool) (int, error) { info, err := c.Fs.Stat(c.pruneAllRootDir) if err != nil { if os.IsNotExist(err) { return 0, nil } return 0, err } if !force && !c.isExpired(info.ModTime()) { return 0, nil } return hugofs.MakeReadableAndRemoveAllModulePkgDir(c.Fs, c.pruneAllRootDir) } hugo-0.92.2/cache/filecache/filecache_pruner_test.go000066400000000000000000000047321420147000300223750ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package filecache import ( "fmt" "testing" "time" "github.com/spf13/afero" qt "github.com/frankban/quicktest" ) func TestPrune(t *testing.T) { t.Parallel() c := qt.New(t) configStr := ` resourceDir = "myresources" contentDir = "content" dataDir = "data" i18nDir = "i18n" layoutDir = "layouts" assetDir = "assets" archeTypedir = "archetypes" [caches] [caches.getjson] maxAge = "200ms" dir = "/cache/c" [caches.getcsv] maxAge = "200ms" dir = "/cache/d" [caches.assets] maxAge = "200ms" dir = ":resourceDir/_gen" [caches.images] maxAge = "200ms" dir = ":resourceDir/_gen" ` for _, name := range []string{cacheKeyGetCSV, cacheKeyGetJSON, cacheKeyAssets, cacheKeyImages} { msg := qt.Commentf("cache: %s", name) p := newPathsSpec(t, afero.NewMemMapFs(), configStr) caches, err := NewCaches(p) c.Assert(err, qt.IsNil) cache := caches[name] for i := 0; i < 10; i++ { id := fmt.Sprintf("i%d", i) cache.GetOrCreateBytes(id, func() ([]byte, error) { return []byte("abc"), nil }) if i == 4 { // This will expire the first 5 time.Sleep(201 * time.Millisecond) } } count, err := caches.Prune() c.Assert(err, qt.IsNil) c.Assert(count, qt.Equals, 5, msg) for i := 0; i < 10; i++ { id := fmt.Sprintf("i%d", i) v := cache.getString(id) if i < 5 { c.Assert(v, qt.Equals, "") } else { c.Assert(v, qt.Equals, "abc") } } caches, err = NewCaches(p) c.Assert(err, qt.IsNil) cache = caches[name] // Touch one and then prune. cache.GetOrCreateBytes("i5", func() ([]byte, error) { return []byte("abc"), nil }) count, err = caches.Prune() c.Assert(err, qt.IsNil) c.Assert(count, qt.Equals, 4) // Now only the i5 should be left. for i := 0; i < 10; i++ { id := fmt.Sprintf("i%d", i) v := cache.getString(id) if i != 5 { c.Assert(v, qt.Equals, "") } else { c.Assert(v, qt.Equals, "abc") } } } } hugo-0.92.2/cache/filecache/filecache_test.go000066400000000000000000000210021420147000300207670ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package filecache import ( "errors" "fmt" "io" "io/ioutil" "os" "path/filepath" "strings" "sync" "testing" "time" "github.com/gobwas/glob" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/modules" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/spf13/afero" qt "github.com/frankban/quicktest" ) func TestFileCache(t *testing.T) { t.Parallel() c := qt.New(t) tempWorkingDir, err := ioutil.TempDir("", "hugo_filecache_test_work") c.Assert(err, qt.IsNil) defer os.Remove(tempWorkingDir) tempCacheDir, err := ioutil.TempDir("", "hugo_filecache_test_cache") c.Assert(err, qt.IsNil) defer os.Remove(tempCacheDir) osfs := afero.NewOsFs() for _, test := range []struct { cacheDir string workingDir string }{ // Run with same dirs twice to make sure that works. {tempCacheDir, tempWorkingDir}, {tempCacheDir, tempWorkingDir}, } { configStr := ` workingDir = "WORKING_DIR" resourceDir = "resources" cacheDir = "CACHEDIR" contentDir = "content" dataDir = "data" i18nDir = "i18n" layoutDir = "layouts" assetDir = "assets" archeTypedir = "archetypes" [caches] [caches.getJSON] maxAge = "10h" dir = ":cacheDir/c" ` winPathSep := "\\\\" replacer := strings.NewReplacer("CACHEDIR", test.cacheDir, "WORKING_DIR", test.workingDir) configStr = replacer.Replace(configStr) configStr = strings.Replace(configStr, "\\", winPathSep, -1) p := newPathsSpec(t, osfs, configStr) caches, err := NewCaches(p) c.Assert(err, qt.IsNil) cache := caches.Get("GetJSON") c.Assert(cache, qt.Not(qt.IsNil)) c.Assert(cache.maxAge.String(), qt.Equals, "10h0m0s") bfs, ok := cache.Fs.(*afero.BasePathFs) c.Assert(ok, qt.Equals, true) filename, err := bfs.RealPath("key") c.Assert(err, qt.IsNil) if test.cacheDir != "" { c.Assert(filename, qt.Equals, filepath.Join(test.cacheDir, "c/"+filecacheRootDirname+"/getjson/key")) } else { // Temp dir. c.Assert(filename, qt.Matches, ".*hugo_cache.*"+filecacheRootDirname+".*key") } cache = caches.Get("Images") c.Assert(cache, qt.Not(qt.IsNil)) c.Assert(cache.maxAge, qt.Equals, time.Duration(-1)) bfs, ok = cache.Fs.(*afero.BasePathFs) c.Assert(ok, qt.Equals, true) filename, _ = bfs.RealPath("key") c.Assert(filename, qt.Equals, filepath.FromSlash("_gen/images/key")) rf := func(s string) func() (io.ReadCloser, error) { return func() (io.ReadCloser, error) { return struct { io.ReadSeeker io.Closer }{ strings.NewReader(s), ioutil.NopCloser(nil), }, nil } } bf := func() ([]byte, error) { return []byte("bcd"), nil } for _, ca := range []*Cache{caches.ImageCache(), caches.AssetsCache(), caches.GetJSONCache(), caches.GetCSVCache()} { for i := 0; i < 2; i++ { info, r, err := ca.GetOrCreate("a", rf("abc")) c.Assert(err, qt.IsNil) c.Assert(r, qt.Not(qt.IsNil)) c.Assert(info.Name, qt.Equals, "a") b, _ := ioutil.ReadAll(r) r.Close() c.Assert(string(b), qt.Equals, "abc") info, b, err = ca.GetOrCreateBytes("b", bf) c.Assert(err, qt.IsNil) c.Assert(r, qt.Not(qt.IsNil)) c.Assert(info.Name, qt.Equals, "b") c.Assert(string(b), qt.Equals, "bcd") _, b, err = ca.GetOrCreateBytes("a", bf) c.Assert(err, qt.IsNil) c.Assert(string(b), qt.Equals, "abc") _, r, err = ca.GetOrCreate("a", rf("bcd")) c.Assert(err, qt.IsNil) b, _ = ioutil.ReadAll(r) r.Close() c.Assert(string(b), qt.Equals, "abc") } } c.Assert(caches.Get("getJSON"), qt.Not(qt.IsNil)) info, w, err := caches.ImageCache().WriteCloser("mykey") c.Assert(err, qt.IsNil) c.Assert(info.Name, qt.Equals, "mykey") io.WriteString(w, "Hugo is great!") w.Close() c.Assert(caches.ImageCache().getString("mykey"), qt.Equals, "Hugo is great!") info, r, err := caches.ImageCache().Get("mykey") c.Assert(err, qt.IsNil) c.Assert(r, qt.Not(qt.IsNil)) c.Assert(info.Name, qt.Equals, "mykey") b, _ := ioutil.ReadAll(r) r.Close() c.Assert(string(b), qt.Equals, "Hugo is great!") info, b, err = caches.ImageCache().GetBytes("mykey") c.Assert(err, qt.IsNil) c.Assert(info.Name, qt.Equals, "mykey") c.Assert(string(b), qt.Equals, "Hugo is great!") } } func TestFileCacheConcurrent(t *testing.T) { t.Parallel() c := qt.New(t) configStr := ` resourceDir = "myresources" contentDir = "content" dataDir = "data" i18nDir = "i18n" layoutDir = "layouts" assetDir = "assets" archeTypedir = "archetypes" [caches] [caches.getjson] maxAge = "1s" dir = "/cache/c" ` p := newPathsSpec(t, afero.NewMemMapFs(), configStr) caches, err := NewCaches(p) c.Assert(err, qt.IsNil) const cacheName = "getjson" filenameData := func(i int) (string, string) { data := fmt.Sprintf("data: %d", i) filename := fmt.Sprintf("file%d", i) return filename, data } var wg sync.WaitGroup for i := 0; i < 50; i++ { wg.Add(1) go func(i int) { defer wg.Done() for j := 0; j < 20; j++ { ca := caches.Get(cacheName) c.Assert(ca, qt.Not(qt.IsNil)) filename, data := filenameData(i) _, r, err := ca.GetOrCreate(filename, func() (io.ReadCloser, error) { return hugio.ToReadCloser(strings.NewReader(data)), nil }) c.Assert(err, qt.IsNil) b, _ := ioutil.ReadAll(r) r.Close() c.Assert(string(b), qt.Equals, data) // Trigger some expiration. time.Sleep(50 * time.Millisecond) } }(i) } wg.Wait() } func TestFileCacheReadOrCreateErrorInRead(t *testing.T) { t.Parallel() c := qt.New(t) var result string rf := func(failLevel int) func(info ItemInfo, r io.ReadSeeker) error { return func(info ItemInfo, r io.ReadSeeker) error { if failLevel > 0 { if failLevel > 1 { return ErrFatal } return errors.New("fail") } b, _ := ioutil.ReadAll(r) result = string(b) return nil } } bf := func(s string) func(info ItemInfo, w io.WriteCloser) error { return func(info ItemInfo, w io.WriteCloser) error { defer w.Close() result = s _, err := w.Write([]byte(s)) return err } } cache := NewCache(afero.NewMemMapFs(), 100*time.Hour, "") const id = "a32" _, err := cache.ReadOrCreate(id, rf(0), bf("v1")) c.Assert(err, qt.IsNil) c.Assert(result, qt.Equals, "v1") _, err = cache.ReadOrCreate(id, rf(0), bf("v2")) c.Assert(err, qt.IsNil) c.Assert(result, qt.Equals, "v1") _, err = cache.ReadOrCreate(id, rf(1), bf("v3")) c.Assert(err, qt.IsNil) c.Assert(result, qt.Equals, "v3") _, err = cache.ReadOrCreate(id, rf(2), bf("v3")) c.Assert(err, qt.Equals, ErrFatal) } func TestCleanID(t *testing.T) { c := qt.New(t) c.Assert(cleanID(filepath.FromSlash("/a/b//c.txt")), qt.Equals, filepath.FromSlash("a/b/c.txt")) c.Assert(cleanID(filepath.FromSlash("a/b//c.txt")), qt.Equals, filepath.FromSlash("a/b/c.txt")) } func initConfig(fs afero.Fs, cfg config.Provider) error { if _, err := langs.LoadLanguageSettings(cfg, nil); err != nil { return err } modConfig, err := modules.DecodeConfig(cfg) if err != nil { return err } workingDir := cfg.GetString("workingDir") themesDir := cfg.GetString("themesDir") if !filepath.IsAbs(themesDir) { themesDir = filepath.Join(workingDir, themesDir) } globAll := glob.MustCompile("**", '/') modulesClient := modules.NewClient(modules.ClientConfig{ Fs: fs, WorkingDir: workingDir, ThemesDir: themesDir, ModuleConfig: modConfig, IgnoreVendor: globAll, }) moduleConfig, err := modulesClient.Collect() if err != nil { return err } if err := modules.ApplyProjectConfigDefaults(cfg, moduleConfig.ActiveModules[len(moduleConfig.ActiveModules)-1]); err != nil { return err } cfg.Set("allModules", moduleConfig.ActiveModules) return nil } func newPathsSpec(t *testing.T, fs afero.Fs, configStr string) *helpers.PathSpec { c := qt.New(t) cfg, err := config.FromConfigString(configStr, "toml") c.Assert(err, qt.IsNil) initConfig(fs, cfg) p, err := helpers.NewPathSpec(hugofs.NewFrom(fs, cfg), cfg, nil) c.Assert(err, qt.IsNil) return p } hugo-0.92.2/cache/namedmemcache/000077500000000000000000000000001420147000300163475ustar00rootroot00000000000000hugo-0.92.2/cache/namedmemcache/named_cache.go000066400000000000000000000040451420147000300211100ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package namedmemcache provides a memory cache with a named lock. This is suitable // for situations where creating the cached resource can be time consuming or otherwise // resource hungry, or in situations where a "once only per key" is a requirement. package namedmemcache import ( "sync" "github.com/BurntSushi/locker" ) // Cache holds the cached values. type Cache struct { nlocker *locker.Locker cache map[string]cacheEntry mu sync.RWMutex } type cacheEntry struct { value interface{} err error } // New creates a new cache. func New() *Cache { return &Cache{ nlocker: locker.NewLocker(), cache: make(map[string]cacheEntry), } } // Clear clears the cache state. func (c *Cache) Clear() { c.mu.Lock() defer c.mu.Unlock() c.cache = make(map[string]cacheEntry) c.nlocker = locker.NewLocker() } // GetOrCreate tries to get the value with the given cache key, if not found // create will be called and cached. // This method is thread safe. It also guarantees that the create func for a given // key is invoked only once for this cache. func (c *Cache) GetOrCreate(key string, create func() (interface{}, error)) (interface{}, error) { c.mu.RLock() entry, found := c.cache[key] c.mu.RUnlock() if found { return entry.value, entry.err } c.nlocker.Lock(key) defer c.nlocker.Unlock(key) // Create it. value, err := create() c.mu.Lock() c.cache[key] = cacheEntry{value: value, err: err} c.mu.Unlock() return value, err } hugo-0.92.2/cache/namedmemcache/named_cache_test.go000066400000000000000000000033051420147000300221450ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package namedmemcache import ( "fmt" "sync" "testing" qt "github.com/frankban/quicktest" ) func TestNamedCache(t *testing.T) { t.Parallel() c := qt.New(t) cache := New() counter := 0 create := func() (interface{}, error) { counter++ return counter, nil } for i := 0; i < 5; i++ { v1, err := cache.GetOrCreate("a1", create) c.Assert(err, qt.IsNil) c.Assert(v1, qt.Equals, 1) v2, err := cache.GetOrCreate("a2", create) c.Assert(err, qt.IsNil) c.Assert(v2, qt.Equals, 2) } cache.Clear() v3, err := cache.GetOrCreate("a2", create) c.Assert(err, qt.IsNil) c.Assert(v3, qt.Equals, 3) } func TestNamedCacheConcurrent(t *testing.T) { t.Parallel() c := qt.New(t) var wg sync.WaitGroup cache := New() create := func(i int) func() (interface{}, error) { return func() (interface{}, error) { return i, nil } } for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() for j := 0; j < 100; j++ { id := fmt.Sprintf("id%d", j) v, err := cache.GetOrCreate(id, create(j)) c.Assert(err, qt.IsNil) c.Assert(v, qt.Equals, j) } }() } wg.Wait() } hugo-0.92.2/codegen/000077500000000000000000000000001420147000300141415ustar00rootroot00000000000000hugo-0.92.2/codegen/methods.go000066400000000000000000000303151420147000300161350ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // Some functions in this file (see comments) is based on the Go source code, // copyright The Go Authors and governed by a BSD-style license. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package codegen contains helpers for code generation. package codegen import ( "fmt" "go/ast" "go/parser" "go/token" "os" "path" "path/filepath" "reflect" "regexp" "sort" "strings" "sync" ) // Make room for insertions const weightWidth = 1000 // NewInspector creates a new Inspector given a source root. func NewInspector(root string) *Inspector { return &Inspector{ProjectRootDir: root} } // Inspector provides methods to help code generation. It uses a combination // of reflection and source code AST to do the heavy lifting. type Inspector struct { ProjectRootDir string init sync.Once // Determines method order. Go's reflect sorts lexicographically, so // we must parse the source to preserve this order. methodWeight map[string]map[string]int } // MethodsFromTypes create a method set from the include slice, excluding any // method in exclude. func (c *Inspector) MethodsFromTypes(include []reflect.Type, exclude []reflect.Type) Methods { c.parseSource() var methods Methods excludes := make(map[string]bool) if len(exclude) > 0 { for _, m := range c.MethodsFromTypes(exclude, nil) { excludes[m.Name] = true } } // There may be overlapping interfaces in types. Do a simple check for now. seen := make(map[string]bool) nameAndPackage := func(t reflect.Type) (string, string) { var name, pkg string isPointer := t.Kind() == reflect.Ptr if isPointer { t = t.Elem() } pkgPrefix := "" if pkgPath := t.PkgPath(); pkgPath != "" { pkgPath = strings.TrimSuffix(pkgPath, "/") _, shortPath := path.Split(pkgPath) pkgPrefix = shortPath + "." pkg = pkgPath } name = t.Name() if name == "" { // interface{} name = t.String() } if isPointer { pkgPrefix = "*" + pkgPrefix } name = pkgPrefix + name return name, pkg } for _, t := range include { for i := 0; i < t.NumMethod(); i++ { m := t.Method(i) if excludes[m.Name] || seen[m.Name] { continue } seen[m.Name] = true if m.PkgPath != "" { // Not exported continue } numIn := m.Type.NumIn() ownerName, _ := nameAndPackage(t) method := Method{Owner: t, OwnerName: ownerName, Name: m.Name} for i := 0; i < numIn; i++ { in := m.Type.In(i) name, pkg := nameAndPackage(in) if pkg != "" { method.Imports = append(method.Imports, pkg) } method.In = append(method.In, name) } numOut := m.Type.NumOut() if numOut > 0 { for i := 0; i < numOut; i++ { out := m.Type.Out(i) name, pkg := nameAndPackage(out) if pkg != "" { method.Imports = append(method.Imports, pkg) } method.Out = append(method.Out, name) } } methods = append(methods, method) } } sort.SliceStable(methods, func(i, j int) bool { mi, mj := methods[i], methods[j] wi := c.methodWeight[mi.OwnerName][mi.Name] wj := c.methodWeight[mj.OwnerName][mj.Name] if wi == wj { return mi.Name < mj.Name } return wi < wj }) return methods } func (c *Inspector) parseSource() { c.init.Do(func() { if !strings.Contains(c.ProjectRootDir, "hugo") { panic("dir must be set to the Hugo root") } c.methodWeight = make(map[string]map[string]int) dirExcludes := regexp.MustCompile("docs|examples") fileExcludes := regexp.MustCompile("autogen") var filenames []string filepath.Walk(c.ProjectRootDir, func(path string, info os.FileInfo, err error) error { if info.IsDir() { if dirExcludes.MatchString(info.Name()) { return filepath.SkipDir } } if !strings.HasSuffix(path, ".go") || fileExcludes.MatchString(path) { return nil } filenames = append(filenames, path) return nil }) for _, filename := range filenames { pkg := c.packageFromPath(filename) fset := token.NewFileSet() node, err := parser.ParseFile(fset, filename, nil, parser.ParseComments) if err != nil { panic(err) } ast.Inspect(node, func(n ast.Node) bool { switch t := n.(type) { case *ast.TypeSpec: if t.Name.IsExported() { switch it := t.Type.(type) { case *ast.InterfaceType: iface := pkg + "." + t.Name.Name methodNames := collectMethodsRecursive(pkg, it.Methods.List) weights := make(map[string]int) weight := weightWidth for _, name := range methodNames { weights[name] = weight weight += weightWidth } c.methodWeight[iface] = weights } } } return true }) } // Complement for _, v1 := range c.methodWeight { for k2, w := range v1 { if v, found := c.methodWeight[k2]; found { for k3, v3 := range v { v1[k3] = (v3 / weightWidth) + w } } } } }) } func (c *Inspector) packageFromPath(p string) string { p = filepath.ToSlash(p) base := path.Base(p) if !strings.Contains(base, ".") { return base } return path.Base(strings.TrimSuffix(p, base)) } // Method holds enough information about it to recreate it. type Method struct { // The interface we extracted this method from. Owner reflect.Type // String version of the above, on the form PACKAGE.NAME, e.g. // page.Page OwnerName string // Method name. Name string // Imports needed to satisfy the method signature. Imports []string // Argument types, including any package prefix, e.g. string, int, interface{}, // net.Url In []string // Return types. Out []string } // Declaration creates a method declaration (without any body) for the given receiver. func (m Method) Declaration(receiver string) string { return fmt.Sprintf("func (%s %s) %s%s %s", receiverShort(receiver), receiver, m.Name, m.inStr(), m.outStr()) } // DeclarationNamed creates a method declaration (without any body) for the given receiver // with named return values. func (m Method) DeclarationNamed(receiver string) string { return fmt.Sprintf("func (%s %s) %s%s %s", receiverShort(receiver), receiver, m.Name, m.inStr(), m.outStrNamed()) } // Delegate creates a delegate call string. func (m Method) Delegate(receiver, delegate string) string { ret := "" if len(m.Out) > 0 { ret = "return " } return fmt.Sprintf("%s%s.%s.%s%s", ret, receiverShort(receiver), delegate, m.Name, m.inOutStr()) } func (m Method) String() string { return m.Name + m.inStr() + " " + m.outStr() + "\n" } func (m Method) inOutStr() string { if len(m.In) == 0 { return "()" } args := make([]string, len(m.In)) for i := 0; i < len(args); i++ { args[i] = fmt.Sprintf("arg%d", i) } return "(" + strings.Join(args, ", ") + ")" } func (m Method) inStr() string { if len(m.In) == 0 { return "()" } args := make([]string, len(m.In)) for i := 0; i < len(args); i++ { args[i] = fmt.Sprintf("arg%d %s", i, m.In[i]) } return "(" + strings.Join(args, ", ") + ")" } func (m Method) outStr() string { if len(m.Out) == 0 { return "" } if len(m.Out) == 1 { return m.Out[0] } return "(" + strings.Join(m.Out, ", ") + ")" } func (m Method) outStrNamed() string { if len(m.Out) == 0 { return "" } outs := make([]string, len(m.Out)) for i := 0; i < len(outs); i++ { outs[i] = fmt.Sprintf("o%d %s", i, m.Out[i]) } return "(" + strings.Join(outs, ", ") + ")" } // Methods represents a list of methods for one or more interfaces. // The order matches the defined order in their source file(s). type Methods []Method // Imports returns a sorted list of package imports needed to satisfy the // signatures of all methods. func (m Methods) Imports() []string { var pkgImports []string for _, method := range m { pkgImports = append(pkgImports, method.Imports...) } if len(pkgImports) > 0 { pkgImports = uniqueNonEmptyStrings(pkgImports) sort.Strings(pkgImports) } return pkgImports } // ToMarshalJSON creates a MarshalJSON method for these methods. Any method name // matching any of the regexps in excludes will be ignored. func (m Methods) ToMarshalJSON(receiver, pkgPath string, excludes ...string) (string, []string) { var sb strings.Builder r := receiverShort(receiver) what := firstToUpper(trimAsterisk(receiver)) pgkName := path.Base(pkgPath) fmt.Fprintf(&sb, "func Marshal%sToJSON(%s %s) ([]byte, error) {\n", what, r, receiver) var methods Methods excludeRes := make([]*regexp.Regexp, len(excludes)) for i, exclude := range excludes { excludeRes[i] = regexp.MustCompile(exclude) } for _, method := range m { // Exclude methods with arguments and incompatible return values if len(method.In) > 0 || len(method.Out) == 0 || len(method.Out) > 2 { continue } if len(method.Out) == 2 { if method.Out[1] != "error" { continue } } for _, re := range excludeRes { if re.MatchString(method.Name) { continue } } methods = append(methods, method) } for _, method := range methods { varn := varName(method.Name) if len(method.Out) == 1 { fmt.Fprintf(&sb, "\t%s := %s.%s()\n", varn, r, method.Name) } else { fmt.Fprintf(&sb, "\t%s, err := %s.%s()\n", varn, r, method.Name) fmt.Fprint(&sb, "\tif err != nil {\n\t\treturn nil, err\n\t}\n") } } fmt.Fprint(&sb, "\n\ts := struct {\n") for _, method := range methods { fmt.Fprintf(&sb, "\t\t%s %s\n", method.Name, typeName(method.Out[0], pgkName)) } fmt.Fprint(&sb, "\n\t}{\n") for _, method := range methods { varn := varName(method.Name) fmt.Fprintf(&sb, "\t\t%s: %s,\n", method.Name, varn) } fmt.Fprint(&sb, "\n\t}\n\n") fmt.Fprint(&sb, "\treturn json.Marshal(&s)\n}") pkgImports := append(methods.Imports(), "encoding/json") if pkgPath != "" { // Exclude self for i, pkgImp := range pkgImports { if pkgImp == pkgPath { pkgImports = append(pkgImports[:i], pkgImports[i+1:]...) } } } return sb.String(), pkgImports } func collectMethodsRecursive(pkg string, f []*ast.Field) []string { var methodNames []string for _, m := range f { if m.Names != nil { methodNames = append(methodNames, m.Names[0].Name) continue } if ident, ok := m.Type.(*ast.Ident); ok && ident.Obj != nil { // Embedded interface methodNames = append( methodNames, collectMethodsRecursive( pkg, ident.Obj.Decl.(*ast.TypeSpec).Type.(*ast.InterfaceType).Methods.List)...) } else { // Embedded, but in a different file/package. Return the // package.Name and deal with that later. name := packageName(m.Type) if !strings.Contains(name, ".") { // Assume current package name = pkg + "." + name } methodNames = append(methodNames, name) } } return methodNames } func firstToLower(name string) string { return strings.ToLower(name[:1]) + name[1:] } func firstToUpper(name string) string { return strings.ToUpper(name[:1]) + name[1:] } func packageName(e ast.Expr) string { switch tp := e.(type) { case *ast.Ident: return tp.Name case *ast.SelectorExpr: return fmt.Sprintf("%s.%s", packageName(tp.X), packageName(tp.Sel)) } return "" } func receiverShort(receiver string) string { return strings.ToLower(trimAsterisk(receiver))[:1] } func trimAsterisk(name string) string { return strings.TrimPrefix(name, "*") } func typeName(name, pkg string) string { return strings.TrimPrefix(name, pkg+".") } func uniqueNonEmptyStrings(s []string) []string { var unique []string set := map[string]interface{}{} for _, val := range s { if val == "" { continue } if _, ok := set[val]; !ok { unique = append(unique, val) set[val] = val } } return unique } func varName(name string) string { name = firstToLower(name) // Adjust some reserved keywords, see https://golang.org/ref/spec#Keywords switch name { case "type": name = "typ" case "package": name = "pkg" // Not reserved, but syntax highlighters has it as a keyword. case "len": name = "length" } return name } hugo-0.92.2/codegen/methods2_test.go000066400000000000000000000013221420147000300172520ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package codegen type IEmbed interface { MethodEmbed3(s string) string MethodEmbed1() string MethodEmbed2() } hugo-0.92.2/codegen/methods_test.go000066400000000000000000000050611420147000300171740ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package codegen import ( "fmt" "net" "os" "reflect" "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/common/herrors" ) func TestMethods(t *testing.T) { var ( zeroIE = reflect.TypeOf((*IEmbed)(nil)).Elem() zeroIEOnly = reflect.TypeOf((*IEOnly)(nil)).Elem() zeroI = reflect.TypeOf((*I)(nil)).Elem() ) dir, _ := os.Getwd() insp := NewInspector(dir) t.Run("MethodsFromTypes", func(t *testing.T) { c := qt.New(t) methods := insp.MethodsFromTypes([]reflect.Type{zeroI}, nil) methodsStr := fmt.Sprint(methods) c.Assert(methodsStr, qt.Contains, "Method1(arg0 herrors.ErrorContext)") c.Assert(methodsStr, qt.Contains, "Method7() interface {}") c.Assert(methodsStr, qt.Contains, "Method0() string\n Method4() string") c.Assert(methodsStr, qt.Contains, "MethodEmbed3(arg0 string) string\n MethodEmbed1() string") c.Assert(methods.Imports(), qt.Contains, "github.com/gohugoio/hugo/common/herrors") }) t.Run("EmbedOnly", func(t *testing.T) { c := qt.New(t) methods := insp.MethodsFromTypes([]reflect.Type{zeroIEOnly}, nil) methodsStr := fmt.Sprint(methods) c.Assert(methodsStr, qt.Contains, "MethodEmbed3(arg0 string) string") }) t.Run("ToMarshalJSON", func(t *testing.T) { c := qt.New(t) m, pkg := insp.MethodsFromTypes( []reflect.Type{zeroI}, []reflect.Type{zeroIE}).ToMarshalJSON("*page", "page") c.Assert(m, qt.Contains, "method6 := p.Method6()") c.Assert(m, qt.Contains, "Method0: method0,") c.Assert(m, qt.Contains, "return json.Marshal(&s)") c.Assert(pkg, qt.Contains, "github.com/gohugoio/hugo/common/herrors") c.Assert(pkg, qt.Contains, "encoding/json") fmt.Println(pkg) }) } type I interface { IEmbed Method0() string Method4() string Method1(myerr herrors.ErrorContext) Method3(myint int, mystring string) Method5() (string, error) Method6() *net.IP Method7() interface{} Method8() herrors.ErrorContext method2() method9() os.FileInfo } type IEOnly interface { IEmbed } hugo-0.92.2/commands/000077500000000000000000000000001420147000300143365ustar00rootroot00000000000000hugo-0.92.2/commands/commandeer.go000066400000000000000000000237761420147000300170160ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "bytes" "errors" "io/ioutil" "os" "path/filepath" "regexp" "sync" "time" hconfig "github.com/gohugoio/hugo/config" "golang.org/x/sync/semaphore" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/hugo" jww "github.com/spf13/jwalterweatherman" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/config" "github.com/spf13/cobra" "github.com/gohugoio/hugo/hugolib" "github.com/spf13/afero" "github.com/bep/debounce" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/langs" ) type commandeerHugoState struct { *deps.DepsCfg hugoSites *hugolib.HugoSites fsCreate sync.Once created chan struct{} } type commandeer struct { *commandeerHugoState logger loggers.Logger serverConfig *config.Server buildLock func() (unlock func(), err error) // Loading state mustHaveConfigFile bool failOnInitErr bool running bool // Currently only set when in "fast render mode". But it seems to // be fast enough that we could maybe just add it for all server modes. changeDetector *fileChangeDetector // We need to reuse this on server rebuilds. destinationFs afero.Fs h *hugoBuilderCommon ftch flagsToConfigHandler visitedURLs *types.EvictingStringQueue cfgInit func(c *commandeer) error // We watch these for changes. configFiles []string // Used in cases where we get flooded with events in server mode. debounce func(f func()) serverPorts []int languagesConfigured bool languages langs.Languages doLiveReload bool fastRenderMode bool showErrorInBrowser bool wasError bool configured bool paused bool fullRebuildSem *semaphore.Weighted // Any error from the last build. buildErr error } func newCommandeerHugoState() *commandeerHugoState { return &commandeerHugoState{ created: make(chan struct{}), } } func (c *commandeerHugoState) hugo() *hugolib.HugoSites { <-c.created return c.hugoSites } func (c *commandeer) errCount() int { return int(c.logger.LogCounters().ErrorCounter.Count()) } func (c *commandeer) getErrorWithContext() interface{} { errCount := c.errCount() if errCount == 0 { return nil } m := make(map[string]interface{}) m["Error"] = errors.New(removeErrorPrefixFromLog(c.logger.Errors())) m["Version"] = hugo.BuildVersionString() fe := herrors.UnwrapErrorWithFileContext(c.buildErr) if fe != nil { m["File"] = fe } if c.h.verbose { var b bytes.Buffer herrors.FprintStackTraceFromErr(&b, c.buildErr) m["StackTrace"] = b.String() } return m } func (c *commandeer) Set(key string, value interface{}) { if c.configured { panic("commandeer cannot be changed") } c.Cfg.Set(key, value) } func (c *commandeer) initFs(fs *hugofs.Fs) error { c.destinationFs = fs.Destination c.DepsCfg.Fs = fs return nil } func newCommandeer(mustHaveConfigFile, failOnInitErr, running bool, h *hugoBuilderCommon, f flagsToConfigHandler, cfgInit func(c *commandeer) error, subCmdVs ...*cobra.Command) (*commandeer, error) { var rebuildDebouncer func(f func()) if running { // The time value used is tested with mass content replacements in a fairly big Hugo site. // It is better to wait for some seconds in those cases rather than get flooded // with rebuilds. rebuildDebouncer = debounce.New(4 * time.Second) } out := ioutil.Discard if !h.quiet { out = os.Stdout } c := &commandeer{ h: h, ftch: f, commandeerHugoState: newCommandeerHugoState(), cfgInit: cfgInit, visitedURLs: types.NewEvictingStringQueue(10), debounce: rebuildDebouncer, fullRebuildSem: semaphore.NewWeighted(1), // Init state mustHaveConfigFile: mustHaveConfigFile, failOnInitErr: failOnInitErr, running: running, // This will be replaced later, but we need something to log to before the configuration is read. logger: loggers.NewLogger(jww.LevelWarn, jww.LevelError, out, ioutil.Discard, running), } return c, c.loadConfig() } type fileChangeDetector struct { sync.Mutex current map[string]string prev map[string]string irrelevantRe *regexp.Regexp } func (f *fileChangeDetector) OnFileClose(name, md5sum string) { f.Lock() defer f.Unlock() f.current[name] = md5sum } func (f *fileChangeDetector) changed() []string { if f == nil { return nil } f.Lock() defer f.Unlock() var c []string for k, v := range f.current { vv, found := f.prev[k] if !found || v != vv { c = append(c, k) } } return f.filterIrrelevant(c) } func (f *fileChangeDetector) filterIrrelevant(in []string) []string { var filtered []string for _, v := range in { if !f.irrelevantRe.MatchString(v) { filtered = append(filtered, v) } } return filtered } func (f *fileChangeDetector) PrepareNew() { if f == nil { return } f.Lock() defer f.Unlock() if f.current == nil { f.current = make(map[string]string) f.prev = make(map[string]string) return } f.prev = make(map[string]string) for k, v := range f.current { f.prev[k] = v } f.current = make(map[string]string) } func (c *commandeer) loadConfig() error { if c.DepsCfg == nil { c.DepsCfg = &deps.DepsCfg{} } if c.logger != nil { // Truncate the error log if this is a reload. c.logger.Reset() } cfg := c.DepsCfg c.configured = false cfg.Running = c.running var dir string if c.h.source != "" { dir, _ = filepath.Abs(c.h.source) } else { dir, _ = os.Getwd() } var sourceFs afero.Fs = hugofs.Os if c.DepsCfg.Fs != nil { sourceFs = c.DepsCfg.Fs.Source } environment := c.h.getEnvironment(c.running) doWithConfig := func(cfg config.Provider) error { if c.ftch != nil { c.ftch.flagsToConfig(cfg) } cfg.Set("workingDir", dir) cfg.Set("environment", environment) return nil } cfgSetAndInit := func(cfg config.Provider) error { c.Cfg = cfg if c.cfgInit == nil { return nil } err := c.cfgInit(c) return err } configPath := c.h.source if configPath == "" { configPath = dir } config, configFiles, err := hugolib.LoadConfig( hugolib.ConfigSourceDescriptor{ Fs: sourceFs, Logger: c.logger, Path: configPath, WorkingDir: dir, Filename: c.h.cfgFile, AbsConfigDir: c.h.getConfigDir(dir), Environment: environment, }, cfgSetAndInit, doWithConfig) if err != nil { // We should improve the error handling here, // but with hugo mod init and similar there is a chicken and egg situation // with modules already configured in config.toml, so ignore those errors. if c.mustHaveConfigFile || (c.failOnInitErr && !moduleNotFoundRe.MatchString(err.Error())) { return err } else { // Just make it a warning. c.logger.Warnln(err) } } else if c.mustHaveConfigFile && len(configFiles) == 0 { return hugolib.ErrNoConfigFile } c.configFiles = configFiles if l, ok := c.Cfg.Get("languagesSorted").(langs.Languages); ok { c.languagesConfigured = true c.languages = l } // Set some commonly used flags c.doLiveReload = c.running && !c.Cfg.GetBool("disableLiveReload") c.fastRenderMode = c.doLiveReload && !c.Cfg.GetBool("disableFastRender") c.showErrorInBrowser = c.doLiveReload && !c.Cfg.GetBool("disableBrowserError") // This is potentially double work, but we need to do this one more time now // that all the languages have been configured. if c.cfgInit != nil { if err := c.cfgInit(c); err != nil { return err } } logger, err := c.createLogger(config) if err != nil { return err } cfg.Logger = logger c.logger = logger c.serverConfig, err = hconfig.DecodeServer(cfg.Cfg) if err != nil { return err } createMemFs := config.GetBool("renderToMemory") if createMemFs { // Rendering to memoryFS, publish to Root regardless of publishDir. config.Set("publishDir", "/") } c.fsCreate.Do(func() { fs := hugofs.NewFrom(sourceFs, config) if c.destinationFs != nil { // Need to reuse the destination on server rebuilds. fs.Destination = c.destinationFs } else if createMemFs { // Hugo writes the output to memory instead of the disk. fs.Destination = new(afero.MemMapFs) } if c.fastRenderMode { // For now, fast render mode only. It should, however, be fast enough // for the full variant, too. changeDetector := &fileChangeDetector{ // We use this detector to decide to do a Hot reload of a single path or not. // We need to filter out source maps and possibly some other to be able // to make that decision. irrelevantRe: regexp.MustCompile(`\.map$`), } changeDetector.PrepareNew() fs.Destination = hugofs.NewHashingFs(fs.Destination, changeDetector) c.changeDetector = changeDetector } if c.Cfg.GetBool("logPathWarnings") { fs.Destination = hugofs.NewCreateCountingFs(fs.Destination) } // To debug hard-to-find path issues. // fs.Destination = hugofs.NewStacktracerFs(fs.Destination, `fr/fr`) err = c.initFs(fs) if err != nil { close(c.created) return } var h *hugolib.HugoSites var createErr error h, createErr = hugolib.NewHugoSites(*c.DepsCfg) if h == nil || c.failOnInitErr { err = createErr } c.hugoSites = h // TODO(bep) improve. if c.buildLock == nil { c.buildLock = h.LockBuild } close(c.created) }) if err != nil { return err } cacheDir, err := helpers.GetCacheDir(sourceFs, config) if err != nil { return err } config.Set("cacheDir", cacheDir) return nil } hugo-0.92.2/commands/commands.go000066400000000000000000000255021420147000300164720ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "fmt" "os" "time" "github.com/gohugoio/hugo/hugolib/paths" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/helpers" "github.com/spf13/cobra" ) type commandsBuilder struct { hugoBuilderCommon commands []cmder } func newCommandsBuilder() *commandsBuilder { return &commandsBuilder{} } func (b *commandsBuilder) addCommands(commands ...cmder) *commandsBuilder { b.commands = append(b.commands, commands...) return b } func (b *commandsBuilder) addAll() *commandsBuilder { b.addCommands( b.newServerCmd(), newVersionCmd(), newEnvCmd(), b.newConfigCmd(), b.newDeployCmd(), b.newConvertCmd(), b.newNewCmd(), b.newListCmd(), newImportCmd(), newGenCmd(), createReleaser(), b.newModCmd(), ) return b } func (b *commandsBuilder) build() *hugoCmd { h := b.newHugoCmd() addCommands(h.getCommand(), b.commands...) return h } func addCommands(root *cobra.Command, commands ...cmder) { for _, command := range commands { cmd := command.getCommand() if cmd == nil { continue } root.AddCommand(cmd) } } type baseCmd struct { cmd *cobra.Command } var _ commandsBuilderGetter = (*baseBuilderCmd)(nil) // Used in tests. type commandsBuilderGetter interface { getCommandsBuilder() *commandsBuilder } type baseBuilderCmd struct { *baseCmd *commandsBuilder } func (b *baseBuilderCmd) getCommandsBuilder() *commandsBuilder { return b.commandsBuilder } func (c *baseCmd) getCommand() *cobra.Command { return c.cmd } func newBaseCmd(cmd *cobra.Command) *baseCmd { return &baseCmd{cmd: cmd} } func (b *commandsBuilder) newBuilderCmd(cmd *cobra.Command) *baseBuilderCmd { bcmd := &baseBuilderCmd{commandsBuilder: b, baseCmd: &baseCmd{cmd: cmd}} bcmd.hugoBuilderCommon.handleFlags(cmd) return bcmd } func (b *commandsBuilder) newBuilderBasicCmd(cmd *cobra.Command) *baseBuilderCmd { bcmd := &baseBuilderCmd{commandsBuilder: b, baseCmd: &baseCmd{cmd: cmd}} bcmd.hugoBuilderCommon.handleCommonBuilderFlags(cmd) return bcmd } func (c *baseCmd) flagsToConfig(cfg config.Provider) { initializeFlags(c.cmd, cfg) } type hugoCmd struct { *baseBuilderCmd // Need to get the sites once built. c *commandeer } var _ cmder = (*nilCommand)(nil) type nilCommand struct{} func (c *nilCommand) getCommand() *cobra.Command { return nil } func (c *nilCommand) flagsToConfig(cfg config.Provider) { } func (b *commandsBuilder) newHugoCmd() *hugoCmd { cc := &hugoCmd{} cc.baseBuilderCmd = b.newBuilderCmd(&cobra.Command{ Use: "hugo", Short: "hugo builds your site", Long: `hugo is the main command, used to build your Hugo site. Hugo is a Fast and Flexible Static Site Generator built with love by spf13 and friends in Go. Complete documentation is available at http://gohugo.io/.`, RunE: func(cmd *cobra.Command, args []string) error { defer cc.timeTrack(time.Now(), "Total") cfgInit := func(c *commandeer) error { if cc.buildWatch { c.Set("disableLiveReload", true) } return nil } // prevent cobra printing error so it can be handled here (before the timeTrack prints) cmd.SilenceErrors = true c, err := initializeConfig(true, true, cc.buildWatch, &cc.hugoBuilderCommon, cc, cfgInit) if err != nil { cmd.PrintErrln("Error:", err.Error()) return err } cc.c = c err = c.build() if err != nil { cmd.PrintErrln("Error:", err.Error()) } return err }, }) cc.cmd.PersistentFlags().StringVar(&cc.cfgFile, "config", "", "config file (default is path/config.yaml|json|toml)") cc.cmd.PersistentFlags().StringVar(&cc.cfgDir, "configDir", "config", "config dir") cc.cmd.PersistentFlags().BoolVar(&cc.quiet, "quiet", false, "build in quiet mode") // Set bash-completion _ = cc.cmd.PersistentFlags().SetAnnotation("config", cobra.BashCompFilenameExt, config.ValidConfigFileExtensions) cc.cmd.PersistentFlags().BoolVarP(&cc.verbose, "verbose", "v", false, "verbose output") cc.cmd.PersistentFlags().BoolVarP(&cc.debug, "debug", "", false, "debug output") cc.cmd.PersistentFlags().BoolVar(&cc.logging, "log", false, "enable Logging") cc.cmd.PersistentFlags().StringVar(&cc.logFile, "logFile", "", "log File path (if set, logging enabled automatically)") cc.cmd.PersistentFlags().BoolVar(&cc.verboseLog, "verboseLog", false, "verbose logging") cc.cmd.Flags().BoolVarP(&cc.buildWatch, "watch", "w", false, "watch filesystem for changes and recreate as needed") cc.cmd.Flags().Bool("renderToMemory", false, "render to memory (only useful for benchmark testing)") // Set bash-completion _ = cc.cmd.PersistentFlags().SetAnnotation("logFile", cobra.BashCompFilenameExt, []string{}) cc.cmd.SetGlobalNormalizationFunc(helpers.NormalizeHugoFlags) cc.cmd.SilenceUsage = true return cc } type hugoBuilderCommon struct { source string baseURL string environment string buildWatch bool poll string gc bool // Profile flags (for debugging of performance problems) cpuprofile string memprofile string mutexprofile string traceprofile string printm bool // TODO(bep) var vs string logging bool verbose bool verboseLog bool debug bool quiet bool cfgFile string cfgDir string logFile string } func (cc *hugoBuilderCommon) timeTrack(start time.Time, name string) { if cc.quiet { return } elapsed := time.Since(start) fmt.Printf("%s in %v ms\n", name, int(1000*elapsed.Seconds())) } func (cc *hugoBuilderCommon) getConfigDir(baseDir string) string { if cc.cfgDir != "" { return paths.AbsPathify(baseDir, cc.cfgDir) } if v, found := os.LookupEnv("HUGO_CONFIGDIR"); found { return paths.AbsPathify(baseDir, v) } return paths.AbsPathify(baseDir, "config") } func (cc *hugoBuilderCommon) getEnvironment(isServer bool) string { if cc.environment != "" { return cc.environment } if v, found := os.LookupEnv("HUGO_ENVIRONMENT"); found { return v } // Used by Netlify and Forestry if v, found := os.LookupEnv("HUGO_ENV"); found { return v } if isServer { return hugo.EnvironmentDevelopment } return hugo.EnvironmentProduction } func (cc *hugoBuilderCommon) handleCommonBuilderFlags(cmd *cobra.Command) { cmd.PersistentFlags().StringVarP(&cc.source, "source", "s", "", "filesystem path to read files relative from") cmd.PersistentFlags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{}) cmd.PersistentFlags().StringVarP(&cc.environment, "environment", "e", "", "build environment") cmd.PersistentFlags().StringP("themesDir", "", "", "filesystem path to themes directory") cmd.PersistentFlags().StringP("ignoreVendorPaths", "", "", "ignores any _vendor for module paths matching the given Glob pattern") } func (cc *hugoBuilderCommon) handleFlags(cmd *cobra.Command) { cc.handleCommonBuilderFlags(cmd) cmd.Flags().Bool("cleanDestinationDir", false, "remove files from destination not found in static directories") cmd.Flags().BoolP("buildDrafts", "D", false, "include content marked as draft") cmd.Flags().BoolP("buildFuture", "F", false, "include content with publishdate in the future") cmd.Flags().BoolP("buildExpired", "E", false, "include expired content") cmd.Flags().StringP("contentDir", "c", "", "filesystem path to content directory") cmd.Flags().StringP("layoutDir", "l", "", "filesystem path to layout directory") cmd.Flags().StringP("cacheDir", "", "", "filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/") cmd.Flags().BoolP("ignoreCache", "", false, "ignores the cache directory") cmd.Flags().StringP("destination", "d", "", "filesystem path to write files to") cmd.Flags().StringSliceP("theme", "t", []string{}, "themes to use (located in /themes/THEMENAME/)") cmd.Flags().StringVarP(&cc.baseURL, "baseURL", "b", "", "hostname (and path) to the root, e.g. http://spf13.com/") cmd.Flags().Bool("enableGitInfo", false, "add Git revision, date and author info to the pages") cmd.Flags().BoolVar(&cc.gc, "gc", false, "enable to run some cleanup tasks (remove unused cache files) after the build") cmd.Flags().StringVar(&cc.poll, "poll", "", "set this to a poll interval, e.g --poll 700ms, to use a poll based approach to watch for file system changes") cmd.Flags().BoolVar(&loggers.PanicOnWarning, "panicOnWarning", false, "panic on first WARNING log") cmd.Flags().Bool("templateMetrics", false, "display metrics about template executions") cmd.Flags().Bool("templateMetricsHints", false, "calculate some improvement hints when combined with --templateMetrics") cmd.Flags().BoolP("forceSyncStatic", "", false, "copy all files when static is changed.") cmd.Flags().BoolP("noTimes", "", false, "don't sync modification time of files") cmd.Flags().BoolP("noChmod", "", false, "don't sync permission mode of files") cmd.Flags().BoolP("i18n-warnings", "", false, "print missing translations") cmd.Flags().BoolP("path-warnings", "", false, "print warnings on duplicate target paths etc.") cmd.Flags().StringVarP(&cc.cpuprofile, "profile-cpu", "", "", "write cpu profile to `file`") cmd.Flags().StringVarP(&cc.memprofile, "profile-mem", "", "", "write memory profile to `file`") cmd.Flags().BoolVarP(&cc.printm, "print-mem", "", false, "print memory usage to screen at intervals") cmd.Flags().StringVarP(&cc.mutexprofile, "profile-mutex", "", "", "write Mutex profile to `file`") cmd.Flags().StringVarP(&cc.traceprofile, "trace", "", "", "write trace to `file` (not useful in general)") // Hide these for now. cmd.Flags().MarkHidden("profile-cpu") cmd.Flags().MarkHidden("profile-mem") cmd.Flags().MarkHidden("profile-mutex") cmd.Flags().StringSlice("disableKinds", []string{}, "disable different kind of pages (home, RSS etc.)") cmd.Flags().Bool("minify", false, "minify any supported output format (HTML, XML etc.)") // Set bash-completion. // Each flag must first be defined before using the SetAnnotation() call. _ = cmd.Flags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{}) _ = cmd.Flags().SetAnnotation("cacheDir", cobra.BashCompSubdirsInDir, []string{}) _ = cmd.Flags().SetAnnotation("destination", cobra.BashCompSubdirsInDir, []string{}) _ = cmd.Flags().SetAnnotation("theme", cobra.BashCompSubdirsInDir, []string{"themes"}) } func checkErr(logger loggers.Logger, err error, s ...string) { if err == nil { return } for _, message := range s { logger.Errorln(message) } logger.Errorln(err) } hugo-0.92.2/commands/commands_test.go000066400000000000000000000273511420147000300175350ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "fmt" "io/ioutil" "os" "path/filepath" "testing" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/htesting" "github.com/spf13/afero" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/common/types" "github.com/spf13/cobra" qt "github.com/frankban/quicktest" ) func TestExecute(t *testing.T) { c := qt.New(t) createSite := func(c *qt.C) (string, func()) { dir, clean, err := createSimpleTestSite(t, testSiteConfig{}) c.Assert(err, qt.IsNil) return dir, clean } c.Run("hugo", func(c *qt.C) { dir, clean := createSite(c) defer clean() resp := Execute([]string{"-s=" + dir}) c.Assert(resp.Err, qt.IsNil) result := resp.Result c.Assert(len(result.Sites) == 1, qt.Equals, true) c.Assert(len(result.Sites[0].RegularPages()) == 1, qt.Equals, true) c.Assert(result.Sites[0].Info.Params()["myparam"], qt.Equals, "paramproduction") }) c.Run("hugo, set environment", func(c *qt.C) { dir, clean := createSite(c) defer clean() resp := Execute([]string{"-s=" + dir, "-e=staging"}) c.Assert(resp.Err, qt.IsNil) result := resp.Result c.Assert(result.Sites[0].Info.Params()["myparam"], qt.Equals, "paramstaging") }) c.Run("convert toJSON", func(c *qt.C) { dir, clean := createSite(c) output := filepath.Join(dir, "myjson") defer clean() resp := Execute([]string{"convert", "toJSON", "-s=" + dir, "-e=staging", "-o=" + output}) c.Assert(resp.Err, qt.IsNil) converted := readFileFrom(c, filepath.Join(output, "content", "p1.md")) c.Assert(converted, qt.Equals, "{\n \"title\": \"P1\",\n \"weight\": 1\n}\n\nContent\n\n", qt.Commentf(converted)) }) c.Run("config, set environment", func(c *qt.C) { dir, clean := createSite(c) defer clean() out, err := captureStdout(func() error { resp := Execute([]string{"config", "-s=" + dir, "-e=staging"}) return resp.Err }) c.Assert(err, qt.IsNil) c.Assert(out, qt.Contains, "params = map[myparam:paramstaging]", qt.Commentf(out)) }) c.Run("deploy, environment set", func(c *qt.C) { dir, clean := createSite(c) defer clean() resp := Execute([]string{"deploy", "-s=" + dir, "-e=staging", "--target=mydeployment", "--dryRun"}) c.Assert(resp.Err, qt.Not(qt.IsNil)) c.Assert(resp.Err.Error(), qt.Contains, `no driver registered for "hugocloud"`) }) c.Run("list", func(c *qt.C) { dir, clean := createSite(c) defer clean() out, err := captureStdout(func() error { resp := Execute([]string{"list", "all", "-s=" + dir, "-e=staging"}) return resp.Err }) c.Assert(err, qt.IsNil) c.Assert(out, qt.Contains, "p1.md") }) c.Run("new theme", func(c *qt.C) { dir, clean := createSite(c) defer clean() themesDir := filepath.Join(dir, "mythemes") resp := Execute([]string{"new", "theme", "mytheme", "-s=" + dir, "-e=staging", "--themesDir=" + themesDir}) c.Assert(resp.Err, qt.IsNil) themeTOML := readFileFrom(c, filepath.Join(themesDir, "mytheme", "theme.toml")) c.Assert(themeTOML, qt.Contains, "name = \"Mytheme\"") }) c.Run("new site", func(c *qt.C) { dir, clean := createSite(c) defer clean() siteDir := filepath.Join(dir, "mysite") resp := Execute([]string{"new", "site", siteDir, "-e=staging"}) c.Assert(resp.Err, qt.IsNil) config := readFileFrom(c, filepath.Join(siteDir, "config.toml")) c.Assert(config, qt.Contains, "baseURL = 'http://example.org/'") checkNewSiteInited(c, siteDir) }) } func checkNewSiteInited(c *qt.C, basepath string) { paths := []string{ filepath.Join(basepath, "layouts"), filepath.Join(basepath, "content"), filepath.Join(basepath, "archetypes"), filepath.Join(basepath, "static"), filepath.Join(basepath, "data"), filepath.Join(basepath, "config.toml"), } for _, path := range paths { _, err := os.Stat(path) c.Assert(err, qt.IsNil) } } func readFileFrom(c *qt.C, filename string) string { c.Helper() filename = filepath.Clean(filename) b, err := afero.ReadFile(hugofs.Os, filename) c.Assert(err, qt.IsNil) return string(b) } func TestFlags(t *testing.T) { c := qt.New(t) noOpRunE := func(cmd *cobra.Command, args []string) error { return nil } tests := []struct { name string args []string check func(c *qt.C, cmd *serverCmd) }{ { // https://github.com/gohugoio/hugo/issues/7642 name: "ignoreVendorPaths", args: []string{"server", "--ignoreVendorPaths=github.com/**"}, check: func(c *qt.C, cmd *serverCmd) { cfg := config.New() cmd.flagsToConfig(cfg) c.Assert(cfg.Get("ignoreVendorPaths"), qt.Equals, "github.com/**") }, }, { name: "Persistent flags", args: []string{ "server", "--config=myconfig.toml", "--configDir=myconfigdir", "--contentDir=mycontent", "--disableKinds=page,home", "--environment=testing", "--configDir=myconfigdir", "--layoutDir=mylayouts", "--theme=mytheme", "--gc", "--themesDir=mythemes", "--cleanDestinationDir", "--navigateToChanged", "--disableLiveReload", "--noHTTPCache", "--i18n-warnings", "--destination=/tmp/mydestination", "-b=https://example.com/b/", "--port=1366", "--renderToDisk", "--source=mysource", "--path-warnings", }, check: func(c *qt.C, sc *serverCmd) { c.Assert(sc, qt.Not(qt.IsNil)) c.Assert(sc.navigateToChanged, qt.Equals, true) c.Assert(sc.disableLiveReload, qt.Equals, true) c.Assert(sc.noHTTPCache, qt.Equals, true) c.Assert(sc.renderToDisk, qt.Equals, true) c.Assert(sc.serverPort, qt.Equals, 1366) c.Assert(sc.environment, qt.Equals, "testing") cfg := config.New() sc.flagsToConfig(cfg) c.Assert(cfg.GetString("publishDir"), qt.Equals, "/tmp/mydestination") c.Assert(cfg.GetString("contentDir"), qt.Equals, "mycontent") c.Assert(cfg.GetString("layoutDir"), qt.Equals, "mylayouts") c.Assert(cfg.GetStringSlice("theme"), qt.DeepEquals, []string{"mytheme"}) c.Assert(cfg.GetString("themesDir"), qt.Equals, "mythemes") c.Assert(cfg.GetString("baseURL"), qt.Equals, "https://example.com/b/") c.Assert(cfg.Get("disableKinds"), qt.DeepEquals, []string{"page", "home"}) c.Assert(cfg.GetBool("gc"), qt.Equals, true) // The flag is named path-warnings c.Assert(cfg.GetBool("logPathWarnings"), qt.Equals, true) // The flag is named i18n-warnings c.Assert(cfg.GetBool("logI18nWarnings"), qt.Equals, true) }, }, } for _, test := range tests { c.Run(test.name, func(c *qt.C) { b := newCommandsBuilder() root := b.addAll().build() for _, cmd := range b.commands { if cmd.getCommand() == nil { continue } // We are only intereseted in the flag handling here. cmd.getCommand().RunE = noOpRunE } rootCmd := root.getCommand() rootCmd.SetArgs(test.args) c.Assert(rootCmd.Execute(), qt.IsNil) test.check(c, b.commands[0].(*serverCmd)) }) } } func TestCommandsExecute(t *testing.T) { c := qt.New(t) dir, clean, err := createSimpleTestSite(t, testSiteConfig{}) c.Assert(err, qt.IsNil) dirOut, clean2, err := htesting.CreateTempDir(hugofs.Os, "hugo-cli-out") c.Assert(err, qt.IsNil) defer clean() defer clean2() sourceFlag := fmt.Sprintf("-s=%s", dir) tests := []struct { commands []string flags []string expectErrToContain string }{ // TODO(bep) permission issue on my OSX? "operation not permitted" {[]string{"check", "ulimit"}, nil, false}, {[]string{"env"}, nil, ""}, {[]string{"version"}, nil, ""}, // no args = hugo build {nil, []string{sourceFlag}, ""}, {nil, []string{sourceFlag, "--renderToMemory"}, ""}, {[]string{"completion", "bash"}, nil, ""}, {[]string{"completion", "fish"}, nil, ""}, {[]string{"completion", "powershell"}, nil, ""}, {[]string{"completion", "zsh"}, nil, ""}, {[]string{"config"}, []string{sourceFlag}, ""}, {[]string{"convert", "toTOML"}, []string{sourceFlag, "-o=" + filepath.Join(dirOut, "toml")}, ""}, {[]string{"convert", "toYAML"}, []string{sourceFlag, "-o=" + filepath.Join(dirOut, "yaml")}, ""}, {[]string{"convert", "toJSON"}, []string{sourceFlag, "-o=" + filepath.Join(dirOut, "json")}, ""}, {[]string{"gen", "chromastyles"}, []string{"--style=manni"}, ""}, {[]string{"gen", "doc"}, []string{"--dir=" + filepath.Join(dirOut, "doc")}, ""}, {[]string{"gen", "man"}, []string{"--dir=" + filepath.Join(dirOut, "man")}, ""}, {[]string{"list", "drafts"}, []string{sourceFlag}, ""}, {[]string{"list", "expired"}, []string{sourceFlag}, ""}, {[]string{"list", "future"}, []string{sourceFlag}, ""}, {[]string{"new", "new-page.md"}, []string{sourceFlag}, ""}, {[]string{"new", "site", filepath.Join(dirOut, "new-site")}, nil, ""}, {[]string{"unknowncommand"}, nil, "unknown command"}, // TODO(bep) cli refactor fix https://github.com/gohugoio/hugo/issues/4450 //{[]string{"new", "theme", filepath.Join(dirOut, "new-theme")}, nil,false}, } for _, test := range tests { b := newCommandsBuilder().addAll().build() hugoCmd := b.getCommand() test.flags = append(test.flags, "--quiet") hugoCmd.SetArgs(append(test.commands, test.flags...)) // TODO(bep) capture output and add some simple asserts // TODO(bep) misspelled subcommands does not return an error. We should investigate this // but before that, check for "Error: unknown command". _, err := hugoCmd.ExecuteC() if test.expectErrToContain != "" { c.Assert(err, qt.Not(qt.IsNil)) c.Assert(err.Error(), qt.Contains, test.expectErrToContain) } else { c.Assert(err, qt.IsNil) } // Assert that we have not left any development debug artifacts in // the code. if b.c != nil { _, ok := b.c.destinationFs.(types.DevMarker) c.Assert(ok, qt.Equals, false) } } } type testSiteConfig struct { configTOML string contentDir string } func createSimpleTestSite(t *testing.T, cfg testSiteConfig) (string, func(), error) { d, clean, e := htesting.CreateTempDir(hugofs.Os, "hugo-cli") if e != nil { return "", nil, e } cfgStr := ` baseURL = "https://example.org" title = "Hugo Commands" ` contentDir := "content" if cfg.configTOML != "" { cfgStr = cfg.configTOML } if cfg.contentDir != "" { contentDir = cfg.contentDir } os.MkdirAll(filepath.Join(d, "public"), 0777) // Just the basic. These are for CLI tests, not site testing. writeFile(t, filepath.Join(d, "config.toml"), cfgStr) writeFile(t, filepath.Join(d, "config", "staging", "params.toml"), `myparam="paramstaging"`) writeFile(t, filepath.Join(d, "config", "staging", "deployment.toml"), ` [[targets]] name = "mydeployment" URL = "hugocloud://hugotestbucket" `) writeFile(t, filepath.Join(d, "config", "testing", "params.toml"), `myparam="paramtesting"`) writeFile(t, filepath.Join(d, "config", "production", "params.toml"), `myparam="paramproduction"`) writeFile(t, filepath.Join(d, contentDir, "p1.md"), ` --- title: "P1" weight: 1 --- Content `) writeFile(t, filepath.Join(d, "layouts", "_default", "single.html"), ` Single: {{ .Title }} `) writeFile(t, filepath.Join(d, "layouts", "_default", "list.html"), ` List: {{ .Title }} Environment: {{ hugo.Environment }} `) return d, clean, nil } func writeFile(t *testing.T, filename, content string) { must(t, os.MkdirAll(filepath.Dir(filename), os.FileMode(0755))) must(t, ioutil.WriteFile(filename, []byte(content), os.FileMode(0755))) } func must(t *testing.T, err error) { if err != nil { t.Fatal(err) } } hugo-0.92.2/commands/config.go000066400000000000000000000107151420147000300161360ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License.Print the version number of Hug package commands import ( "encoding/json" "fmt" "os" "reflect" "regexp" "sort" "strings" "time" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/parser" "github.com/gohugoio/hugo/parser/metadecoders" "github.com/gohugoio/hugo/modules" "github.com/spf13/cobra" ) var _ cmder = (*configCmd)(nil) type configCmd struct { *baseBuilderCmd } func (b *commandsBuilder) newConfigCmd() *configCmd { cc := &configCmd{} cmd := &cobra.Command{ Use: "config", Short: "Print the site configuration", Long: `Print the site configuration, both default and custom settings.`, RunE: cc.printConfig, } printMountsCmd := &cobra.Command{ Use: "mounts", Short: "Print the configured file mounts", RunE: cc.printMounts, } cmd.AddCommand(printMountsCmd) cc.baseBuilderCmd = b.newBuilderBasicCmd(cmd) return cc } func (c *configCmd) printMounts(cmd *cobra.Command, args []string) error { cfg, err := initializeConfig(true, false, false, &c.hugoBuilderCommon, c, nil) if err != nil { return err } allModules := cfg.Cfg.Get("allmodules").(modules.Modules) for _, m := range allModules { if err := parser.InterfaceToConfig(&modMounts{m: m, verbose: c.verbose}, metadecoders.JSON, os.Stdout); err != nil { return err } } return nil } func (c *configCmd) printConfig(cmd *cobra.Command, args []string) error { cfg, err := initializeConfig(true, false, false, &c.hugoBuilderCommon, c, nil) if err != nil { return err } allSettings := cfg.Cfg.Get("").(maps.Params) // We need to clean up this, but we store objects in the config that // isn't really interesting to the end user, so filter these. ignoreKeysRe := regexp.MustCompile("client|sorted|filecacheconfigs|allmodules|multilingual") separator := ": " if len(cfg.configFiles) > 0 && strings.HasSuffix(cfg.configFiles[0], ".toml") { separator = " = " } var keys []string for k := range allSettings { if ignoreKeysRe.MatchString(k) { continue } keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { kv := reflect.ValueOf(allSettings[k]) if kv.Kind() == reflect.String { fmt.Printf("%s%s\"%+v\"\n", k, separator, allSettings[k]) } else { fmt.Printf("%s%s%+v\n", k, separator, allSettings[k]) } } return nil } type modMounts struct { verbose bool m modules.Module } type modMount struct { Source string `json:"source"` Target string `json:"target"` Lang string `json:"lang,omitempty"` } func (m *modMounts) MarshalJSON() ([]byte, error) { var mounts []modMount for _, mount := range m.m.Mounts() { mounts = append(mounts, modMount{ Source: mount.Source, Target: mount.Target, Lang: mount.Lang, }) } var ownerPath string if m.m.Owner() != nil { ownerPath = m.m.Owner().Path() } if m.verbose { config := m.m.Config() return json.Marshal(&struct { Path string `json:"path"` Version string `json:"version"` Time time.Time `json:"time"` Owner string `json:"owner"` Dir string `json:"dir"` Meta map[string]interface{} `json:"meta"` HugoVersion modules.HugoVersion `json:"hugoVersion"` Mounts []modMount `json:"mounts"` }{ Path: m.m.Path(), Version: m.m.Version(), Time: m.m.Time(), Owner: ownerPath, Dir: m.m.Dir(), Meta: config.Params, HugoVersion: config.HugoVersion, Mounts: mounts, }) } return json.Marshal(&struct { Path string `json:"path"` Version string `json:"version"` Time time.Time `json:"time"` Owner string `json:"owner"` Dir string `json:"dir"` Mounts []modMount `json:"mounts"` }{ Path: m.m.Path(), Version: m.m.Version(), Time: m.m.Time(), Owner: ownerPath, Dir: m.m.Dir(), Mounts: mounts, }) } hugo-0.92.2/commands/convert.go000066400000000000000000000124311420147000300163460ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "bytes" "fmt" "path/filepath" "strings" "time" "github.com/gohugoio/hugo/parser/pageparser" "github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/parser" "github.com/gohugoio/hugo/parser/metadecoders" "github.com/pkg/errors" "github.com/gohugoio/hugo/hugolib" "github.com/spf13/cobra" ) var _ cmder = (*convertCmd)(nil) type convertCmd struct { outputDir string unsafe bool *baseBuilderCmd } func (b *commandsBuilder) newConvertCmd() *convertCmd { cc := &convertCmd{} cmd := &cobra.Command{ Use: "convert", Short: "Convert your content to different formats", Long: `Convert your content (e.g. front matter) to different formats. See convert's subcommands toJSON, toTOML and toYAML for more information.`, RunE: nil, } cmd.AddCommand( &cobra.Command{ Use: "toJSON", Short: "Convert front matter to JSON", Long: `toJSON converts all front matter in the content directory to use JSON for the front matter.`, RunE: func(cmd *cobra.Command, args []string) error { return cc.convertContents(metadecoders.JSON) }, }, &cobra.Command{ Use: "toTOML", Short: "Convert front matter to TOML", Long: `toTOML converts all front matter in the content directory to use TOML for the front matter.`, RunE: func(cmd *cobra.Command, args []string) error { return cc.convertContents(metadecoders.TOML) }, }, &cobra.Command{ Use: "toYAML", Short: "Convert front matter to YAML", Long: `toYAML converts all front matter in the content directory to use YAML for the front matter.`, RunE: func(cmd *cobra.Command, args []string) error { return cc.convertContents(metadecoders.YAML) }, }, ) cmd.PersistentFlags().StringVarP(&cc.outputDir, "output", "o", "", "filesystem path to write files to") cmd.PersistentFlags().BoolVar(&cc.unsafe, "unsafe", false, "enable less safe operations, please backup first") cc.baseBuilderCmd = b.newBuilderBasicCmd(cmd) return cc } func (cc *convertCmd) convertContents(format metadecoders.Format) error { if cc.outputDir == "" && !cc.unsafe { return newUserError("Unsafe operation not allowed, use --unsafe or set a different output path") } c, err := initializeConfig(true, false, false, &cc.hugoBuilderCommon, cc, nil) if err != nil { return err } c.Cfg.Set("buildDrafts", true) h, err := hugolib.NewHugoSites(*c.DepsCfg) if err != nil { return err } if err := h.Build(hugolib.BuildCfg{SkipRender: true}); err != nil { return err } site := h.Sites[0] site.Log.Println("processing", len(site.AllPages()), "content files") for _, p := range site.AllPages() { if err := cc.convertAndSavePage(p, site, format); err != nil { return err } } return nil } func (cc *convertCmd) convertAndSavePage(p page.Page, site *hugolib.Site, targetFormat metadecoders.Format) error { // The resources are not in .Site.AllPages. for _, r := range p.Resources().ByType("page") { if err := cc.convertAndSavePage(r.(page.Page), site, targetFormat); err != nil { return err } } if p.File().IsZero() { // No content file. return nil } errMsg := fmt.Errorf("Error processing file %q", p.File().Path()) site.Log.Infoln("Attempting to convert", p.File().Filename()) f := p.File() file, err := f.FileInfo().Meta().Open() if err != nil { site.Log.Errorln(errMsg) file.Close() return nil } pf, err := pageparser.ParseFrontMatterAndContent(file) if err != nil { site.Log.Errorln(errMsg) file.Close() return err } file.Close() // better handling of dates in formats that don't have support for them if pf.FrontMatterFormat == metadecoders.JSON || pf.FrontMatterFormat == metadecoders.YAML || pf.FrontMatterFormat == metadecoders.TOML { for k, v := range pf.FrontMatter { switch vv := v.(type) { case time.Time: pf.FrontMatter[k] = vv.Format(time.RFC3339) } } } var newContent bytes.Buffer err = parser.InterfaceToFrontMatter(pf.FrontMatter, targetFormat, &newContent) if err != nil { site.Log.Errorln(errMsg) return err } newContent.Write(pf.Content) newFilename := p.File().Filename() if cc.outputDir != "" { contentDir := strings.TrimSuffix(newFilename, p.File().Path()) contentDir = filepath.Base(contentDir) newFilename = filepath.Join(cc.outputDir, contentDir, p.File().Path()) } fs := hugofs.Os if err := helpers.WriteToDisk(newFilename, &newContent, fs); err != nil { return errors.Wrapf(err, "Failed to save file %q:", newFilename) } return nil } type parsedFile struct { frontMatterFormat metadecoders.Format frontMatterSource []byte frontMatter map[string]interface{} // Everything after Front Matter content []byte } hugo-0.92.2/commands/deploy.go000066400000000000000000000054341420147000300161670ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build !nodeploy package commands import ( "context" "github.com/gohugoio/hugo/deploy" "github.com/spf13/cobra" ) var _ cmder = (*deployCmd)(nil) // deployCmd supports deploying sites to Cloud providers. type deployCmd struct { *baseBuilderCmd invalidateCDN bool maxDeletes int } // TODO: In addition to the "deploy" command, consider adding a "--deploy" // flag for the default command; this would build the site and then deploy it. // It's not obvious how to do this; would all of the deploy-specific flags // have to exist at the top level as well? // TODO: The output files change every time "hugo" is executed, it looks // like because of map order randomization. This means that you can // run "hugo && hugo deploy" again and again and upload new stuff every time. Is // this intended? func (b *commandsBuilder) newDeployCmd() *deployCmd { cc := &deployCmd{} cmd := &cobra.Command{ Use: "deploy", Short: "Deploy your site to a Cloud provider.", Long: `Deploy your site to a Cloud provider. See https://gohugo.io/hosting-and-deployment/hugo-deploy/ for detailed documentation. `, RunE: func(cmd *cobra.Command, args []string) error { cfgInit := func(c *commandeer) error { c.Set("invalidateCDN", cc.invalidateCDN) c.Set("maxDeletes", cc.maxDeletes) return nil } comm, err := initializeConfig(true, true, false, &cc.hugoBuilderCommon, cc, cfgInit) if err != nil { return err } deployer, err := deploy.New(comm.Cfg, comm.hugo().PathSpec.PublishFs) if err != nil { return err } return deployer.Deploy(context.Background()) }, } cmd.Flags().String("target", "", "target deployment from deployments section in config file; defaults to the first one") cmd.Flags().Bool("confirm", false, "ask for confirmation before making changes to the target") cmd.Flags().Bool("dryRun", false, "dry run") cmd.Flags().Bool("force", false, "force upload of all files") cmd.Flags().BoolVar(&cc.invalidateCDN, "invalidateCDN", true, "invalidate the CDN cache listed in the deployment target") cmd.Flags().IntVar(&cc.maxDeletes, "maxDeletes", 256, "maximum # of files to delete, or -1 to disable") cc.baseBuilderCmd = b.newBuilderBasicCmd(cmd) return cc } hugo-0.92.2/commands/env.go000066400000000000000000000031031420147000300154520ustar00rootroot00000000000000// Copyright 2016 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "runtime" "github.com/gohugoio/hugo/common/hugo" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*envCmd)(nil) type envCmd struct { *baseCmd } func newEnvCmd() *envCmd { return &envCmd{ baseCmd: newBaseCmd(&cobra.Command{ Use: "env", Short: "Print Hugo version and environment info", Long: `Print Hugo version and environment info. This is useful in Hugo bug reports. If you add the -v flag, you will get a full dependency list. `, RunE: func(cmd *cobra.Command, args []string) error { printHugoVersion() jww.FEEDBACK.Printf("GOOS=%q\n", runtime.GOOS) jww.FEEDBACK.Printf("GOARCH=%q\n", runtime.GOARCH) jww.FEEDBACK.Printf("GOVERSION=%q\n", runtime.Version()) isVerbose, _ := cmd.Flags().GetBool("verbose") if isVerbose { deps := hugo.GetDependencyList() for _, dep := range deps { jww.FEEDBACK.Printf("%s\n", dep) } } return nil }, }), } } hugo-0.92.2/commands/gen.go000066400000000000000000000020501420147000300154330ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "github.com/spf13/cobra" ) var _ cmder = (*genCmd)(nil) type genCmd struct { *baseCmd } func newGenCmd() *genCmd { cc := &genCmd{} cc.baseCmd = newBaseCmd(&cobra.Command{ Use: "gen", Short: "A collection of several useful generators.", }) cc.cmd.AddCommand( newGenDocCmd().getCommand(), newGenManCmd().getCommand(), createGenDocsHelper().getCommand(), createGenChromaStyles().getCommand()) return cc } hugo-0.92.2/commands/genchromastyles.go000066400000000000000000000045411420147000300201000ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "os" "github.com/alecthomas/chroma" "github.com/alecthomas/chroma/formatters/html" "github.com/alecthomas/chroma/styles" "github.com/spf13/cobra" ) var _ cmder = (*genChromaStyles)(nil) type genChromaStyles struct { style string highlightStyle string linesStyle string *baseCmd } // TODO(bep) highlight func createGenChromaStyles() *genChromaStyles { g := &genChromaStyles{ baseCmd: newBaseCmd(&cobra.Command{ Use: "chromastyles", Short: "Generate CSS stylesheet for the Chroma code highlighter", Long: `Generate CSS stylesheet for the Chroma code highlighter for a given style. This stylesheet is needed if markup.highlight.noClasses is disabled in config. See https://xyproto.github.io/splash/docs/all.html for a preview of the available styles`, }), } g.cmd.RunE = func(cmd *cobra.Command, args []string) error { return g.generate() } g.cmd.PersistentFlags().StringVar(&g.style, "style", "friendly", "highlighter style (see https://xyproto.github.io/splash/docs/)") g.cmd.PersistentFlags().StringVar(&g.highlightStyle, "highlightStyle", "bg:#ffffcc", "style used for highlighting lines (see https://github.com/alecthomas/chroma)") g.cmd.PersistentFlags().StringVar(&g.linesStyle, "linesStyle", "", "style used for line numbers (see https://github.com/alecthomas/chroma)") return g } func (g *genChromaStyles) generate() error { builder := styles.Get(g.style).Builder() if g.highlightStyle != "" { builder.Add(chroma.LineHighlight, g.highlightStyle) } if g.linesStyle != "" { builder.Add(chroma.LineNumbers, g.linesStyle) } style, err := builder.Build() if err != nil { return err } formatter := html.New(html.WithAllClasses(true)) formatter.WriteCSS(os.Stdout, style) return nil } hugo-0.92.2/commands/gendoc.go000066400000000000000000000056461420147000300161370ustar00rootroot00000000000000// Copyright 2016 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "fmt" "path" "path/filepath" "strings" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*genDocCmd)(nil) type genDocCmd struct { gendocdir string *baseCmd } func newGenDocCmd() *genDocCmd { const gendocFrontmatterTemplate = `--- title: "%s" slug: %s url: %s --- ` cc := &genDocCmd{} cc.baseCmd = newBaseCmd(&cobra.Command{ Use: "doc", Short: "Generate Markdown documentation for the Hugo CLI.", Long: `Generate Markdown documentation for the Hugo CLI. This command is, mostly, used to create up-to-date documentation of Hugo's command-line interface for http://gohugo.io/. It creates one Markdown file per command with front matter suitable for rendering in Hugo.`, RunE: func(cmd *cobra.Command, args []string) error { cmd.VisitParents(func(c *cobra.Command) { // Disable the "Auto generated by spf13/cobra on DATE" // as it creates a lot of diffs. c.DisableAutoGenTag = true }) if !strings.HasSuffix(cc.gendocdir, helpers.FilePathSeparator) { cc.gendocdir += helpers.FilePathSeparator } if found, _ := helpers.Exists(cc.gendocdir, hugofs.Os); !found { jww.FEEDBACK.Println("Directory", cc.gendocdir, "does not exist, creating...") if err := hugofs.Os.MkdirAll(cc.gendocdir, 0777); err != nil { return err } } prepender := func(filename string) string { name := filepath.Base(filename) base := strings.TrimSuffix(name, path.Ext(name)) url := "/commands/" + strings.ToLower(base) + "/" return fmt.Sprintf(gendocFrontmatterTemplate, strings.Replace(base, "_", " ", -1), base, url) } linkHandler := func(name string) string { base := strings.TrimSuffix(name, path.Ext(name)) return "/commands/" + strings.ToLower(base) + "/" } jww.FEEDBACK.Println("Generating Hugo command-line documentation in", cc.gendocdir, "...") doc.GenMarkdownTreeCustom(cmd.Root(), cc.gendocdir, prepender, linkHandler) jww.FEEDBACK.Println("Done.") return nil }, }) cc.cmd.PersistentFlags().StringVar(&cc.gendocdir, "dir", "/tmp/hugodoc/", "the directory to write the doc.") // For bash-completion cc.cmd.PersistentFlags().SetAnnotation("dir", cobra.BashCompSubdirsInDir, []string{}) return cc } hugo-0.92.2/commands/gendocshelper.go000066400000000000000000000031641420147000300175130ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "encoding/json" "fmt" "os" "path/filepath" "github.com/gohugoio/hugo/docshelper" "github.com/spf13/cobra" ) var _ cmder = (*genDocsHelper)(nil) type genDocsHelper struct { target string *baseCmd } func createGenDocsHelper() *genDocsHelper { g := &genDocsHelper{ baseCmd: newBaseCmd(&cobra.Command{ Use: "docshelper", Short: "Generate some data files for the Hugo docs.", Hidden: true, }), } g.cmd.RunE = func(cmd *cobra.Command, args []string) error { return g.generate() } g.cmd.PersistentFlags().StringVarP(&g.target, "dir", "", "docs/data", "data dir") return g } func (g *genDocsHelper) generate() error { fmt.Println("Generate docs data to", g.target) targetFile := filepath.Join(g.target, "docs.json") f, err := os.Create(targetFile) if err != nil { return err } defer f.Close() enc := json.NewEncoder(f) enc.SetIndent("", " ") if err := enc.Encode(docshelper.GetDocProvider()); err != nil { return err } fmt.Println("Done!") return nil } hugo-0.92.2/commands/genman.go000066400000000000000000000044371420147000300161420ustar00rootroot00000000000000// Copyright 2016 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "fmt" "strings" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*genManCmd)(nil) type genManCmd struct { genmandir string *baseCmd } func newGenManCmd() *genManCmd { cc := &genManCmd{} cc.baseCmd = newBaseCmd(&cobra.Command{ Use: "man", Short: "Generate man pages for the Hugo CLI", Long: `This command automatically generates up-to-date man pages of Hugo's command-line interface. By default, it creates the man page files in the "man" directory under the current directory.`, RunE: func(cmd *cobra.Command, args []string) error { header := &doc.GenManHeader{ Section: "1", Manual: "Hugo Manual", Source: fmt.Sprintf("Hugo %s", hugo.CurrentVersion), } if !strings.HasSuffix(cc.genmandir, helpers.FilePathSeparator) { cc.genmandir += helpers.FilePathSeparator } if found, _ := helpers.Exists(cc.genmandir, hugofs.Os); !found { jww.FEEDBACK.Println("Directory", cc.genmandir, "does not exist, creating...") if err := hugofs.Os.MkdirAll(cc.genmandir, 0777); err != nil { return err } } cmd.Root().DisableAutoGenTag = true jww.FEEDBACK.Println("Generating Hugo man pages in", cc.genmandir, "...") doc.GenManTree(cmd.Root(), header, cc.genmandir) jww.FEEDBACK.Println("Done.") return nil }, }) cc.cmd.PersistentFlags().StringVar(&cc.genmandir, "dir", "man/", "the directory to write the man pages.") // For bash-completion cc.cmd.PersistentFlags().SetAnnotation("dir", cobra.BashCompSubdirsInDir, []string{}) return cc } hugo-0.92.2/commands/helpers.go000066400000000000000000000041721420147000300163330ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package commands defines and implements command-line commands and flags // used by Hugo. Commands and flags are implemented using Cobra. package commands import ( "fmt" "regexp" "github.com/gohugoio/hugo/config" "github.com/spf13/cobra" ) const ( ansiEsc = "\u001B" clearLine = "\r\033[K" hideCursor = ansiEsc + "[?25l" showCursor = ansiEsc + "[?25h" ) type flagsToConfigHandler interface { flagsToConfig(cfg config.Provider) } type cmder interface { flagsToConfigHandler getCommand() *cobra.Command } // commandError is an error used to signal different error situations in command handling. type commandError struct { s string userError bool } func (c commandError) Error() string { return c.s } func (c commandError) isUserError() bool { return c.userError } func newUserError(a ...interface{}) commandError { return commandError{s: fmt.Sprintln(a...), userError: true} } func newSystemError(a ...interface{}) commandError { return commandError{s: fmt.Sprintln(a...), userError: false} } func newSystemErrorF(format string, a ...interface{}) commandError { return commandError{s: fmt.Sprintf(format, a...), userError: false} } // Catch some of the obvious user errors from Cobra. // We don't want to show the usage message for every error. // The below may be to generic. Time will show. var userErrorRegexp = regexp.MustCompile("unknown flag") func isUserError(err error) bool { if cErr, ok := err.(commandError); ok && cErr.isUserError() { return true } return userErrorRegexp.MatchString(err.Error()) } hugo-0.92.2/commands/hugo.go000066400000000000000000000727151420147000300156430ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package commands defines and implements command-line commands and flags // used by Hugo. Commands and flags are implemented using Cobra. package commands import ( "context" "fmt" "io/ioutil" "os" "os/signal" "path/filepath" "runtime" "runtime/pprof" "runtime/trace" "strings" "sync/atomic" "syscall" "time" "github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/resources/page" "github.com/pkg/errors" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/common/terminal" "github.com/gohugoio/hugo/hugolib/filesystems" "golang.org/x/sync/errgroup" "github.com/gohugoio/hugo/config" flag "github.com/spf13/pflag" "github.com/fsnotify/fsnotify" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugolib" "github.com/gohugoio/hugo/livereload" "github.com/gohugoio/hugo/watcher" "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/fsync" jww "github.com/spf13/jwalterweatherman" ) // The Response value from Execute. type Response struct { // The build Result will only be set in the hugo build command. Result *hugolib.HugoSites // Err is set when the command failed to execute. Err error // The command that was executed. Cmd *cobra.Command } // IsUserError returns true is the Response error is a user error rather than a // system error. func (r Response) IsUserError() bool { return r.Err != nil && isUserError(r.Err) } // Execute adds all child commands to the root command HugoCmd and sets flags appropriately. // The args are usually filled with os.Args[1:]. func Execute(args []string) Response { hugoCmd := newCommandsBuilder().addAll().build() cmd := hugoCmd.getCommand() cmd.SetArgs(args) c, err := cmd.ExecuteC() var resp Response if c == cmd && hugoCmd.c != nil { // Root command executed resp.Result = hugoCmd.c.hugo() } if err == nil { errCount := int(loggers.GlobalErrorCounter.Count()) if errCount > 0 { err = fmt.Errorf("logged %d errors", errCount) } else if resp.Result != nil { errCount = resp.Result.NumLogErrors() if errCount > 0 { err = fmt.Errorf("logged %d errors", errCount) } } } resp.Err = err resp.Cmd = c return resp } // InitializeConfig initializes a config file with sensible default configuration flags. func initializeConfig(mustHaveConfigFile, failOnInitErr, running bool, h *hugoBuilderCommon, f flagsToConfigHandler, cfgInit func(c *commandeer) error) (*commandeer, error) { c, err := newCommandeer(mustHaveConfigFile, failOnInitErr, running, h, f, cfgInit) if err != nil { return nil, err } return c, nil } func (c *commandeer) createLogger(cfg config.Provider) (loggers.Logger, error) { var ( logHandle = ioutil.Discard logThreshold = jww.LevelWarn logFile = cfg.GetString("logFile") outHandle = ioutil.Discard stdoutThreshold = jww.LevelWarn ) if !c.h.quiet { outHandle = os.Stdout } if c.h.verboseLog || c.h.logging || (c.h.logFile != "") { var err error if logFile != "" { logHandle, err = os.OpenFile(logFile, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) if err != nil { return nil, newSystemError("Failed to open log file:", logFile, err) } } else { logHandle, err = ioutil.TempFile("", "hugo") if err != nil { return nil, newSystemError(err) } } } else if !c.h.quiet && cfg.GetBool("verbose") { stdoutThreshold = jww.LevelInfo } if cfg.GetBool("debug") { stdoutThreshold = jww.LevelDebug } if c.h.verboseLog { logThreshold = jww.LevelInfo if cfg.GetBool("debug") { logThreshold = jww.LevelDebug } } loggers.InitGlobalLogger(stdoutThreshold, logThreshold, outHandle, logHandle) helpers.InitLoggers() return loggers.NewLogger(stdoutThreshold, logThreshold, outHandle, logHandle, c.running), nil } func initializeFlags(cmd *cobra.Command, cfg config.Provider) { persFlagKeys := []string{ "debug", "verbose", "logFile", // Moved from vars } flagKeys := []string{ "cleanDestinationDir", "buildDrafts", "buildFuture", "buildExpired", "uglyURLs", "canonifyURLs", "enableRobotsTXT", "enableGitInfo", "pluralizeListTitles", "preserveTaxonomyNames", "ignoreCache", "forceSyncStatic", "noTimes", "noChmod", "ignoreVendorPaths", "templateMetrics", "templateMetricsHints", // Moved from vars. "baseURL", "buildWatch", "cacheDir", "cfgFile", "confirm", "contentDir", "debug", "destination", "disableKinds", "dryRun", "force", "gc", "i18n-warnings", "invalidateCDN", "layoutDir", "logFile", "maxDeletes", "quiet", "renderToMemory", "source", "target", "theme", "themesDir", "verbose", "verboseLog", "duplicateTargetPaths", } for _, key := range persFlagKeys { setValueFromFlag(cmd.PersistentFlags(), key, cfg, "", false) } for _, key := range flagKeys { setValueFromFlag(cmd.Flags(), key, cfg, "", false) } setValueFromFlag(cmd.Flags(), "minify", cfg, "minifyOutput", true) // Set some "config aliases" setValueFromFlag(cmd.Flags(), "destination", cfg, "publishDir", false) setValueFromFlag(cmd.Flags(), "i18n-warnings", cfg, "logI18nWarnings", false) setValueFromFlag(cmd.Flags(), "path-warnings", cfg, "logPathWarnings", false) } func setValueFromFlag(flags *flag.FlagSet, key string, cfg config.Provider, targetKey string, force bool) { key = strings.TrimSpace(key) if (force && flags.Lookup(key) != nil) || flags.Changed(key) { f := flags.Lookup(key) configKey := key if targetKey != "" { configKey = targetKey } // Gotta love this API. switch f.Value.Type() { case "bool": bv, _ := flags.GetBool(key) cfg.Set(configKey, bv) case "string": cfg.Set(configKey, f.Value.String()) case "stringSlice": bv, _ := flags.GetStringSlice(key) cfg.Set(configKey, bv) case "int": iv, _ := flags.GetInt(key) cfg.Set(configKey, iv) default: panic(fmt.Sprintf("update switch with %s", f.Value.Type())) } } } func isTerminal() bool { return terminal.IsTerminal(os.Stdout) } func (c *commandeer) fullBuild(noBuildLock bool) error { var ( g errgroup.Group langCount map[string]uint64 ) if !c.h.quiet { fmt.Println("Start building sites … ") fmt.Println(hugo.BuildVersionString()) if isTerminal() { defer func() { fmt.Print(showCursor + clearLine) }() } } copyStaticFunc := func() error { cnt, err := c.copyStatic() if err != nil { return errors.Wrap(err, "Error copying static files") } langCount = cnt return nil } buildSitesFunc := func() error { if err := c.buildSites(noBuildLock); err != nil { return errors.Wrap(err, "Error building site") } return nil } // Do not copy static files and build sites in parallel if cleanDestinationDir is enabled. // This flag deletes all static resources in /public folder that are missing in /static, // and it does so at the end of copyStatic() call. if c.Cfg.GetBool("cleanDestinationDir") { if err := copyStaticFunc(); err != nil { return err } if err := buildSitesFunc(); err != nil { return err } } else { g.Go(copyStaticFunc) g.Go(buildSitesFunc) if err := g.Wait(); err != nil { return err } } for _, s := range c.hugo().Sites { s.ProcessingStats.Static = langCount[s.Language().Lang] } if c.h.gc { count, err := c.hugo().GC() if err != nil { return err } for _, s := range c.hugo().Sites { // We have no way of knowing what site the garbage belonged to. s.ProcessingStats.Cleaned = uint64(count) } } return nil } func (c *commandeer) initCPUProfile() (func(), error) { if c.h.cpuprofile == "" { return nil, nil } f, err := os.Create(c.h.cpuprofile) if err != nil { return nil, errors.Wrap(err, "failed to create CPU profile") } if err := pprof.StartCPUProfile(f); err != nil { return nil, errors.Wrap(err, "failed to start CPU profile") } return func() { pprof.StopCPUProfile() f.Close() }, nil } func (c *commandeer) initMemProfile() { if c.h.memprofile == "" { return } f, err := os.Create(c.h.memprofile) if err != nil { c.logger.Errorf("could not create memory profile: ", err) } defer f.Close() runtime.GC() // get up-to-date statistics if err := pprof.WriteHeapProfile(f); err != nil { c.logger.Errorf("could not write memory profile: ", err) } } func (c *commandeer) initTraceProfile() (func(), error) { if c.h.traceprofile == "" { return nil, nil } f, err := os.Create(c.h.traceprofile) if err != nil { return nil, errors.Wrap(err, "failed to create trace file") } if err := trace.Start(f); err != nil { return nil, errors.Wrap(err, "failed to start trace") } return func() { trace.Stop() f.Close() }, nil } func (c *commandeer) initMutexProfile() (func(), error) { if c.h.mutexprofile == "" { return nil, nil } f, err := os.Create(c.h.mutexprofile) if err != nil { return nil, err } runtime.SetMutexProfileFraction(1) return func() { pprof.Lookup("mutex").WriteTo(f, 0) f.Close() }, nil } func (c *commandeer) initMemTicker() func() { memticker := time.NewTicker(5 * time.Second) quit := make(chan struct{}) printMem := func() { var m runtime.MemStats runtime.ReadMemStats(&m) fmt.Printf("\n\nAlloc = %v\nTotalAlloc = %v\nSys = %v\nNumGC = %v\n\n", formatByteCount(m.Alloc), formatByteCount(m.TotalAlloc), formatByteCount(m.Sys), m.NumGC) } go func() { for { select { case <-memticker.C: printMem() case <-quit: memticker.Stop() printMem() return } } }() return func() { close(quit) } } func (c *commandeer) initProfiling() (func(), error) { stopCPUProf, err := c.initCPUProfile() if err != nil { return nil, err } stopMutexProf, err := c.initMutexProfile() if err != nil { return nil, err } stopTraceProf, err := c.initTraceProfile() if err != nil { return nil, err } var stopMemTicker func() if c.h.printm { stopMemTicker = c.initMemTicker() } return func() { c.initMemProfile() if stopCPUProf != nil { stopCPUProf() } if stopMutexProf != nil { stopMutexProf() } if stopTraceProf != nil { stopTraceProf() } if stopMemTicker != nil { stopMemTicker() } }, nil } func (c *commandeer) build() error { stopProfiling, err := c.initProfiling() if err != nil { return err } defer func() { if stopProfiling != nil { stopProfiling() } }() if err := c.fullBuild(false); err != nil { return err } // TODO(bep) Feedback? if !c.h.quiet { fmt.Println() c.hugo().PrintProcessingStats(os.Stdout) fmt.Println() if createCounter, ok := c.destinationFs.(hugofs.DuplicatesReporter); ok { dupes := createCounter.ReportDuplicates() if dupes != "" { c.logger.Warnln("Duplicate target paths:", dupes) } } } if c.h.buildWatch { watchDirs, err := c.getDirList() if err != nil { return err } baseWatchDir := c.Cfg.GetString("workingDir") rootWatchDirs := getRootWatchDirsStr(baseWatchDir, watchDirs) c.logger.Printf("Watching for changes in %s%s{%s}\n", baseWatchDir, helpers.FilePathSeparator, rootWatchDirs) c.logger.Println("Press Ctrl+C to stop") watcher, err := c.newWatcher(c.h.poll, watchDirs...) checkErr(c.Logger, err) defer watcher.Close() sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) <-sigs } return nil } func (c *commandeer) serverBuild() error { stopProfiling, err := c.initProfiling() if err != nil { return err } defer func() { if stopProfiling != nil { stopProfiling() } }() if err := c.fullBuild(false); err != nil { return err } // TODO(bep) Feedback? if !c.h.quiet { fmt.Println() c.hugo().PrintProcessingStats(os.Stdout) fmt.Println() } return nil } func (c *commandeer) copyStatic() (map[string]uint64, error) { m, err := c.doWithPublishDirs(c.copyStaticTo) if err == nil || os.IsNotExist(err) { return m, nil } return m, err } func (c *commandeer) doWithPublishDirs(f func(sourceFs *filesystems.SourceFilesystem) (uint64, error)) (map[string]uint64, error) { langCount := make(map[string]uint64) staticFilesystems := c.hugo().BaseFs.SourceFilesystems.Static if len(staticFilesystems) == 0 { c.logger.Infoln("No static directories found to sync") return langCount, nil } for lang, fs := range staticFilesystems { cnt, err := f(fs) if err != nil { return langCount, err } if lang == "" { // Not multihost for _, l := range c.languages { langCount[l.Lang] = cnt } } else { langCount[lang] = cnt } } return langCount, nil } type countingStatFs struct { afero.Fs statCounter uint64 } func (fs *countingStatFs) Stat(name string) (os.FileInfo, error) { f, err := fs.Fs.Stat(name) if err == nil { if !f.IsDir() { atomic.AddUint64(&fs.statCounter, 1) } } return f, err } func chmodFilter(dst, src os.FileInfo) bool { // Hugo publishes data from multiple sources, potentially // with overlapping directory structures. We cannot sync permissions // for directories as that would mean that we might end up with write-protected // directories inside /public. // One example of this would be syncing from the Go Module cache, // which have 0555 directories. return src.IsDir() } func (c *commandeer) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint64, error) { publishDir := c.hugo().PathSpec.PublishDir // If root, remove the second '/' if publishDir == "//" { publishDir = helpers.FilePathSeparator } if sourceFs.PublishFolder != "" { publishDir = filepath.Join(publishDir, sourceFs.PublishFolder) } fs := &countingStatFs{Fs: sourceFs.Fs} syncer := fsync.NewSyncer() syncer.NoTimes = c.Cfg.GetBool("noTimes") syncer.NoChmod = c.Cfg.GetBool("noChmod") syncer.ChmodFilter = chmodFilter syncer.SrcFs = fs syncer.DestFs = c.Fs.Destination // Now that we are using a unionFs for the static directories // We can effectively clean the publishDir on initial sync syncer.Delete = c.Cfg.GetBool("cleanDestinationDir") if syncer.Delete { c.logger.Infoln("removing all files from destination that don't exist in static dirs") syncer.DeleteFilter = func(f os.FileInfo) bool { return f.IsDir() && strings.HasPrefix(f.Name(), ".") } } c.logger.Infoln("syncing static files to", publishDir) // because we are using a baseFs (to get the union right). // set sync src to root err := syncer.Sync(publishDir, helpers.FilePathSeparator) if err != nil { return 0, err } // Sync runs Stat 3 times for every source file (which sounds much) numFiles := fs.statCounter / 3 return numFiles, err } func (c *commandeer) firstPathSpec() *helpers.PathSpec { return c.hugo().Sites[0].PathSpec } func (c *commandeer) timeTrack(start time.Time, name string) { elapsed := time.Since(start) c.logger.Printf("%s in %v ms", name, int(1000*elapsed.Seconds())) } // getDirList provides NewWatcher() with a list of directories to watch for changes. func (c *commandeer) getDirList() ([]string, error) { var filenames []string walkFn := func(path string, fi hugofs.FileMetaInfo, err error) error { if err != nil { c.logger.Errorln("walker: ", err) return nil } if fi.IsDir() { if fi.Name() == ".git" || fi.Name() == "node_modules" || fi.Name() == "bower_components" { return filepath.SkipDir } filenames = append(filenames, fi.Meta().Filename) } return nil } watchFiles := c.hugo().PathSpec.BaseFs.WatchDirs() for _, fi := range watchFiles { if !fi.IsDir() { filenames = append(filenames, fi.Meta().Filename) continue } w := hugofs.NewWalkway(hugofs.WalkwayConfig{Logger: c.logger, Info: fi, WalkFn: walkFn}) if err := w.Walk(); err != nil { c.logger.Errorln("walker: ", err) } } filenames = helpers.UniqueStringsSorted(filenames) return filenames, nil } func (c *commandeer) buildSites(noBuildLock bool) (err error) { return c.hugo().Build(hugolib.BuildCfg{NoBuildLock: noBuildLock}) } func (c *commandeer) handleBuildErr(err error, msg string) { c.buildErr = err c.logger.Errorln(msg + ":\n") c.logger.Errorln(helpers.FirstUpper(err.Error())) if !c.h.quiet && c.h.verbose { herrors.PrintStackTraceFromErr(err) } } func (c *commandeer) rebuildSites(events []fsnotify.Event) error { c.buildErr = nil visited := c.visitedURLs.PeekAllSet() if c.fastRenderMode { // Make sure we always render the home pages for _, l := range c.languages { langPath := c.hugo().PathSpec.GetLangSubDir(l.Lang) if langPath != "" { langPath = langPath + "/" } home := c.hugo().PathSpec.PrependBasePath("/"+langPath, false) visited[home] = true } } return c.hugo().Build(hugolib.BuildCfg{NoBuildLock: true, RecentlyVisited: visited, ErrRecovery: c.wasError}, events...) } func (c *commandeer) partialReRender(urls ...string) error { defer func() { c.wasError = false }() c.buildErr = nil visited := make(map[string]bool) for _, url := range urls { visited[url] = true } // Note: We do not set NoBuildLock as the file lock is not acquired at this stage. return c.hugo().Build(hugolib.BuildCfg{NoBuildLock: false, RecentlyVisited: visited, PartialReRender: true, ErrRecovery: c.wasError}) } func (c *commandeer) fullRebuild(changeType string) { if changeType == configChangeGoMod { // go.mod may be changed during the build itself, and // we really want to prevent superfluous builds. if !c.fullRebuildSem.TryAcquire(1) { return } c.fullRebuildSem.Release(1) } c.fullRebuildSem.Acquire(context.Background(), 1) go func() { defer c.fullRebuildSem.Release(1) c.printChangeDetected(changeType) defer func() { // Allow any file system events to arrive back. // This will block any rebuild on config changes for the // duration of the sleep. time.Sleep(2 * time.Second) }() defer c.timeTrack(time.Now(), "Rebuilt") c.commandeerHugoState = newCommandeerHugoState() err := c.loadConfig() if err != nil { // Set the processing on pause until the state is recovered. c.paused = true c.handleBuildErr(err, "Failed to reload config") } else { c.paused = false } if !c.paused { _, err := c.copyStatic() if err != nil { c.logger.Errorln(err) return } err = c.buildSites(true) if err != nil { c.logger.Errorln(err) } else if !c.h.buildWatch && !c.Cfg.GetBool("disableLiveReload") { livereload.ForceRefresh() } } }() } // newWatcher creates a new watcher to watch filesystem events. func (c *commandeer) newWatcher(pollIntervalStr string, dirList ...string) (*watcher.Batcher, error) { if runtime.GOOS == "darwin" { tweakLimit() } staticSyncer, err := newStaticSyncer(c) if err != nil { return nil, err } var pollInterval time.Duration poll := pollIntervalStr != "" if poll { pollInterval, err = types.ToDurationE(pollIntervalStr) if err != nil { return nil, fmt.Errorf("invalid value for flag poll: %s", err) } c.logger.Printf("Use watcher with poll interval %v", pollInterval) } if pollInterval == 0 { pollInterval = 500 * time.Millisecond } watcher, err := watcher.New(500*time.Millisecond, pollInterval, poll) if err != nil { return nil, err } for _, d := range dirList { if d != "" { _ = watcher.Add(d) } } // Identifies changes to config (config.toml) files. configSet := make(map[string]bool) c.logger.Println("Watching for config changes in", strings.Join(c.configFiles, ", ")) for _, configFile := range c.configFiles { watcher.Add(configFile) configSet[configFile] = true } go func() { for { select { case evs := <-watcher.Events: unlock, err := c.buildLock() if err != nil { c.logger.Errorln("Failed to acquire a build lock: %s", err) return } c.handleEvents(watcher, staticSyncer, evs, configSet) if c.showErrorInBrowser && c.errCount() > 0 { // Need to reload browser to show the error livereload.ForceRefresh() } unlock() case err := <-watcher.Errors(): if err != nil && !os.IsNotExist(err) { c.logger.Errorln("Error while watching:", err) } } } }() return watcher, nil } func (c *commandeer) printChangeDetected(typ string) { msg := "\nChange" if typ != "" { msg += " of " + typ } msg += " detected, rebuilding site." c.logger.Println(msg) const layout = "2006-01-02 15:04:05.000 -0700" c.logger.Println(time.Now().Format(layout)) } const ( configChangeConfig = "config file" configChangeGoMod = "go.mod file" ) func (c *commandeer) handleEvents(watcher *watcher.Batcher, staticSyncer *staticSyncer, evs []fsnotify.Event, configSet map[string]bool) { defer func() { c.wasError = false }() var isHandled bool for _, ev := range evs { isConfig := configSet[ev.Name] configChangeType := configChangeConfig if isConfig { if strings.Contains(ev.Name, "go.mod") { configChangeType = configChangeGoMod } } if !isConfig { // It may be one of the /config folders dirname := filepath.Dir(ev.Name) if dirname != "." && configSet[dirname] { isConfig = true } } if isConfig { isHandled = true if ev.Op&fsnotify.Chmod == fsnotify.Chmod { continue } if ev.Op&fsnotify.Remove == fsnotify.Remove || ev.Op&fsnotify.Rename == fsnotify.Rename { for _, configFile := range c.configFiles { counter := 0 for watcher.Add(configFile) != nil { counter++ if counter >= 100 { break } time.Sleep(100 * time.Millisecond) } } } // Config file(s) changed. Need full rebuild. c.fullRebuild(configChangeType) return } } if isHandled { return } if c.paused { // Wait for the server to get into a consistent state before // we continue with processing. return } if len(evs) > 50 { // This is probably a mass edit of the content dir. // Schedule a full rebuild for when it slows down. c.debounce(func() { c.fullRebuild("") }) return } c.logger.Infoln("Received System Events:", evs) staticEvents := []fsnotify.Event{} dynamicEvents := []fsnotify.Event{} filtered := []fsnotify.Event{} for _, ev := range evs { if c.hugo().ShouldSkipFileChangeEvent(ev) { continue } // Check the most specific first, i.e. files. contentMapped := c.hugo().ContentChanges.GetSymbolicLinkMappings(ev.Name) if len(contentMapped) > 0 { for _, mapped := range contentMapped { filtered = append(filtered, fsnotify.Event{Name: mapped, Op: ev.Op}) } continue } // Check for any symbolic directory mapping. dir, name := filepath.Split(ev.Name) contentMapped = c.hugo().ContentChanges.GetSymbolicLinkMappings(dir) if len(contentMapped) == 0 { filtered = append(filtered, ev) continue } for _, mapped := range contentMapped { mappedFilename := filepath.Join(mapped, name) filtered = append(filtered, fsnotify.Event{Name: mappedFilename, Op: ev.Op}) } } evs = filtered for _, ev := range evs { ext := filepath.Ext(ev.Name) baseName := filepath.Base(ev.Name) istemp := strings.HasSuffix(ext, "~") || (ext == ".swp") || // vim (ext == ".swx") || // vim (ext == ".tmp") || // generic temp file (ext == ".DS_Store") || // OSX Thumbnail baseName == "4913" || // vim strings.HasPrefix(ext, ".goutputstream") || // gnome strings.HasSuffix(ext, "jb_old___") || // intelliJ strings.HasSuffix(ext, "jb_tmp___") || // intelliJ strings.HasSuffix(ext, "jb_bak___") || // intelliJ strings.HasPrefix(ext, ".sb-") || // byword strings.HasPrefix(baseName, ".#") || // emacs strings.HasPrefix(baseName, "#") // emacs if istemp { continue } if c.hugo().Deps.SourceSpec.IgnoreFile(ev.Name) { continue } // Sometimes during rm -rf operations a '"": REMOVE' is triggered. Just ignore these if ev.Name == "" { continue } // Write and rename operations are often followed by CHMOD. // There may be valid use cases for rebuilding the site on CHMOD, // but that will require more complex logic than this simple conditional. // On OS X this seems to be related to Spotlight, see: // https://github.com/go-fsnotify/fsnotify/issues/15 // A workaround is to put your site(s) on the Spotlight exception list, // but that may be a little mysterious for most end users. // So, for now, we skip reload on CHMOD. // We do have to check for WRITE though. On slower laptops a Chmod // could be aggregated with other important events, and we still want // to rebuild on those if ev.Op&(fsnotify.Chmod|fsnotify.Write|fsnotify.Create) == fsnotify.Chmod { continue } walkAdder := func(path string, f hugofs.FileMetaInfo, err error) error { if f.IsDir() { c.logger.Println("adding created directory to watchlist", path) if err := watcher.Add(path); err != nil { return err } } else if !staticSyncer.isStatic(path) { // Hugo's rebuilding logic is entirely file based. When you drop a new folder into // /content on OSX, the above logic will handle future watching of those files, // but the initial CREATE is lost. dynamicEvents = append(dynamicEvents, fsnotify.Event{Name: path, Op: fsnotify.Create}) } return nil } // recursively add new directories to watch list // When mkdir -p is used, only the top directory triggers an event (at least on OSX) if ev.Op&fsnotify.Create == fsnotify.Create { if s, err := c.Fs.Source.Stat(ev.Name); err == nil && s.Mode().IsDir() { _ = helpers.SymbolicWalk(c.Fs.Source, ev.Name, walkAdder) } } if staticSyncer.isStatic(ev.Name) { staticEvents = append(staticEvents, ev) } else { dynamicEvents = append(dynamicEvents, ev) } } if len(staticEvents) > 0 { c.printChangeDetected("Static files") if c.Cfg.GetBool("forceSyncStatic") { c.logger.Printf("Syncing all static files\n") _, err := c.copyStatic() if err != nil { c.logger.Errorln("Error copying static files to publish dir:", err) return } } else { if err := staticSyncer.syncsStaticEvents(staticEvents); err != nil { c.logger.Errorln("Error syncing static files to publish dir:", err) return } } if !c.h.buildWatch && !c.Cfg.GetBool("disableLiveReload") { // Will block forever trying to write to a channel that nobody is reading if livereload isn't initialized // force refresh when more than one file if !c.wasError && len(staticEvents) == 1 { ev := staticEvents[0] path := c.hugo().BaseFs.SourceFilesystems.MakeStaticPathRelative(ev.Name) path = c.firstPathSpec().RelURL(helpers.ToSlashTrimLeading(path), false) livereload.RefreshPath(path) } else { livereload.ForceRefresh() } } } if len(dynamicEvents) > 0 { partitionedEvents := partitionDynamicEvents( c.firstPathSpec().BaseFs.SourceFilesystems, dynamicEvents) doLiveReload := !c.h.buildWatch && !c.Cfg.GetBool("disableLiveReload") onePageName := pickOneWriteOrCreatePath(partitionedEvents.ContentEvents) c.printChangeDetected("") c.changeDetector.PrepareNew() func() { defer c.timeTrack(time.Now(), "Total") if err := c.rebuildSites(dynamicEvents); err != nil { c.handleBuildErr(err, "Rebuild failed") } }() if doLiveReload { if len(partitionedEvents.ContentEvents) == 0 && len(partitionedEvents.AssetEvents) > 0 { if c.wasError { livereload.ForceRefresh() return } changed := c.changeDetector.changed() if c.changeDetector != nil && len(changed) == 0 { // Nothing has changed. return } else if len(changed) == 1 { pathToRefresh := c.firstPathSpec().RelURL(helpers.ToSlashTrimLeading(changed[0]), false) livereload.RefreshPath(pathToRefresh) } else { livereload.ForceRefresh() } } if len(partitionedEvents.ContentEvents) > 0 { navigate := c.Cfg.GetBool("navigateToChanged") // We have fetched the same page above, but it may have // changed. var p page.Page if navigate { if onePageName != "" { p = c.hugo().GetContentPage(onePageName) } } if p != nil { livereload.NavigateToPathForPort(p.RelPermalink(), p.Site().ServerPort()) } else { livereload.ForceRefresh() } } } } } // dynamicEvents contains events that is considered dynamic, as in "not static". // Both of these categories will trigger a new build, but the asset events // does not fit into the "navigate to changed" logic. type dynamicEvents struct { ContentEvents []fsnotify.Event AssetEvents []fsnotify.Event } func partitionDynamicEvents(sourceFs *filesystems.SourceFilesystems, events []fsnotify.Event) (de dynamicEvents) { for _, e := range events { if sourceFs.IsAsset(e.Name) { de.AssetEvents = append(de.AssetEvents, e) } else { de.ContentEvents = append(de.ContentEvents, e) } } return } func pickOneWriteOrCreatePath(events []fsnotify.Event) string { name := "" for _, ev := range events { if ev.Op&fsnotify.Write == fsnotify.Write || ev.Op&fsnotify.Create == fsnotify.Create { if files.IsIndexContentFile(ev.Name) { return ev.Name } if files.IsContentFile(ev.Name) { name = ev.Name } } } return name } func formatByteCount(b uint64) string { const unit = 1000 if b < unit { return fmt.Sprintf("%d B", b) } div, exp := int64(unit), 0 for n := b / unit; n >= unit; n /= unit { div *= unit exp++ } return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp]) } hugo-0.92.2/commands/hugo_test.go000066400000000000000000000023351420147000300166710ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "testing" qt "github.com/frankban/quicktest" ) // Issue #5662 func TestHugoWithContentDirOverride(t *testing.T) { c := qt.New(t) hugoCmd := newCommandsBuilder().addAll().build() cmd := hugoCmd.getCommand() contentDir := "contentOverride" cfgStr := ` baseURL = "https://example.org" title = "Hugo Commands" contentDir = "thisdoesnotexist" ` dir, clean, err := createSimpleTestSite(t, testSiteConfig{configTOML: cfgStr, contentDir: contentDir}) c.Assert(err, qt.IsNil) defer clean() cmd.SetArgs([]string{"-s=" + dir, "-c=" + contentDir}) _, err = cmd.ExecuteC() c.Assert(err, qt.IsNil) } hugo-0.92.2/commands/hugo_windows.go000066400000000000000000000020271420147000300174020ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( // For time zone lookups on Windows without Go installed. // See #8892 _ "time/tzdata" "github.com/spf13/cobra" ) func init() { // This message to show to Windows users if Hugo is opened from explorer.exe cobra.MousetrapHelpText = ` Hugo is a command-line tool for generating static website. You need to open cmd.exe and run Hugo from there. Visit https://gohugo.io/ for more information.` } hugo-0.92.2/commands/import_jekyll.go000066400000000000000000000366531420147000300175660ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "bytes" "errors" "fmt" "io/ioutil" "os" "path/filepath" "regexp" "strconv" "strings" "time" "unicode" "github.com/gohugoio/hugo/parser/pageparser" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/parser/metadecoders" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugolib" "github.com/gohugoio/hugo/parser" "github.com/spf13/afero" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*importCmd)(nil) type importCmd struct { *baseCmd } func newImportCmd() *importCmd { cc := &importCmd{} cc.baseCmd = newBaseCmd(&cobra.Command{ Use: "import", Short: "Import your site from others.", Long: `Import your site from other web site generators like Jekyll. Import requires a subcommand, e.g. ` + "`hugo import jekyll jekyll_root_path target_path`.", RunE: nil, }) importJekyllCmd := &cobra.Command{ Use: "jekyll", Short: "hugo import from Jekyll", Long: `hugo import from Jekyll. Import from Jekyll requires two paths, e.g. ` + "`hugo import jekyll jekyll_root_path target_path`.", RunE: cc.importFromJekyll, } importJekyllCmd.Flags().Bool("force", false, "allow import into non-empty target directory") cc.cmd.AddCommand(importJekyllCmd) return cc } func (i *importCmd) importFromJekyll(cmd *cobra.Command, args []string) error { if len(args) < 2 { return newUserError(`import from jekyll requires two paths, e.g. ` + "`hugo import jekyll jekyll_root_path target_path`.") } jekyllRoot, err := filepath.Abs(filepath.Clean(args[0])) if err != nil { return newUserError("path error:", args[0]) } targetDir, err := filepath.Abs(filepath.Clean(args[1])) if err != nil { return newUserError("path error:", args[1]) } jww.INFO.Println("Import Jekyll from:", jekyllRoot, "to:", targetDir) if strings.HasPrefix(filepath.Dir(targetDir), jekyllRoot) { return newUserError("abort: target path should not be inside the Jekyll root") } forceImport, _ := cmd.Flags().GetBool("force") fs := afero.NewOsFs() jekyllPostDirs, hasAnyPost := i.getJekyllDirInfo(fs, jekyllRoot) if !hasAnyPost { return errors.New("abort: jekyll root contains neither posts nor drafts") } err = i.createSiteFromJekyll(jekyllRoot, targetDir, jekyllPostDirs, forceImport) if err != nil { return newUserError(err) } jww.FEEDBACK.Println("Importing...") fileCount := 0 callback := func(path string, fi hugofs.FileMetaInfo, err error) error { if err != nil { return err } if fi.IsDir() { return nil } relPath, err := filepath.Rel(jekyllRoot, path) if err != nil { return newUserError("get rel path error:", path) } relPath = filepath.ToSlash(relPath) draft := false switch { case strings.Contains(relPath, "_posts/"): relPath = filepath.Join("content/post", strings.Replace(relPath, "_posts/", "", -1)) case strings.Contains(relPath, "_drafts/"): relPath = filepath.Join("content/draft", strings.Replace(relPath, "_drafts/", "", -1)) draft = true default: return nil } fileCount++ return convertJekyllPost(path, relPath, targetDir, draft) } for jekyllPostDir, hasAnyPostInDir := range jekyllPostDirs { if hasAnyPostInDir { if err = helpers.SymbolicWalk(hugofs.Os, filepath.Join(jekyllRoot, jekyllPostDir), callback); err != nil { return err } } } jww.FEEDBACK.Println("Congratulations!", fileCount, "post(s) imported!") jww.FEEDBACK.Println("Now, start Hugo by yourself:\n" + "$ git clone https://github.com/spf13/herring-cove.git " + args[1] + "/themes/herring-cove") jww.FEEDBACK.Println("$ cd " + args[1] + "\n$ hugo server --theme=herring-cove") return nil } func (i *importCmd) getJekyllDirInfo(fs afero.Fs, jekyllRoot string) (map[string]bool, bool) { postDirs := make(map[string]bool) hasAnyPost := false if entries, err := ioutil.ReadDir(jekyllRoot); err == nil { for _, entry := range entries { if entry.IsDir() { subDir := filepath.Join(jekyllRoot, entry.Name()) if isPostDir, hasAnyPostInDir := i.retrieveJekyllPostDir(fs, subDir); isPostDir { postDirs[entry.Name()] = hasAnyPostInDir if hasAnyPostInDir { hasAnyPost = true } } } } } return postDirs, hasAnyPost } func (i *importCmd) retrieveJekyllPostDir(fs afero.Fs, dir string) (bool, bool) { if strings.HasSuffix(dir, "_posts") || strings.HasSuffix(dir, "_drafts") { isEmpty, _ := helpers.IsEmpty(dir, fs) return true, !isEmpty } if entries, err := ioutil.ReadDir(dir); err == nil { for _, entry := range entries { if entry.IsDir() { subDir := filepath.Join(dir, entry.Name()) if isPostDir, hasAnyPost := i.retrieveJekyllPostDir(fs, subDir); isPostDir { return isPostDir, hasAnyPost } } } } return false, true } func (i *importCmd) createSiteFromJekyll(jekyllRoot, targetDir string, jekyllPostDirs map[string]bool, force bool) error { s, err := hugolib.NewSiteDefaultLang() if err != nil { return err } fs := s.Fs.Source if exists, _ := helpers.Exists(targetDir, fs); exists { if isDir, _ := helpers.IsDir(targetDir, fs); !isDir { return errors.New("target path \"" + targetDir + "\" exists but is not a directory") } isEmpty, _ := helpers.IsEmpty(targetDir, fs) if !isEmpty && !force { return errors.New("target path \"" + targetDir + "\" exists and is not empty") } } jekyllConfig := i.loadJekyllConfig(fs, jekyllRoot) mkdir(targetDir, "layouts") mkdir(targetDir, "content") mkdir(targetDir, "archetypes") mkdir(targetDir, "static") mkdir(targetDir, "data") mkdir(targetDir, "themes") i.createConfigFromJekyll(fs, targetDir, "yaml", jekyllConfig) i.copyJekyllFilesAndFolders(jekyllRoot, filepath.Join(targetDir, "static"), jekyllPostDirs) return nil } func (i *importCmd) loadJekyllConfig(fs afero.Fs, jekyllRoot string) map[string]interface{} { path := filepath.Join(jekyllRoot, "_config.yml") exists, err := helpers.Exists(path, fs) if err != nil || !exists { jww.WARN.Println("_config.yaml not found: Is the specified Jekyll root correct?") return nil } f, err := fs.Open(path) if err != nil { return nil } defer f.Close() b, err := ioutil.ReadAll(f) if err != nil { return nil } c, err := metadecoders.Default.UnmarshalToMap(b, metadecoders.YAML) if err != nil { return nil } return c } func (i *importCmd) createConfigFromJekyll(fs afero.Fs, inpath string, kind metadecoders.Format, jekyllConfig map[string]interface{}) (err error) { title := "My New Hugo Site" baseURL := "http://example.org/" for key, value := range jekyllConfig { lowerKey := strings.ToLower(key) switch lowerKey { case "title": if str, ok := value.(string); ok { title = str } case "url": if str, ok := value.(string); ok { baseURL = str } } } in := map[string]interface{}{ "baseURL": baseURL, "title": title, "languageCode": "en-us", "disablePathToLower": true, } var buf bytes.Buffer err = parser.InterfaceToConfig(in, kind, &buf) if err != nil { return err } return helpers.WriteToDisk(filepath.Join(inpath, "config."+string(kind)), &buf, fs) } func (i *importCmd) copyJekyllFilesAndFolders(jekyllRoot, dest string, jekyllPostDirs map[string]bool) (err error) { fs := hugofs.Os fi, err := fs.Stat(jekyllRoot) if err != nil { return err } if !fi.IsDir() { return errors.New(jekyllRoot + " is not a directory") } err = os.MkdirAll(dest, fi.Mode()) if err != nil { return err } entries, err := ioutil.ReadDir(jekyllRoot) if err != nil { return err } for _, entry := range entries { sfp := filepath.Join(jekyllRoot, entry.Name()) dfp := filepath.Join(dest, entry.Name()) if entry.IsDir() { if entry.Name()[0] != '_' && entry.Name()[0] != '.' { if _, ok := jekyllPostDirs[entry.Name()]; !ok { err = hugio.CopyDir(fs, sfp, dfp, nil) if err != nil { jww.ERROR.Println(err) } } } } else { lowerEntryName := strings.ToLower(entry.Name()) exceptSuffix := []string{ ".md", ".markdown", ".html", ".htm", ".xml", ".textile", "rakefile", "gemfile", ".lock", } isExcept := false for _, suffix := range exceptSuffix { if strings.HasSuffix(lowerEntryName, suffix) { isExcept = true break } } if !isExcept && entry.Name()[0] != '.' && entry.Name()[0] != '_' { err = hugio.CopyFile(fs, sfp, dfp) if err != nil { jww.ERROR.Println(err) } } } } return nil } func parseJekyllFilename(filename string) (time.Time, string, error) { re := regexp.MustCompile(`(\d+-\d+-\d+)-(.+)\..*`) r := re.FindAllStringSubmatch(filename, -1) if len(r) == 0 { return time.Now(), "", errors.New("filename not match") } postDate, err := time.Parse("2006-1-2", r[0][1]) if err != nil { return time.Now(), "", err } postName := r[0][2] return postDate, postName, nil } func convertJekyllPost(path, relPath, targetDir string, draft bool) error { jww.TRACE.Println("Converting", path) filename := filepath.Base(path) postDate, postName, err := parseJekyllFilename(filename) if err != nil { jww.WARN.Printf("Failed to parse filename '%s': %s. Skipping.", filename, err) return nil } jww.TRACE.Println(filename, postDate, postName) targetFile := filepath.Join(targetDir, relPath) targetParentDir := filepath.Dir(targetFile) os.MkdirAll(targetParentDir, 0777) contentBytes, err := ioutil.ReadFile(path) if err != nil { jww.ERROR.Println("Read file error:", path) return err } pf, err := pageparser.ParseFrontMatterAndContent(bytes.NewReader(contentBytes)) if err != nil { jww.ERROR.Println("Parse file error:", path) return err } newmetadata, err := convertJekyllMetaData(pf.FrontMatter, postName, postDate, draft) if err != nil { jww.ERROR.Println("Convert metadata error:", path) return err } content, err := convertJekyllContent(newmetadata, string(pf.Content)) if err != nil { jww.ERROR.Println("Converting Jekyll error:", path) return err } fs := hugofs.Os if err := helpers.WriteToDisk(targetFile, strings.NewReader(content), fs); err != nil { return fmt.Errorf("failed to save file %q: %s", filename, err) } return nil } func convertJekyllMetaData(m interface{}, postName string, postDate time.Time, draft bool) (interface{}, error) { metadata, err := maps.ToStringMapE(m) if err != nil { return nil, err } if draft { metadata["draft"] = true } for key, value := range metadata { lowerKey := strings.ToLower(key) switch lowerKey { case "layout": delete(metadata, key) case "permalink": if str, ok := value.(string); ok { metadata["url"] = str } delete(metadata, key) case "category": if str, ok := value.(string); ok { metadata["categories"] = []string{str} } delete(metadata, key) case "excerpt_separator": if key != lowerKey { delete(metadata, key) metadata[lowerKey] = value } case "date": if str, ok := value.(string); ok { re := regexp.MustCompile(`(\d+):(\d+):(\d+)`) r := re.FindAllStringSubmatch(str, -1) if len(r) > 0 { hour, _ := strconv.Atoi(r[0][1]) minute, _ := strconv.Atoi(r[0][2]) second, _ := strconv.Atoi(r[0][3]) postDate = time.Date(postDate.Year(), postDate.Month(), postDate.Day(), hour, minute, second, 0, time.UTC) } } delete(metadata, key) } } metadata["date"] = postDate.Format(time.RFC3339) return metadata, nil } func convertJekyllContent(m interface{}, content string) (string, error) { metadata, _ := maps.ToStringMapE(m) lines := strings.Split(content, "\n") var resultLines []string for _, line := range lines { resultLines = append(resultLines, strings.Trim(line, "\r\n")) } content = strings.Join(resultLines, "\n") excerptSep := "" if value, ok := metadata["excerpt_separator"]; ok { if str, strOk := value.(string); strOk { content = strings.Replace(content, strings.TrimSpace(str), excerptSep, -1) } } replaceList := []struct { re *regexp.Regexp replace string }{ {regexp.MustCompile("(?i)"), ""}, {regexp.MustCompile(`\{%\s*raw\s*%\}\s*(.*?)\s*\{%\s*endraw\s*%\}`), "$1"}, {regexp.MustCompile(`{%\s*endhighlight\s*%}`), "{{< / highlight >}}"}, } for _, replace := range replaceList { content = replace.re.ReplaceAllString(content, replace.replace) } replaceListFunc := []struct { re *regexp.Regexp replace func(string) string }{ // Octopress image tag: http://octopress.org/docs/plugins/image-tag/ {regexp.MustCompile(`{%\s+img\s*(.*?)\s*%}`), replaceImageTag}, {regexp.MustCompile(`{%\s*highlight\s*(.*?)\s*%}`), replaceHighlightTag}, } for _, replace := range replaceListFunc { content = replace.re.ReplaceAllStringFunc(content, replace.replace) } var buf bytes.Buffer if len(metadata) != 0 { err := parser.InterfaceToFrontMatter(m, metadecoders.YAML, &buf) if err != nil { return "", err } } buf.WriteString(content) return buf.String(), nil } func replaceHighlightTag(match string) string { r := regexp.MustCompile(`{%\s*highlight\s*(.*?)\s*%}`) parts := r.FindStringSubmatch(match) lastQuote := rune(0) f := func(c rune) bool { switch { case c == lastQuote: lastQuote = rune(0) return false case lastQuote != rune(0): return false case unicode.In(c, unicode.Quotation_Mark): lastQuote = c return false default: return unicode.IsSpace(c) } } // splitting string by space but considering quoted section items := strings.FieldsFunc(parts[1], f) result := bytes.NewBufferString("{{< highlight ") result.WriteString(items[0]) // language options := items[1:] for i, opt := range options { opt = strings.Replace(opt, "\"", "", -1) if opt == "linenos" { opt = "linenos=table" } if i == 0 { opt = " \"" + opt } if i < len(options)-1 { opt += "," } else if i == len(options)-1 { opt += "\"" } result.WriteString(opt) } result.WriteString(" >}}") return result.String() } func replaceImageTag(match string) string { r := regexp.MustCompile(`{%\s+img\s*(\p{L}*)\s+([\S]*/[\S]+)\s+(\d*)\s*(\d*)\s*(.*?)\s*%}`) result := bytes.NewBufferString("{{< figure ") parts := r.FindStringSubmatch(match) // Index 0 is the entire string, ignore replaceOptionalPart(result, "class", parts[1]) replaceOptionalPart(result, "src", parts[2]) replaceOptionalPart(result, "width", parts[3]) replaceOptionalPart(result, "height", parts[4]) // title + alt part := parts[5] if len(part) > 0 { splits := strings.Split(part, "'") lenSplits := len(splits) if lenSplits == 1 { replaceOptionalPart(result, "title", splits[0]) } else if lenSplits == 3 { replaceOptionalPart(result, "title", splits[1]) } else if lenSplits == 5 { replaceOptionalPart(result, "title", splits[1]) replaceOptionalPart(result, "alt", splits[3]) } } result.WriteString(">}}") return result.String() } func replaceOptionalPart(buffer *bytes.Buffer, partName string, part string) { if len(part) > 0 { buffer.WriteString(partName + "=\"" + part + "\" ") } } hugo-0.92.2/commands/import_jekyll_test.go000066400000000000000000000143211420147000300206110ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "encoding/json" "testing" "time" qt "github.com/frankban/quicktest" ) func TestParseJekyllFilename(t *testing.T) { c := qt.New(t) filenameArray := []string{ "2015-01-02-test.md", "2012-03-15-中文.markup", } expectResult := []struct { postDate time.Time postName string }{ {time.Date(2015, time.January, 2, 0, 0, 0, 0, time.UTC), "test"}, {time.Date(2012, time.March, 15, 0, 0, 0, 0, time.UTC), "中文"}, } for i, filename := range filenameArray { postDate, postName, err := parseJekyllFilename(filename) c.Assert(err, qt.IsNil) c.Assert(expectResult[i].postDate.Format("2006-01-02"), qt.Equals, postDate.Format("2006-01-02")) c.Assert(expectResult[i].postName, qt.Equals, postName) } } func TestConvertJekyllMetadata(t *testing.T) { c := qt.New(t) testDataList := []struct { metadata interface{} postName string postDate time.Time draft bool expect string }{ { map[interface{}]interface{}{}, "testPost", time.Date(2015, 10, 1, 0, 0, 0, 0, time.UTC), false, `{"date":"2015-10-01T00:00:00Z"}`, }, { map[interface{}]interface{}{}, "testPost", time.Date(2015, 10, 1, 0, 0, 0, 0, time.UTC), true, `{"date":"2015-10-01T00:00:00Z","draft":true}`, }, { map[interface{}]interface{}{"Permalink": "/permalink.html", "layout": "post"}, "testPost", time.Date(2015, 10, 1, 0, 0, 0, 0, time.UTC), false, `{"date":"2015-10-01T00:00:00Z","url":"/permalink.html"}`, }, { map[interface{}]interface{}{"permalink": "/permalink.html"}, "testPost", time.Date(2015, 10, 1, 0, 0, 0, 0, time.UTC), false, `{"date":"2015-10-01T00:00:00Z","url":"/permalink.html"}`, }, { map[interface{}]interface{}{"category": nil, "permalink": 123}, "testPost", time.Date(2015, 10, 1, 0, 0, 0, 0, time.UTC), false, `{"date":"2015-10-01T00:00:00Z"}`, }, { map[interface{}]interface{}{"Excerpt_Separator": "sep"}, "testPost", time.Date(2015, 10, 1, 0, 0, 0, 0, time.UTC), false, `{"date":"2015-10-01T00:00:00Z","excerpt_separator":"sep"}`, }, { map[interface{}]interface{}{"category": "book", "layout": "post", "Others": "Goods", "Date": "2015-10-01 12:13:11"}, "testPost", time.Date(2015, 10, 1, 0, 0, 0, 0, time.UTC), false, `{"Others":"Goods","categories":["book"],"date":"2015-10-01T12:13:11Z"}`, }, } for _, data := range testDataList { result, err := convertJekyllMetaData(data.metadata, data.postName, data.postDate, data.draft) c.Assert(err, qt.IsNil) jsonResult, err := json.Marshal(result) c.Assert(err, qt.IsNil) c.Assert(string(jsonResult), qt.Equals, data.expect) } } func TestConvertJekyllContent(t *testing.T) { c := qt.New(t) testDataList := []struct { metadata interface{} content string expect string }{ { map[interface{}]interface{}{}, "Test content\r\n\npart2 content", "Test content\n\npart2 content", }, { map[interface{}]interface{}{}, "Test content\n\npart2 content", "Test content\n\npart2 content", }, { map[interface{}]interface{}{"excerpt_separator": ""}, "Test content\n\npart2 content", "---\nexcerpt_separator: \n---\nTest content\n\npart2 content", }, {map[interface{}]interface{}{}, "{% raw %}text{% endraw %}", "text"}, {map[interface{}]interface{}{}, "{%raw%} text2 {%endraw %}", "text2"}, { map[interface{}]interface{}{}, "{% highlight go %}\nvar s int\n{% endhighlight %}", "{{< highlight go >}}\nvar s int\n{{< / highlight >}}", }, { map[interface{}]interface{}{}, "{% highlight go linenos hl_lines=\"1 2\" %}\nvar s string\nvar i int\n{% endhighlight %}", "{{< highlight go \"linenos=table,hl_lines=1 2\" >}}\nvar s string\nvar i int\n{{< / highlight >}}", }, // Octopress image tag { map[interface{}]interface{}{}, "{% img http://placekitten.com/890/280 %}", "{{< figure src=\"http://placekitten.com/890/280\" >}}", }, { map[interface{}]interface{}{}, "{% img left http://placekitten.com/320/250 Place Kitten #2 %}", "{{< figure class=\"left\" src=\"http://placekitten.com/320/250\" title=\"Place Kitten #2\" >}}", }, { map[interface{}]interface{}{}, "{% img right http://placekitten.com/300/500 150 250 'Place Kitten #3' %}", "{{< figure class=\"right\" src=\"http://placekitten.com/300/500\" width=\"150\" height=\"250\" title=\"Place Kitten #3\" >}}", }, { map[interface{}]interface{}{}, "{% img right http://placekitten.com/300/500 150 250 'Place Kitten #4' 'An image of a very cute kitten' %}", "{{< figure class=\"right\" src=\"http://placekitten.com/300/500\" width=\"150\" height=\"250\" title=\"Place Kitten #4\" alt=\"An image of a very cute kitten\" >}}", }, { map[interface{}]interface{}{}, "{% img http://placekitten.com/300/500 150 250 'Place Kitten #4' 'An image of a very cute kitten' %}", "{{< figure src=\"http://placekitten.com/300/500\" width=\"150\" height=\"250\" title=\"Place Kitten #4\" alt=\"An image of a very cute kitten\" >}}", }, { map[interface{}]interface{}{}, "{% img right /placekitten/300/500 'Place Kitten #4' 'An image of a very cute kitten' %}", "{{< figure class=\"right\" src=\"/placekitten/300/500\" title=\"Place Kitten #4\" alt=\"An image of a very cute kitten\" >}}", }, { map[interface{}]interface{}{"category": "book", "layout": "post", "Date": "2015-10-01 12:13:11"}, "somecontent", "---\nDate: \"2015-10-01 12:13:11\"\ncategory: book\nlayout: post\n---\nsomecontent", }, } for _, data := range testDataList { result, err := convertJekyllContent(data.metadata, data.content) c.Assert(result, qt.Equals, data.expect) c.Assert(err, qt.IsNil) } } hugo-0.92.2/commands/limit_darwin.go000066400000000000000000000044731420147000300173570ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "syscall" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*limitCmd)(nil) type limitCmd struct { *baseCmd } func newLimitCmd() *limitCmd { ccmd := &cobra.Command{ Use: "ulimit", Short: "Check system ulimit settings", Long: `Hugo will inspect the current ulimit settings on the system. This is primarily to ensure that Hugo can watch enough files on some OSs`, RunE: func(cmd *cobra.Command, args []string) error { var rLimit syscall.Rlimit err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) if err != nil { return newSystemError("Error Getting rlimit ", err) } jww.FEEDBACK.Println("Current rLimit:", rLimit) if rLimit.Cur >= newRlimit { return nil } jww.FEEDBACK.Println("Attempting to increase limit") rLimit.Cur = newRlimit err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) if err != nil { return newSystemError("Error Setting rLimit ", err) } err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) if err != nil { return newSystemError("Error Getting rLimit ", err) } jww.FEEDBACK.Println("rLimit after change:", rLimit) return nil }, } return &limitCmd{baseCmd: newBaseCmd(ccmd)} } const newRlimit = 10240 func tweakLimit() { var rLimit syscall.Rlimit err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) if err != nil { jww.WARN.Println("Unable to get rlimit:", err) return } if rLimit.Cur < newRlimit { rLimit.Cur = newRlimit err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) if err != nil { // This may not succeed, see https://github.com/golang/go/issues/30401 jww.INFO.Println("Unable to increase number of open files limit:", err) } } } hugo-0.92.2/commands/limit_others.go000066400000000000000000000012561420147000300173730ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build !darwin package commands func tweakLimit() { // nothing to do } hugo-0.92.2/commands/list.go000066400000000000000000000124321420147000300156420ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "encoding/csv" "os" "strconv" "strings" "time" "github.com/gohugoio/hugo/hugolib" "github.com/gohugoio/hugo/resources/resource" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*listCmd)(nil) type listCmd struct { *baseBuilderCmd } func (lc *listCmd) buildSites(config map[string]interface{}) (*hugolib.HugoSites, error) { cfgInit := func(c *commandeer) error { for key, value := range config { c.Set(key, value) } return nil } c, err := initializeConfig(true, true, false, &lc.hugoBuilderCommon, lc, cfgInit) if err != nil { return nil, err } sites, err := hugolib.NewHugoSites(*c.DepsCfg) if err != nil { return nil, newSystemError("Error creating sites", err) } if err := sites.Build(hugolib.BuildCfg{SkipRender: true}); err != nil { return nil, newSystemError("Error Processing Source Content", err) } return sites, nil } func (b *commandsBuilder) newListCmd() *listCmd { cc := &listCmd{} cmd := &cobra.Command{ Use: "list", Short: "Listing out various types of content", Long: `Listing out various types of content. List requires a subcommand, e.g. ` + "`hugo list drafts`.", RunE: nil, } cmd.AddCommand( &cobra.Command{ Use: "drafts", Short: "List all drafts", Long: `List all of the drafts in your content directory.`, RunE: func(cmd *cobra.Command, args []string) error { sites, err := cc.buildSites(map[string]interface{}{"buildDrafts": true}) if err != nil { return newSystemError("Error building sites", err) } for _, p := range sites.Pages() { if p.Draft() { jww.FEEDBACK.Println(strings.TrimPrefix(p.File().Filename(), sites.WorkingDir+string(os.PathSeparator))) } } return nil }, }, &cobra.Command{ Use: "future", Short: "List all posts dated in the future", Long: `List all of the posts in your content directory which will be posted in the future.`, RunE: func(cmd *cobra.Command, args []string) error { sites, err := cc.buildSites(map[string]interface{}{"buildFuture": true}) if err != nil { return newSystemError("Error building sites", err) } writer := csv.NewWriter(os.Stdout) defer writer.Flush() for _, p := range sites.Pages() { if resource.IsFuture(p) { err := writer.Write([]string{ strings.TrimPrefix(p.File().Filename(), sites.WorkingDir+string(os.PathSeparator)), p.PublishDate().Format(time.RFC3339), }) if err != nil { return newSystemError("Error writing future posts to stdout", err) } } } return nil }, }, &cobra.Command{ Use: "expired", Short: "List all posts already expired", Long: `List all of the posts in your content directory which has already expired.`, RunE: func(cmd *cobra.Command, args []string) error { sites, err := cc.buildSites(map[string]interface{}{"buildExpired": true}) if err != nil { return newSystemError("Error building sites", err) } writer := csv.NewWriter(os.Stdout) defer writer.Flush() for _, p := range sites.Pages() { if resource.IsExpired(p) { err := writer.Write([]string{ strings.TrimPrefix(p.File().Filename(), sites.WorkingDir+string(os.PathSeparator)), p.ExpiryDate().Format(time.RFC3339), }) if err != nil { return newSystemError("Error writing expired posts to stdout", err) } } } return nil }, }, &cobra.Command{ Use: "all", Short: "List all posts", Long: `List all of the posts in your content directory, include drafts, future and expired pages.`, RunE: func(cmd *cobra.Command, args []string) error { sites, err := cc.buildSites(map[string]interface{}{ "buildExpired": true, "buildDrafts": true, "buildFuture": true, }) if err != nil { return newSystemError("Error building sites", err) } writer := csv.NewWriter(os.Stdout) defer writer.Flush() writer.Write([]string{ "path", "slug", "title", "date", "expiryDate", "publishDate", "draft", "permalink", }) for _, p := range sites.Pages() { if !p.IsPage() { continue } err := writer.Write([]string{ strings.TrimPrefix(p.File().Filename(), sites.WorkingDir+string(os.PathSeparator)), p.Slug(), p.Title(), p.Date().Format(time.RFC3339), p.ExpiryDate().Format(time.RFC3339), p.PublishDate().Format(time.RFC3339), strconv.FormatBool(p.Draft()), p.Permalink(), }) if err != nil { return newSystemError("Error writing posts to stdout", err) } } return nil }, }, ) cc.baseBuilderCmd = b.newBuilderBasicCmd(cmd) return cc } hugo-0.92.2/commands/list_test.go000066400000000000000000000024171420147000300167030ustar00rootroot00000000000000package commands import ( "bytes" "encoding/csv" "io" "os" "path/filepath" "strings" "testing" qt "github.com/frankban/quicktest" ) func captureStdout(f func() error) (string, error) { old := os.Stdout r, w, _ := os.Pipe() os.Stdout = w err := f() w.Close() os.Stdout = old var buf bytes.Buffer io.Copy(&buf, r) return buf.String(), err } func TestListAll(t *testing.T) { c := qt.New(t) dir, clean, err := createSimpleTestSite(t, testSiteConfig{}) defer clean() c.Assert(err, qt.IsNil) hugoCmd := newCommandsBuilder().addAll().build() cmd := hugoCmd.getCommand() defer func() { os.RemoveAll(dir) }() cmd.SetArgs([]string{"-s=" + dir, "list", "all"}) out, err := captureStdout(func() error { _, err := cmd.ExecuteC() return err }) c.Assert(err, qt.IsNil) r := csv.NewReader(strings.NewReader(out)) header, err := r.Read() c.Assert(err, qt.IsNil) c.Assert(header, qt.DeepEquals, []string{ "path", "slug", "title", "date", "expiryDate", "publishDate", "draft", "permalink", }) record, err := r.Read() c.Assert(err, qt.IsNil) c.Assert(record, qt.DeepEquals, []string{ filepath.Join("content", "p1.md"), "", "P1", "0001-01-01T00:00:00Z", "0001-01-01T00:00:00Z", "0001-01-01T00:00:00Z", "false", "https://example.org/p1/", }) } hugo-0.92.2/commands/mod.go000066400000000000000000000176741420147000300154630ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "errors" "fmt" "os" "path/filepath" "regexp" "github.com/gohugoio/hugo/hugolib" "github.com/gohugoio/hugo/modules" "github.com/spf13/cobra" ) var _ cmder = (*modCmd)(nil) type modCmd struct { *baseBuilderCmd } func (c *modCmd) newVerifyCmd() *cobra.Command { var clean bool verifyCmd := &cobra.Command{ Use: "verify", Short: "Verify dependencies.", Long: `Verify checks that the dependencies of the current module, which are stored in a local downloaded source cache, have not been modified since being downloaded. `, RunE: func(cmd *cobra.Command, args []string) error { return c.withModsClient(true, func(c *modules.Client) error { return c.Verify(clean) }) }, } verifyCmd.Flags().BoolVarP(&clean, "clean", "", false, "delete module cache for dependencies that fail verification") return verifyCmd } var moduleNotFoundRe = regexp.MustCompile("module.*not found") func (c *modCmd) newCleanCmd() *cobra.Command { var pattern string var all bool cmd := &cobra.Command{ Use: "clean", Short: "Delete the Hugo Module cache for the current project.", Long: `Delete the Hugo Module cache for the current project. Note that after you run this command, all of your dependencies will be re-downloaded next time you run "hugo". Also note that if you configure a positive maxAge for the "modules" file cache, it will also be cleaned as part of "hugo --gc". `, RunE: func(cmd *cobra.Command, args []string) error { if all { com, err := c.initConfig(false) if err != nil && com == nil { return err } count, err := com.hugo().FileCaches.ModulesCache().Prune(true) com.logger.Printf("Deleted %d files from module cache.", count) return err } return c.withModsClient(true, func(c *modules.Client) error { return c.Clean(pattern) }) }, } cmd.Flags().StringVarP(&pattern, "pattern", "", "", `pattern matching module paths to clean (all if not set), e.g. "**hugo*"`) cmd.Flags().BoolVarP(&all, "all", "", false, "clean entire module cache") return cmd } func (b *commandsBuilder) newModCmd() *modCmd { c := &modCmd{} const commonUsage = ` Note that Hugo will always start out by resolving the components defined in the site configuration, provided by a _vendor directory (if no --ignoreVendorPaths flag provided), Go Modules, or a folder inside the themes directory, in that order. See https://gohugo.io/hugo-modules/ for more information. ` cmd := &cobra.Command{ Use: "mod", Short: "Various Hugo Modules helpers.", Long: `Various helpers to help manage the modules in your project's dependency graph. Most operations here requires a Go version installed on your system (>= Go 1.12) and the relevant VCS client (typically Git). This is not needed if you only operate on modules inside /themes or if you have vendored them via "hugo mod vendor". ` + commonUsage, RunE: nil, } cmd.AddCommand(newModNPMCmd(c)) cmd.AddCommand( &cobra.Command{ Use: "get", DisableFlagParsing: true, Short: "Resolves dependencies in your current Hugo Project.", Long: ` Resolves dependencies in your current Hugo Project. Some examples: Install the latest version possible for a given module: hugo mod get github.com/gohugoio/testshortcodes Install a specific version: hugo mod get github.com/gohugoio/testshortcodes@v0.3.0 Install the latest versions of all module dependencies: hugo mod get -u hugo mod get -u ./... (recursive) Run "go help get" for more information. All flags available for "go get" is also relevant here. ` + commonUsage, RunE: func(cmd *cobra.Command, args []string) error { // We currently just pass on the flags we get to Go and // need to do the flag handling manually. if len(args) == 1 && args[0] == "-h" { return cmd.Help() } var lastArg string if len(args) != 0 { lastArg = args[len(args)-1] } if lastArg == "./..." { args = args[:len(args)-1] // Do a recursive update. dirname, err := os.Getwd() if err != nil { return err } // Sanity check. We do recursive walking and want to avoid // accidents. if len(dirname) < 5 { return errors.New("must not be run from the file system root") } filepath.Walk(dirname, func(path string, info os.FileInfo, err error) error { if info.IsDir() { return nil } if info.Name() == "go.mod" { // Found a module. dir := filepath.Dir(path) fmt.Println("Update module in", dir) c.source = dir err := c.withModsClient(false, func(c *modules.Client) error { if len(args) == 1 && args[0] == "-h" { return cmd.Help() } return c.Get(args...) }) if err != nil { return err } } return nil }) return nil } return c.withModsClient(false, func(c *modules.Client) error { return c.Get(args...) }) }, }, &cobra.Command{ Use: "graph", Short: "Print a module dependency graph.", Long: `Print a module dependency graph with information about module status (disabled, vendored). Note that for vendored modules, that is the version listed and not the one from go.mod. `, RunE: func(cmd *cobra.Command, args []string) error { return c.withModsClient(true, func(c *modules.Client) error { return c.Graph(os.Stdout) }) }, }, &cobra.Command{ Use: "init", Short: "Initialize this project as a Hugo Module.", Long: `Initialize this project as a Hugo Module. It will try to guess the module path, but you may help by passing it as an argument, e.g: hugo mod init github.com/gohugoio/testshortcodes Note that Hugo Modules supports multi-module projects, so you can initialize a Hugo Module inside a subfolder on GitHub, as one example. `, RunE: func(cmd *cobra.Command, args []string) error { var path string if len(args) >= 1 { path = args[0] } return c.withModsClient(false, func(c *modules.Client) error { return c.Init(path) }) }, }, &cobra.Command{ Use: "vendor", Short: "Vendor all module dependencies into the _vendor directory.", Long: `Vendor all module dependencies into the _vendor directory. If a module is vendored, that is where Hugo will look for it's dependencies. `, RunE: func(cmd *cobra.Command, args []string) error { return c.withModsClient(true, func(c *modules.Client) error { return c.Vendor() }) }, }, c.newVerifyCmd(), &cobra.Command{ Use: "tidy", Short: "Remove unused entries in go.mod and go.sum.", RunE: func(cmd *cobra.Command, args []string) error { return c.withModsClient(true, func(c *modules.Client) error { return c.Tidy() }) }, }, c.newCleanCmd(), ) c.baseBuilderCmd = b.newBuilderCmd(cmd) return c } func (c *modCmd) withModsClient(failOnMissingConfig bool, f func(*modules.Client) error) error { com, err := c.initConfig(failOnMissingConfig) if err != nil { return err } return f(com.hugo().ModulesClient) } func (c *modCmd) withHugo(f func(*hugolib.HugoSites) error) error { com, err := c.initConfig(true) if err != nil { return err } return f(com.hugo()) } func (c *modCmd) initConfig(failOnNoConfig bool) (*commandeer, error) { com, err := initializeConfig(failOnNoConfig, false, false, &c.hugoBuilderCommon, c, nil) if err != nil { return nil, err } return com, nil } hugo-0.92.2/commands/mod_npm.go000066400000000000000000000037341420147000300163250ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "github.com/gohugoio/hugo/hugolib" "github.com/gohugoio/hugo/modules/npm" "github.com/spf13/cobra" ) func newModNPMCmd(c *modCmd) *cobra.Command { cmd := &cobra.Command{ Use: "npm", Short: "Various npm helpers.", Long: `Various npm (Node package manager) helpers.`, RunE: func(cmd *cobra.Command, args []string) error { return c.withHugo(func(h *hugolib.HugoSites) error { return nil }) }, } cmd.AddCommand(&cobra.Command{ Use: "pack", Short: "Experimental: Prepares and writes a composite package.json file for your project.", Long: `Prepares and writes a composite package.json file for your project. On first run it creates a "package.hugo.json" in the project root if not already there. This file will be used as a template file with the base dependency set. This set will be merged with all "package.hugo.json" files found in the dependency tree, picking the version closest to the project. This command is marked as 'Experimental'. We think it's a great idea, so it's not likely to be removed from Hugo, but we need to test this out in "real life" to get a feel of it, so this may/will change in future versions of Hugo. `, RunE: func(cmd *cobra.Command, args []string) error { return c.withHugo(func(h *hugolib.HugoSites) error { return npm.Pack(h.BaseFs.SourceFs, h.BaseFs.Assets.Dirs) }) }, }) return cmd } hugo-0.92.2/commands/new.go000066400000000000000000000064521420147000300154650ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "bytes" "os" "path/filepath" "strings" "github.com/gohugoio/hugo/create" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugolib" "github.com/spf13/afero" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*newCmd)(nil) type newCmd struct { contentEditor string contentType string *baseBuilderCmd } func (b *commandsBuilder) newNewCmd() *newCmd { cmd := &cobra.Command{ Use: "new [path]", Short: "Create new content for your site", Long: `Create a new content file and automatically set the date and title. It will guess which kind of file to create based on the path provided. You can also specify the kind with ` + "`-k KIND`" + `. If archetypes are provided in your theme or site, they will be used. Ensure you run this within the root directory of your site.`, } cc := &newCmd{baseBuilderCmd: b.newBuilderCmd(cmd)} cmd.Flags().StringVarP(&cc.contentType, "kind", "k", "", "content type to create") cmd.Flags().StringVar(&cc.contentEditor, "editor", "", "edit new content with this editor, if provided") cmd.AddCommand(b.newNewSiteCmd().getCommand()) cmd.AddCommand(b.newNewThemeCmd().getCommand()) cmd.RunE = cc.newContent return cc } func (n *newCmd) newContent(cmd *cobra.Command, args []string) error { cfgInit := func(c *commandeer) error { if cmd.Flags().Changed("editor") { c.Set("newContentEditor", n.contentEditor) } return nil } c, err := initializeConfig(true, true, false, &n.hugoBuilderCommon, n, cfgInit) if err != nil { return err } if len(args) < 1 { return newUserError("path needs to be provided") } return create.NewContent(c.hugo(), n.contentType, args[0]) } func mkdir(x ...string) { p := filepath.Join(x...) err := os.MkdirAll(p, 0777) // before umask if err != nil { jww.FATAL.Fatalln(err) } } func touchFile(fs afero.Fs, x ...string) { inpath := filepath.Join(x...) mkdir(filepath.Dir(inpath)) err := helpers.WriteToDisk(inpath, bytes.NewReader([]byte{}), fs) if err != nil { jww.FATAL.Fatalln(err) } } func newContentPathSection(h *hugolib.HugoSites, path string) (string, string) { // Forward slashes is used in all examples. Convert if needed. // Issue #1133 createpath := filepath.FromSlash(path) if h != nil { for _, dir := range h.BaseFs.Content.Dirs { createpath = strings.TrimPrefix(createpath, dir.Meta().Filename) } } var section string // assume the first directory is the section (kind) if strings.Contains(createpath[1:], helpers.FilePathSeparator) { parts := strings.Split(strings.TrimPrefix(createpath, helpers.FilePathSeparator), helpers.FilePathSeparator) if len(parts) > 0 { section = parts[0] } } return createpath, section } hugo-0.92.2/commands/new_content_test.go000066400000000000000000000016621420147000300202540ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "path/filepath" "testing" qt "github.com/frankban/quicktest" ) // Issue #1133 func TestNewContentPathSectionWithForwardSlashes(t *testing.T) { c := qt.New(t) p, s := newContentPathSection(nil, "/post/new.md") c.Assert(p, qt.Equals, filepath.FromSlash("/post/new.md")) c.Assert(s, qt.Equals, "post") } hugo-0.92.2/commands/new_site.go000066400000000000000000000112661420147000300165100ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "bytes" "errors" "path/filepath" "strings" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/parser/metadecoders" _errors "github.com/pkg/errors" "github.com/gohugoio/hugo/create" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/parser" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*newSiteCmd)(nil) type newSiteCmd struct { configFormat string *baseBuilderCmd } func (b *commandsBuilder) newNewSiteCmd() *newSiteCmd { cc := &newSiteCmd{} cmd := &cobra.Command{ Use: "site [path]", Short: "Create a new site (skeleton)", Long: `Create a new site in the provided directory. The new site will have the correct structure, but no content or theme yet. Use ` + "`hugo new [contentPath]`" + ` to create new content.`, RunE: cc.newSite, } cmd.Flags().StringVarP(&cc.configFormat, "format", "f", "toml", "config file format") cmd.Flags().Bool("force", false, "init inside non-empty directory") cc.baseBuilderCmd = b.newBuilderBasicCmd(cmd) return cc } func (n *newSiteCmd) doNewSite(fs *hugofs.Fs, basepath string, force bool) error { archeTypePath := filepath.Join(basepath, "archetypes") dirs := []string{ filepath.Join(basepath, "layouts"), filepath.Join(basepath, "content"), archeTypePath, filepath.Join(basepath, "static"), filepath.Join(basepath, "data"), filepath.Join(basepath, "themes"), } if exists, _ := helpers.Exists(basepath, fs.Source); exists { if isDir, _ := helpers.IsDir(basepath, fs.Source); !isDir { return errors.New(basepath + " already exists but not a directory") } isEmpty, _ := helpers.IsEmpty(basepath, fs.Source) switch { case !isEmpty && !force: return errors.New(basepath + " already exists and is not empty. See --force.") case !isEmpty && force: all := append(dirs, filepath.Join(basepath, "config."+n.configFormat)) for _, path := range all { if exists, _ := helpers.Exists(path, fs.Source); exists { return errors.New(path + " already exists") } } } } for _, dir := range dirs { if err := fs.Source.MkdirAll(dir, 0777); err != nil { return _errors.Wrap(err, "Failed to create dir") } } createConfig(fs, basepath, n.configFormat) // Create a default archetype file. helpers.SafeWriteToDisk(filepath.Join(archeTypePath, "default.md"), strings.NewReader(create.DefaultArchetypeTemplateTemplate), fs.Source) jww.FEEDBACK.Printf("Congratulations! Your new Hugo site is created in %s.\n\n", basepath) jww.FEEDBACK.Println(nextStepsText()) return nil } // newSite creates a new Hugo site and initializes a structured Hugo directory. func (n *newSiteCmd) newSite(cmd *cobra.Command, args []string) error { if len(args) < 1 { return newUserError("path needs to be provided") } createpath, err := filepath.Abs(filepath.Clean(args[0])) if err != nil { return newUserError(err) } forceNew, _ := cmd.Flags().GetBool("force") return n.doNewSite(hugofs.NewDefault(config.New()), createpath, forceNew) } func createConfig(fs *hugofs.Fs, inpath string, kind string) (err error) { in := map[string]string{ "baseURL": "http://example.org/", "title": "My New Hugo Site", "languageCode": "en-us", } var buf bytes.Buffer err = parser.InterfaceToConfig(in, metadecoders.FormatFromString(kind), &buf) if err != nil { return err } return helpers.WriteToDisk(filepath.Join(inpath, "config."+kind), &buf, fs.Source) } func nextStepsText() string { var nextStepsText bytes.Buffer nextStepsText.WriteString(`Just a few more steps and you're ready to go: 1. Download a theme into the same-named folder. Choose a theme from https://themes.gohugo.io/ or create your own with the "hugo new theme " command. 2. Perhaps you want to add some content. You can add single files with "hugo new `) nextStepsText.WriteString(filepath.Join("", ".")) nextStepsText.WriteString(`". 3. Start the built-in live server via "hugo server". Visit https://gohugo.io/ for quickstart guide and full documentation.`) return nextStepsText.String() } hugo-0.92.2/commands/new_theme.go000066400000000000000000000124141420147000300166420ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "bytes" "errors" "path/filepath" "strings" "time" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*newThemeCmd)(nil) type newThemeCmd struct { *baseBuilderCmd } func (b *commandsBuilder) newNewThemeCmd() *newThemeCmd { cc := &newThemeCmd{} cmd := &cobra.Command{ Use: "theme [name]", Short: "Create a new theme", Long: `Create a new theme (skeleton) called [name] in ./themes. New theme is a skeleton. Please add content to the touched files. Add your name to the copyright line in the license and adjust the theme.toml file as you see fit.`, RunE: cc.newTheme, } cc.baseBuilderCmd = b.newBuilderBasicCmd(cmd) return cc } // newTheme creates a new Hugo theme template func (n *newThemeCmd) newTheme(cmd *cobra.Command, args []string) error { c, err := initializeConfig(false, false, false, &n.hugoBuilderCommon, n, nil) if err != nil { return err } if len(args) < 1 { return newUserError("theme name needs to be provided") } createpath := c.hugo().PathSpec.AbsPathify(filepath.Join(c.Cfg.GetString("themesDir"), args[0])) jww.FEEDBACK.Println("Creating theme at", createpath) cfg := c.DepsCfg if x, _ := helpers.Exists(createpath, cfg.Fs.Source); x { return errors.New(createpath + " already exists") } mkdir(createpath, "layouts", "_default") mkdir(createpath, "layouts", "partials") touchFile(cfg.Fs.Source, createpath, "layouts", "index.html") touchFile(cfg.Fs.Source, createpath, "layouts", "404.html") touchFile(cfg.Fs.Source, createpath, "layouts", "_default", "list.html") touchFile(cfg.Fs.Source, createpath, "layouts", "_default", "single.html") baseofDefault := []byte(` {{- partial "head.html" . -}} {{- partial "header.html" . -}}
{{- block "main" . }}{{- end }}
{{- partial "footer.html" . -}} `) err = helpers.WriteToDisk(filepath.Join(createpath, "layouts", "_default", "baseof.html"), bytes.NewReader(baseofDefault), cfg.Fs.Source) if err != nil { return err } touchFile(cfg.Fs.Source, createpath, "layouts", "partials", "head.html") touchFile(cfg.Fs.Source, createpath, "layouts", "partials", "header.html") touchFile(cfg.Fs.Source, createpath, "layouts", "partials", "footer.html") mkdir(createpath, "archetypes") archDefault := []byte("+++\n+++\n") err = helpers.WriteToDisk(filepath.Join(createpath, "archetypes", "default.md"), bytes.NewReader(archDefault), cfg.Fs.Source) if err != nil { return err } mkdir(createpath, "static", "js") mkdir(createpath, "static", "css") by := []byte(`The MIT License (MIT) Copyright (c) ` + time.Now().Format("2006") + ` YOUR_NAME_HERE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. `) err = helpers.WriteToDisk(filepath.Join(createpath, "LICENSE"), bytes.NewReader(by), cfg.Fs.Source) if err != nil { return err } n.createThemeMD(cfg.Fs, createpath) return nil } func (n *newThemeCmd) createThemeMD(fs *hugofs.Fs, inpath string) (err error) { by := []byte(`# theme.toml template for a Hugo theme # See https://github.com/gohugoio/hugoThemes#themetoml for an example name = "` + strings.Title(helpers.MakeTitle(filepath.Base(inpath))) + `" license = "MIT" licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE" description = "" homepage = "http://example.com/" tags = [] features = [] min_version = "0.41.0" [author] name = "" homepage = "" # If porting an existing theme [original] name = "" homepage = "" repo = "" `) err = helpers.WriteToDisk(filepath.Join(inpath, "theme.toml"), bytes.NewReader(by), fs.Source) if err != nil { return } return nil } hugo-0.92.2/commands/nodeploy.go000066400000000000000000000025011420147000300165140ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build nodeploy package commands import ( "errors" "github.com/spf13/cobra" ) var _ cmder = (*deployCmd)(nil) // deployCmd supports deploying sites to Cloud providers. type deployCmd struct { *baseBuilderCmd } func (b *commandsBuilder) newDeployCmd() *deployCmd { cc := &deployCmd{} cmd := &cobra.Command{ Use: "deploy", Short: "Deploy your site to a Cloud provider.", Long: `Deploy your site to a Cloud provider. See https://gohugo.io/hosting-and-deployment/hugo-deploy/ for detailed documentation. `, RunE: func(cmd *cobra.Command, args []string) error { return errors.New("build without HUGO_BUILD_TAGS=nodeploy to use this command") }, } cc.baseBuilderCmd = b.newBuilderBasicCmd(cmd) return cc } hugo-0.92.2/commands/release.go000066400000000000000000000037671420147000300163220ustar00rootroot00000000000000// +build release // Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "errors" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/releaser" "github.com/spf13/cobra" ) var _ cmder = (*releaseCommandeer)(nil) type releaseCommandeer struct { cmd *cobra.Command version string skipPublish bool try bool } func createReleaser() cmder { // Note: This is a command only meant for internal use and must be run // via "go run -tags release main.go release" on the actual code base that is in the release. r := &releaseCommandeer{ cmd: &cobra.Command{ Use: "release", Short: "Release a new version of Hugo.", Hidden: true, }, } r.cmd.RunE = func(cmd *cobra.Command, args []string) error { return r.release() } r.cmd.PersistentFlags().StringVarP(&r.version, "rel", "r", "", "new release version, i.e. 0.25.1") r.cmd.PersistentFlags().BoolVarP(&r.skipPublish, "skip-publish", "", false, "skip all publishing pipes of the release") r.cmd.PersistentFlags().BoolVarP(&r.try, "try", "", false, "simulate a release, i.e. no changes") return r } func (c *releaseCommandeer) getCommand() *cobra.Command { return c.cmd } func (c *releaseCommandeer) flagsToConfig(cfg config.Provider) { } func (r *releaseCommandeer) release() error { if r.version == "" { return errors.New("must set the --rel flag to the relevant version number") } return releaser.New(r.version, r.skipPublish, r.try).Run() } hugo-0.92.2/commands/release_noop.go000066400000000000000000000012751420147000300173450ustar00rootroot00000000000000// +build !release // Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands func createReleaser() cmder { return &nilCommand{} } hugo-0.92.2/commands/server.go000066400000000000000000000407061420147000300162020ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "bytes" "fmt" "io" "net" "net/http" "net/url" "os" "os/signal" "path/filepath" "regexp" "runtime" "strconv" "strings" "sync" "syscall" "time" "github.com/gohugoio/hugo/common/paths" "github.com/pkg/errors" "github.com/gohugoio/hugo/livereload" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/helpers" "github.com/spf13/afero" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" ) type serverCmd struct { // Can be used to stop the server. Useful in tests stop <-chan bool disableLiveReload bool navigateToChanged bool renderToDisk bool serverAppend bool serverInterface string serverPort int liveReloadPort int serverWatch bool noHTTPCache bool disableFastRender bool disableBrowserError bool *baseBuilderCmd } func (b *commandsBuilder) newServerCmd() *serverCmd { return b.newServerCmdSignaled(nil) } func (b *commandsBuilder) newServerCmdSignaled(stop <-chan bool) *serverCmd { cc := &serverCmd{stop: stop} cc.baseBuilderCmd = b.newBuilderCmd(&cobra.Command{ Use: "server", Aliases: []string{"serve"}, Short: "A high performance webserver", Long: `Hugo provides its own webserver which builds and serves the site. While hugo server is high performance, it is a webserver with limited options. Many run it in production, but the standard behavior is for people to use it in development and use a more full featured server such as Nginx or Caddy. 'hugo server' will avoid writing the rendered and served content to disk, preferring to store it in memory. By default hugo will also watch your files for any changes you make and automatically rebuild the site. It will then live reload any open browser pages and push the latest content to them. As most Hugo sites are built in a fraction of a second, you will be able to save and see your changes nearly instantly.`, RunE: cc.server, }) cc.cmd.Flags().IntVarP(&cc.serverPort, "port", "p", 1313, "port on which the server will listen") cc.cmd.Flags().IntVar(&cc.liveReloadPort, "liveReloadPort", -1, "port for live reloading (i.e. 443 in HTTPS proxy situations)") cc.cmd.Flags().StringVarP(&cc.serverInterface, "bind", "", "127.0.0.1", "interface to which the server will bind") cc.cmd.Flags().BoolVarP(&cc.serverWatch, "watch", "w", true, "watch filesystem for changes and recreate as needed") cc.cmd.Flags().BoolVar(&cc.noHTTPCache, "noHTTPCache", false, "prevent HTTP caching") cc.cmd.Flags().BoolVarP(&cc.serverAppend, "appendPort", "", true, "append port to baseURL") cc.cmd.Flags().BoolVar(&cc.disableLiveReload, "disableLiveReload", false, "watch without enabling live browser reload on rebuild") cc.cmd.Flags().BoolVar(&cc.navigateToChanged, "navigateToChanged", false, "navigate to changed content file on live browser reload") cc.cmd.Flags().BoolVar(&cc.renderToDisk, "renderToDisk", false, "render to Destination path (default is render to memory & serve from there)") cc.cmd.Flags().BoolVar(&cc.disableFastRender, "disableFastRender", false, "enables full re-renders on changes") cc.cmd.Flags().BoolVar(&cc.disableBrowserError, "disableBrowserError", false, "do not show build errors in the browser") cc.cmd.Flags().String("memstats", "", "log memory usage to this file") cc.cmd.Flags().String("meminterval", "100ms", "interval to poll memory usage (requires --memstats), valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".") return cc } type filesOnlyFs struct { fs http.FileSystem } type noDirFile struct { http.File } func (fs filesOnlyFs) Open(name string) (http.File, error) { f, err := fs.fs.Open(name) if err != nil { return nil, err } return noDirFile{f}, nil } func (f noDirFile) Readdir(count int) ([]os.FileInfo, error) { return nil, nil } var serverPorts []int func (sc *serverCmd) server(cmd *cobra.Command, args []string) error { // If a Destination is provided via flag write to disk destination, _ := cmd.Flags().GetString("destination") if destination != "" { sc.renderToDisk = true } var serverCfgInit sync.Once cfgInit := func(c *commandeer) error { c.Set("renderToMemory", !sc.renderToDisk) if cmd.Flags().Changed("navigateToChanged") { c.Set("navigateToChanged", sc.navigateToChanged) } if cmd.Flags().Changed("disableLiveReload") { c.Set("disableLiveReload", sc.disableLiveReload) } if cmd.Flags().Changed("disableFastRender") { c.Set("disableFastRender", sc.disableFastRender) } if cmd.Flags().Changed("disableBrowserError") { c.Set("disableBrowserError", sc.disableBrowserError) } if sc.serverWatch { c.Set("watch", true) } // TODO(bep) yes, we should fix. if !c.languagesConfigured { return nil } var err error // We can only do this once. serverCfgInit.Do(func() { serverPorts = make([]int, 1) if c.languages.IsMultihost() { if !sc.serverAppend { err = newSystemError("--appendPort=false not supported when in multihost mode") } serverPorts = make([]int, len(c.languages)) } currentServerPort := sc.serverPort for i := 0; i < len(serverPorts); i++ { l, err := net.Listen("tcp", net.JoinHostPort(sc.serverInterface, strconv.Itoa(currentServerPort))) if err == nil { l.Close() serverPorts[i] = currentServerPort } else { if i == 0 && sc.cmd.Flags().Changed("port") { // port set explicitly by user -- he/she probably meant it! err = newSystemErrorF("Server startup failed: %s", err) } c.logger.Println("port", sc.serverPort, "already in use, attempting to use an available port") sp, err := helpers.FindAvailablePort() if err != nil { err = newSystemError("Unable to find alternative port to use:", err) } serverPorts[i] = sp.Port } currentServerPort = serverPorts[i] + 1 } }) c.serverPorts = serverPorts c.Set("port", sc.serverPort) if sc.liveReloadPort != -1 { c.Set("liveReloadPort", sc.liveReloadPort) } else { c.Set("liveReloadPort", serverPorts[0]) } isMultiHost := c.languages.IsMultihost() for i, language := range c.languages { var serverPort int if isMultiHost { serverPort = serverPorts[i] } else { serverPort = serverPorts[0] } baseURL, err := sc.fixURL(language, sc.baseURL, serverPort) if err != nil { return nil } if isMultiHost { language.Set("baseURL", baseURL) } if i == 0 { c.Set("baseURL", baseURL) } } return err } if err := memStats(); err != nil { jww.WARN.Println("memstats error:", err) } // silence errors in cobra so we can handle them here cmd.SilenceErrors = true c, err := initializeConfig(true, true, true, &sc.hugoBuilderCommon, sc, cfgInit) if err != nil { cmd.PrintErrln("Error:", err.Error()) return err } err = func() error { defer c.timeTrack(time.Now(), "Built") err := c.serverBuild() if err != nil { cmd.PrintErrln("Error:", err.Error()) } return err }() if err != nil { return err } for _, s := range c.hugo().Sites { s.RegisterMediaTypes() } // Watch runs its own server as part of the routine if sc.serverWatch { watchDirs, err := c.getDirList() if err != nil { return err } watchGroups := helpers.ExtractAndGroupRootPaths(watchDirs) for _, group := range watchGroups { jww.FEEDBACK.Printf("Watching for changes in %s\n", group) } watcher, err := c.newWatcher(sc.poll, watchDirs...) if err != nil { return err } defer watcher.Close() } return c.serve(sc) } func getRootWatchDirsStr(baseDir string, watchDirs []string) string { relWatchDirs := make([]string, len(watchDirs)) for i, dir := range watchDirs { relWatchDirs[i], _ = paths.GetRelativePath(dir, baseDir) } return strings.Join(helpers.UniqueStringsSorted(helpers.ExtractRootPaths(relWatchDirs)), ",") } type fileServer struct { baseURLs []string roots []string errorTemplate func(err interface{}) (io.Reader, error) c *commandeer s *serverCmd } func (f *fileServer) rewriteRequest(r *http.Request, toPath string) *http.Request { r2 := new(http.Request) *r2 = *r r2.URL = new(url.URL) *r2.URL = *r.URL r2.URL.Path = toPath r2.Header.Set("X-Rewrite-Original-URI", r.URL.RequestURI()) return r2 } func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, error) { baseURL := f.baseURLs[i] root := f.roots[i] port := f.c.serverPorts[i] publishDir := f.c.Cfg.GetString("publishDir") if root != "" { publishDir = filepath.Join(publishDir, root) } absPublishDir := f.c.hugo().PathSpec.AbsPathify(publishDir) jww.FEEDBACK.Printf("Environment: %q", f.c.hugo().Deps.Site.Hugo().Environment) if i == 0 { if f.s.renderToDisk { jww.FEEDBACK.Println("Serving pages from " + absPublishDir) } else { jww.FEEDBACK.Println("Serving pages from memory") } } httpFs := afero.NewHttpFs(f.c.destinationFs) fs := filesOnlyFs{httpFs.Dir(absPublishDir)} if i == 0 && f.c.fastRenderMode { jww.FEEDBACK.Println("Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender") } // We're only interested in the path u, err := url.Parse(baseURL) if err != nil { return nil, "", "", errors.Wrap(err, "Invalid baseURL") } decorate := func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if f.c.showErrorInBrowser { // First check the error state err := f.c.getErrorWithContext() if err != nil { f.c.wasError = true w.WriteHeader(500) r, err := f.errorTemplate(err) if err != nil { f.c.logger.Errorln(err) } port = 1313 if !f.c.paused { port = f.c.Cfg.GetInt("liveReloadPort") } lr := *u lr.Host = fmt.Sprintf("%s:%d", lr.Hostname(), port) fmt.Fprint(w, injectLiveReloadScript(r, lr)) return } } if f.s.noHTTPCache { w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0") w.Header().Set("Pragma", "no-cache") } // Ignore any query params for the operations below. requestURI := strings.TrimSuffix(r.RequestURI, "?"+r.URL.RawQuery) for _, header := range f.c.serverConfig.MatchHeaders(requestURI) { w.Header().Set(header.Key, header.Value) } if redirect := f.c.serverConfig.MatchRedirect(requestURI); !redirect.IsZero() { doRedirect := true // This matches Netlify's behaviour and is needed for SPA behaviour. // See https://docs.netlify.com/routing/redirects/rewrites-proxies/ if !redirect.Force { path := filepath.Clean(strings.TrimPrefix(requestURI, u.Path)) fi, err := f.c.hugo().BaseFs.PublishFs.Stat(path) if err == nil { if fi.IsDir() { // There will be overlapping directories, so we // need to check for a file. _, err = f.c.hugo().BaseFs.PublishFs.Stat(filepath.Join(path, "index.html")) doRedirect = err != nil } else { doRedirect = false } } } if doRedirect { if redirect.Status == 200 { if r2 := f.rewriteRequest(r, strings.TrimPrefix(redirect.To, u.Path)); r2 != nil { requestURI = redirect.To r = r2 } } else { w.Header().Set("Content-Type", "") http.Redirect(w, r, redirect.To, redirect.Status) return } } } if f.c.fastRenderMode && f.c.buildErr == nil { if strings.HasSuffix(requestURI, "/") || strings.HasSuffix(requestURI, "html") || strings.HasSuffix(requestURI, "htm") { if !f.c.visitedURLs.Contains(requestURI) { // If not already on stack, re-render that single page. if err := f.c.partialReRender(requestURI); err != nil { f.c.handleBuildErr(err, fmt.Sprintf("Failed to render %q", requestURI)) if f.c.showErrorInBrowser { http.Redirect(w, r, requestURI, http.StatusMovedPermanently) return } } } f.c.visitedURLs.Add(requestURI) } } h.ServeHTTP(w, r) }) } fileserver := decorate(http.FileServer(fs)) mu := http.NewServeMux() if u.Path == "" || u.Path == "/" { mu.Handle("/", fileserver) } else { mu.Handle(u.Path, http.StripPrefix(u.Path, fileserver)) } endpoint := net.JoinHostPort(f.s.serverInterface, strconv.Itoa(port)) return mu, u.String(), endpoint, nil } var logErrorRe = regexp.MustCompile(`(?s)ERROR \d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} `) func removeErrorPrefixFromLog(content string) string { return logErrorRe.ReplaceAllLiteralString(content, "") } func (c *commandeer) serve(s *serverCmd) error { isMultiHost := c.hugo().IsMultihost() var ( baseURLs []string roots []string ) if isMultiHost { for _, s := range c.hugo().Sites { baseURLs = append(baseURLs, s.BaseURL.String()) roots = append(roots, s.Language().Lang) } } else { s := c.hugo().Sites[0] baseURLs = []string{s.BaseURL.String()} roots = []string{""} } templ, err := c.hugo().TextTmpl().Parse("__default_server_error", buildErrorTemplate) if err != nil { return err } srv := &fileServer{ baseURLs: baseURLs, roots: roots, c: c, s: s, errorTemplate: func(ctx interface{}) (io.Reader, error) { b := &bytes.Buffer{} err := c.hugo().Tmpl().Execute(templ, b, ctx) return b, err }, } doLiveReload := !c.Cfg.GetBool("disableLiveReload") if doLiveReload { livereload.Initialize() } sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) for i := range baseURLs { mu, serverURL, endpoint, err := srv.createEndpoint(i) if doLiveReload { u, err := url.Parse(helpers.SanitizeURL(baseURLs[i])) if err != nil { return err } mu.HandleFunc(u.Path+"/livereload.js", livereload.ServeJS) mu.HandleFunc(u.Path+"/livereload", livereload.Handler) } jww.FEEDBACK.Printf("Web Server is available at %s (bind address %s)\n", serverURL, s.serverInterface) go func() { err = http.ListenAndServe(endpoint, mu) if err != nil { c.logger.Errorf("Error: %s\n", err.Error()) os.Exit(1) } }() } jww.FEEDBACK.Println("Press Ctrl+C to stop") if s.stop != nil { select { case <-sigs: case <-s.stop: } } else { <-sigs } c.hugo().Close() return nil } // fixURL massages the baseURL into a form needed for serving // all pages correctly. func (sc *serverCmd) fixURL(cfg config.Provider, s string, port int) (string, error) { useLocalhost := false if s == "" { s = cfg.GetString("baseURL") useLocalhost = true } if !strings.HasSuffix(s, "/") { s = s + "/" } // do an initial parse of the input string u, err := url.Parse(s) if err != nil { return "", err } // if no Host is defined, then assume that no schema or double-slash were // present in the url. Add a double-slash and make a best effort attempt. if u.Host == "" && s != "/" { s = "//" + s u, err = url.Parse(s) if err != nil { return "", err } } if useLocalhost { if u.Scheme == "https" { u.Scheme = "http" } u.Host = "localhost" } if sc.serverAppend { if strings.Contains(u.Host, ":") { u.Host, _, err = net.SplitHostPort(u.Host) if err != nil { return "", errors.Wrap(err, "Failed to split baseURL hostpost") } } u.Host += fmt.Sprintf(":%d", port) } return u.String(), nil } func memStats() error { b := newCommandsBuilder() sc := b.newServerCmd().getCommand() memstats := sc.Flags().Lookup("memstats").Value.String() if memstats != "" { interval, err := time.ParseDuration(sc.Flags().Lookup("meminterval").Value.String()) if err != nil { interval, _ = time.ParseDuration("100ms") } fileMemStats, err := os.Create(memstats) if err != nil { return err } fileMemStats.WriteString("# Time\tHeapSys\tHeapAlloc\tHeapIdle\tHeapReleased\n") go func() { var stats runtime.MemStats start := time.Now().UnixNano() for { runtime.ReadMemStats(&stats) if fileMemStats != nil { fileMemStats.WriteString(fmt.Sprintf("%d\t%d\t%d\t%d\t%d\n", (time.Now().UnixNano()-start)/1000000, stats.HeapSys, stats.HeapAlloc, stats.HeapIdle, stats.HeapReleased)) time.Sleep(interval) } else { break } } }() } return nil } hugo-0.92.2/commands/server_errors.go000066400000000000000000000046351420147000300175770ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "bytes" "io" "net/url" "github.com/gohugoio/hugo/transform" "github.com/gohugoio/hugo/transform/livereloadinject" ) var buildErrorTemplate = ` Hugo Server: Error
{{ highlight .Error "apl" "linenos=false,noclasses=true,style=paraiso-dark" }} {{ with .File }} {{ $params := printf "noclasses=true,style=paraiso-dark,linenos=table,hl_lines=%d,linenostart=%d" (add .LinesPos 1) (sub .Position.LineNumber .LinesPos) }} {{ $lexer := .ChromaLexer | default "go-html-template" }} {{ highlight (delimit .Lines "\n") $lexer $params }} {{ end }} {{ with .StackTrace }} {{ highlight . "apl" "noclasses=true,style=paraiso-dark" }} {{ end }}

{{ .Version }}

Reload Page
` func injectLiveReloadScript(src io.Reader, baseURL url.URL) string { var b bytes.Buffer chain := transform.Chain{livereloadinject.New(baseURL)} chain.Apply(&b, src) return b.String() } hugo-0.92.2/commands/server_test.go000066400000000000000000000102021420147000300172250ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "fmt" "net/http" "os" "runtime" "strings" "testing" "time" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/helpers" qt "github.com/frankban/quicktest" ) func TestServer(t *testing.T) { if isWindowsCI() { // TODO(bep) not sure why server tests have started to fail on the Windows CI server. t.Skip("Skip server test on appveyor") } c := qt.New(t) dir, clean, err := createSimpleTestSite(t, testSiteConfig{}) defer clean() c.Assert(err, qt.IsNil) // Let us hope that this port is available on all systems ... port := 1331 defer func() { os.RemoveAll(dir) }() stop := make(chan bool) b := newCommandsBuilder() scmd := b.newServerCmdSignaled(stop) cmd := scmd.getCommand() cmd.SetArgs([]string{"-s=" + dir, fmt.Sprintf("-p=%d", port)}) go func() { _, err = cmd.ExecuteC() c.Assert(err, qt.IsNil) }() // There is no way to know exactly when the server is ready for connections. // We could improve by something like https://golang.org/pkg/net/http/httptest/#Server // But for now, let us sleep and pray! time.Sleep(2 * time.Second) resp, err := http.Get("http://localhost:1331/") c.Assert(err, qt.IsNil) defer resp.Body.Close() homeContent := helpers.ReaderToString(resp.Body) c.Assert(homeContent, qt.Contains, "List: Hugo Commands") c.Assert(homeContent, qt.Contains, "Environment: development") // Stop the server. stop <- true } func TestFixURL(t *testing.T) { type data struct { TestName string CLIBaseURL string CfgBaseURL string AppendPort bool Port int Result string } tests := []data{ {"Basic http localhost", "", "http://foo.com", true, 1313, "http://localhost:1313/"}, {"Basic https production, http localhost", "", "https://foo.com", true, 1313, "http://localhost:1313/"}, {"Basic subdir", "", "http://foo.com/bar", true, 1313, "http://localhost:1313/bar/"}, {"Basic production", "http://foo.com", "http://foo.com", false, 80, "http://foo.com/"}, {"Production subdir", "http://foo.com/bar", "http://foo.com/bar", false, 80, "http://foo.com/bar/"}, {"No http", "", "foo.com", true, 1313, "//localhost:1313/"}, {"Override configured port", "", "foo.com:2020", true, 1313, "//localhost:1313/"}, {"No http production", "foo.com", "foo.com", false, 80, "//foo.com/"}, {"No http production with port", "foo.com", "foo.com", true, 2020, "//foo.com:2020/"}, {"No config", "", "", true, 1313, "//localhost:1313/"}, } for _, test := range tests { t.Run(test.TestName, func(t *testing.T) { b := newCommandsBuilder() s := b.newServerCmd() v := config.New() baseURL := test.CLIBaseURL v.Set("baseURL", test.CfgBaseURL) s.serverAppend = test.AppendPort s.serverPort = test.Port result, err := s.fixURL(v, baseURL, s.serverPort) if err != nil { t.Errorf("Unexpected error %s", err) } if result != test.Result { t.Errorf("Expected %q, got %q", test.Result, result) } }) } } func TestRemoveErrorPrefixFromLog(t *testing.T) { c := qt.New(t) content := `ERROR 2018/10/07 13:11:12 Error while rendering "home": template: _default/baseof.html:4:3: executing "main" at : error calling partial: template: partials/logo.html:5:84: executing "partials/logo.html" at <$resized.AHeight>: can't evaluate field AHeight in type *resource.Image ERROR 2018/10/07 13:11:12 Rebuild failed: logged 1 error(s) ` withoutError := removeErrorPrefixFromLog(content) c.Assert(strings.Contains(withoutError, "ERROR"), qt.Equals, false) } func isWindowsCI() bool { return runtime.GOOS == "windows" && os.Getenv("CI") != "" } hugo-0.92.2/commands/static_syncer.go000066400000000000000000000106321420147000300175410ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "os" "path/filepath" "github.com/gohugoio/hugo/hugolib/filesystems" "github.com/fsnotify/fsnotify" "github.com/gohugoio/hugo/helpers" "github.com/spf13/fsync" ) type staticSyncer struct { c *commandeer } func newStaticSyncer(c *commandeer) (*staticSyncer, error) { return &staticSyncer{c: c}, nil } func (s *staticSyncer) isStatic(filename string) bool { return s.c.hugo().BaseFs.SourceFilesystems.IsStatic(filename) } func (s *staticSyncer) syncsStaticEvents(staticEvents []fsnotify.Event) error { c := s.c syncFn := func(sourceFs *filesystems.SourceFilesystem) (uint64, error) { publishDir := c.hugo().PathSpec.PublishDir // If root, remove the second '/' if publishDir == "//" { publishDir = helpers.FilePathSeparator } if sourceFs.PublishFolder != "" { publishDir = filepath.Join(publishDir, sourceFs.PublishFolder) } syncer := fsync.NewSyncer() syncer.NoTimes = c.Cfg.GetBool("noTimes") syncer.NoChmod = c.Cfg.GetBool("noChmod") syncer.ChmodFilter = chmodFilter syncer.SrcFs = sourceFs.Fs syncer.DestFs = c.Fs.Destination // prevent spamming the log on changes logger := helpers.NewDistinctErrorLogger() for _, ev := range staticEvents { // Due to our approach of layering both directories and the content's rendered output // into one we can't accurately remove a file not in one of the source directories. // If a file is in the local static dir and also in the theme static dir and we remove // it from one of those locations we expect it to still exist in the destination // // If Hugo generates a file (from the content dir) over a static file // the content generated file should take precedence. // // Because we are now watching and handling individual events it is possible that a static // event that occupies the same path as a content generated file will take precedence // until a regeneration of the content takes places. // // Hugo assumes that these cases are very rare and will permit this bad behavior // The alternative is to track every single file and which pipeline rendered it // and then to handle conflict resolution on every event. fromPath := ev.Name relPath, found := sourceFs.MakePathRelative(fromPath) if !found { // Not member of this virtual host. continue } // Remove || rename is harder and will require an assumption. // Hugo takes the following approach: // If the static file exists in any of the static source directories after this event // Hugo will re-sync it. // If it does not exist in all of the static directories Hugo will remove it. // // This assumes that Hugo has not generated content on top of a static file and then removed // the source of that static file. In this case Hugo will incorrectly remove that file // from the published directory. if ev.Op&fsnotify.Rename == fsnotify.Rename || ev.Op&fsnotify.Remove == fsnotify.Remove { if _, err := sourceFs.Fs.Stat(relPath); os.IsNotExist(err) { // If file doesn't exist in any static dir, remove it toRemove := filepath.Join(publishDir, relPath) logger.Println("File no longer exists in static dir, removing", toRemove) _ = c.Fs.Destination.RemoveAll(toRemove) } else if err == nil { // If file still exists, sync it logger.Println("Syncing", relPath, "to", publishDir) if err := syncer.Sync(filepath.Join(publishDir, relPath), relPath); err != nil { c.logger.Errorln(err) } } else { c.logger.Errorln(err) } continue } // For all other event operations Hugo will sync static. logger.Println("Syncing", relPath, "to", publishDir) if err := syncer.Sync(filepath.Join(publishDir, relPath), relPath); err != nil { c.logger.Errorln(err) } } return 0, nil } _, err := c.doWithPublishDirs(syncFn) return err } hugo-0.92.2/commands/version.go000066400000000000000000000023011420147000300163460ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package commands import ( "github.com/gohugoio/hugo/common/hugo" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*versionCmd)(nil) type versionCmd struct { *baseCmd } func newVersionCmd() *versionCmd { return &versionCmd{ newBaseCmd(&cobra.Command{ Use: "version", Short: "Print the version number of Hugo", Long: `All software has versions. This is Hugo's.`, RunE: func(cmd *cobra.Command, args []string) error { printHugoVersion() return nil }, }), } } func printHugoVersion() { jww.FEEDBACK.Println(hugo.BuildVersionString()) } hugo-0.92.2/common/000077500000000000000000000000001420147000300140255ustar00rootroot00000000000000hugo-0.92.2/common/collections/000077500000000000000000000000001420147000300163435ustar00rootroot00000000000000hugo-0.92.2/common/collections/append.go000066400000000000000000000056511420147000300201500ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "fmt" "reflect" ) // Append appends from to a slice to and returns the resulting slice. // If length of from is one and the only element is a slice of same type as to, // it will be appended. func Append(to interface{}, from ...interface{}) (interface{}, error) { tov, toIsNil := indirect(reflect.ValueOf(to)) toIsNil = toIsNil || to == nil var tot reflect.Type if !toIsNil { if tov.Kind() != reflect.Slice { return nil, fmt.Errorf("expected a slice, got %T", to) } tot = tov.Type().Elem() toIsNil = tov.Len() == 0 if len(from) == 1 { fromv := reflect.ValueOf(from[0]) if fromv.Kind() == reflect.Slice { if toIsNil { // If we get nil []string, we just return the []string return from[0], nil } fromt := reflect.TypeOf(from[0]).Elem() // If we get []string []string, we append the from slice to to if tot == fromt { return reflect.AppendSlice(tov, fromv).Interface(), nil } else if !fromt.AssignableTo(tot) { // Fall back to a []interface{} slice. return appendToInterfaceSliceFromValues(tov, fromv) } } } } if toIsNil { return Slice(from...), nil } for _, f := range from { fv := reflect.ValueOf(f) if !fv.Type().AssignableTo(tot) { // Fall back to a []interface{} slice. tov, _ := indirect(reflect.ValueOf(to)) return appendToInterfaceSlice(tov, from...) } tov = reflect.Append(tov, fv) } return tov.Interface(), nil } func appendToInterfaceSliceFromValues(slice1, slice2 reflect.Value) ([]interface{}, error) { var tos []interface{} for _, slice := range []reflect.Value{slice1, slice2} { for i := 0; i < slice.Len(); i++ { tos = append(tos, slice.Index(i).Interface()) } } return tos, nil } func appendToInterfaceSlice(tov reflect.Value, from ...interface{}) ([]interface{}, error) { var tos []interface{} for i := 0; i < tov.Len(); i++ { tos = append(tos, tov.Index(i).Interface()) } tos = append(tos, from...) return tos, nil } // indirect is borrowed from the Go stdlib: 'text/template/exec.go' // TODO(bep) consolidate func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { if v.IsNil() { return v, true } if v.Kind() == reflect.Interface && v.NumMethod() > 0 { break } } return v, false } hugo-0.92.2/common/collections/append_test.go000066400000000000000000000051471420147000300212070ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "html/template" "testing" qt "github.com/frankban/quicktest" ) func TestAppend(t *testing.T) { t.Parallel() c := qt.New(t) for _, test := range []struct { start interface{} addend []interface{} expected interface{} }{ {[]string{"a", "b"}, []interface{}{"c"}, []string{"a", "b", "c"}}, {[]string{"a", "b"}, []interface{}{"c", "d", "e"}, []string{"a", "b", "c", "d", "e"}}, {[]string{"a", "b"}, []interface{}{[]string{"c", "d", "e"}}, []string{"a", "b", "c", "d", "e"}}, {[]string{"a"}, []interface{}{"b", template.HTML("c")}, []interface{}{"a", "b", template.HTML("c")}}, {nil, []interface{}{"a", "b"}, []string{"a", "b"}}, {nil, []interface{}{nil}, []interface{}{nil}}, {[]interface{}{}, []interface{}{[]string{"c", "d", "e"}}, []string{"c", "d", "e"}}, { tstSlicers{&tstSlicer{"a"}, &tstSlicer{"b"}}, []interface{}{&tstSlicer{"c"}}, tstSlicers{&tstSlicer{"a"}, &tstSlicer{"b"}, &tstSlicer{"c"}}, }, { &tstSlicers{&tstSlicer{"a"}, &tstSlicer{"b"}}, []interface{}{&tstSlicer{"c"}}, tstSlicers{ &tstSlicer{"a"}, &tstSlicer{"b"}, &tstSlicer{"c"}, }, }, { testSlicerInterfaces{&tstSlicerIn1{"a"}, &tstSlicerIn1{"b"}}, []interface{}{&tstSlicerIn1{"c"}}, testSlicerInterfaces{&tstSlicerIn1{"a"}, &tstSlicerIn1{"b"}, &tstSlicerIn1{"c"}}, }, //https://github.com/gohugoio/hugo/issues/5361 { []string{"a", "b"}, []interface{}{tstSlicers{&tstSlicer{"a"}, &tstSlicer{"b"}}}, []interface{}{"a", "b", &tstSlicer{"a"}, &tstSlicer{"b"}}, }, { []string{"a", "b"}, []interface{}{&tstSlicer{"a"}}, []interface{}{"a", "b", &tstSlicer{"a"}}, }, // Errors {"", []interface{}{[]string{"a", "b"}}, false}, // No string concatenation. { "ab", []interface{}{"c"}, false, }, } { result, err := Append(test.start, test.addend...) if b, ok := test.expected.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil)) continue } c.Assert(err, qt.IsNil) c.Assert(result, qt.DeepEquals, test.expected) } } hugo-0.92.2/common/collections/collections.go000066400000000000000000000015631420147000300212150ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package collections contains common Hugo functionality related to collection // handling. package collections // Grouper defines a very generic way to group items by a given key. type Grouper interface { Group(key interface{}, items interface{}) (interface{}, error) } hugo-0.92.2/common/collections/order.go000066400000000000000000000013761420147000300200140ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections type Order interface { // Ordinal is a zero-based ordinal that represents the order of an object // in a collection. Ordinal() int } hugo-0.92.2/common/collections/slice.go000066400000000000000000000037011420147000300177720ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "reflect" ) // Slicer defines a very generic way to create a typed slice. This is used // in collections.Slice template func to get types such as Pages, PageGroups etc. // instead of the less useful []interface{}. type Slicer interface { Slice(items interface{}) (interface{}, error) } // Slice returns a slice of all passed arguments. func Slice(args ...interface{}) interface{} { if len(args) == 0 { return args } first := args[0] firstType := reflect.TypeOf(first) if firstType == nil { return args } if g, ok := first.(Slicer); ok { v, err := g.Slice(args) if err == nil { return v } // If Slice fails, the items are not of the same type and // []interface{} is the best we can do. return args } if len(args) > 1 { // This can be a mix of types. for i := 1; i < len(args); i++ { if firstType != reflect.TypeOf(args[i]) { // []interface{} is the best we can do return args } } } slice := reflect.MakeSlice(reflect.SliceOf(firstType), len(args), len(args)) for i, arg := range args { slice.Index(i).Set(reflect.ValueOf(arg)) } return slice.Interface() } // StringSliceToInterfaceSlice converts ss to []interface{}. func StringSliceToInterfaceSlice(ss []string) []interface{} { result := make([]interface{}, len(ss)) for i, s := range ss { result[i] = s } return result } hugo-0.92.2/common/collections/slice_test.go000066400000000000000000000061461420147000300210370ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "errors" "testing" qt "github.com/frankban/quicktest" ) var ( _ Slicer = (*tstSlicer)(nil) _ Slicer = (*tstSlicerIn1)(nil) _ Slicer = (*tstSlicerIn2)(nil) _ testSlicerInterface = (*tstSlicerIn1)(nil) _ testSlicerInterface = (*tstSlicerIn1)(nil) ) type testSlicerInterface interface { Name() string } type testSlicerInterfaces []testSlicerInterface type tstSlicerIn1 struct { TheName string } type tstSlicerIn2 struct { TheName string } type tstSlicer struct { TheName string } func (p *tstSlicerIn1) Slice(in interface{}) (interface{}, error) { items := in.([]interface{}) result := make(testSlicerInterfaces, len(items)) for i, v := range items { switch vv := v.(type) { case testSlicerInterface: result[i] = vv default: return nil, errors.New("invalid type") } } return result, nil } func (p *tstSlicerIn2) Slice(in interface{}) (interface{}, error) { items := in.([]interface{}) result := make(testSlicerInterfaces, len(items)) for i, v := range items { switch vv := v.(type) { case testSlicerInterface: result[i] = vv default: return nil, errors.New("invalid type") } } return result, nil } func (p *tstSlicerIn1) Name() string { return p.TheName } func (p *tstSlicerIn2) Name() string { return p.TheName } func (p *tstSlicer) Slice(in interface{}) (interface{}, error) { items := in.([]interface{}) result := make(tstSlicers, len(items)) for i, v := range items { switch vv := v.(type) { case *tstSlicer: result[i] = vv default: return nil, errors.New("invalid type") } } return result, nil } type tstSlicers []*tstSlicer func TestSlice(t *testing.T) { t.Parallel() c := qt.New(t) for i, test := range []struct { args []interface{} expected interface{} }{ {[]interface{}{"a", "b"}, []string{"a", "b"}}, {[]interface{}{&tstSlicer{"a"}, &tstSlicer{"b"}}, tstSlicers{&tstSlicer{"a"}, &tstSlicer{"b"}}}, {[]interface{}{&tstSlicer{"a"}, "b"}, []interface{}{&tstSlicer{"a"}, "b"}}, {[]interface{}{}, []interface{}{}}, {[]interface{}{nil}, []interface{}{nil}}, {[]interface{}{5, "b"}, []interface{}{5, "b"}}, {[]interface{}{&tstSlicerIn1{"a"}, &tstSlicerIn2{"b"}}, testSlicerInterfaces{&tstSlicerIn1{"a"}, &tstSlicerIn2{"b"}}}, {[]interface{}{&tstSlicerIn1{"a"}, &tstSlicer{"b"}}, []interface{}{&tstSlicerIn1{"a"}, &tstSlicer{"b"}}}, } { errMsg := qt.Commentf("[%d] %v", i, test.args) result := Slice(test.args...) c.Assert(test.expected, qt.DeepEquals, result, errMsg) } } hugo-0.92.2/common/constants/000077500000000000000000000000001420147000300160415ustar00rootroot00000000000000hugo-0.92.2/common/constants/constants.go000066400000000000000000000016411420147000300204060ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package constants // Error IDs. // Do not change these values. const ( ErrIDAmbigousDisableKindTaxonomy = "error-disable-taxonomy" ErrIDAmbigousOutputKindTaxonomy = "error-output-taxonomy" // IDs for remote errors in tpl/data. ErrRemoteGetJSON = "error-remote-getjson" ErrRemoteGetCSV = "error-remote-getcsv" ) hugo-0.92.2/common/herrors/000077500000000000000000000000001420147000300155115ustar00rootroot00000000000000hugo-0.92.2/common/herrors/error_locator.go000066400000000000000000000145051420147000300207210ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package herrors contains common Hugo errors and error related utilities. package herrors import ( "io" "io/ioutil" "path/filepath" "strings" "github.com/gohugoio/hugo/common/text" "github.com/spf13/afero" ) // LineMatcher contains the elements used to match an error to a line type LineMatcher struct { Position text.Position Error error LineNumber int Offset int Line string } // LineMatcherFn is used to match a line with an error. type LineMatcherFn func(m LineMatcher) bool // SimpleLineMatcher simply matches by line number. var SimpleLineMatcher = func(m LineMatcher) bool { return m.Position.LineNumber == m.LineNumber } var _ text.Positioner = ErrorContext{} // ErrorContext contains contextual information about an error. This will // typically be the lines surrounding some problem in a file. type ErrorContext struct { // If a match will contain the matched line and up to 2 lines before and after. // Will be empty if no match. Lines []string // The position of the error in the Lines above. 0 based. LinesPos int position text.Position // The lexer to use for syntax highlighting. // https://gohugo.io/content-management/syntax-highlighting/#list-of-chroma-highlighting-languages ChromaLexer string } // Position returns the text position of this error. func (e ErrorContext) Position() text.Position { return e.position } var _ causer = (*ErrorWithFileContext)(nil) // ErrorWithFileContext is an error with some additional file context related // to that error. type ErrorWithFileContext struct { cause error ErrorContext } func (e *ErrorWithFileContext) Error() string { pos := e.Position() if pos.IsValid() { return pos.String() + ": " + e.cause.Error() } return e.cause.Error() } func (e *ErrorWithFileContext) Cause() error { return e.cause } // WithFileContextForFile will try to add a file context with lines matching the given matcher. // If no match could be found, the original error is returned with false as the second return value. func WithFileContextForFile(e error, realFilename, filename string, fs afero.Fs, matcher LineMatcherFn) (error, bool) { f, err := fs.Open(filename) if err != nil { return e, false } defer f.Close() return WithFileContext(e, realFilename, f, matcher) } // WithFileContextForFileDefault tries to add file context using the default line matcher. func WithFileContextForFileDefault(err error, filename string, fs afero.Fs) error { err, _ = WithFileContextForFile( err, filename, filename, fs, SimpleLineMatcher) return err } // WithFileContextForFile will try to add a file context with lines matching the given matcher. // If no match could be found, the original error is returned with false as the second return value. func WithFileContext(e error, realFilename string, r io.Reader, matcher LineMatcherFn) (error, bool) { if e == nil { panic("error missing") } le := UnwrapFileError(e) if le == nil { var ok bool if le, ok = ToFileError("", e).(FileError); !ok { return e, false } } var errCtx ErrorContext posle := le.Position() if posle.Offset != -1 { errCtx = locateError(r, le, func(m LineMatcher) bool { if posle.Offset >= m.Offset && posle.Offset < m.Offset+len(m.Line) { lno := posle.LineNumber - m.Position.LineNumber + m.LineNumber m.Position = text.Position{LineNumber: lno} } return matcher(m) }) } else { errCtx = locateError(r, le, matcher) } pos := &errCtx.position if pos.LineNumber == -1 { return e, false } pos.Filename = realFilename if le.Type() != "" { errCtx.ChromaLexer = chromaLexerFromType(le.Type()) } else { errCtx.ChromaLexer = chromaLexerFromFilename(realFilename) } return &ErrorWithFileContext{cause: e, ErrorContext: errCtx}, true } // UnwrapErrorWithFileContext tries to unwrap an ErrorWithFileContext from err. // It returns nil if this is not possible. func UnwrapErrorWithFileContext(err error) *ErrorWithFileContext { for err != nil { switch v := err.(type) { case *ErrorWithFileContext: return v case causer: err = v.Cause() default: return nil } } return nil } func chromaLexerFromType(fileType string) string { switch fileType { case "html", "htm": return "go-html-template" } return fileType } func extNoDelimiter(filename string) string { return strings.TrimPrefix(filepath.Ext(filename), ".") } func chromaLexerFromFilename(filename string) string { if strings.Contains(filename, "layouts") { return "go-html-template" } ext := extNoDelimiter(filename) return chromaLexerFromType(ext) } func locateErrorInString(src string, matcher LineMatcherFn) ErrorContext { return locateError(strings.NewReader(src), &fileError{}, matcher) } func locateError(r io.Reader, le FileError, matches LineMatcherFn) ErrorContext { if le == nil { panic("must provide an error") } errCtx := ErrorContext{position: text.Position{LineNumber: -1, ColumnNumber: 1, Offset: -1}, LinesPos: -1} b, err := ioutil.ReadAll(r) if err != nil { return errCtx } pos := &errCtx.position lepos := le.Position() lines := strings.Split(string(b), "\n") if lepos.ColumnNumber >= 0 { pos.ColumnNumber = lepos.ColumnNumber } lineNo := 0 posBytes := 0 for li, line := range lines { lineNo = li + 1 m := LineMatcher{ Position: le.Position(), Error: le, LineNumber: lineNo, Offset: posBytes, Line: line, } if errCtx.LinesPos == -1 && matches(m) { pos.LineNumber = lineNo break } posBytes += len(line) } if pos.LineNumber != -1 { low := pos.LineNumber - 3 if low < 0 { low = 0 } if pos.LineNumber > 2 { errCtx.LinesPos = 2 } else { errCtx.LinesPos = pos.LineNumber - 1 } high := pos.LineNumber + 2 if high > len(lines) { high = len(lines) } errCtx.Lines = lines[low:high] } return errCtx } hugo-0.92.2/common/herrors/error_locator_test.go000066400000000000000000000064221420147000300217570ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package herrors contains common Hugo errors and error related utilities. package herrors import ( "strings" "testing" qt "github.com/frankban/quicktest" ) func TestErrorLocator(t *testing.T) { c := qt.New(t) lineMatcher := func(m LineMatcher) bool { return strings.Contains(m.Line, "THEONE") } lines := `LINE 1 LINE 2 LINE 3 LINE 4 This is THEONE LINE 6 LINE 7 LINE 8 ` location := locateErrorInString(lines, lineMatcher) c.Assert(location.Lines, qt.DeepEquals, []string{"LINE 3", "LINE 4", "This is THEONE", "LINE 6", "LINE 7"}) pos := location.Position() c.Assert(pos.LineNumber, qt.Equals, 5) c.Assert(location.LinesPos, qt.Equals, 2) c.Assert(locateErrorInString(`This is THEONE`, lineMatcher).Lines, qt.DeepEquals, []string{"This is THEONE"}) location = locateErrorInString(`L1 This is THEONE L2 `, lineMatcher) c.Assert(location.Position().LineNumber, qt.Equals, 2) c.Assert(location.LinesPos, qt.Equals, 1) c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "This is THEONE", "L2", ""}) location = locateErrorInString(`This is THEONE L2 `, lineMatcher) c.Assert(location.LinesPos, qt.Equals, 0) c.Assert(location.Lines, qt.DeepEquals, []string{"This is THEONE", "L2", ""}) location = locateErrorInString(`L1 This THEONE `, lineMatcher) c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "This THEONE", ""}) c.Assert(location.LinesPos, qt.Equals, 1) location = locateErrorInString(`L1 L2 This THEONE `, lineMatcher) c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "L2", "This THEONE", ""}) c.Assert(location.LinesPos, qt.Equals, 2) location = locateErrorInString("NO MATCH", lineMatcher) c.Assert(location.Position().LineNumber, qt.Equals, -1) c.Assert(location.LinesPos, qt.Equals, -1) c.Assert(len(location.Lines), qt.Equals, 0) lineMatcher = func(m LineMatcher) bool { return m.LineNumber == 6 } location = locateErrorInString(`A B C D E F G H I J`, lineMatcher) c.Assert(location.Lines, qt.DeepEquals, []string{"D", "E", "F", "G", "H"}) c.Assert(location.Position().LineNumber, qt.Equals, 6) c.Assert(location.LinesPos, qt.Equals, 2) // Test match EOF lineMatcher = func(m LineMatcher) bool { return m.LineNumber == 4 } location = locateErrorInString(`A B C `, lineMatcher) c.Assert(location.Lines, qt.DeepEquals, []string{"B", "C", ""}) c.Assert(location.Position().LineNumber, qt.Equals, 4) c.Assert(location.LinesPos, qt.Equals, 2) offsetMatcher := func(m LineMatcher) bool { return m.Offset == 1 } location = locateErrorInString(`A B C D E`, offsetMatcher) c.Assert(location.Lines, qt.DeepEquals, []string{"A", "B", "C", "D"}) c.Assert(location.Position().LineNumber, qt.Equals, 2) c.Assert(location.LinesPos, qt.Equals, 1) } hugo-0.92.2/common/herrors/errors.go000066400000000000000000000053241420147000300173600ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package herrors contains common Hugo errors and error related utilities. package herrors import ( "bytes" "errors" "fmt" "io" "os" "runtime" "runtime/debug" "strconv" _errors "github.com/pkg/errors" ) // As defined in https://godoc.org/github.com/pkg/errors type causer interface { Cause() error } type stackTracer interface { StackTrace() _errors.StackTrace } // PrintStackTraceFromErr prints the error's stack trace to stdoud. func PrintStackTraceFromErr(err error) { FprintStackTraceFromErr(os.Stdout, err) } // FprintStackTraceFromErr prints the error's stack trace to w. func FprintStackTraceFromErr(w io.Writer, err error) { if err, ok := err.(stackTracer); ok { for _, f := range err.StackTrace() { fmt.Fprintf(w, "%+s:%d\n", f, f) } } } // PrintStackTrace prints the current stacktrace to w. func PrintStackTrace(w io.Writer) { buf := make([]byte, 1<<16) runtime.Stack(buf, true) fmt.Fprintf(w, "%s", buf) } // ErrorSender is a, typically, non-blocking error handler. type ErrorSender interface { SendError(err error) } // Recover is a helper function that can be used to capture panics. // Put this at the top of a method/function that crashes in a template: // defer herrors.Recover() func Recover(args ...interface{}) { if r := recover(); r != nil { fmt.Println("ERR:", r) args = append(args, "stacktrace from panic: \n"+string(debug.Stack()), "\n") fmt.Println(args...) } } // Get the current goroutine id. Used only for debugging. func GetGID() uint64 { b := make([]byte, 64) b = b[:runtime.Stack(b, false)] b = bytes.TrimPrefix(b, []byte("goroutine ")) b = b[:bytes.IndexByte(b, ' ')] n, _ := strconv.ParseUint(string(b), 10, 64) return n } // ErrFeatureNotAvailable denotes that a feature is unavailable. // // We will, at least to begin with, make some Hugo features (SCSS with libsass) optional, // and this error is used to signal those situations. var ErrFeatureNotAvailable = errors.New("this feature is not available in your current Hugo version, see https://goo.gl/YMrWcn for more information") // Must panics if err != nil. func Must(err error) { if err != nil { panic(err) } } hugo-0.92.2/common/herrors/file_error.go000066400000000000000000000064231420147000300201750ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package herrors import ( "encoding/json" "github.com/gohugoio/hugo/common/text" "github.com/pkg/errors" ) var _ causer = (*fileError)(nil) // FileError represents an error when handling a file: Parsing a config file, // execute a template etc. type FileError interface { error text.Positioner // A string identifying the type of file, e.g. JSON, TOML, markdown etc. Type() string } var _ FileError = (*fileError)(nil) type fileError struct { position text.Position fileType string cause error } // Position returns the text position of this error. func (e fileError) Position() text.Position { return e.position } func (e *fileError) Type() string { return e.fileType } func (e *fileError) Error() string { if e.cause == nil { return "" } return e.cause.Error() } func (f *fileError) Cause() error { return f.cause } // NewFileError creates a new FileError. func NewFileError(fileType string, offset, lineNumber, columnNumber int, err error) FileError { pos := text.Position{Offset: offset, LineNumber: lineNumber, ColumnNumber: columnNumber} return &fileError{cause: err, fileType: fileType, position: pos} } // UnwrapFileError tries to unwrap a FileError from err. // It returns nil if this is not possible. func UnwrapFileError(err error) FileError { for err != nil { switch v := err.(type) { case FileError: return v case causer: err = v.Cause() default: return nil } } return nil } // ToFileErrorWithOffset will return a new FileError with a line number // with the given offset from the original. func ToFileErrorWithOffset(fe FileError, offset int) FileError { pos := fe.Position() return ToFileErrorWithLineNumber(fe, pos.LineNumber+offset) } // ToFileErrorWithOffset will return a new FileError with the given line number. func ToFileErrorWithLineNumber(fe FileError, lineNumber int) FileError { pos := fe.Position() pos.LineNumber = lineNumber return &fileError{cause: fe, fileType: fe.Type(), position: pos} } // ToFileError will convert the given error to an error supporting // the FileError interface. func ToFileError(fileType string, err error) FileError { for _, handle := range lineNumberExtractors { lno, col := handle(err) offset, typ := extractOffsetAndType(err) if fileType == "" { fileType = typ } if lno > 0 || offset != -1 { return NewFileError(fileType, offset, lno, col, err) } } // Fall back to the pointing to line number 1. return NewFileError(fileType, -1, 1, 1, err) } func extractOffsetAndType(e error) (int, string) { e = errors.Cause(e) switch v := e.(type) { case *json.UnmarshalTypeError: return int(v.Offset), "json" case *json.SyntaxError: return int(v.Offset), "json" default: return -1, "" } } hugo-0.92.2/common/herrors/file_error_test.go000066400000000000000000000035051420147000300212320ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package herrors import ( "testing" "github.com/pkg/errors" qt "github.com/frankban/quicktest" ) func TestToLineNumberError(t *testing.T) { t.Parallel() c := qt.New(t) for i, test := range []struct { in error offset int lineNumber int columnNumber int }{ {errors.New("no line number for you"), 0, 1, 1}, {errors.New(`template: _default/single.html:4:15: executing "_default/single.html" at <.Titles>: can't evaluate field Titles in type *hugolib.PageOutput`), 0, 4, 15}, {errors.New("parse failed: template: _default/bundle-resource-meta.html:11: unexpected in operand"), 0, 11, 1}, {errors.New(`failed:: template: _default/bundle-resource-meta.html:2:7: executing "main" at <.Titles>`), 0, 2, 7}, {errors.New(`failed to load translations: (6, 7): was expecting token =, but got "g" instead`), 0, 6, 7}, } { got := ToFileError("template", test.in) errMsg := qt.Commentf("[%d][%T]", i, got) le, ok := got.(FileError) c.Assert(ok, qt.Equals, true) c.Assert(ok, qt.Equals, true, errMsg) pos := le.Position() c.Assert(pos.LineNumber, qt.Equals, test.lineNumber, errMsg) c.Assert(pos.ColumnNumber, qt.Equals, test.columnNumber, errMsg) c.Assert(errors.Cause(got), qt.Not(qt.IsNil)) } } hugo-0.92.2/common/herrors/line_number_extractors.go000066400000000000000000000035221420147000300226170ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package herrors import ( "regexp" "strconv" "github.com/pkg/errors" "github.com/pelletier/go-toml/v2" ) var lineNumberExtractors = []lineNumberExtractor{ // Template/shortcode parse errors newLineNumberErrHandlerFromRegexp(".*:(\\d+):(\\d*):"), newLineNumberErrHandlerFromRegexp(".*:(\\d+):"), // TOML parse errors tomlLineNumberExtractor, // YAML parse errors newLineNumberErrHandlerFromRegexp("line (\\d+):"), // i18n bundle errors newLineNumberErrHandlerFromRegexp("\\((\\d+),\\s(\\d*)"), } type lineNumberExtractor func(e error) (int, int) var tomlLineNumberExtractor = func(e error) (int, int) { e = errors.Cause(e) if terr, ok := e.(*toml.DecodeError); ok { return terr.Position() } return -1, -1 } func newLineNumberErrHandlerFromRegexp(expression string) lineNumberExtractor { re := regexp.MustCompile(expression) return extractLineNo(re) } func extractLineNo(re *regexp.Regexp) lineNumberExtractor { return func(e error) (int, int) { if e == nil { panic("no error") } col := 1 s := e.Error() m := re.FindStringSubmatch(s) if len(m) >= 2 { lno, _ := strconv.Atoi(m[1]) if len(m) > 2 { col, _ = strconv.Atoi(m[2]) } if col <= 0 { col = 1 } return lno, col } return -1, col } } hugo-0.92.2/common/hexec/000077500000000000000000000000001420147000300151215ustar00rootroot00000000000000hugo-0.92.2/common/hexec/exec.go000066400000000000000000000137311420147000300164010ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hexec import ( "bytes" "context" "errors" "fmt" "io" "regexp" "strings" "os" "os/exec" "github.com/cli/safeexec" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config/security" ) var WithDir = func(dir string) func(c *commandeer) { return func(c *commandeer) { c.dir = dir } } var WithContext = func(ctx context.Context) func(c *commandeer) { return func(c *commandeer) { c.ctx = ctx } } var WithStdout = func(w io.Writer) func(c *commandeer) { return func(c *commandeer) { c.stdout = w } } var WithStderr = func(w io.Writer) func(c *commandeer) { return func(c *commandeer) { c.stderr = w } } var WithStdin = func(r io.Reader) func(c *commandeer) { return func(c *commandeer) { c.stdin = r } } var WithEnviron = func(env []string) func(c *commandeer) { return func(c *commandeer) { setOrAppend := func(s string) { k1, _ := config.SplitEnvVar(s) var found bool for i, v := range c.env { k2, _ := config.SplitEnvVar(v) if k1 == k2 { found = true c.env[i] = s } } if !found { c.env = append(c.env, s) } } for _, s := range env { setOrAppend(s) } } } // New creates a new Exec using the provided security config. func New(cfg security.Config) *Exec { var baseEnviron []string for _, v := range os.Environ() { k, _ := config.SplitEnvVar(v) if cfg.Exec.OsEnv.Accept(k) { baseEnviron = append(baseEnviron, v) } } return &Exec{ sc: cfg, baseEnviron: baseEnviron, } } // IsNotFound reports whether this is an error about a binary not found. func IsNotFound(err error) bool { var notFoundErr *NotFoundError return errors.As(err, ¬FoundErr) } // SafeCommand is a wrapper around os/exec Command which uses a LookPath // implementation that does not search in current directory before looking in PATH. // See https://github.com/cli/safeexec and the linked issues. func SafeCommand(name string, arg ...string) (*exec.Cmd, error) { bin, err := safeexec.LookPath(name) if err != nil { return nil, err } return exec.Command(bin, arg...), nil } // Exec encorces a security policy for commands run via os/exec. type Exec struct { sc security.Config // os.Environ filtered by the Exec.OsEnviron whitelist filter. baseEnviron []string } // New will fail if name is not allowed according to the configured security policy. // Else a configured Runner will be returned ready to be Run. func (e *Exec) New(name string, arg ...interface{}) (Runner, error) { if err := e.sc.CheckAllowedExec(name); err != nil { return nil, err } env := make([]string, len(e.baseEnviron)) copy(env, e.baseEnviron) cm := &commandeer{ name: name, env: env, } return cm.command(arg...) } // Npx is a convenience method to create a Runner running npx --no-install 0 case reflect.Bool: truth = val.Bool() case reflect.Complex64, reflect.Complex128: truth = val.Complex() != 0 case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface: truth = !val.IsNil() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: truth = val.Int() != 0 case reflect.Float32, reflect.Float64: truth = val.Float() != 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: truth = val.Uint() != 0 case reflect.Struct: truth = true // Struct values are always true. default: return } return } // Based on: https://github.com/golang/go/blob/178a2c42254166cffed1b25fb1d3c7a5727cada6/src/text/template/exec.go#L931 func indirectInterface(v reflect.Value) reflect.Value { if v.Kind() != reflect.Interface { return v } if v.IsNil() { return reflect.Value{} } return v.Elem() } hugo-0.92.2/common/hreflect/helpers_test.go000066400000000000000000000021611420147000300206510ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hreflect import ( "reflect" "testing" "time" qt "github.com/frankban/quicktest" ) func TestIsTruthful(t *testing.T) { c := qt.New(t) c.Assert(IsTruthful(true), qt.Equals, true) c.Assert(IsTruthful(false), qt.Equals, false) c.Assert(IsTruthful(time.Now()), qt.Equals, true) c.Assert(IsTruthful(time.Time{}), qt.Equals, false) } func BenchmarkIsTruthFul(b *testing.B) { v := reflect.ValueOf("Hugo") b.ResetTimer() for i := 0; i < b.N; i++ { if !IsTruthfulValue(v) { b.Fatal("not truthful") } } } hugo-0.92.2/common/htime/000077500000000000000000000000001420147000300151335ustar00rootroot00000000000000hugo-0.92.2/common/htime/time.go000066400000000000000000000062351420147000300164260ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package htime import ( "strings" "time" "github.com/spf13/cast" toml "github.com/pelletier/go-toml/v2" "github.com/gohugoio/locales" ) var ( longDayNames = []string{ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", } shortDayNames = []string{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", } shortMonthNames = []string{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", } longMonthNames = []string{ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", } ) func NewTimeFormatter(ltr locales.Translator) TimeFormatter { if ltr == nil { panic("must provide a locales.Translator") } return TimeFormatter{ ltr: ltr, } } // TimeFormatter is locale aware. type TimeFormatter struct { ltr locales.Translator } func (f TimeFormatter) Format(t time.Time, layout string) string { if layout == "" { return "" } if layout[0] == ':' { // It may be one of Hugo's custom layouts. switch strings.ToLower(layout[1:]) { case "date_full": return f.ltr.FmtDateFull(t) case "date_long": return f.ltr.FmtDateLong(t) case "date_medium": return f.ltr.FmtDateMedium(t) case "date_short": return f.ltr.FmtDateShort(t) case "time_full": return f.ltr.FmtTimeFull(t) case "time_long": return f.ltr.FmtTimeLong(t) case "time_medium": return f.ltr.FmtTimeMedium(t) case "time_short": return f.ltr.FmtTimeShort(t) } } s := t.Format(layout) monthIdx := t.Month() - 1 // Month() starts at 1. dayIdx := t.Weekday() s = strings.ReplaceAll(s, longMonthNames[monthIdx], f.ltr.MonthWide(t.Month())) if !strings.Contains(s, f.ltr.MonthWide(t.Month())) { s = strings.ReplaceAll(s, shortMonthNames[monthIdx], f.ltr.MonthAbbreviated(t.Month())) } s = strings.ReplaceAll(s, longDayNames[dayIdx], f.ltr.WeekdayWide(t.Weekday())) if !strings.Contains(s, f.ltr.WeekdayWide(t.Weekday())) { s = strings.ReplaceAll(s, shortDayNames[dayIdx], f.ltr.WeekdayAbbreviated(t.Weekday())) } return s } func ToTimeInDefaultLocationE(i interface{}, location *time.Location) (tim time.Time, err error) { switch vv := i.(type) { case toml.LocalDate: return vv.AsTime(location), nil case toml.LocalDateTime: return vv.AsTime(location), nil // issue #8895 // datetimes parsed by `go-toml` have empty zone name // convert back them into string and use `cast` case time.Time: i = vv.Format(time.RFC3339) } return cast.ToTimeInDefaultLocationE(i, location) } hugo-0.92.2/common/htime/time_test.go000066400000000000000000000122241420147000300174600ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package htime import ( "testing" "time" qt "github.com/frankban/quicktest" translators "github.com/gohugoio/localescompressed" ) func TestTimeFormatter(t *testing.T) { c := qt.New(t) june06, _ := time.Parse("2006-Jan-02", "2018-Jun-06") june06 = june06.Add(7777 * time.Second) jan06, _ := time.Parse("2006-Jan-02", "2018-Jan-06") jan06 = jan06.Add(32 * time.Second) mondayNovemberFirst, _ := time.Parse("2006-Jan-02", "2021-11-01") mondayNovemberFirst = mondayNovemberFirst.Add(33 * time.Second) c.Run("Norsk nynorsk", func(c *qt.C) { f := NewTimeFormatter(translators.GetTranslator("nn")) c.Assert(f.Format(june06, "Monday Jan 2 2006"), qt.Equals, "onsdag juni 6 2018") c.Assert(f.Format(june06, "Mon January 2 2006"), qt.Equals, "on. juni 6 2018") c.Assert(f.Format(june06, "Mon Mon"), qt.Equals, "on. on.") }) c.Run("Custom layouts Norsk nynorsk", func(c *qt.C) { f := NewTimeFormatter(translators.GetTranslator("nn")) c.Assert(f.Format(june06, ":date_full"), qt.Equals, "onsdag 6. juni 2018") c.Assert(f.Format(june06, ":date_long"), qt.Equals, "6. juni 2018") c.Assert(f.Format(june06, ":date_medium"), qt.Equals, "6. juni 2018") c.Assert(f.Format(june06, ":date_short"), qt.Equals, "06.06.2018") c.Assert(f.Format(june06, ":time_full"), qt.Equals, "kl. 02:09:37 UTC") c.Assert(f.Format(june06, ":time_long"), qt.Equals, "02:09:37 UTC") c.Assert(f.Format(june06, ":time_medium"), qt.Equals, "02:09:37") c.Assert(f.Format(june06, ":time_short"), qt.Equals, "02:09") }) c.Run("Custom layouts English", func(c *qt.C) { f := NewTimeFormatter(translators.GetTranslator("en")) c.Assert(f.Format(june06, ":date_full"), qt.Equals, "Wednesday, June 6, 2018") c.Assert(f.Format(june06, ":date_long"), qt.Equals, "June 6, 2018") c.Assert(f.Format(june06, ":date_medium"), qt.Equals, "Jun 6, 2018") c.Assert(f.Format(june06, ":date_short"), qt.Equals, "6/6/18") c.Assert(f.Format(june06, ":time_full"), qt.Equals, "2:09:37 am UTC") c.Assert(f.Format(june06, ":time_long"), qt.Equals, "2:09:37 am UTC") c.Assert(f.Format(june06, ":time_medium"), qt.Equals, "2:09:37 am") c.Assert(f.Format(june06, ":time_short"), qt.Equals, "2:09 am") }) c.Run("English", func(c *qt.C) { f := NewTimeFormatter(translators.GetTranslator("en")) c.Assert(f.Format(june06, "Monday Jan 2 2006"), qt.Equals, "Wednesday Jun 6 2018") c.Assert(f.Format(june06, "Mon January 2 2006"), qt.Equals, "Wed June 6 2018") c.Assert(f.Format(june06, "Mon Mon"), qt.Equals, "Wed Wed") }) c.Run("Weekdays German", func(c *qt.C) { tr := translators.GetTranslator("de") f := NewTimeFormatter(tr) // Issue #9107 for i, weekDayWideGerman := range []string{"Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"} { date := mondayNovemberFirst.Add(time.Duration(i*24) * time.Hour) c.Assert(tr.WeekdayWide(date.Weekday()), qt.Equals, weekDayWideGerman) c.Assert(f.Format(date, "Monday"), qt.Equals, weekDayWideGerman) } for i, weekDayAbbreviatedGerman := range []string{"Mo.", "Di.", "Mi.", "Do.", "Fr.", "Sa.", "So."} { date := mondayNovemberFirst.Add(time.Duration(i*24) * time.Hour) c.Assert(tr.WeekdayAbbreviated(date.Weekday()), qt.Equals, weekDayAbbreviatedGerman) c.Assert(f.Format(date, "Mon"), qt.Equals, weekDayAbbreviatedGerman) } }) c.Run("Months German", func(c *qt.C) { tr := translators.GetTranslator("de") f := NewTimeFormatter(tr) // Issue #9107 for i, monthWideNorway := range []string{"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli"} { date := jan06.Add(time.Duration(i*24*31) * time.Hour) c.Assert(tr.MonthWide(date.Month()), qt.Equals, monthWideNorway) c.Assert(f.Format(date, "January"), qt.Equals, monthWideNorway) } }) } func BenchmarkTimeFormatter(b *testing.B) { june06, _ := time.Parse("2006-Jan-02", "2018-Jun-06") b.Run("Native", func(b *testing.B) { for i := 0; i < b.N; i++ { got := june06.Format("Monday Jan 2 2006") if got != "Wednesday Jun 6 2018" { b.Fatalf("invalid format, got %q", got) } } }) b.Run("Localized", func(b *testing.B) { f := NewTimeFormatter(translators.GetTranslator("nn")) b.ResetTimer() for i := 0; i < b.N; i++ { got := f.Format(june06, "Monday Jan 2 2006") if got != "onsdag juni 6 2018" { b.Fatalf("invalid format, got %q", got) } } }) b.Run("Localized Custom", func(b *testing.B) { f := NewTimeFormatter(translators.GetTranslator("nn")) b.ResetTimer() for i := 0; i < b.N; i++ { got := f.Format(june06, ":date_medium") if got != "6. juni 2018" { b.Fatalf("invalid format, got %q", got) } } }) } hugo-0.92.2/common/hugio/000077500000000000000000000000001420147000300151405ustar00rootroot00000000000000hugo-0.92.2/common/hugio/copy.go000066400000000000000000000036621420147000300164500ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugio import ( "io" "io/ioutil" "os" "path/filepath" "github.com/pkg/errors" "github.com/spf13/afero" ) // CopyFile copies a file. func CopyFile(fs afero.Fs, from, to string) error { sf, err := fs.Open(from) if err != nil { return err } defer sf.Close() df, err := fs.Create(to) if err != nil { return err } defer df.Close() _, err = io.Copy(df, sf) if err != nil { return err } si, err := fs.Stat(from) if err != nil { err = fs.Chmod(to, si.Mode()) if err != nil { return err } } return nil } // CopyDir copies a directory. func CopyDir(fs afero.Fs, from, to string, shouldCopy func(filename string) bool) error { fi, err := os.Stat(from) if err != nil { return err } if !fi.IsDir() { return errors.Errorf("%q is not a directory", from) } err = fs.MkdirAll(to, 0777) // before umask if err != nil { return err } entries, _ := ioutil.ReadDir(from) for _, entry := range entries { fromFilename := filepath.Join(from, entry.Name()) toFilename := filepath.Join(to, entry.Name()) if entry.IsDir() { if shouldCopy != nil && !shouldCopy(fromFilename) { continue } if err := CopyDir(fs, fromFilename, toFilename, shouldCopy); err != nil { return err } } else { if err := CopyFile(fs, fromFilename, toFilename); err != nil { return err } } } return nil } hugo-0.92.2/common/hugio/readers.go000066400000000000000000000034741420147000300171240ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugio import ( "io" "strings" ) // ReadSeeker wraps io.Reader and io.Seeker. type ReadSeeker interface { io.Reader io.Seeker } // ReadSeekCloser is implemented by afero.File. We use this as the common type for // content in Resource objects, even for strings. type ReadSeekCloser interface { ReadSeeker io.Closer } // ReadSeekCloserProvider provides a ReadSeekCloser. type ReadSeekCloserProvider interface { ReadSeekCloser() (ReadSeekCloser, error) } // ReadSeekerNoOpCloser implements ReadSeekCloser by doing nothing in Close. // TODO(bep) rename this and similar to ReadSeekerNopCloser, naming used in stdlib, which kind of makes sense. type ReadSeekerNoOpCloser struct { ReadSeeker } // Close does nothing. func (r ReadSeekerNoOpCloser) Close() error { return nil } // NewReadSeekerNoOpCloser creates a new ReadSeekerNoOpCloser with the given ReadSeeker. func NewReadSeekerNoOpCloser(r ReadSeeker) ReadSeekerNoOpCloser { return ReadSeekerNoOpCloser{r} } // NewReadSeekerNoOpCloserFromString uses strings.NewReader to create a new ReadSeekerNoOpCloser // from the given string. func NewReadSeekerNoOpCloserFromString(content string) ReadSeekerNoOpCloser { return ReadSeekerNoOpCloser{strings.NewReader(content)} } hugo-0.92.2/common/hugio/writers.go000066400000000000000000000036221420147000300171710ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugio import ( "io" "io/ioutil" ) type multiWriteCloser struct { io.Writer closers []io.WriteCloser } func (m multiWriteCloser) Close() error { var err error for _, c := range m.closers { if closeErr := c.Close(); err != nil { err = closeErr } } return err } // NewMultiWriteCloser creates a new io.WriteCloser that duplicates its writes to all the // provided writers. func NewMultiWriteCloser(writeClosers ...io.WriteCloser) io.WriteCloser { writers := make([]io.Writer, len(writeClosers)) for i, w := range writeClosers { writers[i] = w } return multiWriteCloser{Writer: io.MultiWriter(writers...), closers: writeClosers} } // ToWriteCloser creates an io.WriteCloser from the given io.Writer. // If it's not already, one will be created with a Close method that does nothing. func ToWriteCloser(w io.Writer) io.WriteCloser { if rw, ok := w.(io.WriteCloser); ok { return rw } return struct { io.Writer io.Closer }{ w, ioutil.NopCloser(nil), } } // ToReadCloser creates an io.ReadCloser from the given io.Reader. // If it's not already, one will be created with a Close method that does nothing. func ToReadCloser(r io.Reader) io.ReadCloser { if rc, ok := r.(io.ReadCloser); ok { return rc } return struct { io.Reader io.Closer }{ r, ioutil.NopCloser(nil), } } hugo-0.92.2/common/hugo/000077500000000000000000000000001420147000300147675ustar00rootroot00000000000000hugo-0.92.2/common/hugo/hugo.go000066400000000000000000000116561420147000300162710ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugo import ( "fmt" "html/template" "os" "path/filepath" "runtime/debug" "sort" "strings" "time" "github.com/gohugoio/hugo/hugofs/files" "github.com/spf13/afero" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/hugofs" ) const ( EnvironmentDevelopment = "development" EnvironmentProduction = "production" ) var ( // commitHash contains the current Git revision. // Use mage to build to make sure this gets set. commitHash string // buildDate contains the date of the current build. buildDate string // vendorInfo contains vendor notes about the current build. vendorInfo string ) // Info contains information about the current Hugo environment type Info struct { CommitHash string BuildDate string // The build environment. // Defaults are "production" (hugo) and "development" (hugo server). // This can also be set by the user. // It can be any string, but it will be all lower case. Environment string deps []*Dependency } // Version returns the current version as a comparable version string. func (i Info) Version() VersionString { return CurrentVersion.Version() } // Generator a Hugo meta generator HTML tag. func (i Info) Generator() template.HTML { return template.HTML(fmt.Sprintf(``, CurrentVersion.String())) } func (i Info) IsProduction() bool { return i.Environment == EnvironmentProduction } func (i Info) IsExtended() bool { return IsExtended } // Deps gets a list of dependencies for this Hugo build. func (i Info) Deps() []*Dependency { return i.deps } // NewInfo creates a new Hugo Info object. func NewInfo(environment string, deps []*Dependency) Info { if environment == "" { environment = EnvironmentProduction } return Info{ CommitHash: commitHash, BuildDate: buildDate, Environment: environment, deps: deps, } } // GetExecEnviron creates and gets the common os/exec environment used in the // external programs we interact with via os/exec, e.g. postcss. func GetExecEnviron(workDir string, cfg config.Provider, fs afero.Fs) []string { var env []string nodepath := filepath.Join(workDir, "node_modules") if np := os.Getenv("NODE_PATH"); np != "" { nodepath = workDir + string(os.PathListSeparator) + np } config.SetEnvVars(&env, "NODE_PATH", nodepath) config.SetEnvVars(&env, "PWD", workDir) config.SetEnvVars(&env, "HUGO_ENVIRONMENT", cfg.GetString("environment")) config.SetEnvVars(&env, "HUGO_ENV", cfg.GetString("environment")) if fs != nil { fis, err := afero.ReadDir(fs, files.FolderJSConfig) if err == nil { for _, fi := range fis { key := fmt.Sprintf("HUGO_FILE_%s", strings.ReplaceAll(strings.ToUpper(fi.Name()), ".", "_")) value := fi.(hugofs.FileMetaInfo).Meta().Filename config.SetEnvVars(&env, key, value) } } } return env } // GetDependencyList returns a sorted dependency list on the format package="version". // It includes both Go dependencies and (a manually maintained) list of C(++) dependencies. func GetDependencyList() []string { var deps []string formatDep := func(path, version string) string { return fmt.Sprintf("%s=%q", path, version) } if IsExtended { deps = append( deps, // TODO(bep) consider adding a DepsNonGo() method to these upstream projects. formatDep("github.com/sass/libsass", "3.6.5"), formatDep("github.com/webmproject/libwebp", "v1.2.0"), ) } bi, ok := debug.ReadBuildInfo() if !ok { return deps } for _, dep := range bi.Deps { deps = append(deps, formatDep(dep.Path, dep.Version)) } sort.Strings(deps) return deps } // IsRunningAsTest reports whether we are running as a test. func IsRunningAsTest() bool { for _, arg := range os.Args { if strings.HasPrefix(arg, "-test") { return true } } return false } // Dependency is a single dependency, which can be either a Hugo Module or a local theme. type Dependency struct { // Returns the path to this module. // This will either be the module path, e.g. "github.com/gohugoio/myshortcodes", // or the path below your /theme folder, e.g. "mytheme". Path string // The module version. Version string // Whether this dependency is vendored. Vendor bool // Time version was created. Time time.Time // In the dependency tree, this is the first module that defines this module // as a dependency. Owner *Dependency // Replaced by this dependency. Replace *Dependency } hugo-0.92.2/common/hugo/hugo_test.go000066400000000000000000000026001420147000300173150ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugo import ( "fmt" "testing" qt "github.com/frankban/quicktest" ) func TestHugoInfo(t *testing.T) { c := qt.New(t) hugoInfo := NewInfo("", nil) c.Assert(hugoInfo.Version(), qt.Equals, CurrentVersion.Version()) c.Assert(fmt.Sprintf("%T", VersionString("")), qt.Equals, fmt.Sprintf("%T", hugoInfo.Version())) c.Assert(hugoInfo.CommitHash, qt.Equals, commitHash) c.Assert(hugoInfo.BuildDate, qt.Equals, buildDate) c.Assert(hugoInfo.Environment, qt.Equals, "production") c.Assert(string(hugoInfo.Generator()), qt.Contains, fmt.Sprintf("Hugo %s", hugoInfo.Version())) c.Assert(hugoInfo.IsProduction(), qt.Equals, true) c.Assert(hugoInfo.IsExtended(), qt.Equals, IsExtended) devHugoInfo := NewInfo("development", nil) c.Assert(devHugoInfo.IsProduction(), qt.Equals, false) } hugo-0.92.2/common/hugo/vars_extended.go000066400000000000000000000012311420147000300201460ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build extended package hugo var IsExtended = true hugo-0.92.2/common/hugo/vars_regular.go000066400000000000000000000012331420147000300200110ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build !extended package hugo var IsExtended = false hugo-0.92.2/common/hugo/version.go000066400000000000000000000141031420147000300170020ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugo import ( "fmt" "io" "runtime" "strings" "github.com/gohugoio/hugo/compare" "github.com/spf13/cast" ) // Version represents the Hugo build version. type Version struct { // Major and minor version. Number float32 // Increment this for bug releases PatchLevel int // HugoVersionSuffix is the suffix used in the Hugo version string. // It will be blank for release versions. Suffix string } var ( _ compare.Eqer = (*VersionString)(nil) _ compare.Comparer = (*VersionString)(nil) ) func (v Version) String() string { return version(v.Number, v.PatchLevel, v.Suffix) } // Version returns the Hugo version. func (v Version) Version() VersionString { return VersionString(v.String()) } // VersionString represents a Hugo version string. type VersionString string func (h VersionString) String() string { return string(h) } // Compare implements the compare.Comparer interface. func (h VersionString) Compare(other interface{}) int { v := MustParseVersion(h.String()) return compareVersionsWithSuffix(v.Number, v.PatchLevel, v.Suffix, other) } // Eq implements the compare.Eqer interface. func (h VersionString) Eq(other interface{}) bool { s, err := cast.ToStringE(other) if err != nil { return false } return s == h.String() } var versionSuffixes = []string{"-test", "-DEV"} // ParseVersion parses a version string. func ParseVersion(s string) (Version, error) { var vv Version for _, suffix := range versionSuffixes { if strings.HasSuffix(s, suffix) { vv.Suffix = suffix s = strings.TrimSuffix(s, suffix) } } v, p := parseVersion(s) vv.Number = v vv.PatchLevel = p return vv, nil } // MustParseVersion parses a version string // and panics if any error occurs. func MustParseVersion(s string) Version { vv, err := ParseVersion(s) if err != nil { panic(err) } return vv } // ReleaseVersion represents the release version. func (v Version) ReleaseVersion() Version { v.Suffix = "" return v } // Next returns the next Hugo release version. func (v Version) Next() Version { return Version{Number: v.Number + 0.01} } // Prev returns the previous Hugo release version. func (v Version) Prev() Version { return Version{Number: v.Number - 0.01} } // NextPatchLevel returns the next patch/bugfix Hugo version. // This will be a patch increment on the previous Hugo version. func (v Version) NextPatchLevel(level int) Version { return Version{Number: v.Number - 0.01, PatchLevel: level} } // BuildVersionString creates a version string. This is what you see when // running "hugo version". func BuildVersionString() string { // program := "Hugo Static Site Generator" program := "hugo" version := "v" + CurrentVersion.String() if commitHash != "" { version += "-" + strings.ToUpper(commitHash) } if IsExtended { version += "+extended" } osArch := runtime.GOOS + "/" + runtime.GOARCH date := buildDate if date == "" { date = "unknown" } versionString := fmt.Sprintf("%s %s %s BuildDate=%s", program, version, osArch, date) if vendorInfo != "" { versionString += " VendorInfo=" + vendorInfo } return versionString } func version(version float32, patchVersion int, suffix string) string { if patchVersion > 0 || version > 0.53 { return fmt.Sprintf("%.2f.%d%s", version, patchVersion, suffix) } return fmt.Sprintf("%.2f%s", version, suffix) } // CompareVersion compares the given version string or number against the // running Hugo version. // It returns -1 if the given version is less than, 0 if equal and 1 if greater than // the running version. func CompareVersion(version interface{}) int { return compareVersionsWithSuffix(CurrentVersion.Number, CurrentVersion.PatchLevel, CurrentVersion.Suffix, version) } func compareVersions(inVersion float32, inPatchVersion int, in interface{}) int { return compareVersionsWithSuffix(inVersion, inPatchVersion, "", in) } func compareVersionsWithSuffix(inVersion float32, inPatchVersion int, suffix string, in interface{}) int { var c int switch d := in.(type) { case float64: c = compareFloatVersions(inVersion, float32(d)) case float32: c = compareFloatVersions(inVersion, d) case int: c = compareFloatVersions(inVersion, float32(d)) case int32: c = compareFloatVersions(inVersion, float32(d)) case int64: c = compareFloatVersions(inVersion, float32(d)) default: s, err := cast.ToStringE(in) if err != nil { return -1 } v, err := ParseVersion(s) if err != nil { return -1 } if v.Number == inVersion && v.PatchLevel == inPatchVersion { return strings.Compare(suffix, v.Suffix) } if v.Number < inVersion || (v.Number == inVersion && v.PatchLevel < inPatchVersion) { return -1 } return 1 } if c == 0 && suffix != "" { return 1 } return c } func parseVersion(s string) (float32, int) { var ( v float32 p int ) if strings.Count(s, ".") == 2 { li := strings.LastIndex(s, ".") p = cast.ToInt(s[li+1:]) s = s[:li] } v = float32(cast.ToFloat64(s)) return v, p } func compareFloatVersions(version float32, v float32) int { if v == version { return 0 } if v < version { return -1 } return 1 } func GoMinorVersion() int { return goMinorVersion(runtime.Version()) } func goMinorVersion(version string) int { if strings.HasPrefix(version, "devel") { return 9999 // magic } var major, minor int var trailing string n, err := fmt.Sscanf(version, "go%d.%d%s", &major, &minor, &trailing) if n == 2 && err == io.EOF { // Means there were no trailing characters (i.e., not an alpha/beta) err = nil } if err != nil { return 0 } return minor } hugo-0.92.2/common/hugo/version_current.go000066400000000000000000000014331420147000300205460ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugo // CurrentVersion represents the current build version. // This should be the only one. var CurrentVersion = Version{ Number: 0.92, PatchLevel: 2, Suffix: "", } hugo-0.92.2/common/hugo/version_test.go000066400000000000000000000071021420147000300200420ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugo import ( "testing" qt "github.com/frankban/quicktest" ) func TestHugoVersion(t *testing.T) { c := qt.New(t) c.Assert(version(0.15, 0, "-DEV"), qt.Equals, "0.15-DEV") c.Assert(version(0.15, 2, "-DEV"), qt.Equals, "0.15.2-DEV") v := Version{Number: 0.21, PatchLevel: 0, Suffix: "-DEV"} c.Assert(v.ReleaseVersion().String(), qt.Equals, "0.21") c.Assert(v.String(), qt.Equals, "0.21-DEV") c.Assert(v.Next().String(), qt.Equals, "0.22") nextVersionString := v.Next().Version() c.Assert(nextVersionString.String(), qt.Equals, "0.22") c.Assert(nextVersionString.Eq("0.22"), qt.Equals, true) c.Assert(nextVersionString.Eq("0.21"), qt.Equals, false) c.Assert(nextVersionString.Eq(nextVersionString), qt.Equals, true) c.Assert(v.NextPatchLevel(3).String(), qt.Equals, "0.20.3") // We started to use full semver versions even for main // releases in v0.54.0 v = Version{Number: 0.53, PatchLevel: 0} c.Assert(v.String(), qt.Equals, "0.53") c.Assert(v.Next().String(), qt.Equals, "0.54.0") c.Assert(v.Next().Next().String(), qt.Equals, "0.55.0") v = Version{Number: 0.54, PatchLevel: 0, Suffix: "-DEV"} c.Assert(v.String(), qt.Equals, "0.54.0-DEV") } func TestCompareVersions(t *testing.T) { c := qt.New(t) c.Assert(compareVersions(0.20, 0, 0.20), qt.Equals, 0) c.Assert(compareVersions(0.20, 0, float32(0.20)), qt.Equals, 0) c.Assert(compareVersions(0.20, 0, float64(0.20)), qt.Equals, 0) c.Assert(compareVersions(0.19, 1, 0.20), qt.Equals, 1) c.Assert(compareVersions(0.19, 3, "0.20.2"), qt.Equals, 1) c.Assert(compareVersions(0.19, 1, 0.01), qt.Equals, -1) c.Assert(compareVersions(0, 1, 3), qt.Equals, 1) c.Assert(compareVersions(0, 1, int32(3)), qt.Equals, 1) c.Assert(compareVersions(0, 1, int64(3)), qt.Equals, 1) c.Assert(compareVersions(0.20, 0, "0.20"), qt.Equals, 0) c.Assert(compareVersions(0.20, 1, "0.20.1"), qt.Equals, 0) c.Assert(compareVersions(0.20, 1, "0.20"), qt.Equals, -1) c.Assert(compareVersions(0.20, 0, "0.20.1"), qt.Equals, 1) c.Assert(compareVersions(0.20, 1, "0.20.2"), qt.Equals, 1) c.Assert(compareVersions(0.21, 1, "0.22.1"), qt.Equals, 1) c.Assert(compareVersions(0.22, 0, "0.22-DEV"), qt.Equals, -1) c.Assert(compareVersions(0.22, 0, "0.22.1-DEV"), qt.Equals, 1) c.Assert(compareVersionsWithSuffix(0.22, 0, "-DEV", "0.22"), qt.Equals, 1) c.Assert(compareVersionsWithSuffix(0.22, 1, "-DEV", "0.22"), qt.Equals, -1) c.Assert(compareVersionsWithSuffix(0.22, 1, "-DEV", "0.22.1-DEV"), qt.Equals, 0) } func TestParseHugoVersion(t *testing.T) { c := qt.New(t) c.Assert(MustParseVersion("0.25").String(), qt.Equals, "0.25") c.Assert(MustParseVersion("0.25.2").String(), qt.Equals, "0.25.2") c.Assert(MustParseVersion("0.25-test").String(), qt.Equals, "0.25-test") c.Assert(MustParseVersion("0.25-DEV").String(), qt.Equals, "0.25-DEV") } func TestGoMinorVersion(t *testing.T) { c := qt.New(t) c.Assert(goMinorVersion("go1.12.5"), qt.Equals, 12) c.Assert(goMinorVersion("go1.14rc1"), qt.Equals, 14) c.Assert(GoMinorVersion() >= 11, qt.Equals, true) } hugo-0.92.2/common/loggers/000077500000000000000000000000001420147000300154675ustar00rootroot00000000000000hugo-0.92.2/common/loggers/ignorableLogger.go000066400000000000000000000035211420147000300211210ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package loggers import ( "fmt" "strings" ) // IgnorableLogger is a logger that ignores certain log statements. type IgnorableLogger interface { Logger Errorsf(statementID, format string, v ...interface{}) Apply(logger Logger) IgnorableLogger } type ignorableLogger struct { Logger statements map[string]bool } // NewIgnorableLogger wraps the given logger and ignores the log statement IDs given. func NewIgnorableLogger(logger Logger, statements ...string) IgnorableLogger { statementsSet := make(map[string]bool) for _, s := range statements { statementsSet[strings.ToLower(s)] = true } return ignorableLogger{ Logger: logger, statements: statementsSet, } } // Errorsf logs statementID as an ERROR if not configured as ignoreable. func (l ignorableLogger) Errorsf(statementID, format string, v ...interface{}) { if l.statements[statementID] { // Ignore. return } ignoreMsg := fmt.Sprintf(` If you feel that this should not be logged as an ERROR, you can ignore it by adding this to your site config: ignoreErrors = [%q]`, statementID) format += ignoreMsg l.Errorf(format, v...) } func (l ignorableLogger) Apply(logger Logger) IgnorableLogger { return ignorableLogger{ Logger: logger, statements: l.statements, } } hugo-0.92.2/common/loggers/loggers.go000066400000000000000000000204051420147000300174610ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package loggers import ( "bytes" "fmt" "io" "io/ioutil" "log" "os" "regexp" "runtime" "time" "github.com/gohugoio/hugo/common/terminal" jww "github.com/spf13/jwalterweatherman" ) var ( // Counts ERROR logs to the global jww logger. GlobalErrorCounter *jww.Counter PanicOnWarning bool ) func init() { GlobalErrorCounter = &jww.Counter{} jww.SetLogListeners(jww.LogCounter(GlobalErrorCounter, jww.LevelError)) } func LoggerToWriterWithPrefix(logger *log.Logger, prefix string) io.Writer { return prefixWriter{ logger: logger, prefix: prefix, } } type prefixWriter struct { logger *log.Logger prefix string } func (w prefixWriter) Write(p []byte) (n int, err error) { w.logger.Printf("%s: %s", w.prefix, p) return len(p), nil } type Logger interface { Printf(format string, v ...interface{}) Println(v ...interface{}) PrintTimerIfDelayed(start time.Time, name string) Debug() *log.Logger Debugf(format string, v ...interface{}) Debugln(v ...interface{}) Info() *log.Logger Infof(format string, v ...interface{}) Infoln(v ...interface{}) Warn() *log.Logger Warnf(format string, v ...interface{}) Warnln(v ...interface{}) Error() *log.Logger Errorf(format string, v ...interface{}) Errorln(v ...interface{}) Errors() string Out() io.Writer Reset() // Used in tests. LogCounters() *LogCounters } type LogCounters struct { ErrorCounter *jww.Counter WarnCounter *jww.Counter } type logger struct { *jww.Notepad // The writer that represents stdout. // Will be ioutil.Discard when in quiet mode. out io.Writer logCounters *LogCounters // This is only set in server mode. errors *bytes.Buffer } func (l *logger) Printf(format string, v ...interface{}) { l.FEEDBACK.Printf(format, v...) } func (l *logger) Println(v ...interface{}) { l.FEEDBACK.Println(v...) } func (l *logger) Debug() *log.Logger { return l.DEBUG } func (l *logger) Debugf(format string, v ...interface{}) { l.DEBUG.Printf(format, v...) } func (l *logger) Debugln(v ...interface{}) { l.DEBUG.Println(v...) } func (l *logger) Infof(format string, v ...interface{}) { l.INFO.Printf(format, v...) } func (l *logger) Infoln(v ...interface{}) { l.INFO.Println(v...) } func (l *logger) Info() *log.Logger { return l.INFO } const panicOnWarningMessage = "Warning trapped. Remove the --panicOnWarning flag to continue." func (l *logger) Warnf(format string, v ...interface{}) { l.WARN.Printf(format, v...) if PanicOnWarning { panic(panicOnWarningMessage) } } func (l *logger) Warnln(v ...interface{}) { l.WARN.Println(v...) if PanicOnWarning { panic(panicOnWarningMessage) } } func (l *logger) Warn() *log.Logger { return l.WARN } func (l *logger) Errorf(format string, v ...interface{}) { l.ERROR.Printf(format, v...) } func (l *logger) Errorln(v ...interface{}) { l.ERROR.Println(v...) } func (l *logger) Error() *log.Logger { return l.ERROR } func (l *logger) LogCounters() *LogCounters { return l.logCounters } func (l *logger) Out() io.Writer { return l.out } // PrintTimerIfDelayed prints a time statement to the FEEDBACK logger // if considerable time is spent. func (l *logger) PrintTimerIfDelayed(start time.Time, name string) { elapsed := time.Since(start) milli := int(1000 * elapsed.Seconds()) if milli < 500 { return } l.Printf("%s in %v ms", name, milli) } func (l *logger) PrintTimer(start time.Time, name string) { elapsed := time.Since(start) milli := int(1000 * elapsed.Seconds()) l.Printf("%s in %v ms", name, milli) } func (l *logger) Errors() string { if l.errors == nil { return "" } return ansiColorRe.ReplaceAllString(l.errors.String(), "") } // Reset resets the logger's internal state. func (l *logger) Reset() { l.logCounters.ErrorCounter.Reset() if l.errors != nil { l.errors.Reset() } } // NewLogger creates a new Logger for the given thresholds func NewLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle io.Writer, saveErrors bool) Logger { return newLogger(stdoutThreshold, logThreshold, outHandle, logHandle, saveErrors) } // NewDebugLogger is a convenience function to create a debug logger. func NewDebugLogger() Logger { return NewBasicLogger(jww.LevelDebug) } // NewWarningLogger is a convenience function to create a warning logger. func NewWarningLogger() Logger { return NewBasicLogger(jww.LevelWarn) } // NewInfoLogger is a convenience function to create a info logger. func NewInfoLogger() Logger { return NewBasicLogger(jww.LevelInfo) } // NewErrorLogger is a convenience function to create an error logger. func NewErrorLogger() Logger { return NewBasicLogger(jww.LevelError) } // NewBasicLogger creates a new basic logger writing to Stdout. func NewBasicLogger(t jww.Threshold) Logger { return newLogger(t, jww.LevelError, os.Stdout, ioutil.Discard, false) } // NewBasicLoggerForWriter creates a new basic logger writing to w. func NewBasicLoggerForWriter(t jww.Threshold, w io.Writer) Logger { return newLogger(t, jww.LevelError, w, ioutil.Discard, false) } var ( ansiColorRe = regexp.MustCompile("(?s)\\033\\[\\d*(;\\d*)*m") errorRe = regexp.MustCompile("^(ERROR|FATAL|WARN)") ) type ansiCleaner struct { w io.Writer } func (a ansiCleaner) Write(p []byte) (n int, err error) { return a.w.Write(ansiColorRe.ReplaceAll(p, []byte(""))) } type labelColorizer struct { w io.Writer } func (a labelColorizer) Write(p []byte) (n int, err error) { replaced := errorRe.ReplaceAllStringFunc(string(p), func(m string) string { switch m { case "ERROR", "FATAL": return terminal.Error(m) case "WARN": return terminal.Warning(m) default: return m } }) // io.MultiWriter will abort if we return a bigger write count than input // bytes, so we lie a little. _, err = a.w.Write([]byte(replaced)) return len(p), err } // InitGlobalLogger initializes the global logger, used in some rare cases. func InitGlobalLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle io.Writer) { outHandle, logHandle = getLogWriters(outHandle, logHandle) jww.SetStdoutOutput(outHandle) jww.SetLogOutput(logHandle) jww.SetLogThreshold(logThreshold) jww.SetStdoutThreshold(stdoutThreshold) } func getLogWriters(outHandle, logHandle io.Writer) (io.Writer, io.Writer) { isTerm := terminal.IsTerminal(os.Stdout) if logHandle != ioutil.Discard && isTerm { // Remove any Ansi coloring from log output logHandle = ansiCleaner{w: logHandle} } if isTerm { outHandle = labelColorizer{w: outHandle} } return outHandle, logHandle } type fatalLogWriter int func (s fatalLogWriter) Write(p []byte) (n int, err error) { trace := make([]byte, 1500) runtime.Stack(trace, true) fmt.Printf("\n===========\n\n%s\n", trace) os.Exit(-1) return 0, nil } var fatalLogListener = func(t jww.Threshold) io.Writer { if t != jww.LevelError { // Only interested in ERROR return nil } return new(fatalLogWriter) } func newLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle io.Writer, saveErrors bool) *logger { errorCounter := &jww.Counter{} warnCounter := &jww.Counter{} outHandle, logHandle = getLogWriters(outHandle, logHandle) listeners := []jww.LogListener{jww.LogCounter(errorCounter, jww.LevelError), jww.LogCounter(warnCounter, jww.LevelWarn)} var errorBuff *bytes.Buffer if saveErrors { errorBuff = new(bytes.Buffer) errorCapture := func(t jww.Threshold) io.Writer { if t != jww.LevelError { // Only interested in ERROR return nil } return errorBuff } listeners = append(listeners, errorCapture) } return &logger{ Notepad: jww.NewNotepad(stdoutThreshold, logThreshold, outHandle, logHandle, "", log.Ldate|log.Ltime, listeners...), out: outHandle, logCounters: &LogCounters{ ErrorCounter: errorCounter, WarnCounter: warnCounter, }, errors: errorBuff, } } hugo-0.92.2/common/loggers/loggers_test.go000066400000000000000000000022501420147000300205160ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package loggers import ( "bytes" "fmt" "log" "testing" qt "github.com/frankban/quicktest" ) func TestLogger(t *testing.T) { c := qt.New(t) l := NewWarningLogger() l.Errorln("One error") l.Errorln("Two error") l.Warnln("A warning") c.Assert(l.LogCounters().ErrorCounter.Count(), qt.Equals, uint64(2)) } func TestLoggerToWriterWithPrefix(t *testing.T) { c := qt.New(t) var b bytes.Buffer logger := log.New(&b, "", 0) w := LoggerToWriterWithPrefix(logger, "myprefix") fmt.Fprint(w, "Hello Hugo!") c.Assert(b.String(), qt.Equals, "myprefix: Hello Hugo!\n") } hugo-0.92.2/common/maps/000077500000000000000000000000001420147000300147655ustar00rootroot00000000000000hugo-0.92.2/common/maps/maps.go000066400000000000000000000106431420147000300162600ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package maps import ( "fmt" "strings" "github.com/gohugoio/hugo/common/types" "github.com/gobwas/glob" "github.com/spf13/cast" ) // ToStringMapE converts in to map[string]interface{}. func ToStringMapE(in interface{}) (map[string]interface{}, error) { switch vv := in.(type) { case Params: return vv, nil case map[string]string: var m = map[string]interface{}{} for k, v := range vv { m[k] = v } return m, nil default: return cast.ToStringMapE(in) } } // ToParamsAndPrepare converts in to Params and prepares it for use. // If in is nil, an empty map is returned. // See PrepareParams. func ToParamsAndPrepare(in interface{}) (Params, bool) { if types.IsNil(in) { return Params{}, true } m, err := ToStringMapE(in) if err != nil { return nil, false } PrepareParams(m) return m, true } // MustToParamsAndPrepare calls ToParamsAndPrepare and panics if it fails. func MustToParamsAndPrepare(in interface{}) Params { if p, ok := ToParamsAndPrepare(in); ok { return p } else { panic(fmt.Sprintf("cannot convert %T to maps.Params", in)) } } // ToStringMap converts in to map[string]interface{}. func ToStringMap(in interface{}) map[string]interface{} { m, _ := ToStringMapE(in) return m } // ToStringMapStringE converts in to map[string]string. func ToStringMapStringE(in interface{}) (map[string]string, error) { m, err := ToStringMapE(in) if err != nil { return nil, err } return cast.ToStringMapStringE(m) } // ToStringMapString converts in to map[string]string. func ToStringMapString(in interface{}) map[string]string { m, _ := ToStringMapStringE(in) return m } // ToStringMapBool converts in to bool. func ToStringMapBool(in interface{}) map[string]bool { m, _ := ToStringMapE(in) return cast.ToStringMapBool(m) } // ToSliceStringMap converts in to []map[string]interface{}. func ToSliceStringMap(in interface{}) ([]map[string]interface{}, error) { switch v := in.(type) { case []map[string]interface{}: return v, nil case []interface{}: var s []map[string]interface{} for _, entry := range v { if vv, ok := entry.(map[string]interface{}); ok { s = append(s, vv) } } return s, nil default: return nil, fmt.Errorf("unable to cast %#v of type %T to []map[string]interface{}", in, in) } } type keyRename struct { pattern glob.Glob newKey string } // KeyRenamer supports renaming of keys in a map. type KeyRenamer struct { renames []keyRename } // NewKeyRenamer creates a new KeyRenamer given a list of pattern and new key // value pairs. func NewKeyRenamer(patternKeys ...string) (KeyRenamer, error) { var renames []keyRename for i := 0; i < len(patternKeys); i += 2 { g, err := glob.Compile(strings.ToLower(patternKeys[i]), '/') if err != nil { return KeyRenamer{}, err } renames = append(renames, keyRename{pattern: g, newKey: patternKeys[i+1]}) } return KeyRenamer{renames: renames}, nil } func (r KeyRenamer) getNewKey(keyPath string) string { for _, matcher := range r.renames { if matcher.pattern.Match(keyPath) { return matcher.newKey } } return "" } // Rename renames the keys in the given map according // to the patterns in the current KeyRenamer. func (r KeyRenamer) Rename(m map[string]interface{}) { r.renamePath("", m) } func (KeyRenamer) keyPath(k1, k2 string) string { k1, k2 = strings.ToLower(k1), strings.ToLower(k2) if k1 == "" { return k2 } return k1 + "/" + k2 } func (r KeyRenamer) renamePath(parentKeyPath string, m map[string]interface{}) { for key, val := range m { keyPath := r.keyPath(parentKeyPath, key) switch val.(type) { case map[interface{}]interface{}: val = cast.ToStringMap(val) r.renamePath(keyPath, val.(map[string]interface{})) case map[string]interface{}: r.renamePath(keyPath, val.(map[string]interface{})) } newKey := r.getNewKey(keyPath) if newKey != "" { delete(m, key) m[newKey] = val } } } hugo-0.92.2/common/maps/maps_test.go000066400000000000000000000065631420147000300173250ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package maps import ( "fmt" "reflect" "testing" qt "github.com/frankban/quicktest" ) func TestPrepareParams(t *testing.T) { tests := []struct { input Params expected Params }{ { map[string]interface{}{ "abC": 32, }, Params{ "abc": 32, }, }, { map[string]interface{}{ "abC": 32, "deF": map[interface{}]interface{}{ 23: "A value", 24: map[string]interface{}{ "AbCDe": "A value", "eFgHi": "Another value", }, }, "gHi": map[string]interface{}{ "J": 25, }, "jKl": map[string]string{ "M": "26", }, }, Params{ "abc": 32, "def": Params{ "23": "A value", "24": Params{ "abcde": "A value", "efghi": "Another value", }, }, "ghi": Params{ "j": 25, }, "jkl": Params{ "m": "26", }, }, }, } for i, test := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) { // PrepareParams modifies input. PrepareParams(test.input) if !reflect.DeepEqual(test.expected, test.input) { t.Errorf("[%d] Expected\n%#v, got\n%#v\n", i, test.expected, test.input) } }) } } func TestToSliceStringMap(t *testing.T) { c := qt.New(t) tests := []struct { input interface{} expected []map[string]interface{} }{ { input: []map[string]interface{}{ {"abc": 123}, }, expected: []map[string]interface{}{ {"abc": 123}, }, }, { input: []interface{}{ map[string]interface{}{ "def": 456, }, }, expected: []map[string]interface{}{ {"def": 456}, }, }, } for _, test := range tests { v, err := ToSliceStringMap(test.input) c.Assert(err, qt.IsNil) c.Assert(v, qt.DeepEquals, test.expected) } } func TestToParamsAndPrepare(t *testing.T) { c := qt.New(t) _, ok := ToParamsAndPrepare(map[string]interface{}{"A": "av"}) c.Assert(ok, qt.IsTrue) params, ok := ToParamsAndPrepare(nil) c.Assert(ok, qt.IsTrue) c.Assert(params, qt.DeepEquals, Params{}) } func TestRenameKeys(t *testing.T) { c := qt.New(t) m := map[string]interface{}{ "a": 32, "ren1": "m1", "ren2": "m1_2", "sub": map[string]interface{}{ "subsub": map[string]interface{}{ "REN1": "m2", "ren2": "m2_2", }, }, "no": map[string]interface{}{ "ren1": "m2", "ren2": "m2_2", }, } expected := map[string]interface{}{ "a": 32, "new1": "m1", "new2": "m1_2", "sub": map[string]interface{}{ "subsub": map[string]interface{}{ "new1": "m2", "ren2": "m2_2", }, }, "no": map[string]interface{}{ "ren1": "m2", "ren2": "m2_2", }, } renamer, err := NewKeyRenamer( "{ren1,sub/*/ren1}", "new1", "{Ren2,sub/ren2}", "new2", ) c.Assert(err, qt.IsNil) renamer.Rename(m) if !reflect.DeepEqual(expected, m) { t.Errorf("Expected\n%#v, got\n%#v\n", expected, m) } } hugo-0.92.2/common/maps/params.go000066400000000000000000000150331420147000300166010ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package maps import ( "fmt" "strings" "github.com/spf13/cast" ) // Params is a map where all keys are lower case. type Params map[string]interface{} // Get does a lower case and nested search in this map. // It will return nil if none found. func (p Params) Get(indices ...string) interface{} { v, _, _ := getNested(p, indices) return v } // Set overwrites values in p with values in pp for common or new keys. // This is done recursively. func (p Params) Set(pp Params) { for k, v := range pp { vv, found := p[k] if !found { p[k] = v } else { switch vvv := vv.(type) { case Params: if pv, ok := v.(Params); ok { vvv.Set(pv) } else { p[k] = v } default: p[k] = v } } } } // IsZero returns true if p is considered empty. func (p Params) IsZero() bool { if p == nil || len(p) == 0 { return true } if len(p) > 1 { return false } for k, _ := range p { return k == mergeStrategyKey } return false } // Merge transfers values from pp to p for new keys. // This is done recursively. func (p Params) Merge(pp Params) { p.merge("", pp) } // MergeRoot transfers values from pp to p for new keys where p is the // root of the tree. // This is done recursively. func (p Params) MergeRoot(pp Params) { ms, _ := p.GetMergeStrategy() p.merge(ms, pp) } func (p Params) merge(ps ParamsMergeStrategy, pp Params) { ns, found := p.GetMergeStrategy() var ms = ns if !found && ps != "" { ms = ps } noUpdate := ms == ParamsMergeStrategyNone noUpdate = noUpdate || (ps != "" && ps == ParamsMergeStrategyShallow) for k, v := range pp { if k == mergeStrategyKey { continue } vv, found := p[k] if found { // Key matches, if both sides are Params, we try to merge. if vvv, ok := vv.(Params); ok { if pv, ok := v.(Params); ok { vvv.merge(ms, pv) } } } else if !noUpdate { p[k] = v } } } func (p Params) GetMergeStrategy() (ParamsMergeStrategy, bool) { if v, found := p[mergeStrategyKey]; found { if s, ok := v.(ParamsMergeStrategy); ok { return s, true } } return ParamsMergeStrategyShallow, false } func (p Params) DeleteMergeStrategy() bool { if _, found := p[mergeStrategyKey]; found { delete(p, mergeStrategyKey) return true } return false } func (p Params) SetDefaultMergeStrategy(s ParamsMergeStrategy) { switch s { case ParamsMergeStrategyDeep, ParamsMergeStrategyNone, ParamsMergeStrategyShallow: default: panic(fmt.Sprintf("invalid merge strategy %q", s)) } p[mergeStrategyKey] = s } func getNested(m map[string]interface{}, indices []string) (interface{}, string, map[string]interface{}) { if len(indices) == 0 { return nil, "", nil } first := indices[0] v, found := m[strings.ToLower(cast.ToString(first))] if !found { if len(indices) == 1 { return nil, first, m } return nil, "", nil } if len(indices) == 1 { return v, first, m } switch m2 := v.(type) { case Params: return getNested(m2, indices[1:]) case map[string]interface{}: return getNested(m2, indices[1:]) default: return nil, "", nil } } // GetNestedParam gets the first match of the keyStr in the candidates given. // It will first try the exact match and then try to find it as a nested map value, // using the given separator, e.g. "mymap.name". // It assumes that all the maps given have lower cased keys. func GetNestedParam(keyStr, separator string, candidates ...Params) (interface{}, error) { keyStr = strings.ToLower(keyStr) // Try exact match first for _, m := range candidates { if v, ok := m[keyStr]; ok { return v, nil } } keySegments := strings.Split(keyStr, separator) for _, m := range candidates { if v := m.Get(keySegments...); v != nil { return v, nil } } return nil, nil } func GetNestedParamFn(keyStr, separator string, lookupFn func(key string) interface{}) (interface{}, string, map[string]interface{}, error) { keySegments := strings.Split(keyStr, separator) if len(keySegments) == 0 { return nil, "", nil, nil } first := lookupFn(keySegments[0]) if first == nil { return nil, "", nil, nil } if len(keySegments) == 1 { return first, keySegments[0], nil, nil } switch m := first.(type) { case map[string]interface{}: v, key, owner := getNested(m, keySegments[1:]) return v, key, owner, nil case Params: v, key, owner := getNested(m, keySegments[1:]) return v, key, owner, nil } return nil, "", nil, nil } // ParamsMergeStrategy tells what strategy to use in Params.Merge. type ParamsMergeStrategy string const ( // Do not merge. ParamsMergeStrategyNone ParamsMergeStrategy = "none" // Only add new keys. ParamsMergeStrategyShallow ParamsMergeStrategy = "shallow" // Add new keys, merge existing. ParamsMergeStrategyDeep ParamsMergeStrategy = "deep" mergeStrategyKey = "_merge" ) func toMergeStrategy(v interface{}) ParamsMergeStrategy { s := ParamsMergeStrategy(cast.ToString(v)) switch s { case ParamsMergeStrategyDeep, ParamsMergeStrategyNone, ParamsMergeStrategyShallow: return s default: return ParamsMergeStrategyDeep } } // PrepareParams // * makes all the keys in the given map lower cased and will do so // * This will modify the map given. // * Any nested map[interface{}]interface{}, map[string]interface{},map[string]string will be converted to Params. // * Any _merge value will be converted to proper type and value. func PrepareParams(m Params) { for k, v := range m { var retyped bool lKey := strings.ToLower(k) if lKey == mergeStrategyKey { v = toMergeStrategy(v) retyped = true } else { switch vv := v.(type) { case map[interface{}]interface{}: var p Params = cast.ToStringMap(v) v = p PrepareParams(p) retyped = true case map[string]interface{}: var p Params = v.(map[string]interface{}) v = p PrepareParams(p) retyped = true case map[string]string: p := make(Params) for k, v := range vv { p[k] = v } v = p PrepareParams(p) retyped = true } } if retyped || k != lKey { delete(m, k) m[lKey] = v } } } hugo-0.92.2/common/maps/params_test.go000066400000000000000000000076541420147000300176520ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package maps import ( "testing" qt "github.com/frankban/quicktest" ) func TestGetNestedParam(t *testing.T) { m := map[string]interface{}{ "string": "value", "first": 1, "with_underscore": 2, "nested": map[string]interface{}{ "color": "blue", "nestednested": map[string]interface{}{ "color": "green", }, }, } c := qt.New(t) must := func(keyStr, separator string, candidates ...Params) interface{} { v, err := GetNestedParam(keyStr, separator, candidates...) c.Assert(err, qt.IsNil) return v } c.Assert(must("first", "_", m), qt.Equals, 1) c.Assert(must("First", "_", m), qt.Equals, 1) c.Assert(must("with_underscore", "_", m), qt.Equals, 2) c.Assert(must("nested_color", "_", m), qt.Equals, "blue") c.Assert(must("nested.nestednested.color", ".", m), qt.Equals, "green") c.Assert(must("string.name", ".", m), qt.IsNil) c.Assert(must("nested.foo", ".", m), qt.IsNil) } // https://github.com/gohugoio/hugo/issues/7903 func TestGetNestedParamFnNestedNewKey(t *testing.T) { c := qt.New(t) nested := map[string]interface{}{ "color": "blue", } m := map[string]interface{}{ "nested": nested, } existing, nestedKey, owner, err := GetNestedParamFn("nested.new", ".", func(key string) interface{} { return m[key] }) c.Assert(err, qt.IsNil) c.Assert(existing, qt.IsNil) c.Assert(nestedKey, qt.Equals, "new") c.Assert(owner, qt.DeepEquals, nested) } func TestParamsSetAndMerge(t *testing.T) { c := qt.New(t) createParamsPair := func() (Params, Params) { p1 := Params{"a": "av", "c": "cv", "nested": Params{"al2": "al2v", "cl2": "cl2v"}} p2 := Params{"b": "bv", "a": "abv", "nested": Params{"bl2": "bl2v", "al2": "al2bv"}, mergeStrategyKey: ParamsMergeStrategyDeep} return p1, p2 } p1, p2 := createParamsPair() p1.Set(p2) c.Assert(p1, qt.DeepEquals, Params{ "a": "abv", "c": "cv", "nested": Params{ "al2": "al2bv", "cl2": "cl2v", "bl2": "bl2v", }, "b": "bv", mergeStrategyKey: ParamsMergeStrategyDeep, }) p1, p2 = createParamsPair() p1.Merge(p2) // Default is to do a shallow merge. c.Assert(p1, qt.DeepEquals, Params{ "c": "cv", "nested": Params{ "al2": "al2v", "cl2": "cl2v", }, "b": "bv", "a": "av", }) p1, p2 = createParamsPair() p1.SetDefaultMergeStrategy(ParamsMergeStrategyNone) p1.Merge(p2) p1.DeleteMergeStrategy() c.Assert(p1, qt.DeepEquals, Params{ "a": "av", "c": "cv", "nested": Params{ "al2": "al2v", "cl2": "cl2v", }, }) p1, p2 = createParamsPair() p1.SetDefaultMergeStrategy(ParamsMergeStrategyShallow) p1.Merge(p2) p1.DeleteMergeStrategy() c.Assert(p1, qt.DeepEquals, Params{ "a": "av", "c": "cv", "nested": Params{ "al2": "al2v", "cl2": "cl2v", }, "b": "bv", }) p1, p2 = createParamsPair() p1.SetDefaultMergeStrategy(ParamsMergeStrategyDeep) p1.Merge(p2) p1.DeleteMergeStrategy() c.Assert(p1, qt.DeepEquals, Params{ "nested": Params{ "al2": "al2v", "cl2": "cl2v", "bl2": "bl2v", }, "b": "bv", "a": "av", "c": "cv", }) } func TestParamsIsZero(t *testing.T) { c := qt.New(t) var nilParams Params c.Assert(Params{}.IsZero(), qt.IsTrue) c.Assert(nilParams.IsZero(), qt.IsTrue) c.Assert(Params{"foo": "bar"}.IsZero(), qt.IsFalse) c.Assert(Params{"_merge": "foo", "foo": "bar"}.IsZero(), qt.IsFalse) c.Assert(Params{"_merge": "foo"}.IsZero(), qt.IsTrue) } hugo-0.92.2/common/maps/scratch.go000066400000000000000000000105071420147000300167460ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package maps import ( "reflect" "sort" "sync" "github.com/gohugoio/hugo/common/collections" "github.com/gohugoio/hugo/common/math" ) // Scratch is a writable context used for stateful operations in Page/Node rendering. type Scratch struct { values map[string]interface{} mu sync.RWMutex } // Scratcher provides a scratching service. type Scratcher interface { Scratch() *Scratch } type scratcher struct { s *Scratch } func (s scratcher) Scratch() *Scratch { return s.s } // NewScratcher creates a new Scratcher. func NewScratcher() Scratcher { return scratcher{s: NewScratch()} } // Add will, for single values, add (using the + operator) the addend to the existing addend (if found). // Supports numeric values and strings. // // If the first add for a key is an array or slice, then the next value(s) will be appended. func (c *Scratch) Add(key string, newAddend interface{}) (string, error) { var newVal interface{} c.mu.RLock() existingAddend, found := c.values[key] c.mu.RUnlock() if found { var err error addendV := reflect.TypeOf(existingAddend) if addendV.Kind() == reflect.Slice || addendV.Kind() == reflect.Array { newVal, err = collections.Append(existingAddend, newAddend) if err != nil { return "", err } } else { newVal, err = math.DoArithmetic(existingAddend, newAddend, '+') if err != nil { return "", err } } } else { newVal = newAddend } c.mu.Lock() c.values[key] = newVal c.mu.Unlock() return "", nil // have to return something to make it work with the Go templates } // Set stores a value with the given key in the Node context. // This value can later be retrieved with Get. func (c *Scratch) Set(key string, value interface{}) string { c.mu.Lock() c.values[key] = value c.mu.Unlock() return "" } // Delete deletes the given key. func (c *Scratch) Delete(key string) string { c.mu.Lock() delete(c.values, key) c.mu.Unlock() return "" } // Get returns a value previously set by Add or Set. func (c *Scratch) Get(key string) interface{} { c.mu.RLock() val := c.values[key] c.mu.RUnlock() return val } // Values returns the raw backing map. Note that you should just use // this method on the locally scoped Scratch instances you obtain via newScratch, not // .Page.Scratch etc., as that will lead to concurrency issues. func (c *Scratch) Values() map[string]interface{} { c.mu.RLock() defer c.mu.RUnlock() return c.values } // SetInMap stores a value to a map with the given key in the Node context. // This map can later be retrieved with GetSortedMapValues. func (c *Scratch) SetInMap(key string, mapKey string, value interface{}) string { c.mu.Lock() _, found := c.values[key] if !found { c.values[key] = make(map[string]interface{}) } c.values[key].(map[string]interface{})[mapKey] = value c.mu.Unlock() return "" } // DeleteInMap deletes a value to a map with the given key in the Node context. func (c *Scratch) DeleteInMap(key string, mapKey string) string { c.mu.Lock() _, found := c.values[key] if found { delete(c.values[key].(map[string]interface{}), mapKey) } c.mu.Unlock() return "" } // GetSortedMapValues returns a sorted map previously filled with SetInMap. func (c *Scratch) GetSortedMapValues(key string) interface{} { c.mu.RLock() if c.values[key] == nil { c.mu.RUnlock() return nil } unsortedMap := c.values[key].(map[string]interface{}) c.mu.RUnlock() var keys []string for mapKey := range unsortedMap { keys = append(keys, mapKey) } sort.Strings(keys) sortedArray := make([]interface{}, len(unsortedMap)) for i, mapKey := range keys { sortedArray[i] = unsortedMap[mapKey] } return sortedArray } // NewScratch returns a new instance of Scratch. func NewScratch() *Scratch { return &Scratch{values: make(map[string]interface{})} } hugo-0.92.2/common/maps/scratch_test.go000066400000000000000000000123071420147000300200050ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package maps import ( "reflect" "sync" "testing" qt "github.com/frankban/quicktest" ) func TestScratchAdd(t *testing.T) { t.Parallel() c := qt.New(t) scratch := NewScratch() scratch.Add("int1", 10) scratch.Add("int1", 20) scratch.Add("int2", 20) c.Assert(scratch.Get("int1"), qt.Equals, int64(30)) c.Assert(scratch.Get("int2"), qt.Equals, 20) scratch.Add("float1", float64(10.5)) scratch.Add("float1", float64(20.1)) c.Assert(scratch.Get("float1"), qt.Equals, float64(30.6)) scratch.Add("string1", "Hello ") scratch.Add("string1", "big ") scratch.Add("string1", "World!") c.Assert(scratch.Get("string1"), qt.Equals, "Hello big World!") scratch.Add("scratch", scratch) _, err := scratch.Add("scratch", scratch) m := scratch.Values() c.Assert(m, qt.HasLen, 5) if err == nil { t.Errorf("Expected error from invalid arithmetic") } } func TestScratchAddSlice(t *testing.T) { t.Parallel() c := qt.New(t) scratch := NewScratch() _, err := scratch.Add("intSlice", []int{1, 2}) c.Assert(err, qt.IsNil) _, err = scratch.Add("intSlice", 3) c.Assert(err, qt.IsNil) sl := scratch.Get("intSlice") expected := []int{1, 2, 3} if !reflect.DeepEqual(expected, sl) { t.Errorf("Slice difference, go %q expected %q", sl, expected) } _, err = scratch.Add("intSlice", []int{4, 5}) c.Assert(err, qt.IsNil) sl = scratch.Get("intSlice") expected = []int{1, 2, 3, 4, 5} if !reflect.DeepEqual(expected, sl) { t.Errorf("Slice difference, go %q expected %q", sl, expected) } } // https://github.com/gohugoio/hugo/issues/5275 func TestScratchAddTypedSliceToInterfaceSlice(t *testing.T) { t.Parallel() c := qt.New(t) scratch := NewScratch() scratch.Set("slice", []interface{}{}) _, err := scratch.Add("slice", []int{1, 2}) c.Assert(err, qt.IsNil) c.Assert(scratch.Get("slice"), qt.DeepEquals, []int{1, 2}) } // https://github.com/gohugoio/hugo/issues/5361 func TestScratchAddDifferentTypedSliceToInterfaceSlice(t *testing.T) { t.Parallel() c := qt.New(t) scratch := NewScratch() scratch.Set("slice", []string{"foo"}) _, err := scratch.Add("slice", []int{1, 2}) c.Assert(err, qt.IsNil) c.Assert(scratch.Get("slice"), qt.DeepEquals, []interface{}{"foo", 1, 2}) } func TestScratchSet(t *testing.T) { t.Parallel() c := qt.New(t) scratch := NewScratch() scratch.Set("key", "val") c.Assert(scratch.Get("key"), qt.Equals, "val") } func TestScratchDelete(t *testing.T) { t.Parallel() c := qt.New(t) scratch := NewScratch() scratch.Set("key", "val") scratch.Delete("key") scratch.Add("key", "Lucy Parsons") c.Assert(scratch.Get("key"), qt.Equals, "Lucy Parsons") } // Issue #2005 func TestScratchInParallel(t *testing.T) { var wg sync.WaitGroup scratch := NewScratch() key := "counter" scratch.Set(key, int64(1)) for i := 1; i <= 10; i++ { wg.Add(1) go func(j int) { for k := 0; k < 10; k++ { newVal := int64(k + j) _, err := scratch.Add(key, newVal) if err != nil { t.Errorf("Got err %s", err) } scratch.Set(key, newVal) val := scratch.Get(key) if counter, ok := val.(int64); ok { if counter < 1 { t.Errorf("Got %d", counter) } } else { t.Errorf("Got %T", val) } } wg.Done() }(i) } wg.Wait() } func TestScratchGet(t *testing.T) { t.Parallel() scratch := NewScratch() nothing := scratch.Get("nothing") if nothing != nil { t.Errorf("Should not return anything, but got %v", nothing) } } func TestScratchSetInMap(t *testing.T) { t.Parallel() c := qt.New(t) scratch := NewScratch() scratch.SetInMap("key", "lux", "Lux") scratch.SetInMap("key", "abc", "Abc") scratch.SetInMap("key", "zyx", "Zyx") scratch.SetInMap("key", "abc", "Abc (updated)") scratch.SetInMap("key", "def", "Def") c.Assert(scratch.GetSortedMapValues("key"), qt.DeepEquals, []interface{}{0: "Abc (updated)", 1: "Def", 2: "Lux", 3: "Zyx"}) } func TestScratchDeleteInMap(t *testing.T) { t.Parallel() c := qt.New(t) scratch := NewScratch() scratch.SetInMap("key", "lux", "Lux") scratch.SetInMap("key", "abc", "Abc") scratch.SetInMap("key", "zyx", "Zyx") scratch.DeleteInMap("key", "abc") scratch.SetInMap("key", "def", "Def") scratch.DeleteInMap("key", "lmn") // Do nothing c.Assert(scratch.GetSortedMapValues("key"), qt.DeepEquals, []interface{}{0: "Def", 1: "Lux", 2: "Zyx"}) } func TestScratchGetSortedMapValues(t *testing.T) { t.Parallel() scratch := NewScratch() nothing := scratch.GetSortedMapValues("nothing") if nothing != nil { t.Errorf("Should not return anything, but got %v", nothing) } } func BenchmarkScratchGet(b *testing.B) { scratch := NewScratch() scratch.Add("A", 1) b.ResetTimer() for i := 0; i < b.N; i++ { scratch.Get("A") } } hugo-0.92.2/common/math/000077500000000000000000000000001420147000300147565ustar00rootroot00000000000000hugo-0.92.2/common/math/math.go000066400000000000000000000073511420147000300162440ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package math import ( "errors" "reflect" ) // DoArithmetic performs arithmetic operations (+,-,*,/) using reflection to // determine the type of the two terms. func DoArithmetic(a, b interface{}, op rune) (interface{}, error) { av := reflect.ValueOf(a) bv := reflect.ValueOf(b) var ai, bi int64 var af, bf float64 var au, bu uint64 switch av.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ai = av.Int() switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: bi = bv.Int() case reflect.Float32, reflect.Float64: af = float64(ai) // may overflow ai = 0 bf = bv.Float() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: bu = bv.Uint() if ai >= 0 { au = uint64(ai) ai = 0 } else { bi = int64(bu) // may overflow bu = 0 } default: return nil, errors.New("can't apply the operator to the values") } case reflect.Float32, reflect.Float64: af = av.Float() switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: bf = float64(bv.Int()) // may overflow case reflect.Float32, reflect.Float64: bf = bv.Float() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: bf = float64(bv.Uint()) // may overflow default: return nil, errors.New("can't apply the operator to the values") } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: au = av.Uint() switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: bi = bv.Int() if bi >= 0 { bu = uint64(bi) bi = 0 } else { ai = int64(au) // may overflow au = 0 } case reflect.Float32, reflect.Float64: af = float64(au) // may overflow au = 0 bf = bv.Float() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: bu = bv.Uint() default: return nil, errors.New("can't apply the operator to the values") } case reflect.String: as := av.String() if bv.Kind() == reflect.String && op == '+' { bs := bv.String() return as + bs, nil } return nil, errors.New("can't apply the operator to the values") default: return nil, errors.New("can't apply the operator to the values") } switch op { case '+': if ai != 0 || bi != 0 { return ai + bi, nil } else if af != 0 || bf != 0 { return af + bf, nil } else if au != 0 || bu != 0 { return au + bu, nil } return 0, nil case '-': if ai != 0 || bi != 0 { return ai - bi, nil } else if af != 0 || bf != 0 { return af - bf, nil } else if au != 0 || bu != 0 { return au - bu, nil } return 0, nil case '*': if ai != 0 || bi != 0 { return ai * bi, nil } else if af != 0 || bf != 0 { return af * bf, nil } else if au != 0 || bu != 0 { return au * bu, nil } return 0, nil case '/': if bi != 0 { return ai / bi, nil } else if bf != 0 { return af / bf, nil } else if bu != 0 { return au / bu, nil } return nil, errors.New("can't divide the value by 0") default: return nil, errors.New("there is no such an operation") } } hugo-0.92.2/common/math/math_test.go000066400000000000000000000057061420147000300173050ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package math import ( "testing" qt "github.com/frankban/quicktest" ) func TestDoArithmetic(t *testing.T) { t.Parallel() c := qt.New(t) for _, test := range []struct { a interface{} b interface{} op rune expect interface{} }{ {3, 2, '+', int64(5)}, {3, 2, '-', int64(1)}, {3, 2, '*', int64(6)}, {3, 2, '/', int64(1)}, {3.0, 2, '+', float64(5)}, {3.0, 2, '-', float64(1)}, {3.0, 2, '*', float64(6)}, {3.0, 2, '/', float64(1.5)}, {3, 2.0, '+', float64(5)}, {3, 2.0, '-', float64(1)}, {3, 2.0, '*', float64(6)}, {3, 2.0, '/', float64(1.5)}, {3.0, 2.0, '+', float64(5)}, {3.0, 2.0, '-', float64(1)}, {3.0, 2.0, '*', float64(6)}, {3.0, 2.0, '/', float64(1.5)}, {uint(3), uint(2), '+', uint64(5)}, {uint(3), uint(2), '-', uint64(1)}, {uint(3), uint(2), '*', uint64(6)}, {uint(3), uint(2), '/', uint64(1)}, {uint(3), 2, '+', uint64(5)}, {uint(3), 2, '-', uint64(1)}, {uint(3), 2, '*', uint64(6)}, {uint(3), 2, '/', uint64(1)}, {3, uint(2), '+', uint64(5)}, {3, uint(2), '-', uint64(1)}, {3, uint(2), '*', uint64(6)}, {3, uint(2), '/', uint64(1)}, {uint(3), -2, '+', int64(1)}, {uint(3), -2, '-', int64(5)}, {uint(3), -2, '*', int64(-6)}, {uint(3), -2, '/', int64(-1)}, {-3, uint(2), '+', int64(-1)}, {-3, uint(2), '-', int64(-5)}, {-3, uint(2), '*', int64(-6)}, {-3, uint(2), '/', int64(-1)}, {uint(3), 2.0, '+', float64(5)}, {uint(3), 2.0, '-', float64(1)}, {uint(3), 2.0, '*', float64(6)}, {uint(3), 2.0, '/', float64(1.5)}, {3.0, uint(2), '+', float64(5)}, {3.0, uint(2), '-', float64(1)}, {3.0, uint(2), '*', float64(6)}, {3.0, uint(2), '/', float64(1.5)}, {0, 0, '+', 0}, {0, 0, '-', 0}, {0, 0, '*', 0}, {"foo", "bar", '+', "foobar"}, {3, 0, '/', false}, {3.0, 0, '/', false}, {3, 0.0, '/', false}, {uint(3), uint(0), '/', false}, {3, uint(0), '/', false}, {-3, uint(0), '/', false}, {uint(3), 0, '/', false}, {3.0, uint(0), '/', false}, {uint(3), 0.0, '/', false}, {3, "foo", '+', false}, {3.0, "foo", '+', false}, {uint(3), "foo", '+', false}, {"foo", 3, '+', false}, {"foo", "bar", '-', false}, {3, 2, '%', false}, } { result, err := DoArithmetic(test.a, test.b, test.op) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil)) continue } c.Assert(err, qt.IsNil) c.Assert(test.expect, qt.Equals, result) } } hugo-0.92.2/common/para/000077500000000000000000000000001420147000300147505ustar00rootroot00000000000000hugo-0.92.2/common/para/para.go000066400000000000000000000034421420147000300162250ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package para implements parallel execution helpers. package para import ( "context" "golang.org/x/sync/errgroup" ) // Workers configures a task executor with the most number of tasks to be executed in parallel. type Workers struct { sem chan struct{} } // Runner wraps the lifecycle methods of a new task set. // // Run wil block until a worker is available or the context is cancelled, // and then run the given func in a new goroutine. // Wait will wait for all the running goroutines to finish. type Runner interface { Run(func() error) Wait() error } type errGroupRunner struct { *errgroup.Group w *Workers ctx context.Context } func (g *errGroupRunner) Run(fn func() error) { select { case g.w.sem <- struct{}{}: case <-g.ctx.Done(): return } g.Go(func() error { err := fn() <-g.w.sem return err }) } // New creates a new Workers with the given number of workers. func New(numWorkers int) *Workers { return &Workers{ sem: make(chan struct{}, numWorkers), } } // Start starts a new Runner. func (w *Workers) Start(ctx context.Context) (Runner, context.Context) { g, ctx := errgroup.WithContext(ctx) return &errGroupRunner{ Group: g, ctx: ctx, w: w, }, ctx } hugo-0.92.2/common/para/para_test.go000066400000000000000000000041171420147000300172640ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package para import ( "context" "runtime" "sort" "sync" "sync/atomic" "testing" "time" "github.com/gohugoio/hugo/htesting" qt "github.com/frankban/quicktest" ) func TestPara(t *testing.T) { if runtime.NumCPU() < 4 { t.Skipf("skip para test, CPU count is %d", runtime.NumCPU()) } if !htesting.IsCI() { t.Skip("skip para test when not running on CI") } c := qt.New(t) c.Run("Order", func(c *qt.C) { n := 500 ints := make([]int, n) for i := 0; i < n; i++ { ints[i] = i } p := New(4) r, _ := p.Start(context.Background()) var result []int var mu sync.Mutex for i := 0; i < n; i++ { i := i r.Run(func() error { mu.Lock() defer mu.Unlock() result = append(result, i) return nil }) } c.Assert(r.Wait(), qt.IsNil) c.Assert(result, qt.HasLen, len(ints)) c.Assert(sort.IntsAreSorted(result), qt.Equals, false, qt.Commentf("Para does not seem to be parallel")) sort.Ints(result) c.Assert(result, qt.DeepEquals, ints) }) c.Run("Time", func(c *qt.C) { const n = 100 p := New(5) r, _ := p.Start(context.Background()) start := time.Now() var counter int64 for i := 0; i < n; i++ { r.Run(func() error { atomic.AddInt64(&counter, 1) time.Sleep(1 * time.Millisecond) return nil }) } c.Assert(r.Wait(), qt.IsNil) c.Assert(counter, qt.Equals, int64(n)) since := time.Since(start) limit := n / 2 * time.Millisecond c.Assert(since < limit, qt.Equals, true, qt.Commentf("%s >= %s", since, limit)) }) } hugo-0.92.2/common/paths/000077500000000000000000000000001420147000300151445ustar00rootroot00000000000000hugo-0.92.2/common/paths/path.go000066400000000000000000000165521420147000300164400ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package paths import ( "errors" "fmt" "path" "path/filepath" "regexp" "strings" ) // FilePathSeparator as defined by os.Separator. const FilePathSeparator = string(filepath.Separator) // filepathPathBridge is a bridge for common functionality in filepath vs path type filepathPathBridge interface { Base(in string) string Clean(in string) string Dir(in string) string Ext(in string) string Join(elem ...string) string Separator() string } type filepathBridge struct{} func (filepathBridge) Base(in string) string { return filepath.Base(in) } func (filepathBridge) Clean(in string) string { return filepath.Clean(in) } func (filepathBridge) Dir(in string) string { return filepath.Dir(in) } func (filepathBridge) Ext(in string) string { return filepath.Ext(in) } func (filepathBridge) Join(elem ...string) string { return filepath.Join(elem...) } func (filepathBridge) Separator() string { return FilePathSeparator } var fpb filepathBridge // MakeTitle converts the path given to a suitable title, trimming whitespace // and replacing hyphens with whitespace. func MakeTitle(inpath string) string { return strings.Replace(strings.TrimSpace(inpath), "-", " ", -1) } // ReplaceExtension takes a path and an extension, strips the old extension // and returns the path with the new extension. func ReplaceExtension(path string, newExt string) string { f, _ := fileAndExt(path, fpb) return f + "." + newExt } func makePathRelative(inPath string, possibleDirectories ...string) (string, error) { for _, currentPath := range possibleDirectories { if strings.HasPrefix(inPath, currentPath) { return strings.TrimPrefix(inPath, currentPath), nil } } return inPath, errors.New("can't extract relative path, unknown prefix") } // Should be good enough for Hugo. var isFileRe = regexp.MustCompile(`.*\..{1,6}$`) // GetDottedRelativePath expects a relative path starting after the content directory. // It returns a relative path with dots ("..") navigating up the path structure. func GetDottedRelativePath(inPath string) string { inPath = filepath.Clean(filepath.FromSlash(inPath)) if inPath == "." { return "./" } if !isFileRe.MatchString(inPath) && !strings.HasSuffix(inPath, FilePathSeparator) { inPath += FilePathSeparator } if !strings.HasPrefix(inPath, FilePathSeparator) { inPath = FilePathSeparator + inPath } dir, _ := filepath.Split(inPath) sectionCount := strings.Count(dir, FilePathSeparator) if sectionCount == 0 || dir == FilePathSeparator { return "./" } var dottedPath string for i := 1; i < sectionCount; i++ { dottedPath += "../" } return dottedPath } // ExtNoDelimiter takes a path and returns the extension, excluding the delimiter, i.e. "md". func ExtNoDelimiter(in string) string { return strings.TrimPrefix(Ext(in), ".") } // Ext takes a path and returns the extension, including the delimiter, i.e. ".md". func Ext(in string) string { _, ext := fileAndExt(in, fpb) return ext } // PathAndExt is the same as FileAndExt, but it uses the path package. func PathAndExt(in string) (string, string) { return fileAndExt(in, pb) } // FileAndExt takes a path and returns the file and extension separated, // the extension including the delimiter, i.e. ".md". func FileAndExt(in string) (string, string) { return fileAndExt(in, fpb) } // FileAndExtNoDelimiter takes a path and returns the file and extension separated, // the extension excluding the delimiter, e.g "md". func FileAndExtNoDelimiter(in string) (string, string) { file, ext := fileAndExt(in, fpb) return file, strings.TrimPrefix(ext, ".") } // Filename takes a file path, strips out the extension, // and returns the name of the file. func Filename(in string) (name string) { name, _ = fileAndExt(in, fpb) return } // PathNoExt takes a path, strips out the extension, // and returns the name of the file. func PathNoExt(in string) string { return strings.TrimSuffix(in, path.Ext(in)) } // FileAndExt returns the filename and any extension of a file path as // two separate strings. // // If the path, in, contains a directory name ending in a slash, // then both name and ext will be empty strings. // // If the path, in, is either the current directory, the parent // directory or the root directory, or an empty string, // then both name and ext will be empty strings. // // If the path, in, represents the path of a file without an extension, // then name will be the name of the file and ext will be an empty string. // // If the path, in, represents a filename with an extension, // then name will be the filename minus any extension - including the dot // and ext will contain the extension - minus the dot. func fileAndExt(in string, b filepathPathBridge) (name string, ext string) { ext = b.Ext(in) base := b.Base(in) return extractFilename(in, ext, base, b.Separator()), ext } func extractFilename(in, ext, base, pathSeparator string) (name string) { // No file name cases. These are defined as: // 1. any "in" path that ends in a pathSeparator // 2. any "base" consisting of just an pathSeparator // 3. any "base" consisting of just an empty string // 4. any "base" consisting of just the current directory i.e. "." // 5. any "base" consisting of just the parent directory i.e. ".." if (strings.LastIndex(in, pathSeparator) == len(in)-1) || base == "" || base == "." || base == ".." || base == pathSeparator { name = "" // there is NO filename } else if ext != "" { // there was an Extension // return the filename minus the extension (and the ".") name = base[:strings.LastIndex(base, ".")] } else { // no extension case so just return base, which willi // be the filename name = base } return } // GetRelativePath returns the relative path of a given path. func GetRelativePath(path, base string) (final string, err error) { if filepath.IsAbs(path) && base == "" { return "", errors.New("source: missing base directory") } name := filepath.Clean(path) base = filepath.Clean(base) name, err = filepath.Rel(base, name) if err != nil { return "", err } if strings.HasSuffix(filepath.FromSlash(path), FilePathSeparator) && !strings.HasSuffix(name, FilePathSeparator) { name += FilePathSeparator } return name, nil } func prettifyPath(in string, b filepathPathBridge) string { if filepath.Ext(in) == "" { // /section/name/ -> /section/name/index.html if len(in) < 2 { return b.Separator() } return b.Join(in, "index.html") } name, ext := fileAndExt(in, b) if name == "index" { // /section/name/index.html -> /section/name/index.html return b.Clean(in) } // /section/name.html -> /section/name/index.html return b.Join(b.Dir(in), name, "index"+ext) } type NamedSlice struct { Name string Slice []string } func (n NamedSlice) String() string { if len(n.Slice) == 0 { return n.Name } return fmt.Sprintf("%s%s{%s}", n.Name, FilePathSeparator, strings.Join(n.Slice, ",")) } hugo-0.92.2/common/paths/path_test.go000066400000000000000000000154061420147000300174740ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package paths import ( "path/filepath" "testing" qt "github.com/frankban/quicktest" ) func TestGetRelativePath(t *testing.T) { tests := []struct { path string base string expect interface{} }{ {filepath.FromSlash("/a/b"), filepath.FromSlash("/a"), filepath.FromSlash("b")}, {filepath.FromSlash("/a/b/c/"), filepath.FromSlash("/a"), filepath.FromSlash("b/c/")}, {filepath.FromSlash("/c"), filepath.FromSlash("/a/b"), filepath.FromSlash("../../c")}, {filepath.FromSlash("/c"), "", false}, } for i, this := range tests { // ultimately a fancy wrapper around filepath.Rel result, err := GetRelativePath(this.path, this.base) if b, ok := this.expect.(bool); ok && !b { if err == nil { t.Errorf("[%d] GetRelativePath didn't return an expected error", i) } } else { if err != nil { t.Errorf("[%d] GetRelativePath failed: %s", i, err) continue } if result != this.expect { t.Errorf("[%d] GetRelativePath got %v but expected %v", i, result, this.expect) } } } } func TestMakePathRelative(t *testing.T) { type test struct { inPath, path1, path2, output string } data := []test{ {"/abc/bcd/ab.css", "/abc/bcd", "/bbc/bcd", "/ab.css"}, {"/abc/bcd/ab.css", "/abcd/bcd", "/abc/bcd", "/ab.css"}, } for i, d := range data { output, _ := makePathRelative(d.inPath, d.path1, d.path2) if d.output != output { t.Errorf("Test #%d failed. Expected %q got %q", i, d.output, output) } } _, error := makePathRelative("a/b/c.ss", "/a/c", "/d/c", "/e/f") if error == nil { t.Errorf("Test failed, expected error") } } func TestGetDottedRelativePath(t *testing.T) { // on Windows this will receive both kinds, both country and western ... for _, f := range []func(string) string{filepath.FromSlash, func(s string) string { return s }} { doTestGetDottedRelativePath(f, t) } } func doTestGetDottedRelativePath(urlFixer func(string) string, t *testing.T) { type test struct { input, expected string } data := []test{ {"", "./"}, {urlFixer("/"), "./"}, {urlFixer("post"), "../"}, {urlFixer("/post"), "../"}, {urlFixer("post/"), "../"}, {urlFixer("tags/foo.html"), "../"}, {urlFixer("/tags/foo.html"), "../"}, {urlFixer("/post/"), "../"}, {urlFixer("////post/////"), "../"}, {urlFixer("/foo/bar/index.html"), "../../"}, {urlFixer("/foo/bar/foo/"), "../../../"}, {urlFixer("/foo/bar/foo"), "../../../"}, {urlFixer("foo/bar/foo/"), "../../../"}, {urlFixer("foo/bar/foo/bar"), "../../../../"}, {"404.html", "./"}, {"404.xml", "./"}, {"/404.html", "./"}, } for i, d := range data { output := GetDottedRelativePath(d.input) if d.expected != output { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) } } } func TestMakeTitle(t *testing.T) { type test struct { input, expected string } data := []test{ {"Make-Title", "Make Title"}, {"MakeTitle", "MakeTitle"}, {"make_title", "make_title"}, } for i, d := range data { output := MakeTitle(d.input) if d.expected != output { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) } } } // Replace Extension is probably poorly named, but the intent of the // function is to accept a path and return only the file name with a // new extension. It's intentionally designed to strip out the path // and only provide the name. We should probably rename the function to // be more explicit at some point. func TestReplaceExtension(t *testing.T) { type test struct { input, newext, expected string } data := []test{ // These work according to the above definition {"/some/random/path/file.xml", "html", "file.html"}, {"/banana.html", "xml", "banana.xml"}, {"./banana.html", "xml", "banana.xml"}, {"banana/pie/index.html", "xml", "index.xml"}, {"../pies/fish/index.html", "xml", "index.xml"}, // but these all fail {"filename-without-an-ext", "ext", "filename-without-an-ext.ext"}, {"/filename-without-an-ext", "ext", "filename-without-an-ext.ext"}, {"/directory/mydir/", "ext", ".ext"}, {"mydir/", "ext", ".ext"}, } for i, d := range data { output := ReplaceExtension(filepath.FromSlash(d.input), d.newext) if d.expected != output { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) } } } func TestExtNoDelimiter(t *testing.T) { c := qt.New(t) c.Assert(ExtNoDelimiter(filepath.FromSlash("/my/data.json")), qt.Equals, "json") } func TestFilename(t *testing.T) { type test struct { input, expected string } data := []test{ {"index.html", "index"}, {"./index.html", "index"}, {"/index.html", "index"}, {"index", "index"}, {"/tmp/index.html", "index"}, {"./filename-no-ext", "filename-no-ext"}, {"/filename-no-ext", "filename-no-ext"}, {"filename-no-ext", "filename-no-ext"}, {"directory/", ""}, // no filename case?? {"directory/.hidden.ext", ".hidden"}, {"./directory/../~/banana/gold.fish", "gold"}, {"../directory/banana.man", "banana"}, {"~/mydir/filename.ext", "filename"}, {"./directory//tmp/filename.ext", "filename"}, } for i, d := range data { output := Filename(filepath.FromSlash(d.input)) if d.expected != output { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) } } } func TestFileAndExt(t *testing.T) { type test struct { input, expectedFile, expectedExt string } data := []test{ {"index.html", "index", ".html"}, {"./index.html", "index", ".html"}, {"/index.html", "index", ".html"}, {"index", "index", ""}, {"/tmp/index.html", "index", ".html"}, {"./filename-no-ext", "filename-no-ext", ""}, {"/filename-no-ext", "filename-no-ext", ""}, {"filename-no-ext", "filename-no-ext", ""}, {"directory/", "", ""}, // no filename case?? {"directory/.hidden.ext", ".hidden", ".ext"}, {"./directory/../~/banana/gold.fish", "gold", ".fish"}, {"../directory/banana.man", "banana", ".man"}, {"~/mydir/filename.ext", "filename", ".ext"}, {"./directory//tmp/filename.ext", "filename", ".ext"}, } for i, d := range data { file, ext := fileAndExt(filepath.FromSlash(d.input), fpb) if d.expectedFile != file { t.Errorf("Test %d failed. Expected filename %q got %q.", i, d.expectedFile, file) } if d.expectedExt != ext { t.Errorf("Test %d failed. Expected extension %q got %q.", i, d.expectedExt, ext) } } } hugo-0.92.2/common/paths/url.go000066400000000000000000000074621420147000300163060ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package paths import ( "fmt" "net/url" "path" "strings" ) type pathBridge struct{} func (pathBridge) Base(in string) string { return path.Base(in) } func (pathBridge) Clean(in string) string { return path.Clean(in) } func (pathBridge) Dir(in string) string { return path.Dir(in) } func (pathBridge) Ext(in string) string { return path.Ext(in) } func (pathBridge) Join(elem ...string) string { return path.Join(elem...) } func (pathBridge) Separator() string { return "/" } var pb pathBridge // MakePermalink combines base URL with content path to create full URL paths. // Example // base: http://spf13.com/ // path: post/how-i-blog // result: http://spf13.com/post/how-i-blog func MakePermalink(host, plink string) *url.URL { base, err := url.Parse(host) if err != nil { panic(err) } p, err := url.Parse(plink) if err != nil { panic(err) } if p.Host != "" { panic(fmt.Errorf("can't make permalink from absolute link %q", plink)) } base.Path = path.Join(base.Path, p.Path) // path.Join will strip off the last /, so put it back if it was there. hadTrailingSlash := (plink == "" && strings.HasSuffix(host, "/")) || strings.HasSuffix(p.Path, "/") if hadTrailingSlash && !strings.HasSuffix(base.Path, "/") { base.Path = base.Path + "/" } return base } // AddContextRoot adds the context root to an URL if it's not already set. // For relative URL entries on sites with a base url with a context root set (i.e. http://example.com/mysite), // relative URLs must not include the context root if canonifyURLs is enabled. But if it's disabled, it must be set. func AddContextRoot(baseURL, relativePath string) string { url, err := url.Parse(baseURL) if err != nil { panic(err) } newPath := path.Join(url.Path, relativePath) // path strips trailing slash, ignore root path. if newPath != "/" && strings.HasSuffix(relativePath, "/") { newPath += "/" } return newPath } // URLizeAn // PrettifyURL takes a URL string and returns a semantic, clean URL. func PrettifyURL(in string) string { x := PrettifyURLPath(in) if path.Base(x) == "index.html" { return path.Dir(x) } if in == "" { return "/" } return x } // PrettifyURLPath takes a URL path to a content and converts it // to enable pretty URLs. // /section/name.html becomes /section/name/index.html // /section/name/ becomes /section/name/index.html // /section/name/index.html becomes /section/name/index.html func PrettifyURLPath(in string) string { return prettifyPath(in, pb) } // Uglify does the opposite of PrettifyURLPath(). // /section/name/index.html becomes /section/name.html // /section/name/ becomes /section/name.html // /section/name.html becomes /section/name.html func Uglify(in string) string { if path.Ext(in) == "" { if len(in) < 2 { return "/" } // /section/name/ -> /section/name.html return path.Clean(in) + ".html" } name, ext := fileAndExt(in, pb) if name == "index" { // /section/name/index.html -> /section/name.html d := path.Dir(in) if len(d) > 1 { return d + ext } return in } // /.xml -> /index.xml if name == "" { return path.Dir(in) + "index" + ext } // /section/name.html -> /section/name.html return path.Clean(in) } hugo-0.92.2/common/paths/url_test.go000066400000000000000000000075021420147000300173400ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package paths import ( "testing" qt "github.com/frankban/quicktest" ) func TestMakePermalink(t *testing.T) { type test struct { host, link, output string } data := []test{ {"http://abc.com/foo", "post/bar", "http://abc.com/foo/post/bar"}, {"http://abc.com/foo/", "post/bar", "http://abc.com/foo/post/bar"}, {"http://abc.com", "post/bar", "http://abc.com/post/bar"}, {"http://abc.com", "bar", "http://abc.com/bar"}, {"http://abc.com/foo/bar", "post/bar", "http://abc.com/foo/bar/post/bar"}, {"http://abc.com/foo/bar", "post/bar/", "http://abc.com/foo/bar/post/bar/"}, } for i, d := range data { output := MakePermalink(d.host, d.link).String() if d.output != output { t.Errorf("Test #%d failed. Expected %q got %q", i, d.output, output) } } } func TestAddContextRoot(t *testing.T) { tests := []struct { baseURL string url string expected string }{ {"http://example.com/sub/", "/foo", "/sub/foo"}, {"http://example.com/sub/", "/foo/index.html", "/sub/foo/index.html"}, {"http://example.com/sub1/sub2", "/foo", "/sub1/sub2/foo"}, {"http://example.com", "/foo", "/foo"}, // cannot guess that the context root is already added int the example below {"http://example.com/sub/", "/sub/foo", "/sub/sub/foo"}, {"http://example.com/тря", "/трям/", "/тря/трям/"}, {"http://example.com", "/", "/"}, {"http://example.com/bar", "//", "/bar/"}, } for _, test := range tests { output := AddContextRoot(test.baseURL, test.url) if output != test.expected { t.Errorf("Expected %#v, got %#v\n", test.expected, output) } } } func TestPretty(t *testing.T) { c := qt.New(t) c.Assert("/section/name/index.html", qt.Equals, PrettifyURLPath("/section/name.html")) c.Assert("/section/sub/name/index.html", qt.Equals, PrettifyURLPath("/section/sub/name.html")) c.Assert("/section/name/index.html", qt.Equals, PrettifyURLPath("/section/name/")) c.Assert("/section/name/index.html", qt.Equals, PrettifyURLPath("/section/name/index.html")) c.Assert("/index.html", qt.Equals, PrettifyURLPath("/index.html")) c.Assert("/name/index.xml", qt.Equals, PrettifyURLPath("/name.xml")) c.Assert("/", qt.Equals, PrettifyURLPath("/")) c.Assert("/", qt.Equals, PrettifyURLPath("")) c.Assert("/section/name", qt.Equals, PrettifyURL("/section/name.html")) c.Assert("/section/sub/name", qt.Equals, PrettifyURL("/section/sub/name.html")) c.Assert("/section/name", qt.Equals, PrettifyURL("/section/name/")) c.Assert("/section/name", qt.Equals, PrettifyURL("/section/name/index.html")) c.Assert("/", qt.Equals, PrettifyURL("/index.html")) c.Assert("/name/index.xml", qt.Equals, PrettifyURL("/name.xml")) c.Assert("/", qt.Equals, PrettifyURL("/")) c.Assert("/", qt.Equals, PrettifyURL("")) } func TestUgly(t *testing.T) { c := qt.New(t) c.Assert("/section/name.html", qt.Equals, Uglify("/section/name.html")) c.Assert("/section/sub/name.html", qt.Equals, Uglify("/section/sub/name.html")) c.Assert("/section/name.html", qt.Equals, Uglify("/section/name/")) c.Assert("/section/name.html", qt.Equals, Uglify("/section/name/index.html")) c.Assert("/index.html", qt.Equals, Uglify("/index.html")) c.Assert("/name.xml", qt.Equals, Uglify("/name.xml")) c.Assert("/", qt.Equals, Uglify("/")) c.Assert("/", qt.Equals, Uglify("")) } hugo-0.92.2/common/terminal/000077500000000000000000000000001420147000300156405ustar00rootroot00000000000000hugo-0.92.2/common/terminal/colors.go000066400000000000000000000035671420147000300175030ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package terminal contains helper for the terminal, such as coloring output. package terminal import ( "fmt" "os" "runtime" "strings" isatty "github.com/mattn/go-isatty" ) const ( errorColor = "\033[1;31m%s\033[0m" warningColor = "\033[0;33m%s\033[0m" noticeColor = "\033[1;36m%s\033[0m" ) // IsTerminal return true if the file descriptor is terminal and the TERM // environment variable isn't a dumb one. func IsTerminal(f *os.File) bool { if runtime.GOOS == "windows" { return false } fd := f.Fd() return os.Getenv("TERM") != "dumb" && (isatty.IsTerminal(fd) || isatty.IsCygwinTerminal(fd)) } // Notice colorizes the string in a noticeable color. func Notice(s string) string { return colorize(s, noticeColor) } // Error colorizes the string in a colour that grabs attention. func Error(s string) string { return colorize(s, errorColor) } // Warning colorizes the string in a colour that warns. func Warning(s string) string { return colorize(s, warningColor) } // colorize s in color. func colorize(s, color string) string { s = fmt.Sprintf(color, doublePercent(s)) return singlePercent(s) } func doublePercent(str string) string { return strings.Replace(str, "%", "%%", -1) } func singlePercent(str string) string { return strings.Replace(str, "%%", "%", -1) } hugo-0.92.2/common/text/000077500000000000000000000000001420147000300150115ustar00rootroot00000000000000hugo-0.92.2/common/text/position.go000066400000000000000000000050051420147000300172040ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package text import ( "fmt" "os" "strings" "github.com/gohugoio/hugo/common/terminal" ) // Positioner represents a thing that knows its position in a text file or stream, // typically an error. type Positioner interface { Position() Position } // Position holds a source position in a text file or stream. type Position struct { Filename string // filename, if any Offset int // byte offset, starting at 0. It's set to -1 if not provided. LineNumber int // line number, starting at 1 ColumnNumber int // column number, starting at 1 (character count per line) } func (pos Position) String() string { if pos.Filename == "" { pos.Filename = "" } return positionStringFormatfunc(pos) } // IsValid returns true if line number is > 0. func (pos Position) IsValid() bool { return pos.LineNumber > 0 } var positionStringFormatfunc func(p Position) string func createPositionStringFormatter(formatStr string) func(p Position) string { if formatStr == "" { formatStr = "\":file::line::col\"" } identifiers := []string{":file", ":line", ":col"} var identifiersFound []string for i := range formatStr { for _, id := range identifiers { if strings.HasPrefix(formatStr[i:], id) { identifiersFound = append(identifiersFound, id) } } } replacer := strings.NewReplacer(":file", "%s", ":line", "%d", ":col", "%d") format := replacer.Replace(formatStr) f := func(pos Position) string { args := make([]interface{}, len(identifiersFound)) for i, id := range identifiersFound { switch id { case ":file": args[i] = pos.Filename case ":line": args[i] = pos.LineNumber case ":col": args[i] = pos.ColumnNumber } } msg := fmt.Sprintf(format, args...) if terminal.IsTerminal(os.Stdout) { return terminal.Notice(msg) } return msg } return f } func init() { positionStringFormatfunc = createPositionStringFormatter(os.Getenv("HUGO_FILE_LOG_FORMAT")) } hugo-0.92.2/common/text/position_test.go000066400000000000000000000023621420147000300202460ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package text import ( "testing" qt "github.com/frankban/quicktest" ) func TestPositionStringFormatter(t *testing.T) { c := qt.New(t) pos := Position{Filename: "/my/file.txt", LineNumber: 12, ColumnNumber: 13, Offset: 14} c.Assert(createPositionStringFormatter(":file|:col|:line")(pos), qt.Equals, "/my/file.txt|13|12") c.Assert(createPositionStringFormatter(":col|:file|:line")(pos), qt.Equals, "13|/my/file.txt|12") c.Assert(createPositionStringFormatter("好::col")(pos), qt.Equals, "好:13") c.Assert(createPositionStringFormatter("")(pos), qt.Equals, "\"/my/file.txt:12:13\"") c.Assert(pos.String(), qt.Equals, "\"/my/file.txt:12:13\"") } hugo-0.92.2/common/text/transform.go000066400000000000000000000025321420147000300173550ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package text import ( "sync" "unicode" "golang.org/x/text/runes" "golang.org/x/text/transform" "golang.org/x/text/unicode/norm" ) var accentTransformerPool = &sync.Pool{ New: func() interface{} { return transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC) }, } // RemoveAccents removes all accents from b. func RemoveAccents(b []byte) []byte { t := accentTransformerPool.Get().(transform.Transformer) b, _, _ = transform.Bytes(t, b) t.Reset() accentTransformerPool.Put(t) return b } // RemoveAccentsString removes all accents from s. func RemoveAccentsString(s string) string { t := accentTransformerPool.Get().(transform.Transformer) s, _, _ = transform.String(t, s) t.Reset() accentTransformerPool.Put(t) return s } hugo-0.92.2/common/text/transform_test.go000066400000000000000000000017071420147000300204170ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package text import ( "testing" qt "github.com/frankban/quicktest" ) func TestRemoveAccents(t *testing.T) { c := qt.New(t) c.Assert(string(RemoveAccents([]byte("Resumé"))), qt.Equals, "Resume") c.Assert(string(RemoveAccents([]byte("Hugo Rocks!"))), qt.Equals, "Hugo Rocks!") c.Assert(string(RemoveAccentsString("Resumé")), qt.Equals, "Resume") } hugo-0.92.2/common/types/000077500000000000000000000000001420147000300151715ustar00rootroot00000000000000hugo-0.92.2/common/types/convert.go000066400000000000000000000062301420147000300172010ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package types import ( "encoding/json" "fmt" "html/template" "reflect" "time" "github.com/spf13/cast" ) // ToDuration converts v to time.Duration. // See ToDurationE if you need to handle errors. func ToDuration(v interface{}) time.Duration { d, _ := ToDurationE(v) return d } // ToDurationE converts v to time.Duration. func ToDurationE(v interface{}) (time.Duration, error) { if n := cast.ToInt(v); n > 0 { return time.Duration(n) * time.Millisecond, nil } d, err := time.ParseDuration(cast.ToString(v)) if err != nil { return 0, fmt.Errorf("cannot convert %v to time.Duration", v) } return d, nil } // ToStringSlicePreserveString is the same as ToStringSlicePreserveStringE, // but it never fails. func ToStringSlicePreserveString(v interface{}) []string { vv, _ := ToStringSlicePreserveStringE(v) return vv } // ToStringSlicePreserveStringE converts v to a string slice. // If v is a string, it will be wrapped in a string slice. func ToStringSlicePreserveStringE(v interface{}) ([]string, error) { if v == nil { return nil, nil } if sds, ok := v.(string); ok { return []string{sds}, nil } result, err := cast.ToStringSliceE(v) if err == nil { return result, nil } // Probably []int or similar. Fall back to reflect. vv := reflect.ValueOf(v) switch vv.Kind() { case reflect.Slice, reflect.Array: result = make([]string, vv.Len()) for i := 0; i < vv.Len(); i++ { s, err := cast.ToStringE(vv.Index(i).Interface()) if err != nil { return nil, err } result[i] = s } return result, nil default: return nil, fmt.Errorf("failed to convert %T to a string slice", v) } } // TypeToString converts v to a string if it's a valid string type. // Note that this will not try to convert numeric values etc., // use ToString for that. func TypeToString(v interface{}) (string, bool) { switch s := v.(type) { case string: return s, true case template.HTML: return string(s), true case template.CSS: return string(s), true case template.HTMLAttr: return string(s), true case template.JS: return string(s), true case template.JSStr: return string(s), true case template.URL: return string(s), true case template.Srcset: return string(s), true } return "", false } // ToString converts v to a string. func ToString(v interface{}) string { s, _ := ToStringE(v) return s } // ToStringE converts v to a string. func ToStringE(v interface{}) (string, error) { if s, ok := TypeToString(v); ok { return s, nil } switch s := v.(type) { case json.RawMessage: return string(s), nil default: return cast.ToStringE(v) } } hugo-0.92.2/common/types/convert_test.go000066400000000000000000000032021420147000300202340ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package types import ( "encoding/json" "testing" "time" qt "github.com/frankban/quicktest" ) func TestToStringSlicePreserveString(t *testing.T) { c := qt.New(t) c.Assert(ToStringSlicePreserveString("Hugo"), qt.DeepEquals, []string{"Hugo"}) c.Assert(ToStringSlicePreserveString(qt.Commentf("Hugo")), qt.DeepEquals, []string{"Hugo"}) c.Assert(ToStringSlicePreserveString([]interface{}{"A", "B"}), qt.DeepEquals, []string{"A", "B"}) c.Assert(ToStringSlicePreserveString([]int{1, 3}), qt.DeepEquals, []string{"1", "3"}) c.Assert(ToStringSlicePreserveString(nil), qt.IsNil) } func TestToString(t *testing.T) { c := qt.New(t) c.Assert(ToString([]byte("Hugo")), qt.Equals, "Hugo") c.Assert(ToString(json.RawMessage("Hugo")), qt.Equals, "Hugo") } func TestToDuration(t *testing.T) { c := qt.New(t) c.Assert(ToDuration("200ms"), qt.Equals, 200*time.Millisecond) c.Assert(ToDuration("200"), qt.Equals, 200*time.Millisecond) c.Assert(ToDuration("4m"), qt.Equals, 4*time.Minute) c.Assert(ToDuration("asdfadf"), qt.Equals, time.Duration(0)) } hugo-0.92.2/common/types/evictingqueue.go000066400000000000000000000050741420147000300204030ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package types contains types shared between packages in Hugo. package types import ( "sync" ) // EvictingStringQueue is a queue which automatically evicts elements from the head of // the queue when attempting to add new elements onto the queue and it is full. // This queue orders elements LIFO (last-in-first-out). It throws away duplicates. // Note: This queue currently does not contain any remove (poll etc.) methods. type EvictingStringQueue struct { size int vals []string set map[string]bool mu sync.Mutex } // NewEvictingStringQueue creates a new queue with the given size. func NewEvictingStringQueue(size int) *EvictingStringQueue { return &EvictingStringQueue{size: size, set: make(map[string]bool)} } // Add adds a new string to the tail of the queue if it's not already there. func (q *EvictingStringQueue) Add(v string) { q.mu.Lock() if q.set[v] { q.mu.Unlock() return } if len(q.set) == q.size { // Full delete(q.set, q.vals[0]) q.vals = append(q.vals[:0], q.vals[1:]...) } q.set[v] = true q.vals = append(q.vals, v) q.mu.Unlock() } // Contains returns whether the queue contains v. func (q *EvictingStringQueue) Contains(v string) bool { q.mu.Lock() defer q.mu.Unlock() return q.set[v] } // Peek looks at the last element added to the queue. func (q *EvictingStringQueue) Peek() string { q.mu.Lock() l := len(q.vals) if l == 0 { q.mu.Unlock() return "" } elem := q.vals[l-1] q.mu.Unlock() return elem } // PeekAll looks at all the elements in the queue, with the newest first. func (q *EvictingStringQueue) PeekAll() []string { q.mu.Lock() vals := make([]string, len(q.vals)) copy(vals, q.vals) q.mu.Unlock() for i, j := 0, len(vals)-1; i < j; i, j = i+1, j-1 { vals[i], vals[j] = vals[j], vals[i] } return vals } // PeekAllSet returns PeekAll as a set. func (q *EvictingStringQueue) PeekAllSet() map[string]bool { all := q.PeekAll() set := make(map[string]bool) for _, v := range all { set[v] = true } return set } hugo-0.92.2/common/types/evictingqueue_test.go000066400000000000000000000035231420147000300214370ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package types import ( "sync" "testing" qt "github.com/frankban/quicktest" ) func TestEvictingStringQueue(t *testing.T) { c := qt.New(t) queue := NewEvictingStringQueue(3) c.Assert(queue.Peek(), qt.Equals, "") queue.Add("a") queue.Add("b") queue.Add("a") c.Assert(queue.Peek(), qt.Equals, "b") queue.Add("b") c.Assert(queue.Peek(), qt.Equals, "b") queue.Add("a") queue.Add("b") c.Assert(queue.Contains("a"), qt.Equals, true) c.Assert(queue.Contains("foo"), qt.Equals, false) c.Assert(queue.PeekAll(), qt.DeepEquals, []string{"b", "a"}) c.Assert(queue.Peek(), qt.Equals, "b") queue.Add("c") queue.Add("d") // Overflowed, a should now be removed. c.Assert(queue.PeekAll(), qt.DeepEquals, []string{"d", "c", "b"}) c.Assert(len(queue.PeekAllSet()), qt.Equals, 3) c.Assert(queue.PeekAllSet()["c"], qt.Equals, true) } func TestEvictingStringQueueConcurrent(t *testing.T) { var wg sync.WaitGroup val := "someval" queue := NewEvictingStringQueue(3) for j := 0; j < 100; j++ { wg.Add(1) go func() { defer wg.Done() queue.Add(val) v := queue.Peek() if v != val { t.Error("wrong val") } vals := queue.PeekAll() if len(vals) != 1 || vals[0] != val { t.Error("wrong val") } }() } wg.Wait() } hugo-0.92.2/common/types/types.go000066400000000000000000000043571420147000300166750ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package types contains types shared between packages in Hugo. package types import ( "fmt" "reflect" "github.com/spf13/cast" ) // RLocker represents the read locks in sync.RWMutex. type RLocker interface { RLock() RUnlock() } // KeyValue is a interface{} tuple. type KeyValue struct { Key interface{} Value interface{} } // KeyValueStr is a string tuple. type KeyValueStr struct { Key string Value string } // KeyValues holds an key and a slice of values. type KeyValues struct { Key interface{} Values []interface{} } // KeyString returns the key as a string, an empty string if conversion fails. func (k KeyValues) KeyString() string { return cast.ToString(k.Key) } func (k KeyValues) String() string { return fmt.Sprintf("%v: %v", k.Key, k.Values) } // NewKeyValuesStrings takes a given key and slice of values and returns a new // KeyValues struct. func NewKeyValuesStrings(key string, values ...string) KeyValues { iv := make([]interface{}, len(values)) for i := 0; i < len(values); i++ { iv[i] = values[i] } return KeyValues{Key: key, Values: iv} } // Zeroer, as implemented by time.Time, will be used by the truth template // funcs in Hugo (if, with, not, and, or). type Zeroer interface { IsZero() bool } // IsNil reports whether v is nil. func IsNil(v interface{}) bool { if v == nil { return true } value := reflect.ValueOf(v) switch value.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: return value.IsNil() } return false } // DevMarker is a marker interface for types that should only be used during // development. type DevMarker interface { DevOnly() } hugo-0.92.2/common/types/types_test.go000066400000000000000000000016041420147000300177240ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package types import ( "testing" qt "github.com/frankban/quicktest" ) func TestKeyValues(t *testing.T) { c := qt.New(t) kv := NewKeyValuesStrings("key", "a1", "a2") c.Assert(kv.KeyString(), qt.Equals, "key") c.Assert(kv.Values, qt.DeepEquals, []interface{}{"a1", "a2"}) } hugo-0.92.2/common/urls/000077500000000000000000000000001420147000300150125ustar00rootroot00000000000000hugo-0.92.2/common/urls/ref.go000066400000000000000000000016231420147000300161170ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package urls // RefLinker is implemented by those who support reference linking. // args must contain a path, but can also point to the target // language or output format. type RefLinker interface { Ref(args map[string]interface{}) (string, error) RelRef(args map[string]interface{}) (string, error) } hugo-0.92.2/compare/000077500000000000000000000000001420147000300141635ustar00rootroot00000000000000hugo-0.92.2/compare/compare.go000066400000000000000000000024341420147000300161430ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package compare // Eqer can be used to determine if this value is equal to the other. // The semantics of equals is that the two value are interchangeable // in the Hugo templates. type Eqer interface { Eq(other interface{}) bool } // ProbablyEqer is an equal check that may return false positives, but never // a false negative. type ProbablyEqer interface { ProbablyEq(other interface{}) bool } // Comparer can be used to compare two values. // This will be used when using the le, ge etc. operators in the templates. // Compare returns -1 if the given version is less than, 0 if equal and 1 if greater than // the running version. type Comparer interface { Compare(other interface{}) int } hugo-0.92.2/compare/compare_strings.go000066400000000000000000000042371420147000300177170ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package compare import ( "strings" "unicode" "unicode/utf8" ) // Strings returns an integer comparing two strings lexicographically. func Strings(s, t string) int { c := compareFold(s, t) if c == 0 { // "B" and "b" would be the same so we need a tiebreaker. return strings.Compare(s, t) } return c } // This function is derived from strings.EqualFold in Go's stdlib. // https://github.com/golang/go/blob/ad4a58e31501bce5de2aad90a620eaecdc1eecb8/src/strings/strings.go#L893 func compareFold(s, t string) int { for s != "" && t != "" { var sr, tr rune if s[0] < utf8.RuneSelf { sr, s = rune(s[0]), s[1:] } else { r, size := utf8.DecodeRuneInString(s) sr, s = r, s[size:] } if t[0] < utf8.RuneSelf { tr, t = rune(t[0]), t[1:] } else { r, size := utf8.DecodeRuneInString(t) tr, t = r, t[size:] } if tr == sr { continue } c := 1 if tr < sr { tr, sr = sr, tr c = -c } // ASCII only. if tr < utf8.RuneSelf { if sr >= 'A' && sr <= 'Z' { if tr <= 'Z' { // Same case. return -c } diff := tr - (sr + 'a' - 'A') if diff == 0 { continue } if diff < 0 { return c } if diff > 0 { return -c } } } // Unicode. r := unicode.SimpleFold(sr) for r != sr && r < tr { r = unicode.SimpleFold(r) } if r == tr { continue } return -c } if s == "" && t == "" { return 0 } if s == "" { return -1 } return 1 } // LessStrings returns whether s is less than t lexicographically. func LessStrings(s, t string) bool { return Strings(s, t) < 0 } hugo-0.92.2/compare/compare_strings_test.go000066400000000000000000000027341420147000300207560ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package compare import ( "sort" "strings" "testing" qt "github.com/frankban/quicktest" ) func TestCompare(t *testing.T) { c := qt.New(t) for _, test := range []struct { a string b string }{ {"a", "a"}, {"A", "a"}, {"Ab", "Ac"}, {"az", "Za"}, {"C", "D"}, {"B", "a"}, {"C", ""}, {"", ""}, {"αβδC", "ΑΒΔD"}, {"αβδC", "ΑΒΔ"}, {"αβδ", "ΑΒΔD"}, {"αβδ", "ΑΒΔ"}, {"β", "δ"}, {"好", strings.ToLower("好")}, } { expect := strings.Compare(strings.ToLower(test.a), strings.ToLower(test.b)) got := compareFold(test.a, test.b) c.Assert(got, qt.Equals, expect) } } func TestLexicographicSort(t *testing.T) { c := qt.New(t) s := []string{"b", "Bz", "ba", "A", "Ba", "ba"} sort.Slice(s, func(i, j int) bool { return LessStrings(s[i], s[j]) }) c.Assert(s, qt.DeepEquals, []string{"A", "b", "Ba", "ba", "ba", "Bz"}) } hugo-0.92.2/config/000077500000000000000000000000001420147000300140025ustar00rootroot00000000000000hugo-0.92.2/config/commonConfig.go000066400000000000000000000116031420147000300167500ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "sort" "strings" "sync" "github.com/pkg/errors" "github.com/gohugoio/hugo/common/types" "github.com/gobwas/glob" "github.com/gohugoio/hugo/common/herrors" "github.com/mitchellh/mapstructure" "github.com/spf13/cast" jww "github.com/spf13/jwalterweatherman" ) var DefaultBuild = Build{ UseResourceCacheWhen: "fallback", WriteStats: false, } // Build holds some build related configuration. type Build struct { UseResourceCacheWhen string // never, fallback, always. Default is fallback // When enabled, will collect and write a hugo_stats.json with some build // related aggregated data (e.g. CSS class names). WriteStats bool // Can be used to toggle off writing of the intellinsense /assets/jsconfig.js // file. NoJSConfigInAssets bool } func (b Build) UseResourceCache(err error) bool { if b.UseResourceCacheWhen == "never" { return false } if b.UseResourceCacheWhen == "fallback" { return err == herrors.ErrFeatureNotAvailable } return true } func DecodeBuild(cfg Provider) Build { m := cfg.GetStringMap("build") b := DefaultBuild if m == nil { return b } err := mapstructure.WeakDecode(m, &b) if err != nil { return DefaultBuild } b.UseResourceCacheWhen = strings.ToLower(b.UseResourceCacheWhen) when := b.UseResourceCacheWhen if when != "never" && when != "always" && when != "fallback" { b.UseResourceCacheWhen = "fallback" } return b } // Sitemap configures the sitemap to be generated. type Sitemap struct { ChangeFreq string Priority float64 Filename string } func DecodeSitemap(prototype Sitemap, input map[string]interface{}) Sitemap { for key, value := range input { switch key { case "changefreq": prototype.ChangeFreq = cast.ToString(value) case "priority": prototype.Priority = cast.ToFloat64(value) case "filename": prototype.Filename = cast.ToString(value) default: jww.WARN.Printf("Unknown Sitemap field: %s\n", key) } } return prototype } // Config for the dev server. type Server struct { Headers []Headers Redirects []Redirect compiledInit sync.Once compiledHeaders []glob.Glob compiledRedirects []glob.Glob } func (s *Server) init() { s.compiledInit.Do(func() { for _, h := range s.Headers { s.compiledHeaders = append(s.compiledHeaders, glob.MustCompile(h.For)) } for _, r := range s.Redirects { s.compiledRedirects = append(s.compiledRedirects, glob.MustCompile(r.From)) } }) } func (s *Server) MatchHeaders(pattern string) []types.KeyValueStr { s.init() if s.compiledHeaders == nil { return nil } var matches []types.KeyValueStr for i, g := range s.compiledHeaders { if g.Match(pattern) { h := s.Headers[i] for k, v := range h.Values { matches = append(matches, types.KeyValueStr{Key: k, Value: cast.ToString(v)}) } } } sort.Slice(matches, func(i, j int) bool { return matches[i].Key < matches[j].Key }) return matches } func (s *Server) MatchRedirect(pattern string) Redirect { s.init() if s.compiledRedirects == nil { return Redirect{} } pattern = strings.TrimSuffix(pattern, "index.html") for i, g := range s.compiledRedirects { redir := s.Redirects[i] // No redirect to self. if redir.To == pattern { return Redirect{} } if g.Match(pattern) { return redir } } return Redirect{} } type Headers struct { For string Values map[string]interface{} } type Redirect struct { From string To string Status int Force bool } func (r Redirect) IsZero() bool { return r.From == "" } func DecodeServer(cfg Provider) (*Server, error) { m := cfg.GetStringMap("server") s := &Server{} if m == nil { return s, nil } _ = mapstructure.WeakDecode(m, s) for i, redir := range s.Redirects { // Get it in line with the Hugo server. redir.To = strings.TrimSuffix(redir.To, "index.html") if !strings.HasPrefix(redir.To, "https") && !strings.HasSuffix(redir.To, "/") { // There are some tricky infinite loop situations when dealing // when the target does not have a trailing slash. // This can certainly be handled better, but not time for that now. return nil, errors.Errorf("unsupported redirect to value %q in server config; currently this must be either a remote destination or a local folder, e.g. \"/blog/\" or \"/blog/index.html\"", redir.To) } s.Redirects[i] = redir } return s, nil } hugo-0.92.2/config/commonConfig_test.go000066400000000000000000000066071420147000300200170ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "errors" "testing" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/types" qt "github.com/frankban/quicktest" ) func TestBuild(t *testing.T) { c := qt.New(t) v := New() v.Set("build", map[string]interface{}{ "useResourceCacheWhen": "always", }) b := DecodeBuild(v) c.Assert(b.UseResourceCacheWhen, qt.Equals, "always") v.Set("build", map[string]interface{}{ "useResourceCacheWhen": "foo", }) b = DecodeBuild(v) c.Assert(b.UseResourceCacheWhen, qt.Equals, "fallback") c.Assert(b.UseResourceCache(herrors.ErrFeatureNotAvailable), qt.Equals, true) c.Assert(b.UseResourceCache(errors.New("err")), qt.Equals, false) b.UseResourceCacheWhen = "always" c.Assert(b.UseResourceCache(herrors.ErrFeatureNotAvailable), qt.Equals, true) c.Assert(b.UseResourceCache(errors.New("err")), qt.Equals, true) c.Assert(b.UseResourceCache(nil), qt.Equals, true) b.UseResourceCacheWhen = "never" c.Assert(b.UseResourceCache(herrors.ErrFeatureNotAvailable), qt.Equals, false) c.Assert(b.UseResourceCache(errors.New("err")), qt.Equals, false) c.Assert(b.UseResourceCache(nil), qt.Equals, false) } func TestServer(t *testing.T) { c := qt.New(t) cfg, err := FromConfigString(`[[server.headers]] for = "/*.jpg" [server.headers.values] X-Frame-Options = "DENY" X-XSS-Protection = "1; mode=block" X-Content-Type-Options = "nosniff" [[server.redirects]] from = "/foo/**" to = "/foo/index.html" status = 200 [[server.redirects]] from = "/google/**" to = "https://google.com/" status = 301 [[server.redirects]] from = "/**" to = "/default/index.html" status = 301 `, "toml") c.Assert(err, qt.IsNil) s, err := DecodeServer(cfg) c.Assert(err, qt.IsNil) c.Assert(s.MatchHeaders("/foo.jpg"), qt.DeepEquals, []types.KeyValueStr{ {Key: "X-Content-Type-Options", Value: "nosniff"}, {Key: "X-Frame-Options", Value: "DENY"}, {Key: "X-XSS-Protection", Value: "1; mode=block"}, }) c.Assert(s.MatchRedirect("/foo/bar/baz"), qt.DeepEquals, Redirect{ From: "/foo/**", To: "/foo/", Status: 200, }) c.Assert(s.MatchRedirect("/someother"), qt.DeepEquals, Redirect{ From: "/**", To: "/default/", Status: 301, }) c.Assert(s.MatchRedirect("/google/foo"), qt.DeepEquals, Redirect{ From: "/google/**", To: "https://google.com/", Status: 301, }) // No redirect loop, please. c.Assert(s.MatchRedirect("/default/index.html"), qt.DeepEquals, Redirect{}) c.Assert(s.MatchRedirect("/default/"), qt.DeepEquals, Redirect{}) for _, errorCase := range []string{ `[[server.redirects]] from = "/**" to = "/file" status = 301`, `[[server.redirects]] from = "/**" to = "/foo/file.html" status = 301`, } { cfg, err := FromConfigString(errorCase, "toml") c.Assert(err, qt.IsNil) _, err = DecodeServer(cfg) c.Assert(err, qt.Not(qt.IsNil)) } } hugo-0.92.2/config/compositeConfig.go000066400000000000000000000055301420147000300174640ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "github.com/gohugoio/hugo/common/maps" ) // NewCompositeConfig creates a new composite Provider with a read-only base // and a writeable layer. func NewCompositeConfig(base, layer Provider) Provider { return &compositeConfig{ base: base, layer: layer, } } // compositeConfig contains a read only config base with // a possibly writeable config layer on top. type compositeConfig struct { base Provider layer Provider } func (c *compositeConfig) GetBool(key string) bool { if c.layer.IsSet(key) { return c.layer.GetBool(key) } return c.base.GetBool(key) } func (c *compositeConfig) GetInt(key string) int { if c.layer.IsSet(key) { return c.layer.GetInt(key) } return c.base.GetInt(key) } func (c *compositeConfig) Merge(key string, value interface{}) { c.layer.Merge(key, value) } func (c *compositeConfig) GetParams(key string) maps.Params { if c.layer.IsSet(key) { return c.layer.GetParams(key) } return c.base.GetParams(key) } func (c *compositeConfig) GetStringMap(key string) map[string]interface{} { if c.layer.IsSet(key) { return c.layer.GetStringMap(key) } return c.base.GetStringMap(key) } func (c *compositeConfig) GetStringMapString(key string) map[string]string { if c.layer.IsSet(key) { return c.layer.GetStringMapString(key) } return c.base.GetStringMapString(key) } func (c *compositeConfig) GetStringSlice(key string) []string { if c.layer.IsSet(key) { return c.layer.GetStringSlice(key) } return c.base.GetStringSlice(key) } func (c *compositeConfig) Get(key string) interface{} { if c.layer.IsSet(key) { return c.layer.Get(key) } return c.base.Get(key) } func (c *compositeConfig) IsSet(key string) bool { if c.layer.IsSet(key) { return true } return c.base.IsSet(key) } func (c *compositeConfig) GetString(key string) string { if c.layer.IsSet(key) { return c.layer.GetString(key) } return c.base.GetString(key) } func (c *compositeConfig) Set(key string, value interface{}) { c.layer.Set(key, value) } func (c *compositeConfig) SetDefaults(params maps.Params) { c.layer.SetDefaults(params) } func (c *compositeConfig) WalkParams(walkFn func(params ...KeyParams) bool) { panic("not supported") } func (c *compositeConfig) SetDefaultMergeStrategy() { panic("not supported") } hugo-0.92.2/config/compositeConfig_test.go000066400000000000000000000022331420147000300205200ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "testing" qt "github.com/frankban/quicktest" ) func TestCompositeConfig(t *testing.T) { c := qt.New(t) c.Run("Set and get", func(c *qt.C) { base, layer := New(), New() cfg := NewCompositeConfig(base, layer) layer.Set("a1", "av") base.Set("b1", "bv") cfg.Set("c1", "cv") c.Assert(cfg.Get("a1"), qt.Equals, "av") c.Assert(cfg.Get("b1"), qt.Equals, "bv") c.Assert(cfg.Get("c1"), qt.Equals, "cv") c.Assert(cfg.IsSet("c1"), qt.IsTrue) c.Assert(layer.IsSet("c1"), qt.IsTrue) c.Assert(base.IsSet("c1"), qt.IsFalse) }) } hugo-0.92.2/config/configLoader.go000066400000000000000000000122661420147000300167340ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "os" "path/filepath" "strings" "github.com/gohugoio/hugo/common/herrors" "github.com/pkg/errors" "github.com/gohugoio/hugo/common/paths" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/parser/metadecoders" "github.com/spf13/afero" ) var ( ValidConfigFileExtensions = []string{"toml", "yaml", "yml", "json"} validConfigFileExtensionsMap map[string]bool = make(map[string]bool) ) func init() { for _, ext := range ValidConfigFileExtensions { validConfigFileExtensionsMap[ext] = true } } // IsValidConfigFilename returns whether filename is one of the supported // config formats in Hugo. func IsValidConfigFilename(filename string) bool { ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(filename), ".")) return validConfigFileExtensionsMap[ext] } // FromConfigString creates a config from the given YAML, JSON or TOML config. This is useful in tests. func FromConfigString(config, configType string) (Provider, error) { m, err := readConfig(metadecoders.FormatFromString(configType), []byte(config)) if err != nil { return nil, err } return NewFrom(m), nil } // FromFile loads the configuration from the given filename. func FromFile(fs afero.Fs, filename string) (Provider, error) { m, err := loadConfigFromFile(fs, filename) if err != nil { return nil, herrors.WithFileContextForFileDefault(err, filename, fs) } return NewFrom(m), nil } // FromFileToMap is the same as FromFile, but it returns the config values // as a simple map. func FromFileToMap(fs afero.Fs, filename string) (map[string]interface{}, error) { return loadConfigFromFile(fs, filename) } func readConfig(format metadecoders.Format, data []byte) (map[string]interface{}, error) { m, err := metadecoders.Default.UnmarshalToMap(data, format) if err != nil { return nil, err } RenameKeys(m) return m, nil } func loadConfigFromFile(fs afero.Fs, filename string) (map[string]interface{}, error) { m, err := metadecoders.Default.UnmarshalFileToMap(fs, filename) if err != nil { return nil, err } RenameKeys(m) return m, nil } func LoadConfigFromDir(sourceFs afero.Fs, configDir, environment string) (Provider, []string, error) { defaultConfigDir := filepath.Join(configDir, "_default") environmentConfigDir := filepath.Join(configDir, environment) cfg := New() var configDirs []string // Merge from least to most specific. for _, dir := range []string{defaultConfigDir, environmentConfigDir} { if _, err := sourceFs.Stat(dir); err == nil { configDirs = append(configDirs, dir) } } if len(configDirs) == 0 { return nil, nil, nil } // Keep track of these so we can watch them for changes. var dirnames []string for _, configDir := range configDirs { err := afero.Walk(sourceFs, configDir, func(path string, fi os.FileInfo, err error) error { if fi == nil || err != nil { return nil } if fi.IsDir() { dirnames = append(dirnames, path) return nil } if !IsValidConfigFilename(path) { return nil } name := paths.Filename(filepath.Base(path)) item, err := metadecoders.Default.UnmarshalFileToMap(sourceFs, path) if err != nil { // This will be used in error reporting, use the most specific value. dirnames = []string{path} return errors.Wrapf(err, "failed to unmarshl config for path %q", path) } var keyPath []string if name != "config" { // Can be params.jp, menus.en etc. name, lang := paths.FileAndExtNoDelimiter(name) keyPath = []string{name} if lang != "" { keyPath = []string{"languages", lang} switch name { case "menu", "menus": keyPath = append(keyPath, "menus") case "params": keyPath = append(keyPath, "params") } } } root := item if len(keyPath) > 0 { root = make(map[string]interface{}) m := root for i, key := range keyPath { if i >= len(keyPath)-1 { m[key] = item } else { nm := make(map[string]interface{}) m[key] = nm m = nm } } } // Migrate menu => menus etc. RenameKeys(root) // Set will overwrite keys with the same name, recursively. cfg.Set("", root) return nil }) if err != nil { return nil, dirnames, err } } return cfg, dirnames, nil } var keyAliases maps.KeyRenamer func init() { var err error keyAliases, err = maps.NewKeyRenamer( // Before 0.53 we used singular for "menu". "{menu,languages/*/menu}", "menus", ) if err != nil { panic(err) } } // RenameKeys renames config keys in m recursively according to a global Hugo // alias definition. func RenameKeys(m map[string]interface{}) { keyAliases.Rename(m) } hugo-0.92.2/config/configLoader_test.go000066400000000000000000000021251420147000300177640ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "strings" "testing" qt "github.com/frankban/quicktest" ) func TestIsValidConfigFileName(t *testing.T) { c := qt.New(t) for _, ext := range ValidConfigFileExtensions { filename := "config." + ext c.Assert(IsValidConfigFilename(filename), qt.Equals, true) c.Assert(IsValidConfigFilename(strings.ToUpper(filename)), qt.Equals, true) } c.Assert(IsValidConfigFilename(""), qt.Equals, false) c.Assert(IsValidConfigFilename("config.toml.swp"), qt.Equals, false) } hugo-0.92.2/config/configProvider.go000066400000000000000000000037611420147000300173200ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/types" ) // Provider provides the configuration settings for Hugo. type Provider interface { GetString(key string) string GetInt(key string) int GetBool(key string) bool GetParams(key string) maps.Params GetStringMap(key string) map[string]interface{} GetStringMapString(key string) map[string]string GetStringSlice(key string) []string Get(key string) interface{} Set(key string, value interface{}) Merge(key string, value interface{}) SetDefaults(params maps.Params) SetDefaultMergeStrategy() WalkParams(walkFn func(params ...KeyParams) bool) IsSet(key string) bool } // GetStringSlicePreserveString returns a string slice from the given config and key. // It differs from the GetStringSlice method in that if the config value is a string, // we do not attempt to split it into fields. func GetStringSlicePreserveString(cfg Provider, key string) []string { sd := cfg.Get(key) return types.ToStringSlicePreserveString(sd) } // SetBaseTestDefaults provides some common config defaults used in tests. func SetBaseTestDefaults(cfg Provider) { cfg.Set("resourceDir", "resources") cfg.Set("contentDir", "content") cfg.Set("dataDir", "data") cfg.Set("i18nDir", "i18n") cfg.Set("layoutDir", "layouts") cfg.Set("assetDir", "assets") cfg.Set("archetypeDir", "archetypes") cfg.Set("publishDir", "public") } hugo-0.92.2/config/configProvider_test.go000066400000000000000000000021161420147000300203500ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "testing" qt "github.com/frankban/quicktest" ) func TestGetStringSlicePreserveString(t *testing.T) { c := qt.New(t) cfg := New() s := "This is a string" sSlice := []string{"This", "is", "a", "slice"} cfg.Set("s1", s) cfg.Set("s2", sSlice) c.Assert(GetStringSlicePreserveString(cfg, "s1"), qt.DeepEquals, []string{s}) c.Assert(GetStringSlicePreserveString(cfg, "s2"), qt.DeepEquals, sSlice) c.Assert(GetStringSlicePreserveString(cfg, "s3"), qt.IsNil) } hugo-0.92.2/config/defaultConfigProvider.go000066400000000000000000000236641420147000300206310ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "fmt" "sort" "strings" "sync" "github.com/spf13/cast" "github.com/gohugoio/hugo/common/maps" ) var ( // ConfigRootKeysSet contains all of the config map root keys. ConfigRootKeysSet = map[string]bool{ "build": true, "caches": true, "cascade": true, "frontmatter": true, "languages": true, "imaging": true, "markup": true, "mediatypes": true, "menus": true, "minify": true, "module": true, "outputformats": true, "params": true, "permalinks": true, "related": true, "sitemap": true, "privacy": true, "security": true, "taxonomies": true, } // ConfigRootKeys is a sorted version of ConfigRootKeysSet. ConfigRootKeys []string ) func init() { for k := range ConfigRootKeysSet { ConfigRootKeys = append(ConfigRootKeys, k) } sort.Strings(ConfigRootKeys) } // New creates a Provider backed by an empty maps.Params. func New() Provider { return &defaultConfigProvider{ root: make(maps.Params), } } // NewFrom creates a Provider backed by params. func NewFrom(params maps.Params) Provider { maps.PrepareParams(params) return &defaultConfigProvider{ root: params, } } // defaultConfigProvider is a Provider backed by a map where all keys are lower case. // All methods are thread safe. type defaultConfigProvider struct { mu sync.RWMutex root maps.Params keyCache sync.Map } func (c *defaultConfigProvider) Get(k string) interface{} { if k == "" { return c.root } c.mu.RLock() key, m := c.getNestedKeyAndMap(strings.ToLower(k), false) if m == nil { c.mu.RUnlock() return nil } v := m[key] c.mu.RUnlock() return v } func (c *defaultConfigProvider) GetBool(k string) bool { v := c.Get(k) return cast.ToBool(v) } func (c *defaultConfigProvider) GetInt(k string) int { v := c.Get(k) return cast.ToInt(v) } func (c *defaultConfigProvider) IsSet(k string) bool { var found bool c.mu.RLock() key, m := c.getNestedKeyAndMap(strings.ToLower(k), false) if m != nil { _, found = m[key] } c.mu.RUnlock() return found } func (c *defaultConfigProvider) GetString(k string) string { v := c.Get(k) return cast.ToString(v) } func (c *defaultConfigProvider) GetParams(k string) maps.Params { v := c.Get(k) if v == nil { return nil } return v.(maps.Params) } func (c *defaultConfigProvider) GetStringMap(k string) map[string]interface{} { v := c.Get(k) return maps.ToStringMap(v) } func (c *defaultConfigProvider) GetStringMapString(k string) map[string]string { v := c.Get(k) return maps.ToStringMapString(v) } func (c *defaultConfigProvider) GetStringSlice(k string) []string { v := c.Get(k) return cast.ToStringSlice(v) } func (c *defaultConfigProvider) Set(k string, v interface{}) { c.mu.Lock() defer c.mu.Unlock() k = strings.ToLower(k) if k == "" { if p, ok := maps.ToParamsAndPrepare(v); ok { // Set the values directly in root. c.root.Set(p) } else { c.root[k] = v } return } switch vv := v.(type) { case map[string]interface{}, map[interface{}]interface{}, map[string]string: p := maps.MustToParamsAndPrepare(vv) v = p } key, m := c.getNestedKeyAndMap(k, true) if m == nil { return } if existing, found := m[key]; found { if p1, ok := existing.(maps.Params); ok { if p2, ok := v.(maps.Params); ok { p1.Set(p2) return } } } m[key] = v } // SetDefaults will set values from params if not already set. func (c *defaultConfigProvider) SetDefaults(params maps.Params) { maps.PrepareParams(params) for k, v := range params { if _, found := c.root[k]; !found { c.root[k] = v } } } func (c *defaultConfigProvider) Merge(k string, v interface{}) { c.mu.Lock() defer c.mu.Unlock() k = strings.ToLower(k) const ( languagesKey = "languages" paramsKey = "params" menusKey = "menus" ) if k == "" { rs, f := c.root.GetMergeStrategy() if f && rs == maps.ParamsMergeStrategyNone { // The user has set a "no merge" strategy on this, // nothing more to do. return } if p, ok := maps.ToParamsAndPrepare(v); ok { // As there may be keys in p not in root, we need to handle // those as a special case. var keysToDelete []string for kk, vv := range p { if pp, ok := vv.(maps.Params); ok { if pppi, ok := c.root[kk]; ok { ppp := pppi.(maps.Params) if kk == languagesKey { // Languages is currently a special case. // We may have languages with menus or params in the // right map that is not present in the left map. // With the default merge strategy those items will not // be passed over. var hasParams, hasMenus bool for _, rv := range pp { if lkp, ok := rv.(maps.Params); ok { _, hasMenus = lkp[menusKey] _, hasParams = lkp[paramsKey] } } if hasMenus || hasParams { for _, lv := range ppp { if lkp, ok := lv.(maps.Params); ok { if hasMenus { if _, ok := lkp[menusKey]; !ok { p := maps.Params{} p.SetDefaultMergeStrategy(maps.ParamsMergeStrategyShallow) lkp[menusKey] = p } } if hasParams { if _, ok := lkp[paramsKey]; !ok { p := maps.Params{} p.SetDefaultMergeStrategy(maps.ParamsMergeStrategyShallow) lkp[paramsKey] = p } } } } } } ppp.Merge(pp) } else { // We need to use the default merge strategy for // this key. np := make(maps.Params) strategy := c.determineMergeStrategy(KeyParams{Key: "", Params: c.root}, KeyParams{Key: kk, Params: np}) np.SetDefaultMergeStrategy(strategy) np.Merge(pp) c.root[kk] = np if np.IsZero() { // Just keep it until merge is done. keysToDelete = append(keysToDelete, kk) } } } } // Merge the rest. c.root.MergeRoot(p) for _, k := range keysToDelete { delete(c.root, k) } } else { panic(fmt.Sprintf("unsupported type %T received in Merge", v)) } return } switch vv := v.(type) { case map[string]interface{}, map[interface{}]interface{}, map[string]string: p := maps.MustToParamsAndPrepare(vv) v = p } key, m := c.getNestedKeyAndMap(k, true) if m == nil { return } if existing, found := m[key]; found { if p1, ok := existing.(maps.Params); ok { if p2, ok := v.(maps.Params); ok { p1.Merge(p2) } } } else { m[key] = v } } func (c *defaultConfigProvider) WalkParams(walkFn func(params ...KeyParams) bool) { var walk func(params ...KeyParams) walk = func(params ...KeyParams) { if walkFn(params...) { return } p1 := params[len(params)-1] i := len(params) for k, v := range p1.Params { if p2, ok := v.(maps.Params); ok { paramsplus1 := make([]KeyParams, i+1) copy(paramsplus1, params) paramsplus1[i] = KeyParams{Key: k, Params: p2} walk(paramsplus1...) } } } walk(KeyParams{Key: "", Params: c.root}) } func (c *defaultConfigProvider) determineMergeStrategy(params ...KeyParams) maps.ParamsMergeStrategy { if len(params) == 0 { return maps.ParamsMergeStrategyNone } var ( strategy maps.ParamsMergeStrategy prevIsRoot bool curr = params[len(params)-1] ) if len(params) > 1 { prev := params[len(params)-2] prevIsRoot = prev.Key == "" // Inherit from parent (but not from the root unless it's set by user). s, found := prev.Params.GetMergeStrategy() if !prevIsRoot && !found { panic("invalid state, merge strategy not set on parent") } if found || !prevIsRoot { strategy = s } } switch curr.Key { case "": // Don't set a merge strategy on the root unless set by user. // This will be handled as a special case. case "params": strategy = maps.ParamsMergeStrategyDeep case "outputformats", "mediatypes": if prevIsRoot { strategy = maps.ParamsMergeStrategyShallow } case "menus": isMenuKey := prevIsRoot if !isMenuKey { // Can also be set below languages. // root > languages > en > menus if len(params) == 4 && params[1].Key == "languages" { isMenuKey = true } } if isMenuKey { strategy = maps.ParamsMergeStrategyShallow } default: if strategy == "" { strategy = maps.ParamsMergeStrategyNone } } return strategy } type KeyParams struct { Key string Params maps.Params } func (c *defaultConfigProvider) SetDefaultMergeStrategy() { c.WalkParams(func(params ...KeyParams) bool { if len(params) == 0 { return false } p := params[len(params)-1].Params var found bool if _, found = p.GetMergeStrategy(); found { // Set by user. return false } strategy := c.determineMergeStrategy(params...) if strategy != "" { p.SetDefaultMergeStrategy(strategy) } return false }) } func (c *defaultConfigProvider) getNestedKeyAndMap(key string, create bool) (string, maps.Params) { var parts []string v, ok := c.keyCache.Load(key) if ok { parts = v.([]string) } else { parts = strings.Split(key, ".") c.keyCache.Store(key, parts) } current := c.root for i := 0; i < len(parts)-1; i++ { next, found := current[parts[i]] if !found { if create { next = make(maps.Params) current[parts[i]] = next } else { return "", nil } } var ok bool current, ok = next.(maps.Params) if !ok { // E.g. a string, not a map that we can store values in. return "", nil } } return parts[len(parts)-1], current } hugo-0.92.2/config/defaultConfigProvider_test.go000066400000000000000000000164321420147000300216630ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "context" "errors" "fmt" "strconv" "strings" "testing" "github.com/spf13/viper" "github.com/gohugoio/hugo/common/para" "github.com/gohugoio/hugo/common/maps" qt "github.com/frankban/quicktest" ) func TestDefaultConfigProvider(t *testing.T) { c := qt.New(t) c.Run("Set and get", func(c *qt.C) { cfg := New() var k string var v interface{} k, v = "foo", "bar" cfg.Set(k, v) c.Assert(cfg.Get(k), qt.Equals, v) c.Assert(cfg.Get(strings.ToUpper(k)), qt.Equals, v) c.Assert(cfg.GetString(k), qt.Equals, v) k, v = "foo", 42 cfg.Set(k, v) c.Assert(cfg.Get(k), qt.Equals, v) c.Assert(cfg.GetInt(k), qt.Equals, v) c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{ "foo": 42, }) }) c.Run("Set and get map", func(c *qt.C) { cfg := New() cfg.Set("foo", map[string]interface{}{ "bar": "baz", }) c.Assert(cfg.Get("foo"), qt.DeepEquals, maps.Params{ "bar": "baz", }) c.Assert(cfg.GetStringMap("foo"), qt.DeepEquals, map[string]interface{}{"bar": string("baz")}) c.Assert(cfg.GetStringMapString("foo"), qt.DeepEquals, map[string]string{"bar": string("baz")}) }) c.Run("Set and get nested", func(c *qt.C) { cfg := New() cfg.Set("a", map[string]interface{}{ "B": "bv", }) cfg.Set("a.c", "cv") c.Assert(cfg.Get("a"), qt.DeepEquals, maps.Params{ "b": "bv", "c": "cv", }) c.Assert(cfg.Get("a.c"), qt.Equals, "cv") cfg.Set("b.a", "av") c.Assert(cfg.Get("b"), qt.DeepEquals, maps.Params{ "a": "av", }) cfg.Set("b", map[string]interface{}{ "b": "bv", }) c.Assert(cfg.Get("b"), qt.DeepEquals, maps.Params{ "a": "av", "b": "bv", }) cfg = New() cfg.Set("a", "av") cfg.Set("", map[string]interface{}{ "a": "av2", "b": "bv2", }) c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{ "a": "av2", "b": "bv2", }) cfg = New() cfg.Set("a", "av") cfg.Set("", map[string]interface{}{ "b": "bv2", }) c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{ "a": "av", "b": "bv2", }) cfg = New() cfg.Set("", map[string]interface{}{ "foo": map[string]interface{}{ "a": "av", }, }) cfg.Set("", map[string]interface{}{ "foo": map[string]interface{}{ "b": "bv2", }, }) c.Assert(cfg.Get("foo"), qt.DeepEquals, maps.Params{ "a": "av", "b": "bv2", }) }) c.Run("Merge default strategy", func(c *qt.C) { cfg := New() cfg.Set("a", map[string]interface{}{ "B": "bv", }) cfg.Merge("a", map[string]interface{}{ "B": "bv2", "c": "cv2", }) c.Assert(cfg.Get("a"), qt.DeepEquals, maps.Params{ "b": "bv", "c": "cv2", }) cfg = New() cfg.Set("a", "av") cfg.Merge("", map[string]interface{}{ "a": "av2", "b": "bv2", }) c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{ "a": "av", }) }) c.Run("Merge shallow", func(c *qt.C) { cfg := New() cfg.Set("a", map[string]interface{}{ "_merge": "shallow", "B": "bv", "c": map[string]interface{}{ "b": "bv", }, }) cfg.Merge("a", map[string]interface{}{ "c": map[string]interface{}{ "d": "dv2", }, "e": "ev2", }) c.Assert(cfg.Get("a"), qt.DeepEquals, maps.Params{ "e": "ev2", "_merge": maps.ParamsMergeStrategyShallow, "b": "bv", "c": maps.Params{ "b": "bv", }, }) }) // Issue #8679 c.Run("Merge typed maps", func(c *qt.C) { for _, left := range []interface{}{ map[string]string{ "c": "cv1", }, map[string]interface{}{ "c": "cv1", }, map[interface{}]interface{}{ "c": "cv1", }, } { cfg := New() cfg.Set("", map[string]interface{}{ "b": left, }) cfg.Merge("", maps.Params{ "b": maps.Params{ "c": "cv2", "d": "dv2", }, }) c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{ "b": maps.Params{ "c": "cv1", "d": "dv2", }, }) } for _, left := range []interface{}{ map[string]string{ "b": "bv1", }, map[string]interface{}{ "b": "bv1", }, map[interface{}]interface{}{ "b": "bv1", }, } { for _, right := range []interface{}{ map[string]string{ "b": "bv2", "c": "cv2", }, map[string]interface{}{ "b": "bv2", "c": "cv2", }, map[interface{}]interface{}{ "b": "bv2", "c": "cv2", }, } { cfg := New() cfg.Set("a", left) cfg.Merge("a", right) c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{ "a": maps.Params{ "b": "bv1", "c": "cv2", }, }) } } }) // Issue #8701 c.Run("Prevent _merge only maps", func(c *qt.C) { cfg := New() cfg.Set("", map[string]interface{}{ "B": "bv", }) cfg.Merge("", map[string]interface{}{ "c": map[string]interface{}{ "_merge": "shallow", "d": "dv2", }, }) c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{ "b": "bv", }) }) c.Run("IsSet", func(c *qt.C) { cfg := New() cfg.Set("a", map[string]interface{}{ "B": "bv", }) c.Assert(cfg.IsSet("A"), qt.IsTrue) c.Assert(cfg.IsSet("a.b"), qt.IsTrue) c.Assert(cfg.IsSet("z"), qt.IsFalse) }) c.Run("Para", func(c *qt.C) { cfg := New() p := para.New(4) r, _ := p.Start(context.Background()) setAndGet := func(k string, v int) error { vs := strconv.Itoa(v) cfg.Set(k, v) err := errors.New("get failed") if cfg.Get(k) != v { return err } if cfg.GetInt(k) != v { return err } if cfg.GetString(k) != vs { return err } if !cfg.IsSet(k) { return err } return nil } for i := 0; i < 20; i++ { i := i r.Run(func() error { const v = 42 k := fmt.Sprintf("k%d", i) if err := setAndGet(k, v); err != nil { return err } m := maps.Params{ "new": 42, } cfg.Merge("", m) return nil }) } c.Assert(r.Wait(), qt.IsNil) }) } func BenchmarkDefaultConfigProvider(b *testing.B) { type cfger interface { Get(key string) interface{} Set(key string, value interface{}) IsSet(key string) bool } newMap := func() map[string]interface{} { return map[string]interface{}{ "a": map[string]interface{}{ "b": map[string]interface{}{ "c": 32, "d": 43, }, }, "b": 62, } } runMethods := func(b *testing.B, cfg cfger) { m := newMap() cfg.Set("mymap", m) cfg.Set("num", 32) if !(cfg.IsSet("mymap") && cfg.IsSet("mymap.a") && cfg.IsSet("mymap.a.b") && cfg.IsSet("mymap.a.b.c")) { b.Fatal("IsSet failed") } if cfg.Get("num") != 32 { b.Fatal("Get failed") } if cfg.Get("mymap.a.b.c") != 32 { b.Fatal("Get failed") } } b.Run("Viper", func(b *testing.B) { v := viper.New() for i := 0; i < b.N; i++ { runMethods(b, v) } }) b.Run("Custom", func(b *testing.B) { cfg := New() for i := 0; i < b.N; i++ { runMethods(b, cfg) } }) } hugo-0.92.2/config/docshelper.go000066400000000000000000000024621420147000300164650ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/docshelper" ) // This is is just some helpers used to create some JSON used in the Hugo docs. func init() { docsProvider := func() docshelper.DocProvider { cfg := New() for _, configRoot := range ConfigRootKeys { cfg.Set(configRoot, make(maps.Params)) } lang := maps.Params{ "en": maps.Params{ "menus": maps.Params{}, "params": maps.Params{}, }, } cfg.Set("languages", lang) cfg.SetDefaultMergeStrategy() configHelpers := map[string]interface{}{ "mergeStrategy": cfg.Get(""), } return docshelper.DocProvider{"config": configHelpers} } docshelper.AddDocProviderFunc(docsProvider) } hugo-0.92.2/config/env.go000066400000000000000000000032501420147000300151210ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "os" "runtime" "strconv" "strings" ) // GetNumWorkerMultiplier returns the base value used to calculate the number // of workers to use for Hugo's parallel execution. // It returns the value in HUGO_NUMWORKERMULTIPLIER OS env variable if set to a // positive integer, else the number of logical CPUs. func GetNumWorkerMultiplier() int { if gmp := os.Getenv("HUGO_NUMWORKERMULTIPLIER"); gmp != "" { if p, err := strconv.Atoi(gmp); err == nil && p > 0 { return p } } return runtime.NumCPU() } // SetEnvVars sets vars on the form key=value in the oldVars slice. func SetEnvVars(oldVars *[]string, keyValues ...string) { for i := 0; i < len(keyValues); i += 2 { setEnvVar(oldVars, keyValues[i], keyValues[i+1]) } } func SplitEnvVar(v string) (string, string) { parts := strings.SplitN(v, "=", 2) return parts[0], parts[1] } func setEnvVar(vars *[]string, key, value string) { for i := range *vars { if strings.HasPrefix((*vars)[i], key+"=") { (*vars)[i] = key + "=" + value return } } // New var. *vars = append(*vars, key+"="+value) } hugo-0.92.2/config/env_test.go000066400000000000000000000020431420147000300161570ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "testing" qt "github.com/frankban/quicktest" ) func TestSetEnvVars(t *testing.T) { t.Parallel() c := qt.New(t) vars := []string{"FOO=bar", "HUGO=cool", "BAR=foo"} SetEnvVars(&vars, "HUGO", "rocking!", "NEW", "bar") c.Assert(vars, qt.DeepEquals, []string{"FOO=bar", "HUGO=rocking!", "BAR=foo", "NEW=bar"}) key, val := SplitEnvVar("HUGO=rocks") c.Assert(key, qt.Equals, "HUGO") c.Assert(val, qt.Equals, "rocks") } hugo-0.92.2/config/privacy/000077500000000000000000000000001420147000300154575ustar00rootroot00000000000000hugo-0.92.2/config/privacy/privacyConfig.go000066400000000000000000000071001420147000300206070ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package privacy import ( "github.com/gohugoio/hugo/config" "github.com/mitchellh/mapstructure" ) const privacyConfigKey = "privacy" // Service is the common values for a service in a policy definition. type Service struct { Disable bool } // Config is a privacy configuration for all the relevant services in Hugo. type Config struct { Disqus Disqus GoogleAnalytics GoogleAnalytics Instagram Instagram Twitter Twitter Vimeo Vimeo YouTube YouTube } // Disqus holds the privacy configuration settings related to the Disqus template. type Disqus struct { Service `mapstructure:",squash"` } // GoogleAnalytics holds the privacy configuration settings related to the Google Analytics template. type GoogleAnalytics struct { Service `mapstructure:",squash"` // Enabling this will disable the use of Cookies and use Session Storage to Store the GA Client ID. UseSessionStorage bool // Enabling this will make the GA templates respect the // "Do Not Track" HTTP header. See https://www.paulfurley.com/google-analytics-dnt/. RespectDoNotTrack bool // Enabling this will make it so the users' IP addresses are anonymized within Google Analytics. AnonymizeIP bool } // Instagram holds the privacy configuration settings related to the Instagram shortcode. type Instagram struct { Service `mapstructure:",squash"` // If simple mode is enabled, a static and no-JS version of the Instagram // image card will be built. Simple bool } // Twitter holds the privacy configuration settingsrelated to the Twitter shortcode. type Twitter struct { Service `mapstructure:",squash"` // When set to true, the Tweet and its embedded page on your site are not used // for purposes that include personalized suggestions and personalized ads. EnableDNT bool // If simple mode is enabled, a static and no-JS version of the Tweet will be built. Simple bool } // Vimeo holds the privacy configuration settingsrelated to the Vimeo shortcode. type Vimeo struct { Service `mapstructure:",squash"` // When set to true, the Vimeo player will be blocked from tracking any session data, // including all cookies and stats. EnableDNT bool // If simple mode is enabled, only a thumbnail is fetched from i.vimeocdn.com and // shown with a play button overlaid. If a user clicks the button, he/she will // be taken to the video page on vimeo.com in a new browser tab. Simple bool } // YouTube holds the privacy configuration settingsrelated to the YouTube shortcode. type YouTube struct { Service `mapstructure:",squash"` // When you turn on privacy-enhanced mode, // YouTube won’t store information about visitors on your website // unless the user plays the embedded video. PrivacyEnhanced bool } // DecodeConfig creates a privacy Config from a given Hugo configuration. func DecodeConfig(cfg config.Provider) (pc Config, err error) { if !cfg.IsSet(privacyConfigKey) { return } m := cfg.GetStringMap(privacyConfigKey) err = mapstructure.WeakDecode(m, &pc) return } hugo-0.92.2/config/privacy/privacyConfig_test.go000066400000000000000000000046221420147000300216540ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package privacy import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/config" ) func TestDecodeConfigFromTOML(t *testing.T) { c := qt.New(t) tomlConfig := ` someOtherValue = "foo" [privacy] [privacy.disqus] disable = true [privacy.googleAnalytics] disable = true respectDoNotTrack = true anonymizeIP = true useSessionStorage = true [privacy.instagram] disable = true simple = true [privacy.twitter] disable = true enableDNT = true simple = true [privacy.vimeo] disable = true enableDNT = true simple = true [privacy.youtube] disable = true privacyEnhanced = true simple = true ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) pc, err := DecodeConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(pc, qt.Not(qt.IsNil)) got := []bool{ pc.Disqus.Disable, pc.GoogleAnalytics.Disable, pc.GoogleAnalytics.RespectDoNotTrack, pc.GoogleAnalytics.AnonymizeIP, pc.GoogleAnalytics.UseSessionStorage, pc.Instagram.Disable, pc.Instagram.Simple, pc.Twitter.Disable, pc.Twitter.EnableDNT, pc.Twitter.Simple, pc.Vimeo.Disable, pc.Vimeo.EnableDNT, pc.Vimeo.Simple, pc.YouTube.PrivacyEnhanced, pc.YouTube.Disable, } c.Assert(got, qt.All(qt.Equals), true) } func TestDecodeConfigFromTOMLCaseInsensitive(t *testing.T) { c := qt.New(t) tomlConfig := ` someOtherValue = "foo" [Privacy] [Privacy.YouTube] PrivacyENhanced = true ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) pc, err := DecodeConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(pc, qt.Not(qt.IsNil)) c.Assert(pc.YouTube.PrivacyEnhanced, qt.Equals, true) } func TestDecodeConfigDefault(t *testing.T) { c := qt.New(t) pc, err := DecodeConfig(config.New()) c.Assert(err, qt.IsNil) c.Assert(pc, qt.Not(qt.IsNil)) c.Assert(pc.YouTube.PrivacyEnhanced, qt.Equals, false) } hugo-0.92.2/config/security/000077500000000000000000000000001420147000300156515ustar00rootroot00000000000000hugo-0.92.2/config/security/docshelper.go000066400000000000000000000015411420147000300203310ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package security import ( "github.com/gohugoio/hugo/docshelper" ) func init() { docsProvider := func() docshelper.DocProvider { return docshelper.DocProvider{"config": DefaultConfig.ToSecurityMap()} } docshelper.AddDocProviderFunc(docsProvider) } hugo-0.92.2/config/security/securityConfig.go000066400000000000000000000124701420147000300212010ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package security import ( "bytes" "encoding/json" "errors" "fmt" "reflect" "strings" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/parser" "github.com/gohugoio/hugo/parser/metadecoders" "github.com/mitchellh/mapstructure" ) const securityConfigKey = "security" // DefaultConfig holds the default security policy. var DefaultConfig = Config{ Exec: Exec{ Allow: NewWhitelist( "^dart-sass-embedded$", "^go$", // for Go Modules "^npx$", // used by all Node tools (Babel, PostCSS). "^postcss$", ), // These have been tested to work with Hugo's external programs // on Windows, Linux and MacOS. OsEnv: NewWhitelist("(?i)^(PATH|PATHEXT|APPDATA|TMP|TEMP|TERM)$"), }, Funcs: Funcs{ Getenv: NewWhitelist("^HUGO_"), }, HTTP: HTTP{ URLs: NewWhitelist(".*"), Methods: NewWhitelist("(?i)GET|POST"), }, } // Config is the top level security config. type Config struct { // Restricts access to os.Exec. Exec Exec `json:"exec"` // Restricts access to certain template funcs. Funcs Funcs `json:"funcs"` // Restricts access to resources.Get, getJSON, getCSV. HTTP HTTP `json:"http"` // Allow inline shortcodes EnableInlineShortcodes bool `json:"enableInlineShortcodes"` } // Exec holds os/exec policies. type Exec struct { Allow Whitelist `json:"allow"` OsEnv Whitelist `json:"osEnv"` } // Funcs holds template funcs policies. type Funcs struct { // OS env keys allowed to query in os.Getenv. Getenv Whitelist `json:"getenv"` } type HTTP struct { // URLs to allow in remote HTTP (resources.Get, getJSON, getCSV). URLs Whitelist `json:"urls"` // HTTP methods to allow. Methods Whitelist `json:"methods"` } // ToTOML converts c to TOML with [security] as the root. func (c Config) ToTOML() string { sec := c.ToSecurityMap() var b bytes.Buffer if err := parser.InterfaceToConfig(sec, metadecoders.TOML, &b); err != nil { panic(err) } return strings.TrimSpace(b.String()) } func (c Config) CheckAllowedExec(name string) error { if !c.Exec.Allow.Accept(name) { return &AccessDeniedError{ name: name, path: "security.exec.allow", policies: c.ToTOML(), } } return nil } func (c Config) CheckAllowedGetEnv(name string) error { if !c.Funcs.Getenv.Accept(name) { return &AccessDeniedError{ name: name, path: "security.funcs.getenv", policies: c.ToTOML(), } } return nil } func (c Config) CheckAllowedHTTPURL(url string) error { if !c.HTTP.URLs.Accept(url) { return &AccessDeniedError{ name: url, path: "security.http.urls", policies: c.ToTOML(), } } return nil } func (c Config) CheckAllowedHTTPMethod(method string) error { if !c.HTTP.Methods.Accept(method) { return &AccessDeniedError{ name: method, path: "security.http.method", policies: c.ToTOML(), } } return nil } // ToSecurityMap converts c to a map with 'security' as the root key. func (c Config) ToSecurityMap() map[string]interface{} { // Take it to JSON and back to get proper casing etc. asJson, err := json.Marshal(c) herrors.Must(err) m := make(map[string]interface{}) herrors.Must(json.Unmarshal(asJson, &m)) // Add the root sec := map[string]interface{}{ "security": m, } return sec } // DecodeConfig creates a privacy Config from a given Hugo configuration. func DecodeConfig(cfg config.Provider) (Config, error) { sc := DefaultConfig if cfg.IsSet(securityConfigKey) { m := cfg.GetStringMap(securityConfigKey) dec, err := mapstructure.NewDecoder( &mapstructure.DecoderConfig{ WeaklyTypedInput: true, Result: &sc, DecodeHook: stringSliceToWhitelistHook(), }, ) if err != nil { return sc, err } if err = dec.Decode(m); err != nil { return sc, err } } if !sc.EnableInlineShortcodes { // Legacy sc.EnableInlineShortcodes = cfg.GetBool("enableInlineShortcodes") } return sc, nil } func stringSliceToWhitelistHook() mapstructure.DecodeHookFuncType { return func( f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { if t != reflect.TypeOf(Whitelist{}) { return data, nil } wl := types.ToStringSlicePreserveString(data) return NewWhitelist(wl...), nil } } // AccessDeniedError represents a security policy conflict. type AccessDeniedError struct { path string name string policies string } func (e *AccessDeniedError) Error() string { return fmt.Sprintf("access denied: %q is not whitelisted in policy %q; the current security configuration is:\n\n%s\n\n", e.name, e.path, e.policies) } // IsAccessDenied reports whether err is an AccessDeniedError func IsAccessDenied(err error) bool { var notFoundErr *AccessDeniedError return errors.As(err, ¬FoundErr) } hugo-0.92.2/config/security/securityonfig_test.go000066400000000000000000000100511420147000300221260ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package security import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/config" ) func TestDecodeConfigFromTOML(t *testing.T) { c := qt.New(t) c.Run("Slice whitelist", func(c *qt.C) { c.Parallel() tomlConfig := ` someOtherValue = "bar" [security] enableInlineShortcodes=true [security.exec] allow=["a", "b"] osEnv=["a", "b", "c"] [security.funcs] getEnv=["a", "b"] ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) pc, err := DecodeConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(pc, qt.Not(qt.IsNil)) c.Assert(pc.EnableInlineShortcodes, qt.IsTrue) c.Assert(pc.Exec.Allow.Accept("a"), qt.IsTrue) c.Assert(pc.Exec.Allow.Accept("d"), qt.IsFalse) c.Assert(pc.Exec.OsEnv.Accept("a"), qt.IsTrue) c.Assert(pc.Exec.OsEnv.Accept("e"), qt.IsFalse) c.Assert(pc.Funcs.Getenv.Accept("a"), qt.IsTrue) c.Assert(pc.Funcs.Getenv.Accept("c"), qt.IsFalse) }) c.Run("String whitelist", func(c *qt.C) { c.Parallel() tomlConfig := ` someOtherValue = "bar" [security] [security.exec] allow="a" osEnv="b" ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) pc, err := DecodeConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(pc, qt.Not(qt.IsNil)) c.Assert(pc.Exec.Allow.Accept("a"), qt.IsTrue) c.Assert(pc.Exec.Allow.Accept("d"), qt.IsFalse) c.Assert(pc.Exec.OsEnv.Accept("b"), qt.IsTrue) c.Assert(pc.Exec.OsEnv.Accept("e"), qt.IsFalse) }) c.Run("Default exec.osEnv", func(c *qt.C) { c.Parallel() tomlConfig := ` someOtherValue = "bar" [security] [security.exec] allow="a" ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) pc, err := DecodeConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(pc, qt.Not(qt.IsNil)) c.Assert(pc.Exec.Allow.Accept("a"), qt.IsTrue) c.Assert(pc.Exec.OsEnv.Accept("PATH"), qt.IsTrue) c.Assert(pc.Exec.OsEnv.Accept("e"), qt.IsFalse) }) c.Run("Enable inline shortcodes, legacy", func(c *qt.C) { c.Parallel() tomlConfig := ` someOtherValue = "bar" enableInlineShortcodes=true [security] [security.exec] allow="a" osEnv="b" ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) pc, err := DecodeConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(pc.EnableInlineShortcodes, qt.IsTrue) }) } func TestToTOML(t *testing.T) { c := qt.New(t) got := DefaultConfig.ToTOML() c.Assert(got, qt.Equals, "[security]\n enableInlineShortcodes = false\n [security.exec]\n allow = ['^dart-sass-embedded$', '^go$', '^npx$', '^postcss$']\n osEnv = ['(?i)^(PATH|PATHEXT|APPDATA|TMP|TEMP|TERM)$']\n\n [security.funcs]\n getenv = ['^HUGO_']\n\n [security.http]\n methods = ['(?i)GET|POST']\n urls = ['.*']", ) } func TestDecodeConfigDefault(t *testing.T) { t.Parallel() c := qt.New(t) pc, err := DecodeConfig(config.New()) c.Assert(err, qt.IsNil) c.Assert(pc, qt.Not(qt.IsNil)) c.Assert(pc.Exec.Allow.Accept("a"), qt.IsFalse) c.Assert(pc.Exec.Allow.Accept("npx"), qt.IsTrue) c.Assert(pc.Exec.Allow.Accept("Npx"), qt.IsFalse) c.Assert(pc.Exec.OsEnv.Accept("a"), qt.IsFalse) c.Assert(pc.Exec.OsEnv.Accept("PATH"), qt.IsTrue) c.Assert(pc.Exec.OsEnv.Accept("e"), qt.IsFalse) c.Assert(pc.HTTP.URLs.Accept("https://example.org"), qt.IsTrue) c.Assert(pc.HTTP.Methods.Accept("POST"), qt.IsTrue) c.Assert(pc.HTTP.Methods.Accept("GET"), qt.IsTrue) c.Assert(pc.HTTP.Methods.Accept("get"), qt.IsTrue) c.Assert(pc.HTTP.Methods.Accept("DELETE"), qt.IsFalse) } hugo-0.92.2/config/security/whitelist.go000066400000000000000000000043421420147000300202170ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package security import ( "encoding/json" "fmt" "regexp" "strings" ) const ( acceptNoneKeyword = "none" ) // Whitelist holds a whitelist. type Whitelist struct { acceptNone bool patterns []*regexp.Regexp // Store this for debugging/error reporting patternsStrings []string } func (w Whitelist) MarshalJSON() ([]byte, error) { if w.acceptNone { return json.Marshal(acceptNoneKeyword) } return json.Marshal(w.patternsStrings) } // NewWhitelist creates a new Whitelist from zero or more patterns. // An empty patterns list or a pattern with the value 'none' will create // a whitelist that will Accept noone. func NewWhitelist(patterns ...string) Whitelist { if len(patterns) == 0 { return Whitelist{acceptNone: true} } var acceptSome bool var patternsStrings []string for _, p := range patterns { if p == acceptNoneKeyword { acceptSome = false break } if ps := strings.TrimSpace(p); ps != "" { acceptSome = true patternsStrings = append(patternsStrings, ps) } } if !acceptSome { return Whitelist{ acceptNone: true, } } var patternsr []*regexp.Regexp for i := 0; i < len(patterns); i++ { p := strings.TrimSpace(patterns[i]) if p == "" { continue } patternsr = append(patternsr, regexp.MustCompile(p)) } return Whitelist{patterns: patternsr, patternsStrings: patternsStrings} } // Accepted reports whether name is whitelisted. func (w Whitelist) Accept(name string) bool { if w.acceptNone { return false } for _, p := range w.patterns { if p.MatchString(name) { return true } } return false } func (w Whitelist) String() string { return fmt.Sprint(w.patternsStrings) } hugo-0.92.2/config/security/whitelist_test.go000066400000000000000000000026151420147000300212570ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package security import ( "testing" qt "github.com/frankban/quicktest" ) func TestWhitelist(t *testing.T) { t.Parallel() c := qt.New(t) c.Run("none", func(c *qt.C) { c.Assert(NewWhitelist("none", "foo").Accept("foo"), qt.IsFalse) c.Assert(NewWhitelist().Accept("foo"), qt.IsFalse) c.Assert(NewWhitelist("").Accept("foo"), qt.IsFalse) c.Assert(NewWhitelist(" ", " ").Accept("foo"), qt.IsFalse) c.Assert(Whitelist{}.Accept("foo"), qt.IsFalse) }) c.Run("One", func(c *qt.C) { w := NewWhitelist("^foo.*") c.Assert(w.Accept("foo"), qt.IsTrue) c.Assert(w.Accept("mfoo"), qt.IsFalse) }) c.Run("Multiple", func(c *qt.C) { w := NewWhitelist("^foo.*", "^bar.*") c.Assert(w.Accept("foo"), qt.IsTrue) c.Assert(w.Accept("bar"), qt.IsTrue) c.Assert(w.Accept("mbar"), qt.IsFalse) }) } hugo-0.92.2/config/services/000077500000000000000000000000001420147000300156255ustar00rootroot00000000000000hugo-0.92.2/config/services/servicesConfig.go000066400000000000000000000060041420147000300211250ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "github.com/gohugoio/hugo/config" "github.com/mitchellh/mapstructure" ) const ( servicesConfigKey = "services" disqusShortnameKey = "disqusshortname" googleAnalyticsKey = "googleanalytics" rssLimitKey = "rssLimit" ) // Config is a privacy configuration for all the relevant services in Hugo. type Config struct { Disqus Disqus GoogleAnalytics GoogleAnalytics Instagram Instagram Twitter Twitter RSS RSS } // Disqus holds the functional configuration settings related to the Disqus template. type Disqus struct { // A Shortname is the unique identifier assigned to a Disqus site. Shortname string } // GoogleAnalytics holds the functional configuration settings related to the Google Analytics template. type GoogleAnalytics struct { // The GA tracking ID. ID string } // Instagram holds the functional configuration settings related to the Instagram shortcodes. type Instagram struct { // The Simple variant of the Instagram is decorated with Bootstrap 4 card classes. // This means that if you use Bootstrap 4 or want to provide your own CSS, you want // to disable the inline CSS provided by Hugo. DisableInlineCSS bool // App or Client Access Token. // If you are using a Client Access Token, remember that you must combine it with your App ID // using a pipe symbol (|) otherwise the request will fail. AccessToken string } // Twitter holds the functional configuration settings related to the Twitter shortcodes. type Twitter struct { // The Simple variant of Twitter is decorated with a basic set of inline styles. // This means that if you want to provide your own CSS, you want // to disable the inline CSS provided by Hugo. DisableInlineCSS bool } // RSS holds the functional configuration settings related to the RSS feeds. type RSS struct { // Limit the number of pages. Limit int } // DecodeConfig creates a services Config from a given Hugo configuration. func DecodeConfig(cfg config.Provider) (c Config, err error) { m := cfg.GetStringMap(servicesConfigKey) err = mapstructure.WeakDecode(m, &c) // Keep backwards compatibility. if c.GoogleAnalytics.ID == "" { // Try the global config c.GoogleAnalytics.ID = cfg.GetString(googleAnalyticsKey) } if c.Disqus.Shortname == "" { c.Disqus.Shortname = cfg.GetString(disqusShortnameKey) } if c.RSS.Limit == 0 { c.RSS.Limit = cfg.GetInt(rssLimitKey) } return } hugo-0.92.2/config/services/servicesConfig_test.go000066400000000000000000000033751420147000300221740ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/config" ) func TestDecodeConfigFromTOML(t *testing.T) { c := qt.New(t) tomlConfig := ` someOtherValue = "foo" [services] [services.disqus] shortname = "DS" [services.googleAnalytics] id = "ga_id" [services.instagram] disableInlineCSS = true [services.twitter] disableInlineCSS = true ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) config, err := DecodeConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(config, qt.Not(qt.IsNil)) c.Assert(config.Disqus.Shortname, qt.Equals, "DS") c.Assert(config.GoogleAnalytics.ID, qt.Equals, "ga_id") c.Assert(config.Instagram.DisableInlineCSS, qt.Equals, true) } // Support old root-level GA settings etc. func TestUseSettingsFromRootIfSet(t *testing.T) { c := qt.New(t) cfg := config.New() cfg.Set("disqusShortname", "root_short") cfg.Set("googleAnalytics", "ga_root") config, err := DecodeConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(config, qt.Not(qt.IsNil)) c.Assert(config.Disqus.Shortname, qt.Equals, "root_short") c.Assert(config.GoogleAnalytics.ID, qt.Equals, "ga_root") } hugo-0.92.2/create/000077500000000000000000000000001420147000300140005ustar00rootroot00000000000000hugo-0.92.2/create/content.go000066400000000000000000000220601420147000300160010ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package create provides functions to create new content. package create import ( "bytes" "fmt" "io" "os" "path/filepath" "strings" "github.com/gohugoio/hugo/hugofs/glob" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/paths" "github.com/pkg/errors" "github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugolib" "github.com/spf13/afero" ) const ( // DefaultArchetypeTemplateTemplate is the template used in 'hugo new site' // and the template we use as a fall back. DefaultArchetypeTemplateTemplate = `--- title: "{{ replace .Name "-" " " | title }}" date: {{ .Date }} draft: true --- ` ) // NewContent creates a new content file in h (or a full bundle if the archetype is a directory) // in targetPath. func NewContent(h *hugolib.HugoSites, kind, targetPath string) error { if h.BaseFs.Content.Dirs == nil { return errors.New("no existing content directory configured for this project") } cf := hugolib.NewContentFactory(h) if kind == "" { var err error kind, err = cf.SectionFromFilename(targetPath) if err != nil { return err } } b := &contentBuilder{ archeTypeFs: h.PathSpec.BaseFs.Archetypes.Fs, sourceFs: h.PathSpec.Fs.Source, ps: h.PathSpec, h: h, cf: cf, kind: kind, targetPath: targetPath, } ext := paths.Ext(targetPath) b.setArcheTypeFilenameToUse(ext) withBuildLock := func() (string, error) { unlock, err := h.BaseFs.LockBuild() if err != nil { return "", fmt.Errorf("failed to acquire a build lock: %s", err) } defer unlock() if b.isDir { return "", b.buildDir() } if ext == "" { return "", errors.Errorf("failed to resolve %q to a archetype template", targetPath) } if !files.IsContentFile(b.targetPath) { return "", errors.Errorf("target path %q is not a known content format", b.targetPath) } return b.buildFile() } filename, err := withBuildLock() if err != nil { return err } if filename != "" { return b.openInEditorIfConfigured(filename) } return nil } type contentBuilder struct { archeTypeFs afero.Fs sourceFs afero.Fs ps *helpers.PathSpec h *hugolib.HugoSites cf hugolib.ContentFactory // Builder state archetypeFilename string targetPath string kind string isDir bool dirMap archetypeMap } func (b *contentBuilder) buildDir() error { // Split the dir into content files and the rest. if err := b.mapArcheTypeDir(); err != nil { return err } var contentTargetFilenames []string var baseDir string for _, fi := range b.dirMap.contentFiles { targetFilename := filepath.Join(b.targetPath, strings.TrimPrefix(fi.Meta().Path, b.archetypeFilename)) abs, err := b.cf.CreateContentPlaceHolder(targetFilename) if err != nil { return err } if baseDir == "" { baseDir = strings.TrimSuffix(abs, targetFilename) } contentTargetFilenames = append(contentTargetFilenames, abs) } var contentInclusionFilter *glob.FilenameFilter if !b.dirMap.siteUsed { // We don't need to build everything. contentInclusionFilter = glob.NewFilenameFilterForInclusionFunc(func(filename string) bool { filename = strings.TrimPrefix(filename, string(os.PathSeparator)) for _, cn := range contentTargetFilenames { if strings.Contains(cn, filename) { return true } } return false }) } if err := b.h.Build(hugolib.BuildCfg{NoBuildLock: true, SkipRender: true, ContentInclusionFilter: contentInclusionFilter}); err != nil { return err } for i, filename := range contentTargetFilenames { if err := b.applyArcheType(filename, b.dirMap.contentFiles[i].Meta().Path); err != nil { return err } } // Copy the rest as is. for _, f := range b.dirMap.otherFiles { meta := f.Meta() filename := meta.Path in, err := meta.Open() if err != nil { return errors.Wrap(err, "failed to open non-content file") } targetFilename := filepath.Join(baseDir, b.targetPath, strings.TrimPrefix(filename, b.archetypeFilename)) targetDir := filepath.Dir(targetFilename) if err := b.sourceFs.MkdirAll(targetDir, 0o777); err != nil && !os.IsExist(err) { return errors.Wrapf(err, "failed to create target directory for %q", targetDir) } out, err := b.sourceFs.Create(targetFilename) if err != nil { return err } _, err = io.Copy(out, in) if err != nil { return err } in.Close() out.Close() } b.h.Log.Printf("Content dir %q created", filepath.Join(baseDir, b.targetPath)) return nil } func (b *contentBuilder) buildFile() (string, error) { contentPlaceholderAbsFilename, err := b.cf.CreateContentPlaceHolder(b.targetPath) if err != nil { return "", err } usesSite, err := b.usesSiteVar(b.archetypeFilename) if err != nil { return "", err } var contentInclusionFilter *glob.FilenameFilter if !usesSite { // We don't need to build everything. contentInclusionFilter = glob.NewFilenameFilterForInclusionFunc(func(filename string) bool { filename = strings.TrimPrefix(filename, string(os.PathSeparator)) return strings.Contains(contentPlaceholderAbsFilename, filename) }) } if err := b.h.Build(hugolib.BuildCfg{NoBuildLock: true, SkipRender: true, ContentInclusionFilter: contentInclusionFilter}); err != nil { return "", err } if err := b.applyArcheType(contentPlaceholderAbsFilename, b.archetypeFilename); err != nil { return "", err } b.h.Log.Printf("Content %q created", contentPlaceholderAbsFilename) return contentPlaceholderAbsFilename, nil } func (b *contentBuilder) setArcheTypeFilenameToUse(ext string) { var pathsToCheck []string if b.kind != "" { pathsToCheck = append(pathsToCheck, b.kind+ext) } pathsToCheck = append(pathsToCheck, "default"+ext) for _, p := range pathsToCheck { fi, err := b.archeTypeFs.Stat(p) if err == nil { b.archetypeFilename = p b.isDir = fi.IsDir() return } } } func (b *contentBuilder) applyArcheType(contentFilename, archetypeFilename string) error { p := b.h.GetContentPage(contentFilename) if p == nil { panic(fmt.Sprintf("[BUG] no Page found for %q", contentFilename)) } f, err := b.sourceFs.Create(contentFilename) if err != nil { return err } defer f.Close() if archetypeFilename == "" { return b.cf.AppplyArchetypeTemplate(f, p, b.kind, DefaultArchetypeTemplateTemplate) } return b.cf.AppplyArchetypeFilename(f, p, b.kind, archetypeFilename) } func (b *contentBuilder) mapArcheTypeDir() error { var m archetypeMap walkFn := func(path string, fi hugofs.FileMetaInfo, err error) error { if err != nil { return err } if fi.IsDir() { return nil } fil := fi.(hugofs.FileMetaInfo) if files.IsContentFile(path) { m.contentFiles = append(m.contentFiles, fil) if !m.siteUsed { m.siteUsed, err = b.usesSiteVar(path) if err != nil { return err } } return nil } m.otherFiles = append(m.otherFiles, fil) return nil } walkCfg := hugofs.WalkwayConfig{ WalkFn: walkFn, Fs: b.archeTypeFs, Root: b.archetypeFilename, } w := hugofs.NewWalkway(walkCfg) if err := w.Walk(); err != nil { return errors.Wrapf(err, "failed to walk archetype dir %q", b.archetypeFilename) } b.dirMap = m return nil } func (b *contentBuilder) openInEditorIfConfigured(filename string) error { editor := b.h.Cfg.GetString("newContentEditor") if editor == "" { return nil } editorExec := strings.Fields(editor)[0] editorFlags := strings.Fields(editor)[1:] var args []interface{} for _, editorFlag := range editorFlags { args = append(args, editorFlag) } args = append( args, filename, hexec.WithStdin(os.Stdin), hexec.WithStderr(os.Stderr), hexec.WithStdout(os.Stdout), ) b.h.Log.Printf("Editing %q with %q ...\n", filename, editorExec) cmd, err := b.h.Deps.ExecHelper.New(editorExec, args...) if err != nil { return err } return cmd.Run() } func (b *contentBuilder) usesSiteVar(filename string) (bool, error) { if filename == "" { return false, nil } bb, err := afero.ReadFile(b.archeTypeFs, filename) if err != nil { return false, errors.Wrap(err, "failed to open archetype file") } return bytes.Contains(bb, []byte(".Site")) || bytes.Contains(bb, []byte("site.")), nil } type archetypeMap struct { // These needs to be parsed and executed as Go templates. contentFiles []hugofs.FileMetaInfo // These are just copied to destination. otherFiles []hugofs.FileMetaInfo // If the templates needs a fully built site. This can potentially be // expensive, so only do when needed. siteUsed bool } hugo-0.92.2/create/content_test.go000066400000000000000000000375431420147000300170540ustar00rootroot00000000000000// Copyright 2016 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package create_test import ( "fmt" "os" "path/filepath" "strings" "testing" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/hugolib" "github.com/gohugoio/hugo/hugofs" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/create" "github.com/gohugoio/hugo/helpers" "github.com/spf13/afero" ) // TODO(bep) clean this up. Export the test site builder in Hugolib or something. func TestNewContentFromFile(t *testing.T) { cases := []struct { name string kind string path string expected interface{} }{ {"Post", "post", "post/sample-1.md", []string{`title = "Post Arch title"`, `test = "test1"`, "date = \"2015-01-12T19:20:04-07:00\""}}, {"Post org-mode", "post", "post/org-1.org", []string{`#+title: ORG-1`}}, {"Post, unknown content filetype", "post", "post/sample-1.pdoc", false}, {"Empty date", "emptydate", "post/sample-ed.md", []string{`title = "Empty Date Arch title"`, `test = "test1"`}}, {"Archetype file not found", "stump", "stump/sample-2.md", []string{`title: "Sample 2"`}}, // no archetype file {"No archetype", "", "sample-3.md", []string{`title: "Sample 3"`}}, // no archetype {"Empty archetype", "product", "product/sample-4.md", []string{`title = "SAMPLE-4"`}}, // empty archetype front matter {"Filenames", "filenames", "content/mypage/index.md", []string{"title = \"INDEX\"\n+++\n\n\nContentBaseName: mypage"}}, {"Branch Name", "name", "content/tags/tag-a/_index.md", []string{"+++\ntitle = 'Tag A'\n+++"}}, {"Lang 1", "lang", "post/lang-1.md", []string{`Site Lang: en|Name: Lang 1|i18n: Hugo Rocks!`}}, {"Lang 2", "lang", "post/lang-2.en.md", []string{`Site Lang: en|Name: Lang 2|i18n: Hugo Rocks!`}}, {"Lang nn file", "lang", "content/post/lang-3.nn.md", []string{`Site Lang: nn|Name: Lang 3|i18n: Hugo Rokkar!`}}, {"Lang nn dir", "lang", "content_nn/post/lang-4.md", []string{`Site Lang: nn|Name: Lang 4|i18n: Hugo Rokkar!`}}, {"Lang en in nn dir", "lang", "content_nn/post/lang-5.en.md", []string{`Site Lang: en|Name: Lang 5|i18n: Hugo Rocks!`}}, {"Lang en default", "lang", "post/my-bundle/index.md", []string{`Site Lang: en|Name: My Bundle|i18n: Hugo Rocks!`}}, {"Lang en file", "lang", "post/my-bundle/index.en.md", []string{`Site Lang: en|Name: My Bundle|i18n: Hugo Rocks!`}}, {"Lang nn bundle", "lang", "content/post/my-bundle/index.nn.md", []string{`Site Lang: nn|Name: My Bundle|i18n: Hugo Rokkar!`}}, {"Site", "site", "content/mypage/index.md", []string{"RegularPages .Site: 10", "RegularPages site: 10"}}, {"Shortcodes", "shortcodes", "shortcodes/go.md", []string{ `title = "GO"`, "{{< myshortcode >}}", "{{% myshortcode %}}", "{{}}\n{{%/* comment */%}}", }}, // shortcodes } c := qt.New(t) for i, cas := range cases { cas := cas c.Run(cas.name, func(c *qt.C) { c.Parallel() mm := afero.NewMemMapFs() c.Assert(initFs(mm), qt.IsNil) cfg, fs := newTestCfg(c, mm) h, err := hugolib.NewHugoSites(deps.DepsCfg{Cfg: cfg, Fs: fs}) c.Assert(err, qt.IsNil) err = create.NewContent(h, cas.kind, cas.path) if b, ok := cas.expected.(bool); ok && !b { if !b { c.Assert(err, qt.Not(qt.IsNil)) } return } c.Assert(err, qt.IsNil) fname := filepath.FromSlash(cas.path) if !strings.HasPrefix(fname, "content") { fname = filepath.Join("content", fname) } content := readFileFromFs(c, fs.Source, fname) for _, v := range cas.expected.([]string) { found := strings.Contains(content, v) if !found { c.Fatalf("[%d] %q missing from output:\n%q", i, v, content) } } }) } } func TestNewContentFromDir(t *testing.T) { mm := afero.NewMemMapFs() c := qt.New(t) archetypeDir := filepath.Join("archetypes", "my-bundle") c.Assert(mm.MkdirAll(archetypeDir, 0o755), qt.IsNil) archetypeThemeDir := filepath.Join("themes", "mytheme", "archetypes", "my-theme-bundle") c.Assert(mm.MkdirAll(archetypeThemeDir, 0o755), qt.IsNil) contentFile := ` File: %s Site Lang: {{ .Site.Language.Lang }} Name: {{ replace .Name "-" " " | title }} i18n: {{ T "hugo" }} ` c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.md"), []byte(fmt.Sprintf(contentFile, "index.md")), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.nn.md"), []byte(fmt.Sprintf(contentFile, "index.nn.md")), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "pages", "bio.md"), []byte(fmt.Sprintf(contentFile, "bio.md")), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "resources", "hugo1.json"), []byte(`hugo1: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "resources", "hugo2.xml"), []byte(`hugo2: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeThemeDir, "index.md"), []byte(fmt.Sprintf(contentFile, "index.md")), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeThemeDir, "resources", "hugo1.json"), []byte(`hugo1: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) c.Assert(initFs(mm), qt.IsNil) cfg, fs := newTestCfg(c, mm) h, err := hugolib.NewHugoSites(deps.DepsCfg{Cfg: cfg, Fs: fs}) c.Assert(err, qt.IsNil) c.Assert(len(h.Sites), qt.Equals, 2) c.Assert(create.NewContent(h, "my-bundle", "post/my-post"), qt.IsNil) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo2.xml")), `hugo2: {{ printf "no template handling in here" }}`) // Content files should get the correct site context. // TODO(bep) archetype check i18n cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.md")), `File: index.md`, `Site Lang: en`, `Name: My Post`, `i18n: Hugo Rocks!`) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.nn.md")), `File: index.nn.md`, `Site Lang: nn`, `Name: My Post`, `i18n: Hugo Rokkar!`) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/pages/bio.md")), `File: bio.md`, `Site Lang: en`, `Name: Bio`) c.Assert(create.NewContent(h, "my-theme-bundle", "post/my-theme-post"), qt.IsNil) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/index.md")), `File: index.md`, `Site Lang: en`, `Name: My Theme Post`, `i18n: Hugo Rocks!`) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`) } func TestNewContentFromDirSiteFunction(t *testing.T) { mm := afero.NewMemMapFs() c := qt.New(t) archetypeDir := filepath.Join("archetypes", "my-bundle") defaultArchetypeDir := filepath.Join("archetypes", "default") c.Assert(mm.MkdirAll(archetypeDir, 0o755), qt.IsNil) c.Assert(mm.MkdirAll(defaultArchetypeDir, 0o755), qt.IsNil) contentFile := ` File: %s site RegularPages: {{ len site.RegularPages }} ` c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.md"), []byte(fmt.Sprintf(contentFile, "index.md")), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(defaultArchetypeDir, "index.md"), []byte("default archetype index.md"), 0o755), qt.IsNil) c.Assert(initFs(mm), qt.IsNil) cfg, fs := newTestCfg(c, mm) h, err := hugolib.NewHugoSites(deps.DepsCfg{Cfg: cfg, Fs: fs}) c.Assert(err, qt.IsNil) c.Assert(len(h.Sites), qt.Equals, 2) c.Assert(create.NewContent(h, "my-bundle", "post/my-post"), qt.IsNil) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.md")), `site RegularPages: 10`) // Default bundle archetype c.Assert(create.NewContent(h, "", "post/my-post2"), qt.IsNil) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post2/index.md")), `default archetype index.md`) // Regular file with bundle kind. c.Assert(create.NewContent(h, "my-bundle", "post/foo.md"), qt.IsNil) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/foo.md")), `draft: true`) // Regular files should fall back to the default archetype (we have no regular file archetype). c.Assert(create.NewContent(h, "my-bundle", "mypage.md"), qt.IsNil) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "mypage.md")), `draft: true`) } func TestNewContentFromDirNoSite(t *testing.T) { mm := afero.NewMemMapFs() c := qt.New(t) archetypeDir := filepath.Join("archetypes", "my-bundle") c.Assert(mm.MkdirAll(archetypeDir, 0o755), qt.IsNil) archetypeThemeDir := filepath.Join("themes", "mytheme", "archetypes", "my-theme-bundle") c.Assert(mm.MkdirAll(archetypeThemeDir, 0o755), qt.IsNil) contentFile := ` File: %s Name: {{ replace .Name "-" " " | title }} i18n: {{ T "hugo" }} ` c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.md"), []byte(fmt.Sprintf(contentFile, "index.md")), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.nn.md"), []byte(fmt.Sprintf(contentFile, "index.nn.md")), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "pages", "bio.md"), []byte(fmt.Sprintf(contentFile, "bio.md")), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "resources", "hugo1.json"), []byte(`hugo1: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "resources", "hugo2.xml"), []byte(`hugo2: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeThemeDir, "index.md"), []byte(fmt.Sprintf(contentFile, "index.md")), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join(archetypeThemeDir, "resources", "hugo1.json"), []byte(`hugo1: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) c.Assert(initFs(mm), qt.IsNil) cfg, fs := newTestCfg(c, mm) h, err := hugolib.NewHugoSites(deps.DepsCfg{Cfg: cfg, Fs: fs}) c.Assert(err, qt.IsNil) c.Assert(len(h.Sites), qt.Equals, 2) c.Assert(create.NewContent(h, "my-bundle", "post/my-post"), qt.IsNil) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo2.xml")), `hugo2: {{ printf "no template handling in here" }}`) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.md")), `File: index.md`, `Name: My Post`, `i18n: Hugo Rocks!`) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.nn.md")), `File: index.nn.md`, `Name: My Post`, `i18n: Hugo Rokkar!`) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/pages/bio.md")), `File: bio.md`, `Name: Bio`) c.Assert(create.NewContent(h, "my-theme-bundle", "post/my-theme-post"), qt.IsNil) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/index.md")), `File: index.md`, `Name: My Theme Post`, `i18n: Hugo Rocks!`) cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`) } func initFs(fs afero.Fs) error { perm := os.FileMode(0o755) var err error // create directories dirs := []string{ "archetypes", "content", filepath.Join("themes", "sample", "archetypes"), } for _, dir := range dirs { err = fs.Mkdir(dir, perm) if err != nil && !os.IsExist(err) { return err } } // create some dummy content for i := 1; i <= 10; i++ { filename := filepath.Join("content", fmt.Sprintf("page%d.md", i)) afero.WriteFile(fs, filename, []byte(`--- title: Test --- `), 0666) } // create archetype files for _, v := range []struct { path string content string }{ { path: filepath.Join("archetypes", "post.md"), content: "+++\ndate = \"2015-01-12T19:20:04-07:00\"\ntitle = \"Post Arch title\"\ntest = \"test1\"\n+++\n", }, { path: filepath.Join("archetypes", "post.org"), content: "#+title: {{ .BaseFileName | upper }}", }, { path: filepath.Join("archetypes", "name.md"), content: `+++ title = '{{ replace .Name "-" " " | title }}' +++`, }, { path: filepath.Join("archetypes", "product.md"), content: `+++ title = "{{ .BaseFileName | upper }}" +++`, }, { path: filepath.Join("archetypes", "filenames.md"), content: `... title = "{{ .BaseFileName | upper }}" +++ ContentBaseName: {{ .File.ContentBaseName }} `, }, { path: filepath.Join("archetypes", "site.md"), content: `... title = "{{ .BaseFileName | upper }}" +++ Len RegularPages .Site: {{ len .Site.RegularPages }} Len RegularPages site: {{ len site.RegularPages }} `, }, { path: filepath.Join("archetypes", "emptydate.md"), content: "+++\ndate =\"\"\ntitle = \"Empty Date Arch title\"\ntest = \"test1\"\n+++\n", }, { path: filepath.Join("archetypes", "lang.md"), content: `Site Lang: {{ site.Language.Lang }}|Name: {{ replace .Name "-" " " | title }}|i18n: {{ T "hugo" }}`, }, // #3623x { path: filepath.Join("archetypes", "shortcodes.md"), content: `+++ title = "{{ .BaseFileName | upper }}" +++ {{< myshortcode >}} Some text. {{% myshortcode %}} {{}} {{%/* comment */%}} `, }, } { f, err := fs.Create(v.path) if err != nil { return err } defer f.Close() _, err = f.Write([]byte(v.content)) if err != nil { return err } } return nil } func cContains(c *qt.C, v interface{}, matches ...string) { for _, m := range matches { c.Assert(v, qt.Contains, m) } } // TODO(bep) extract common testing package with this and some others func readFileFromFs(t testing.TB, fs afero.Fs, filename string) string { t.Helper() filename = filepath.FromSlash(filename) b, err := afero.ReadFile(fs, filename) if err != nil { // Print some debug info root := strings.Split(filename, helpers.FilePathSeparator)[0] afero.Walk(fs, root, func(path string, info os.FileInfo, err error) error { if info != nil && !info.IsDir() { fmt.Println(" ", path) } return nil }) t.Fatalf("Failed to read file: %s", err) } return string(b) } func newTestCfg(c *qt.C, mm afero.Fs) (config.Provider, *hugofs.Fs) { cfg := ` theme = "mytheme" [languages] [languages.en] weight = 1 languageName = "English" [languages.nn] weight = 2 languageName = "Nynorsk" [module] [[module.mounts]] source = 'archetypes' target = 'archetypes' [[module.mounts]] source = 'content' target = 'content' lang = 'en' [[module.mounts]] source = 'content_nn' target = 'content' lang = 'nn' ` if mm == nil { mm = afero.NewMemMapFs() } mm.MkdirAll(filepath.FromSlash("content_nn"), 0o777) mm.MkdirAll(filepath.FromSlash("themes/mytheme"), 0o777) c.Assert(afero.WriteFile(mm, filepath.Join("i18n", "en.toml"), []byte(`[hugo] other = "Hugo Rocks!"`), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, filepath.Join("i18n", "nn.toml"), []byte(`[hugo] other = "Hugo Rokkar!"`), 0o755), qt.IsNil) c.Assert(afero.WriteFile(mm, "config.toml", []byte(cfg), 0o755), qt.IsNil) v, _, err := hugolib.LoadConfig(hugolib.ConfigSourceDescriptor{Fs: mm, Filename: "config.toml"}) c.Assert(err, qt.IsNil) return v, hugofs.NewFrom(mm, v) } hugo-0.92.2/deploy/000077500000000000000000000000001420147000300140315ustar00rootroot00000000000000hugo-0.92.2/deploy/cloudfront.go000066400000000000000000000036501420147000300165430ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build !nodeploy package deploy import ( "context" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/cloudfront" ) // InvalidateCloudFront invalidates the CloudFront cache for distributionID. // It uses the default AWS credentials from the environment. func InvalidateCloudFront(ctx context.Context, distributionID string) error { // SharedConfigEnable enables loading "shared config (~/.aws/config) and // shared credentials (~/.aws/credentials) files". // See https://docs.aws.amazon.com/sdk-for-go/api/aws/session/ for more // details. // This is the same codepath used by Go CDK when creating an s3 URL. // TODO: Update this to a Go CDK helper once available // (https://github.com/google/go-cloud/issues/2003). sess, err := session.NewSessionWithOptions(session.Options{SharedConfigState: session.SharedConfigEnable}) if err != nil { return err } req := &cloudfront.CreateInvalidationInput{ DistributionId: aws.String(distributionID), InvalidationBatch: &cloudfront.InvalidationBatch{ CallerReference: aws.String(time.Now().Format("20060102150405")), Paths: &cloudfront.Paths{ Items: []*string{aws.String("/*")}, Quantity: aws.Int64(1), }, }, } _, err = cloudfront.New(sess).CreateInvalidationWithContext(ctx, req) return err } hugo-0.92.2/deploy/deploy.go000066400000000000000000000521351420147000300156620ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build !nodeploy package deploy import ( "bytes" "compress/gzip" "context" "crypto/md5" "fmt" "io" "io/ioutil" "mime" "os" "path/filepath" "regexp" "runtime" "sort" "strings" "sync" "github.com/dustin/go-humanize" "github.com/gobwas/glob" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/media" "github.com/pkg/errors" "github.com/spf13/afero" jww "github.com/spf13/jwalterweatherman" "golang.org/x/text/unicode/norm" "gocloud.dev/blob" _ "gocloud.dev/blob/fileblob" // import _ "gocloud.dev/blob/gcsblob" // import _ "gocloud.dev/blob/s3blob" // import "gocloud.dev/gcerrors" ) // Deployer supports deploying the site to target cloud providers. type Deployer struct { localFs afero.Fs bucket *blob.Bucket target *target // the target to deploy to matchers []*matcher // matchers to apply to uploaded files mediaTypes media.Types // Hugo's MediaType to guess ContentType ordering []*regexp.Regexp // orders uploads quiet bool // true reduces STDOUT confirm bool // true enables confirmation before making changes dryRun bool // true skips conformations and prints changes instead of applying them force bool // true forces upload of all files invalidateCDN bool // true enables invalidate CDN cache (if possible) maxDeletes int // caps the # of files to delete; -1 to disable // For tests... summary deploySummary // summary of latest Deploy results } type deploySummary struct { NumLocal, NumRemote, NumUploads, NumDeletes int } // New constructs a new *Deployer. func New(cfg config.Provider, localFs afero.Fs) (*Deployer, error) { targetName := cfg.GetString("target") // Load the [deployment] section of the config. dcfg, err := decodeConfig(cfg) if err != nil { return nil, err } if len(dcfg.Targets) == 0 { return nil, errors.New("no deployment targets found") } // Find the target to deploy to. var tgt *target if targetName == "" { // Default to the first target. tgt = dcfg.Targets[0] } else { for _, t := range dcfg.Targets { if t.Name == targetName { tgt = t } } if tgt == nil { return nil, fmt.Errorf("deployment target %q not found", targetName) } } return &Deployer{ localFs: localFs, target: tgt, matchers: dcfg.Matchers, ordering: dcfg.ordering, mediaTypes: dcfg.mediaTypes, quiet: cfg.GetBool("quiet"), confirm: cfg.GetBool("confirm"), dryRun: cfg.GetBool("dryRun"), force: cfg.GetBool("force"), invalidateCDN: cfg.GetBool("invalidateCDN"), maxDeletes: cfg.GetInt("maxDeletes"), }, nil } func (d *Deployer) openBucket(ctx context.Context) (*blob.Bucket, error) { if d.bucket != nil { return d.bucket, nil } jww.FEEDBACK.Printf("Deploying to target %q (%s)\n", d.target.Name, d.target.URL) return blob.OpenBucket(ctx, d.target.URL) } // Deploy deploys the site to a target. func (d *Deployer) Deploy(ctx context.Context) error { bucket, err := d.openBucket(ctx) if err != nil { return err } // Load local files from the source directory. var include, exclude glob.Glob if d.target != nil { include, exclude = d.target.includeGlob, d.target.excludeGlob } local, err := walkLocal(d.localFs, d.matchers, include, exclude, d.mediaTypes) if err != nil { return err } jww.INFO.Printf("Found %d local files.\n", len(local)) d.summary.NumLocal = len(local) // Load remote files from the target. remote, err := walkRemote(ctx, bucket, include, exclude) if err != nil { return err } jww.INFO.Printf("Found %d remote files.\n", len(remote)) d.summary.NumRemote = len(remote) // Diff local vs remote to see what changes need to be applied. uploads, deletes := findDiffs(local, remote, d.force) d.summary.NumUploads = len(uploads) d.summary.NumDeletes = len(deletes) if len(uploads)+len(deletes) == 0 { if !d.quiet { jww.FEEDBACK.Println("No changes required.") } return nil } if !d.quiet { jww.FEEDBACK.Println(summarizeChanges(uploads, deletes)) } // Ask for confirmation before proceeding. if d.confirm && !d.dryRun { fmt.Printf("Continue? (Y/n) ") var confirm string if _, err := fmt.Scanln(&confirm); err != nil { return err } if confirm != "" && confirm[0] != 'y' && confirm[0] != 'Y' { return errors.New("aborted") } } // Order the uploads. They are organized in groups; all uploads in a group // must be complete before moving on to the next group. uploadGroups := applyOrdering(d.ordering, uploads) // Apply the changes in parallel, using an inverted worker // pool (https://www.youtube.com/watch?v=5zXAHh5tJqQ&t=26m58s). // sem prevents more than nParallel concurrent goroutines. const nParallel = 10 var errs []error var errMu sync.Mutex // protects errs for _, uploads := range uploadGroups { // Short-circuit for an empty group. if len(uploads) == 0 { continue } // Within the group, apply uploads in parallel. sem := make(chan struct{}, nParallel) for _, upload := range uploads { if d.dryRun { if !d.quiet { jww.FEEDBACK.Printf("[DRY RUN] Would upload: %v\n", upload) } continue } sem <- struct{}{} go func(upload *fileToUpload) { if err := doSingleUpload(ctx, bucket, upload); err != nil { errMu.Lock() defer errMu.Unlock() errs = append(errs, err) } <-sem }(upload) } // Wait for all uploads in the group to finish. for n := nParallel; n > 0; n-- { sem <- struct{}{} } } if d.maxDeletes != -1 && len(deletes) > d.maxDeletes { jww.WARN.Printf("Skipping %d deletes because it is more than --maxDeletes (%d). If this is expected, set --maxDeletes to a larger number, or -1 to disable this check.\n", len(deletes), d.maxDeletes) d.summary.NumDeletes = 0 } else { // Apply deletes in parallel. sort.Slice(deletes, func(i, j int) bool { return deletes[i] < deletes[j] }) sem := make(chan struct{}, nParallel) for _, del := range deletes { if d.dryRun { if !d.quiet { jww.FEEDBACK.Printf("[DRY RUN] Would delete %s\n", del) } continue } sem <- struct{}{} go func(del string) { jww.INFO.Printf("Deleting %s...\n", del) if err := bucket.Delete(ctx, del); err != nil { if gcerrors.Code(err) == gcerrors.NotFound { jww.WARN.Printf("Failed to delete %q because it wasn't found: %v", del, err) } else { errMu.Lock() defer errMu.Unlock() errs = append(errs, err) } } <-sem }(del) } // Wait for all deletes to finish. for n := nParallel; n > 0; n-- { sem <- struct{}{} } } if len(errs) > 0 { if !d.quiet { jww.FEEDBACK.Printf("Encountered %d errors.\n", len(errs)) } return errs[0] } if !d.quiet { jww.FEEDBACK.Println("Success!") } if d.invalidateCDN { if d.target.CloudFrontDistributionID != "" { if d.dryRun { if !d.quiet { jww.FEEDBACK.Printf("[DRY RUN] Would invalidate CloudFront CDN with ID %s\n", d.target.CloudFrontDistributionID) } } else { jww.FEEDBACK.Println("Invalidating CloudFront CDN...") if err := InvalidateCloudFront(ctx, d.target.CloudFrontDistributionID); err != nil { jww.FEEDBACK.Printf("Failed to invalidate CloudFront CDN: %v\n", err) return err } } } if d.target.GoogleCloudCDNOrigin != "" { if d.dryRun { if !d.quiet { jww.FEEDBACK.Printf("[DRY RUN] Would invalidate Google Cloud CDN with origin %s\n", d.target.GoogleCloudCDNOrigin) } } else { jww.FEEDBACK.Println("Invalidating Google Cloud CDN...") if err := InvalidateGoogleCloudCDN(ctx, d.target.GoogleCloudCDNOrigin); err != nil { jww.FEEDBACK.Printf("Failed to invalidate Google Cloud CDN: %v\n", err) return err } } } jww.FEEDBACK.Println("Success!") } return nil } // summarizeChanges creates a text description of the proposed changes. func summarizeChanges(uploads []*fileToUpload, deletes []string) string { uploadSize := int64(0) for _, u := range uploads { uploadSize += u.Local.UploadSize } return fmt.Sprintf("Identified %d file(s) to upload, totaling %s, and %d file(s) to delete.", len(uploads), humanize.Bytes(uint64(uploadSize)), len(deletes)) } // doSingleUpload executes a single file upload. func doSingleUpload(ctx context.Context, bucket *blob.Bucket, upload *fileToUpload) error { jww.INFO.Printf("Uploading %v...\n", upload) opts := &blob.WriterOptions{ CacheControl: upload.Local.CacheControl(), ContentEncoding: upload.Local.ContentEncoding(), ContentType: upload.Local.ContentType(), } w, err := bucket.NewWriter(ctx, upload.Local.SlashPath, opts) if err != nil { return err } r, err := upload.Local.Reader() if err != nil { return err } defer r.Close() _, err = io.Copy(w, r) if err != nil { return err } if err := w.Close(); err != nil { return err } return nil } // localFile represents a local file from the source. Use newLocalFile to // construct one. type localFile struct { // NativePath is the native path to the file (using file.Separator). NativePath string // SlashPath is NativePath converted to use /. SlashPath string // UploadSize is the size of the content to be uploaded. It may not // be the same as the local file size if the content will be // gzipped before upload. UploadSize int64 fs afero.Fs matcher *matcher md5 []byte // cache gzipped bytes.Buffer // cached of gzipped contents if gzipping mediaTypes media.Types } // newLocalFile initializes a *localFile. func newLocalFile(fs afero.Fs, nativePath, slashpath string, m *matcher, mt media.Types) (*localFile, error) { f, err := fs.Open(nativePath) if err != nil { return nil, err } defer f.Close() lf := &localFile{ NativePath: nativePath, SlashPath: slashpath, fs: fs, matcher: m, mediaTypes: mt, } if m != nil && m.Gzip { // We're going to gzip the content. Do it once now, and cache the result // in gzipped. The UploadSize is the size of the gzipped content. gz := gzip.NewWriter(&lf.gzipped) if _, err := io.Copy(gz, f); err != nil { return nil, err } if err := gz.Close(); err != nil { return nil, err } lf.UploadSize = int64(lf.gzipped.Len()) } else { // Raw content. Just get the UploadSize. info, err := f.Stat() if err != nil { return nil, err } lf.UploadSize = info.Size() } return lf, nil } // Reader returns an io.ReadCloser for reading the content to be uploaded. // The caller must call Close on the returned ReaderCloser. // The reader content may not be the same as the local file content due to // gzipping. func (lf *localFile) Reader() (io.ReadCloser, error) { if lf.matcher != nil && lf.matcher.Gzip { // We've got the gzipped contents cached in gzipped. // Note: we can't use lf.gzipped directly as a Reader, since we it discards // data after it is read, and we may read it more than once. return ioutil.NopCloser(bytes.NewReader(lf.gzipped.Bytes())), nil } // Not expected to fail since we did it successfully earlier in newLocalFile, // but could happen due to changes in the underlying filesystem. return lf.fs.Open(lf.NativePath) } // CacheControl returns the Cache-Control header to use for lf, based on the // first matching matcher (if any). func (lf *localFile) CacheControl() string { if lf.matcher == nil { return "" } return lf.matcher.CacheControl } // ContentEncoding returns the Content-Encoding header to use for lf, based // on the matcher's Content-Encoding and Gzip fields. func (lf *localFile) ContentEncoding() string { if lf.matcher == nil { return "" } if lf.matcher.Gzip { return "gzip" } return lf.matcher.ContentEncoding } // ContentType returns the Content-Type header to use for lf. // It first checks if there's a Content-Type header configured via a matching // matcher; if not, it tries to generate one based on the filename extension. // If this fails, the Content-Type will be the empty string. In this case, Go // Cloud will automatically try to infer a Content-Type based on the file // content. func (lf *localFile) ContentType() string { if lf.matcher != nil && lf.matcher.ContentType != "" { return lf.matcher.ContentType } ext := filepath.Ext(lf.NativePath) if mimeType, _, found := lf.mediaTypes.GetFirstBySuffix(strings.TrimPrefix(ext, ".")); found { return mimeType.Type() } return mime.TypeByExtension(ext) } // Force returns true if the file should be forced to re-upload based on the // matching matcher. func (lf *localFile) Force() bool { return lf.matcher != nil && lf.matcher.Force } // MD5 returns an MD5 hash of the content to be uploaded. func (lf *localFile) MD5() []byte { if len(lf.md5) > 0 { return lf.md5 } h := md5.New() r, err := lf.Reader() if err != nil { return nil } defer r.Close() if _, err := io.Copy(h, r); err != nil { return nil } lf.md5 = h.Sum(nil) return lf.md5 } // knownHiddenDirectory checks if the specified name is a well known // hidden directory. func knownHiddenDirectory(name string) bool { knownDirectories := []string{ ".well-known", } for _, dir := range knownDirectories { if name == dir { return true } } return false } // walkLocal walks the source directory and returns a flat list of files, // using localFile.SlashPath as the map keys. func walkLocal(fs afero.Fs, matchers []*matcher, include, exclude glob.Glob, mediaTypes media.Types) (map[string]*localFile, error) { retval := map[string]*localFile{} err := afero.Walk(fs, "", func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { // Skip hidden directories. if path != "" && strings.HasPrefix(info.Name(), ".") { // Except for specific hidden directories if !knownHiddenDirectory(info.Name()) { return filepath.SkipDir } } return nil } // .DS_Store is an internal MacOS attribute file; skip it. if info.Name() == ".DS_Store" { return nil } // When a file system is HFS+, its filepath is in NFD form. if runtime.GOOS == "darwin" { path = norm.NFC.String(path) } // Check include/exclude matchers. slashpath := filepath.ToSlash(path) if include != nil && !include.Match(slashpath) { jww.INFO.Printf(" dropping %q due to include\n", slashpath) return nil } if exclude != nil && exclude.Match(slashpath) { jww.INFO.Printf(" dropping %q due to exclude\n", slashpath) return nil } // Find the first matching matcher (if any). var m *matcher for _, cur := range matchers { if cur.Matches(slashpath) { m = cur break } } lf, err := newLocalFile(fs, path, slashpath, m, mediaTypes) if err != nil { return err } retval[lf.SlashPath] = lf return nil }) if err != nil { return nil, err } return retval, nil } // walkRemote walks the target bucket and returns a flat list. func walkRemote(ctx context.Context, bucket *blob.Bucket, include, exclude glob.Glob) (map[string]*blob.ListObject, error) { retval := map[string]*blob.ListObject{} iter := bucket.List(nil) for { obj, err := iter.Next(ctx) if err == io.EOF { break } if err != nil { return nil, err } // Check include/exclude matchers. if include != nil && !include.Match(obj.Key) { jww.INFO.Printf(" remote dropping %q due to include\n", obj.Key) continue } if exclude != nil && exclude.Match(obj.Key) { jww.INFO.Printf(" remote dropping %q due to exclude\n", obj.Key) continue } // If the remote didn't give us an MD5, compute one. // This can happen for some providers (e.g., fileblob, which uses the // local filesystem), but not for the most common Cloud providers // (S3, GCS, Azure). Although, it can happen for S3 if the blob was uploaded // via a multi-part upload. // Although it's unfortunate to have to read the file, it's likely better // than assuming a delta and re-uploading it. if len(obj.MD5) == 0 { r, err := bucket.NewReader(ctx, obj.Key, nil) if err == nil { h := md5.New() if _, err := io.Copy(h, r); err == nil { obj.MD5 = h.Sum(nil) } r.Close() } } retval[obj.Key] = obj } return retval, nil } // uploadReason is an enum of reasons why a file must be uploaded. type uploadReason string const ( reasonUnknown uploadReason = "unknown" reasonNotFound uploadReason = "not found at target" reasonForce uploadReason = "--force" reasonSize uploadReason = "size differs" reasonMD5Differs uploadReason = "md5 differs" reasonMD5Missing uploadReason = "remote md5 missing" ) // fileToUpload represents a single local file that should be uploaded to // the target. type fileToUpload struct { Local *localFile Reason uploadReason } func (u *fileToUpload) String() string { details := []string{humanize.Bytes(uint64(u.Local.UploadSize))} if s := u.Local.CacheControl(); s != "" { details = append(details, fmt.Sprintf("Cache-Control: %q", s)) } if s := u.Local.ContentEncoding(); s != "" { details = append(details, fmt.Sprintf("Content-Encoding: %q", s)) } if s := u.Local.ContentType(); s != "" { details = append(details, fmt.Sprintf("Content-Type: %q", s)) } return fmt.Sprintf("%s (%s): %v", u.Local.SlashPath, strings.Join(details, ", "), u.Reason) } // findDiffs diffs localFiles vs remoteFiles to see what changes should be // applied to the remote target. It returns a slice of *fileToUpload and a // slice of paths for files to delete. func findDiffs(localFiles map[string]*localFile, remoteFiles map[string]*blob.ListObject, force bool) ([]*fileToUpload, []string) { var uploads []*fileToUpload var deletes []string found := map[string]bool{} for path, lf := range localFiles { upload := false reason := reasonUnknown if remoteFile, ok := remoteFiles[path]; ok { // The file exists in remote. Let's see if we need to upload it anyway. // TODO: We don't register a diff if the metadata (e.g., Content-Type // header) has changed. This would be difficult/expensive to detect; some // providers return metadata along with their "List" result, but others // (notably AWS S3) do not, so gocloud.dev's blob.Bucket doesn't expose // it in the list result. It would require a separate request per blob // to fetch. At least for now, we work around this by documenting it and // providing a "force" flag (to re-upload everything) and a "force" bool // per matcher (to re-upload all files in a matcher whose headers may have // changed). // Idea: extract a sample set of 1 file per extension + 1 file per matcher // and check those files? if force { upload = true reason = reasonForce } else if lf.Force() { upload = true reason = reasonForce } else if lf.UploadSize != remoteFile.Size { upload = true reason = reasonSize } else if len(remoteFile.MD5) == 0 { // This shouldn't happen unless the remote didn't give us an MD5 hash // from List, AND we failed to compute one by reading the remote file. // Default to considering the files different. upload = true reason = reasonMD5Missing } else if !bytes.Equal(lf.MD5(), remoteFile.MD5) { upload = true reason = reasonMD5Differs } else { // Nope! Leave uploaded = false. } found[path] = true } else { // The file doesn't exist in remote. upload = true reason = reasonNotFound } if upload { jww.DEBUG.Printf("%s needs to be uploaded: %v\n", path, reason) uploads = append(uploads, &fileToUpload{lf, reason}) } else { jww.DEBUG.Printf("%s exists at target and does not need to be uploaded", path) } } // Remote files that weren't found locally should be deleted. for path := range remoteFiles { if !found[path] { deletes = append(deletes, path) } } return uploads, deletes } // applyOrdering returns an ordered slice of slices of uploads. // // The returned slice will have length len(ordering)+1. // // The subslice at index i, for i = 0 ... len(ordering)-1, will have all of the // uploads whose Local.SlashPath matched the regex at ordering[i] (but not any // previous ordering regex). // The subslice at index len(ordering) will have the remaining uploads that // didn't match any ordering regex. // // The subslices are sorted by Local.SlashPath. func applyOrdering(ordering []*regexp.Regexp, uploads []*fileToUpload) [][]*fileToUpload { // Sort the whole slice by Local.SlashPath first. sort.Slice(uploads, func(i, j int) bool { return uploads[i].Local.SlashPath < uploads[j].Local.SlashPath }) retval := make([][]*fileToUpload, len(ordering)+1) for _, u := range uploads { matched := false for i, re := range ordering { if re.MatchString(u.Local.SlashPath) { retval[i] = append(retval[i], u) matched = true break } } if !matched { retval[len(ordering)] = append(retval[len(ordering)], u) } } return retval } hugo-0.92.2/deploy/deployConfig.go000066400000000000000000000110411420147000300167770ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //go:build !nodeploy // +build !nodeploy package deploy import ( "fmt" "regexp" "github.com/gobwas/glob" "github.com/gohugoio/hugo/config" hglob "github.com/gohugoio/hugo/hugofs/glob" "github.com/gohugoio/hugo/media" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) const deploymentConfigKey = "deployment" // deployConfig is the complete configuration for deployment. type deployConfig struct { Targets []*target Matchers []*matcher Order []string ordering []*regexp.Regexp // compiled Order mediaTypes media.Types } type target struct { Name string URL string CloudFrontDistributionID string // GoogleCloudCDNOrigin specifies the Google Cloud project and CDN origin to // invalidate when deploying this target. It is specified as /. GoogleCloudCDNOrigin string // Optional patterns of files to include/exclude for this target. // Parsed using github.com/gobwas/glob. Include string Exclude string // Parsed versions of Include/Exclude. includeGlob glob.Glob excludeGlob glob.Glob } func (tgt *target) parseIncludeExclude() error { var err error if tgt.Include != "" { tgt.includeGlob, err = hglob.GetGlob(tgt.Include) if err != nil { return fmt.Errorf("invalid deployment.target.include %q: %v", tgt.Include, err) } } if tgt.Exclude != "" { tgt.excludeGlob, err = hglob.GetGlob(tgt.Exclude) if err != nil { return fmt.Errorf("invalid deployment.target.exclude %q: %v", tgt.Exclude, err) } } return nil } // matcher represents configuration to be applied to files whose paths match // a specified pattern. type matcher struct { // Pattern is the string pattern to match against paths. // Matching is done against paths converted to use / as the path separator. Pattern string // CacheControl specifies caching attributes to use when serving the blob. // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control CacheControl string // ContentEncoding specifies the encoding used for the blob's content, if any. // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding ContentEncoding string // ContentType specifies the MIME type of the blob being written. // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type ContentType string // Gzip determines whether the file should be gzipped before upload. // If so, the ContentEncoding field will automatically be set to "gzip". Gzip bool // Force indicates that matching files should be re-uploaded. Useful when // other route-determined metadata (e.g., ContentType) has changed. Force bool // re is Pattern compiled. re *regexp.Regexp } func (m *matcher) Matches(path string) bool { return m.re.MatchString(path) } // decode creates a config from a given Hugo configuration. func decodeConfig(cfg config.Provider) (deployConfig, error) { var ( mediaTypesConfig []map[string]interface{} dcfg deployConfig ) if !cfg.IsSet(deploymentConfigKey) { return dcfg, nil } if err := mapstructure.WeakDecode(cfg.GetStringMap(deploymentConfigKey), &dcfg); err != nil { return dcfg, err } for _, tgt := range dcfg.Targets { if tgt == nil { return dcfg, errors.New("empty deployment target") } if err := tgt.parseIncludeExclude(); err != nil { return dcfg, err } } var err error for _, m := range dcfg.Matchers { if m == nil { return dcfg, errors.New("empty deployment matcher") } m.re, err = regexp.Compile(m.Pattern) if err != nil { return dcfg, fmt.Errorf("invalid deployment.matchers.pattern: %v", err) } } for _, o := range dcfg.Order { re, err := regexp.Compile(o) if err != nil { return dcfg, fmt.Errorf("invalid deployment.orderings.pattern: %v", err) } dcfg.ordering = append(dcfg.ordering, re) } if cfg.IsSet("mediaTypes") { mediaTypesConfig = append(mediaTypesConfig, cfg.GetStringMap("mediaTypes")) } dcfg.mediaTypes, err = media.DecodeTypes(mediaTypesConfig...) if err != nil { return dcfg, err } return dcfg, nil } hugo-0.92.2/deploy/deployConfig_test.go000066400000000000000000000110731420147000300200430ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //go:build !nodeploy // +build !nodeploy package deploy import ( "fmt" "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/config" ) func TestDecodeConfigFromTOML(t *testing.T) { c := qt.New(t) tomlConfig := ` someOtherValue = "foo" [deployment] order = ["o1", "o2"] # All lowercase. [[deployment.targets]] name = "name0" url = "url0" cloudfrontdistributionid = "cdn0" include = "*.html" # All uppercase. [[deployment.targets]] NAME = "name1" URL = "url1" CLOUDFRONTDISTRIBUTIONID = "cdn1" INCLUDE = "*.jpg" # Camelcase. [[deployment.targets]] name = "name2" url = "url2" cloudFrontDistributionID = "cdn2" exclude = "*.png" # All lowercase. [[deployment.matchers]] pattern = "^pattern0$" cachecontrol = "cachecontrol0" contentencoding = "contentencoding0" contenttype = "contenttype0" # All uppercase. [[deployment.matchers]] PATTERN = "^pattern1$" CACHECONTROL = "cachecontrol1" CONTENTENCODING = "contentencoding1" CONTENTTYPE = "contenttype1" GZIP = true FORCE = true # Camelcase. [[deployment.matchers]] pattern = "^pattern2$" cacheControl = "cachecontrol2" contentEncoding = "contentencoding2" contentType = "contenttype2" gzip = true force = true ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) dcfg, err := decodeConfig(cfg) c.Assert(err, qt.IsNil) // Order. c.Assert(len(dcfg.Order), qt.Equals, 2) c.Assert(dcfg.Order[0], qt.Equals, "o1") c.Assert(dcfg.Order[1], qt.Equals, "o2") c.Assert(len(dcfg.ordering), qt.Equals, 2) // Targets. c.Assert(len(dcfg.Targets), qt.Equals, 3) wantInclude := []string{"*.html", "*.jpg", ""} wantExclude := []string{"", "", "*.png"} for i := 0; i < 3; i++ { tgt := dcfg.Targets[i] c.Assert(tgt.Name, qt.Equals, fmt.Sprintf("name%d", i)) c.Assert(tgt.URL, qt.Equals, fmt.Sprintf("url%d", i)) c.Assert(tgt.CloudFrontDistributionID, qt.Equals, fmt.Sprintf("cdn%d", i)) c.Assert(tgt.Include, qt.Equals, wantInclude[i]) if wantInclude[i] != "" { c.Assert(tgt.includeGlob, qt.Not(qt.IsNil)) } c.Assert(tgt.Exclude, qt.Equals, wantExclude[i]) if wantExclude[i] != "" { c.Assert(tgt.excludeGlob, qt.Not(qt.IsNil)) } } // Matchers. c.Assert(len(dcfg.Matchers), qt.Equals, 3) for i := 0; i < 3; i++ { m := dcfg.Matchers[i] c.Assert(m.Pattern, qt.Equals, fmt.Sprintf("^pattern%d$", i)) c.Assert(m.re, qt.Not(qt.IsNil)) c.Assert(m.CacheControl, qt.Equals, fmt.Sprintf("cachecontrol%d", i)) c.Assert(m.ContentEncoding, qt.Equals, fmt.Sprintf("contentencoding%d", i)) c.Assert(m.ContentType, qt.Equals, fmt.Sprintf("contenttype%d", i)) c.Assert(m.Gzip, qt.Equals, i != 0) c.Assert(m.Force, qt.Equals, i != 0) } } func TestInvalidOrderingPattern(t *testing.T) { c := qt.New(t) tomlConfig := ` someOtherValue = "foo" [deployment] order = ["["] # invalid regular expression ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) _, err = decodeConfig(cfg) c.Assert(err, qt.Not(qt.IsNil)) } func TestInvalidMatcherPattern(t *testing.T) { c := qt.New(t) tomlConfig := ` someOtherValue = "foo" [deployment] [[deployment.matchers]] Pattern = "[" # invalid regular expression ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) _, err = decodeConfig(cfg) c.Assert(err, qt.Not(qt.IsNil)) } func TestDecodeConfigDefault(t *testing.T) { c := qt.New(t) dcfg, err := decodeConfig(config.New()) c.Assert(err, qt.IsNil) c.Assert(len(dcfg.Targets), qt.Equals, 0) c.Assert(len(dcfg.Matchers), qt.Equals, 0) } func TestEmptyTarget(t *testing.T) { c := qt.New(t) tomlConfig := ` [deployment] [[deployment.targets]] ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) _, err = decodeConfig(cfg) c.Assert(err, qt.Not(qt.IsNil)) } func TestEmptyMatcher(t *testing.T) { c := qt.New(t) tomlConfig := ` [deployment] [[deployment.matchers]] ` cfg, err := config.FromConfigString(tomlConfig, "toml") c.Assert(err, qt.IsNil) _, err = decodeConfig(cfg) c.Assert(err, qt.Not(qt.IsNil)) } hugo-0.92.2/deploy/deploy_azure.go000066400000000000000000000013321420147000300170610ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build !solaris,!nodeploy package deploy import ( _ "gocloud.dev/blob" _ "gocloud.dev/blob/azureblob" // import ) hugo-0.92.2/deploy/deploy_test.go000066400000000000000000000733171420147000300167260ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build !nodeploy package deploy import ( "bytes" "compress/gzip" "context" "crypto/md5" "fmt" "io" "io/ioutil" "os" "path" "path/filepath" "regexp" "sort" "testing" "github.com/gohugoio/hugo/media" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/spf13/afero" "gocloud.dev/blob" "gocloud.dev/blob/fileblob" "gocloud.dev/blob/memblob" ) func TestFindDiffs(t *testing.T) { hash1 := []byte("hash 1") hash2 := []byte("hash 2") makeLocal := func(path string, size int64, hash []byte) *localFile { return &localFile{NativePath: path, SlashPath: filepath.ToSlash(path), UploadSize: size, md5: hash} } makeRemote := func(path string, size int64, hash []byte) *blob.ListObject { return &blob.ListObject{Key: path, Size: size, MD5: hash} } tests := []struct { Description string Local []*localFile Remote []*blob.ListObject Force bool WantUpdates []*fileToUpload WantDeletes []string }{ { Description: "empty -> no diffs", }, { Description: "local == remote -> no diffs", Local: []*localFile{ makeLocal("aaa", 1, hash1), makeLocal("bbb", 2, hash1), makeLocal("ccc", 3, hash2), }, Remote: []*blob.ListObject{ makeRemote("aaa", 1, hash1), makeRemote("bbb", 2, hash1), makeRemote("ccc", 3, hash2), }, }, { Description: "local w/ separators == remote -> no diffs", Local: []*localFile{ makeLocal(filepath.Join("aaa", "aaa"), 1, hash1), makeLocal(filepath.Join("bbb", "bbb"), 2, hash1), makeLocal(filepath.Join("ccc", "ccc"), 3, hash2), }, Remote: []*blob.ListObject{ makeRemote("aaa/aaa", 1, hash1), makeRemote("bbb/bbb", 2, hash1), makeRemote("ccc/ccc", 3, hash2), }, }, { Description: "local == remote with force flag true -> diffs", Local: []*localFile{ makeLocal("aaa", 1, hash1), makeLocal("bbb", 2, hash1), makeLocal("ccc", 3, hash2), }, Remote: []*blob.ListObject{ makeRemote("aaa", 1, hash1), makeRemote("bbb", 2, hash1), makeRemote("ccc", 3, hash2), }, Force: true, WantUpdates: []*fileToUpload{ {makeLocal("aaa", 1, nil), reasonForce}, {makeLocal("bbb", 2, nil), reasonForce}, {makeLocal("ccc", 3, nil), reasonForce}, }, }, { Description: "local == remote with route.Force true -> diffs", Local: []*localFile{ {NativePath: "aaa", SlashPath: "aaa", UploadSize: 1, matcher: &matcher{Force: true}, md5: hash1}, makeLocal("bbb", 2, hash1), }, Remote: []*blob.ListObject{ makeRemote("aaa", 1, hash1), makeRemote("bbb", 2, hash1), }, WantUpdates: []*fileToUpload{ {makeLocal("aaa", 1, nil), reasonForce}, }, }, { Description: "extra local file -> upload", Local: []*localFile{ makeLocal("aaa", 1, hash1), makeLocal("bbb", 2, hash2), }, Remote: []*blob.ListObject{ makeRemote("aaa", 1, hash1), }, WantUpdates: []*fileToUpload{ {makeLocal("bbb", 2, nil), reasonNotFound}, }, }, { Description: "extra remote file -> delete", Local: []*localFile{ makeLocal("aaa", 1, hash1), }, Remote: []*blob.ListObject{ makeRemote("aaa", 1, hash1), makeRemote("bbb", 2, hash2), }, WantDeletes: []string{"bbb"}, }, { Description: "diffs in size or md5 -> upload", Local: []*localFile{ makeLocal("aaa", 1, hash1), makeLocal("bbb", 2, hash1), makeLocal("ccc", 1, hash2), }, Remote: []*blob.ListObject{ makeRemote("aaa", 1, nil), makeRemote("bbb", 1, hash1), makeRemote("ccc", 1, hash1), }, WantUpdates: []*fileToUpload{ {makeLocal("aaa", 1, nil), reasonMD5Missing}, {makeLocal("bbb", 2, nil), reasonSize}, {makeLocal("ccc", 1, nil), reasonMD5Differs}, }, }, { Description: "mix of updates and deletes", Local: []*localFile{ makeLocal("same", 1, hash1), makeLocal("updated", 2, hash1), makeLocal("updated2", 1, hash2), makeLocal("new", 1, hash1), makeLocal("new2", 2, hash2), }, Remote: []*blob.ListObject{ makeRemote("same", 1, hash1), makeRemote("updated", 1, hash1), makeRemote("updated2", 1, hash1), makeRemote("stale", 1, hash1), makeRemote("stale2", 1, hash1), }, WantUpdates: []*fileToUpload{ {makeLocal("new", 1, nil), reasonNotFound}, {makeLocal("new2", 2, nil), reasonNotFound}, {makeLocal("updated", 2, nil), reasonSize}, {makeLocal("updated2", 1, nil), reasonMD5Differs}, }, WantDeletes: []string{"stale", "stale2"}, }, } for _, tc := range tests { t.Run(tc.Description, func(t *testing.T) { local := map[string]*localFile{} for _, l := range tc.Local { local[l.SlashPath] = l } remote := map[string]*blob.ListObject{} for _, r := range tc.Remote { remote[r.Key] = r } gotUpdates, gotDeletes := findDiffs(local, remote, tc.Force) gotUpdates = applyOrdering(nil, gotUpdates)[0] sort.Slice(gotDeletes, func(i, j int) bool { return gotDeletes[i] < gotDeletes[j] }) if diff := cmp.Diff(gotUpdates, tc.WantUpdates, cmpopts.IgnoreUnexported(localFile{})); diff != "" { t.Errorf("updates differ:\n%s", diff) } if diff := cmp.Diff(gotDeletes, tc.WantDeletes); diff != "" { t.Errorf("deletes differ:\n%s", diff) } }) } } func TestWalkLocal(t *testing.T) { tests := map[string]struct { Given []string Expect []string }{ "Empty": { Given: []string{}, Expect: []string{}, }, "Normal": { Given: []string{"file.txt", "normal_dir/file.txt"}, Expect: []string{"file.txt", "normal_dir/file.txt"}, }, "Hidden": { Given: []string{"file.txt", ".hidden_dir/file.txt", "normal_dir/file.txt"}, Expect: []string{"file.txt", "normal_dir/file.txt"}, }, "Well Known": { Given: []string{"file.txt", ".hidden_dir/file.txt", ".well-known/file.txt"}, Expect: []string{"file.txt", ".well-known/file.txt"}, }, } for desc, tc := range tests { t.Run(desc, func(t *testing.T) { fs := afero.NewMemMapFs() for _, name := range tc.Given { dir, _ := path.Split(name) if dir != "" { if err := fs.MkdirAll(dir, 0755); err != nil { t.Fatal(err) } } if fd, err := fs.Create(name); err != nil { t.Fatal(err) } else { fd.Close() } } if got, err := walkLocal(fs, nil, nil, nil, media.DefaultTypes); err != nil { t.Fatal(err) } else { expect := map[string]interface{}{} for _, path := range tc.Expect { if _, ok := got[path]; !ok { t.Errorf("expected %q in results, but was not found", path) } expect[path] = nil } for path := range got { if _, ok := expect[path]; !ok { t.Errorf("got %q in results unexpectedly", path) } } } }) } } func TestLocalFile(t *testing.T) { const ( content = "hello world!" ) contentBytes := []byte(content) contentLen := int64(len(contentBytes)) contentMD5 := md5.Sum(contentBytes) var buf bytes.Buffer gz := gzip.NewWriter(&buf) if _, err := gz.Write(contentBytes); err != nil { t.Fatal(err) } gz.Close() gzBytes := buf.Bytes() gzLen := int64(len(gzBytes)) gzMD5 := md5.Sum(gzBytes) tests := []struct { Description string Path string Matcher *matcher MediaTypesConfig []map[string]interface{} WantContent []byte WantSize int64 WantMD5 []byte WantContentType string // empty string is always OK, since content type detection is OS-specific WantCacheControl string WantContentEncoding string }{ { Description: "file with no suffix", Path: "foo", WantContent: contentBytes, WantSize: contentLen, WantMD5: contentMD5[:], }, { Description: "file with .txt suffix", Path: "foo.txt", WantContent: contentBytes, WantSize: contentLen, WantMD5: contentMD5[:], }, { Description: "CacheControl from matcher", Path: "foo.txt", Matcher: &matcher{CacheControl: "max-age=630720000"}, WantContent: contentBytes, WantSize: contentLen, WantMD5: contentMD5[:], WantCacheControl: "max-age=630720000", }, { Description: "ContentEncoding from matcher", Path: "foo.txt", Matcher: &matcher{ContentEncoding: "foobar"}, WantContent: contentBytes, WantSize: contentLen, WantMD5: contentMD5[:], WantContentEncoding: "foobar", }, { Description: "ContentType from matcher", Path: "foo.txt", Matcher: &matcher{ContentType: "foo/bar"}, WantContent: contentBytes, WantSize: contentLen, WantMD5: contentMD5[:], WantContentType: "foo/bar", }, { Description: "gzipped content", Path: "foo.txt", Matcher: &matcher{Gzip: true}, WantContent: gzBytes, WantSize: gzLen, WantMD5: gzMD5[:], WantContentEncoding: "gzip", }, { Description: "Custom MediaType", Path: "foo.hugo", MediaTypesConfig: []map[string]interface{}{ { "hugo/custom": map[string]interface{}{ "suffixes": []string{"hugo"}, }, }, }, WantContent: contentBytes, WantSize: contentLen, WantMD5: contentMD5[:], WantContentType: "hugo/custom", }, } for _, tc := range tests { t.Run(tc.Description, func(t *testing.T) { fs := new(afero.MemMapFs) if err := afero.WriteFile(fs, tc.Path, []byte(content), os.ModePerm); err != nil { t.Fatal(err) } mediaTypes := media.DefaultTypes if len(tc.MediaTypesConfig) > 0 { mt, err := media.DecodeTypes(tc.MediaTypesConfig...) if err != nil { t.Fatal(err) } mediaTypes = mt } lf, err := newLocalFile(fs, tc.Path, filepath.ToSlash(tc.Path), tc.Matcher, mediaTypes) if err != nil { t.Fatal(err) } if got := lf.UploadSize; got != tc.WantSize { t.Errorf("got size %d want %d", got, tc.WantSize) } if got := lf.MD5(); !bytes.Equal(got, tc.WantMD5) { t.Errorf("got MD5 %x want %x", got, tc.WantMD5) } if got := lf.CacheControl(); got != tc.WantCacheControl { t.Errorf("got CacheControl %q want %q", got, tc.WantCacheControl) } if got := lf.ContentEncoding(); got != tc.WantContentEncoding { t.Errorf("got ContentEncoding %q want %q", got, tc.WantContentEncoding) } if tc.WantContentType != "" { if got := lf.ContentType(); got != tc.WantContentType { t.Errorf("got ContentType %q want %q", got, tc.WantContentType) } } // Verify the reader last to ensure the previous operations don't // interfere with it. r, err := lf.Reader() if err != nil { t.Fatal(err) } gotContent, err := ioutil.ReadAll(r) if err != nil { t.Fatal(err) } if !bytes.Equal(gotContent, tc.WantContent) { t.Errorf("got content %q want %q", string(gotContent), string(tc.WantContent)) } r.Close() // Verify we can read again. r, err = lf.Reader() if err != nil { t.Fatal(err) } gotContent, err = ioutil.ReadAll(r) if err != nil { t.Fatal(err) } r.Close() if !bytes.Equal(gotContent, tc.WantContent) { t.Errorf("got content %q want %q", string(gotContent), string(tc.WantContent)) } }) } } func TestOrdering(t *testing.T) { tests := []struct { Description string Uploads []string Ordering []*regexp.Regexp Want [][]string }{ { Description: "empty", Want: [][]string{nil}, }, { Description: "no ordering", Uploads: []string{"c", "b", "a", "d"}, Want: [][]string{{"a", "b", "c", "d"}}, }, { Description: "one ordering", Uploads: []string{"db", "c", "b", "a", "da"}, Ordering: []*regexp.Regexp{regexp.MustCompile("^d")}, Want: [][]string{{"da", "db"}, {"a", "b", "c"}}, }, { Description: "two orderings", Uploads: []string{"db", "c", "b", "a", "da"}, Ordering: []*regexp.Regexp{ regexp.MustCompile("^d"), regexp.MustCompile("^b"), }, Want: [][]string{{"da", "db"}, {"b"}, {"a", "c"}}, }, } for _, tc := range tests { t.Run(tc.Description, func(t *testing.T) { uploads := make([]*fileToUpload, len(tc.Uploads)) for i, u := range tc.Uploads { uploads[i] = &fileToUpload{Local: &localFile{SlashPath: u}} } gotUploads := applyOrdering(tc.Ordering, uploads) var got [][]string for _, subslice := range gotUploads { var gotsubslice []string for _, u := range subslice { gotsubslice = append(gotsubslice, u.Local.SlashPath) } got = append(got, gotsubslice) } if diff := cmp.Diff(got, tc.Want); diff != "" { t.Error(diff) } }) } } type fileData struct { Name string // name of the file Contents string // contents of the file } // initLocalFs initializes fs with some test files. func initLocalFs(ctx context.Context, fs afero.Fs) ([]*fileData, error) { // The initial local filesystem. local := []*fileData{ {"aaa", "aaa"}, {"bbb", "bbb"}, {"subdir/aaa", "subdir-aaa"}, {"subdir/nested/aaa", "subdir-nested-aaa"}, {"subdir2/bbb", "subdir2-bbb"}, } if err := writeFiles(fs, local); err != nil { return nil, err } return local, nil } // fsTest represents an (afero.FS, Go CDK blob.Bucket) against which end-to-end // tests can be run. type fsTest struct { name string fs afero.Fs bucket *blob.Bucket } // initFsTests initializes a pair of tests for end-to-end test: // 1. An in-memory afero.Fs paired with an in-memory Go CDK bucket. // 2. A filesystem-based afero.Fs paired with an filesystem-based Go CDK bucket. // It returns the pair of tests and a cleanup function. func initFsTests() ([]*fsTest, func(), error) { tmpfsdir, err := ioutil.TempDir("", "fs") if err != nil { return nil, nil, err } tmpbucketdir, err := ioutil.TempDir("", "bucket") if err != nil { return nil, nil, err } memfs := afero.NewMemMapFs() membucket := memblob.OpenBucket(nil) filefs := afero.NewBasePathFs(afero.NewOsFs(), tmpfsdir) filebucket, err := fileblob.OpenBucket(tmpbucketdir, nil) if err != nil { return nil, nil, err } tests := []*fsTest{ {"mem", memfs, membucket}, {"file", filefs, filebucket}, } cleanup := func() { membucket.Close() filebucket.Close() os.RemoveAll(tmpfsdir) os.RemoveAll(tmpbucketdir) } return tests, cleanup, nil } // TestEndToEndSync verifies that basic adds, updates, and deletes are working // correctly. func TestEndToEndSync(t *testing.T) { ctx := context.Background() tests, cleanup, err := initFsTests() if err != nil { t.Fatal(err) } defer cleanup() for _, test := range tests { t.Run(test.name, func(t *testing.T) { local, err := initLocalFs(ctx, test.fs) if err != nil { t.Fatal(err) } deployer := &Deployer{ localFs: test.fs, maxDeletes: -1, bucket: test.bucket, mediaTypes: media.DefaultTypes, } // Initial deployment should sync remote with local. if err := deployer.Deploy(ctx); err != nil { t.Errorf("initial deploy: failed: %v", err) } wantSummary := deploySummary{NumLocal: 5, NumRemote: 0, NumUploads: 5, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("initial deploy: got %v, want %v", deployer.summary, wantSummary) } if diff, err := verifyRemote(ctx, deployer.bucket, local); err != nil { t.Errorf("initial deploy: failed to verify remote: %v", err) } else if diff != "" { t.Errorf("initial deploy: remote snapshot doesn't match expected:\n%v", diff) } // A repeat deployment shouldn't change anything. if err := deployer.Deploy(ctx); err != nil { t.Errorf("no-op deploy: %v", err) } wantSummary = deploySummary{NumLocal: 5, NumRemote: 5, NumUploads: 0, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("no-op deploy: got %v, want %v", deployer.summary, wantSummary) } // Make some changes to the local filesystem: // 1. Modify file [0]. // 2. Delete file [1]. // 3. Add a new file (sorted last). updatefd := local[0] updatefd.Contents = "new contents" deletefd := local[1] local = append(local[:1], local[2:]...) // removing deleted [1] newfd := &fileData{"zzz", "zzz"} local = append(local, newfd) if err := writeFiles(test.fs, []*fileData{updatefd, newfd}); err != nil { t.Fatal(err) } if err := test.fs.Remove(deletefd.Name); err != nil { t.Fatal(err) } // A deployment should apply those 3 changes. if err := deployer.Deploy(ctx); err != nil { t.Errorf("deploy after changes: failed: %v", err) } wantSummary = deploySummary{NumLocal: 5, NumRemote: 5, NumUploads: 2, NumDeletes: 1} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("deploy after changes: got %v, want %v", deployer.summary, wantSummary) } if diff, err := verifyRemote(ctx, deployer.bucket, local); err != nil { t.Errorf("deploy after changes: failed to verify remote: %v", err) } else if diff != "" { t.Errorf("deploy after changes: remote snapshot doesn't match expected:\n%v", diff) } // Again, a repeat deployment shouldn't change anything. if err := deployer.Deploy(ctx); err != nil { t.Errorf("no-op deploy: %v", err) } wantSummary = deploySummary{NumLocal: 5, NumRemote: 5, NumUploads: 0, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("no-op deploy: got %v, want %v", deployer.summary, wantSummary) } }) } } // TestMaxDeletes verifies that the "maxDeletes" flag is working correctly. func TestMaxDeletes(t *testing.T) { ctx := context.Background() tests, cleanup, err := initFsTests() if err != nil { t.Fatal(err) } defer cleanup() for _, test := range tests { t.Run(test.name, func(t *testing.T) { local, err := initLocalFs(ctx, test.fs) if err != nil { t.Fatal(err) } deployer := &Deployer{ localFs: test.fs, maxDeletes: -1, bucket: test.bucket, mediaTypes: media.DefaultTypes, } // Sync remote with local. if err := deployer.Deploy(ctx); err != nil { t.Errorf("initial deploy: failed: %v", err) } wantSummary := deploySummary{NumLocal: 5, NumRemote: 0, NumUploads: 5, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("initial deploy: got %v, want %v", deployer.summary, wantSummary) } // Delete two files, [1] and [2]. if err := test.fs.Remove(local[1].Name); err != nil { t.Fatal(err) } if err := test.fs.Remove(local[2].Name); err != nil { t.Fatal(err) } // A deployment with maxDeletes=0 shouldn't change anything. deployer.maxDeletes = 0 if err := deployer.Deploy(ctx); err != nil { t.Errorf("deploy failed: %v", err) } wantSummary = deploySummary{NumLocal: 3, NumRemote: 5, NumUploads: 0, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("deploy: got %v, want %v", deployer.summary, wantSummary) } // A deployment with maxDeletes=1 shouldn't change anything either. deployer.maxDeletes = 1 if err := deployer.Deploy(ctx); err != nil { t.Errorf("deploy failed: %v", err) } wantSummary = deploySummary{NumLocal: 3, NumRemote: 5, NumUploads: 0, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("deploy: got %v, want %v", deployer.summary, wantSummary) } // A deployment with maxDeletes=2 should make the changes. deployer.maxDeletes = 2 if err := deployer.Deploy(ctx); err != nil { t.Errorf("deploy failed: %v", err) } wantSummary = deploySummary{NumLocal: 3, NumRemote: 5, NumUploads: 0, NumDeletes: 2} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("deploy: got %v, want %v", deployer.summary, wantSummary) } // Delete two more files, [0] and [3]. if err := test.fs.Remove(local[0].Name); err != nil { t.Fatal(err) } if err := test.fs.Remove(local[3].Name); err != nil { t.Fatal(err) } // A deployment with maxDeletes=-1 should make the changes. deployer.maxDeletes = -1 if err := deployer.Deploy(ctx); err != nil { t.Errorf("deploy failed: %v", err) } wantSummary = deploySummary{NumLocal: 1, NumRemote: 3, NumUploads: 0, NumDeletes: 2} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("deploy: got %v, want %v", deployer.summary, wantSummary) } }) } } // TestIncludeExclude verifies that the include/exclude options for targets work. func TestIncludeExclude(t *testing.T) { ctx := context.Background() tests := []struct { Include string Exclude string Want deploySummary }{ { Want: deploySummary{NumLocal: 5, NumUploads: 5}, }, { Include: "**aaa", Want: deploySummary{NumLocal: 3, NumUploads: 3}, }, { Include: "**bbb", Want: deploySummary{NumLocal: 2, NumUploads: 2}, }, { Include: "aaa", Want: deploySummary{NumLocal: 1, NumUploads: 1}, }, { Exclude: "**aaa", Want: deploySummary{NumLocal: 2, NumUploads: 2}, }, { Exclude: "**bbb", Want: deploySummary{NumLocal: 3, NumUploads: 3}, }, { Exclude: "aaa", Want: deploySummary{NumLocal: 4, NumUploads: 4}, }, { Include: "**aaa", Exclude: "**nested**", Want: deploySummary{NumLocal: 2, NumUploads: 2}, }, } for _, test := range tests { t.Run(fmt.Sprintf("include %q exclude %q", test.Include, test.Exclude), func(t *testing.T) { fsTests, cleanup, err := initFsTests() if err != nil { t.Fatal(err) } defer cleanup() fsTest := fsTests[1] // just do file-based test _, err = initLocalFs(ctx, fsTest.fs) if err != nil { t.Fatal(err) } tgt := &target{ Include: test.Include, Exclude: test.Exclude, } if err := tgt.parseIncludeExclude(); err != nil { t.Error(err) } deployer := &Deployer{ localFs: fsTest.fs, maxDeletes: -1, bucket: fsTest.bucket, target: tgt, mediaTypes: media.DefaultTypes, } // Sync remote with local. if err := deployer.Deploy(ctx); err != nil { t.Errorf("deploy: failed: %v", err) } if !cmp.Equal(deployer.summary, test.Want) { t.Errorf("deploy: got %v, want %v", deployer.summary, test.Want) } }) } } // TestIncludeExcludeRemoteDelete verifies deleted local files that don't match include/exclude patterns // are not deleted on the remote. func TestIncludeExcludeRemoteDelete(t *testing.T) { ctx := context.Background() tests := []struct { Include string Exclude string Want deploySummary }{ { Want: deploySummary{NumLocal: 3, NumRemote: 5, NumUploads: 0, NumDeletes: 2}, }, { Include: "**aaa", Want: deploySummary{NumLocal: 2, NumRemote: 3, NumUploads: 0, NumDeletes: 1}, }, { Include: "subdir/**", Want: deploySummary{NumLocal: 1, NumRemote: 2, NumUploads: 0, NumDeletes: 1}, }, { Exclude: "**bbb", Want: deploySummary{NumLocal: 2, NumRemote: 3, NumUploads: 0, NumDeletes: 1}, }, { Exclude: "bbb", Want: deploySummary{NumLocal: 3, NumRemote: 4, NumUploads: 0, NumDeletes: 1}, }, } for _, test := range tests { t.Run(fmt.Sprintf("include %q exclude %q", test.Include, test.Exclude), func(t *testing.T) { fsTests, cleanup, err := initFsTests() if err != nil { t.Fatal(err) } defer cleanup() fsTest := fsTests[1] // just do file-based test local, err := initLocalFs(ctx, fsTest.fs) if err != nil { t.Fatal(err) } deployer := &Deployer{ localFs: fsTest.fs, maxDeletes: -1, bucket: fsTest.bucket, mediaTypes: media.DefaultTypes, } // Initial sync to get the files on the remote if err := deployer.Deploy(ctx); err != nil { t.Errorf("deploy: failed: %v", err) } // Delete two files, [1] and [2]. if err := fsTest.fs.Remove(local[1].Name); err != nil { t.Fatal(err) } if err := fsTest.fs.Remove(local[2].Name); err != nil { t.Fatal(err) } // Second sync tgt := &target{ Include: test.Include, Exclude: test.Exclude, } if err := tgt.parseIncludeExclude(); err != nil { t.Error(err) } deployer.target = tgt if err := deployer.Deploy(ctx); err != nil { t.Errorf("deploy: failed: %v", err) } if !cmp.Equal(deployer.summary, test.Want) { t.Errorf("deploy: got %v, want %v", deployer.summary, test.Want) } }) } } // TestCompression verifies that gzip compression works correctly. // In particular, MD5 hashes must be of the compressed content. func TestCompression(t *testing.T) { ctx := context.Background() tests, cleanup, err := initFsTests() if err != nil { t.Fatal(err) } defer cleanup() for _, test := range tests { t.Run(test.name, func(t *testing.T) { local, err := initLocalFs(ctx, test.fs) if err != nil { t.Fatal(err) } deployer := &Deployer{ localFs: test.fs, bucket: test.bucket, matchers: []*matcher{{Pattern: ".*", Gzip: true, re: regexp.MustCompile(".*")}}, mediaTypes: media.DefaultTypes, } // Initial deployment should sync remote with local. if err := deployer.Deploy(ctx); err != nil { t.Errorf("initial deploy: failed: %v", err) } wantSummary := deploySummary{NumLocal: 5, NumRemote: 0, NumUploads: 5, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("initial deploy: got %v, want %v", deployer.summary, wantSummary) } // A repeat deployment shouldn't change anything. if err := deployer.Deploy(ctx); err != nil { t.Errorf("no-op deploy: %v", err) } wantSummary = deploySummary{NumLocal: 5, NumRemote: 5, NumUploads: 0, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("no-op deploy: got %v, want %v", deployer.summary, wantSummary) } // Make an update to the local filesystem, on [1]. updatefd := local[1] updatefd.Contents = "new contents" if err := writeFiles(test.fs, []*fileData{updatefd}); err != nil { t.Fatal(err) } // A deployment should apply the changes. if err := deployer.Deploy(ctx); err != nil { t.Errorf("deploy after changes: failed: %v", err) } wantSummary = deploySummary{NumLocal: 5, NumRemote: 5, NumUploads: 1, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("deploy after changes: got %v, want %v", deployer.summary, wantSummary) } }) } } // TestMatching verifies that matchers match correctly, and that the Force // attribute for matcher works. func TestMatching(t *testing.T) { ctx := context.Background() tests, cleanup, err := initFsTests() if err != nil { t.Fatal(err) } defer cleanup() for _, test := range tests { t.Run(test.name, func(t *testing.T) { _, err := initLocalFs(ctx, test.fs) if err != nil { t.Fatal(err) } deployer := &Deployer{ localFs: test.fs, bucket: test.bucket, matchers: []*matcher{{Pattern: "^subdir/aaa$", Force: true, re: regexp.MustCompile("^subdir/aaa$")}}, mediaTypes: media.DefaultTypes, } // Initial deployment to sync remote with local. if err := deployer.Deploy(ctx); err != nil { t.Errorf("initial deploy: failed: %v", err) } wantSummary := deploySummary{NumLocal: 5, NumRemote: 0, NumUploads: 5, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("initial deploy: got %v, want %v", deployer.summary, wantSummary) } // A repeat deployment should upload a single file, the one that matched the Force matcher. // Note that matching happens based on the ToSlash form, so this matches // even on Windows. if err := deployer.Deploy(ctx); err != nil { t.Errorf("no-op deploy with single force matcher: %v", err) } wantSummary = deploySummary{NumLocal: 5, NumRemote: 5, NumUploads: 1, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("no-op deploy with single force matcher: got %v, want %v", deployer.summary, wantSummary) } // Repeat with a matcher that should now match 3 files. deployer.matchers = []*matcher{{Pattern: "aaa", Force: true, re: regexp.MustCompile("aaa")}} if err := deployer.Deploy(ctx); err != nil { t.Errorf("no-op deploy with triple force matcher: %v", err) } wantSummary = deploySummary{NumLocal: 5, NumRemote: 5, NumUploads: 3, NumDeletes: 0} if !cmp.Equal(deployer.summary, wantSummary) { t.Errorf("no-op deploy with triple force matcher: got %v, want %v", deployer.summary, wantSummary) } }) } } // writeFiles writes the files in fds to fd. func writeFiles(fs afero.Fs, fds []*fileData) error { for _, fd := range fds { dir := path.Dir(fd.Name) if dir != "." { err := fs.MkdirAll(dir, os.ModePerm) if err != nil { return err } } f, err := fs.Create(fd.Name) if err != nil { return err } defer f.Close() _, err = f.WriteString(fd.Contents) if err != nil { return err } } return nil } // verifyRemote that the current contents of bucket matches local. // It returns an empty string if the contents matched, and a non-empty string // capturing the diff if they didn't. func verifyRemote(ctx context.Context, bucket *blob.Bucket, local []*fileData) (string, error) { var cur []*fileData iter := bucket.List(nil) for { obj, err := iter.Next(ctx) if err == io.EOF { break } if err != nil { return "", err } contents, err := bucket.ReadAll(ctx, obj.Key) if err != nil { return "", err } cur = append(cur, &fileData{obj.Key, string(contents)}) } if cmp.Equal(cur, local) { return "", nil } diff := "got: \n" for _, f := range cur { diff += fmt.Sprintf(" %s: %s\n", f.Name, f.Contents) } diff += "want: \n" for _, f := range local { diff += fmt.Sprintf(" %s: %s\n", f.Name, f.Contents) } return diff, nil } hugo-0.92.2/deploy/google.go000066400000000000000000000022741420147000300156410ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build !nodeploy package deploy import ( "context" "fmt" "strings" "google.golang.org/api/compute/v1" ) // Invalidate all of the content in a Google Cloud CDN distribution. func InvalidateGoogleCloudCDN(ctx context.Context, origin string) error { parts := strings.Split(origin, "/") if len(parts) != 2 { return fmt.Errorf("origin must be /") } service, err := compute.NewService(ctx) if err != nil { return err } rule := &compute.CacheInvalidationRule{Path: "/*"} _, err = service.UrlMaps.InvalidateCache(parts[0], parts[1], rule).Context(ctx).Do() return err } hugo-0.92.2/deps/000077500000000000000000000000001420147000300134705ustar00rootroot00000000000000hugo-0.92.2/deps/deps.go000066400000000000000000000243531420147000300147610ustar00rootroot00000000000000package deps import ( "sync" "sync/atomic" "time" "github.com/pkg/errors" "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config/security" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/metrics" "github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/tpl" "github.com/spf13/cast" jww "github.com/spf13/jwalterweatherman" ) // Deps holds dependencies used by many. // There will be normally only one instance of deps in play // at a given time, i.e. one per Site built. type Deps struct { // The logger to use. Log loggers.Logger `json:"-"` // Used to log errors that may repeat itself many times. LogDistinct loggers.Logger ExecHelper *hexec.Exec // The templates to use. This will usually implement the full tpl.TemplateManager. tmpl tpl.TemplateHandler // We use this to parse and execute ad-hoc text templates. textTmpl tpl.TemplateParseFinder // The file systems to use. Fs *hugofs.Fs `json:"-"` // The PathSpec to use *helpers.PathSpec `json:"-"` // The ContentSpec to use *helpers.ContentSpec `json:"-"` // The SourceSpec to use SourceSpec *source.SourceSpec `json:"-"` // The Resource Spec to use ResourceSpec *resources.Spec // The configuration to use Cfg config.Provider `json:"-"` // The file cache to use. FileCaches filecache.Caches // The translation func to use Translate func(translationID string, templateData interface{}) string `json:"-"` // The language in use. TODO(bep) consolidate with site Language *langs.Language // The site building. Site page.Site // All the output formats available for the current site. OutputFormatsConfig output.Formats templateProvider ResourceProvider WithTemplate func(templ tpl.TemplateManager) error `json:"-"` // Used in tests OverloadedTemplateFuncs map[string]interface{} translationProvider ResourceProvider Metrics metrics.Provider // Timeout is configurable in site config. Timeout time.Duration // BuildStartListeners will be notified before a build starts. BuildStartListeners *Listeners // Resources that gets closed when the build is done or the server shuts down. BuildClosers *Closers // Atomic values set during a build. // This is common/global for all sites. BuildState *BuildState // Whether we are in running (server) mode Running bool *globalErrHandler } type globalErrHandler struct { // Channel for some "hard to get to" build errors buildErrors chan error } // SendErr sends the error on a channel to be handled later. // This can be used in situations where returning and aborting the current // operation isn't practical. func (e *globalErrHandler) SendError(err error) { if e.buildErrors != nil { select { case e.buildErrors <- err: default: } return } jww.ERROR.Println(err) } func (e *globalErrHandler) StartErrorCollector() chan error { e.buildErrors = make(chan error, 10) return e.buildErrors } // Listeners represents an event listener. type Listeners struct { sync.Mutex // A list of funcs to be notified about an event. listeners []func() } // Add adds a function to a Listeners instance. func (b *Listeners) Add(f func()) { if b == nil { return } b.Lock() defer b.Unlock() b.listeners = append(b.listeners, f) } // Notify executes all listener functions. func (b *Listeners) Notify() { b.Lock() defer b.Unlock() for _, notify := range b.listeners { notify() } } // ResourceProvider is used to create and refresh, and clone resources needed. type ResourceProvider interface { Update(deps *Deps) error Clone(deps *Deps) error } func (d *Deps) Tmpl() tpl.TemplateHandler { return d.tmpl } func (d *Deps) TextTmpl() tpl.TemplateParseFinder { return d.textTmpl } func (d *Deps) SetTmpl(tmpl tpl.TemplateHandler) { d.tmpl = tmpl } func (d *Deps) SetTextTmpl(tmpl tpl.TemplateParseFinder) { d.textTmpl = tmpl } // LoadResources loads translations and templates. func (d *Deps) LoadResources() error { // Note that the translations need to be loaded before the templates. if err := d.translationProvider.Update(d); err != nil { return errors.Wrap(err, "loading translations") } if err := d.templateProvider.Update(d); err != nil { return errors.Wrap(err, "loading templates") } return nil } // New initializes a Dep struct. // Defaults are set for nil values, // but TemplateProvider, TranslationProvider and Language are always required. func New(cfg DepsCfg) (*Deps, error) { var ( logger = cfg.Logger fs = cfg.Fs ) if cfg.TemplateProvider == nil { panic("Must have a TemplateProvider") } if cfg.TranslationProvider == nil { panic("Must have a TranslationProvider") } if cfg.Language == nil { panic("Must have a Language") } if logger == nil { logger = loggers.NewErrorLogger() } if fs == nil { // Default to the production file system. fs = hugofs.NewDefault(cfg.Language) } if cfg.MediaTypes == nil { cfg.MediaTypes = media.DefaultTypes } if cfg.OutputFormats == nil { cfg.OutputFormats = output.DefaultFormats } securityConfig, err := security.DecodeConfig(cfg.Cfg) if err != nil { return nil, errors.WithMessage(err, "failed to create security config from configuration") } execHelper := hexec.New(securityConfig) ps, err := helpers.NewPathSpec(fs, cfg.Language, logger) if err != nil { return nil, errors.Wrap(err, "create PathSpec") } fileCaches, err := filecache.NewCaches(ps) if err != nil { return nil, errors.WithMessage(err, "failed to create file caches from configuration") } errorHandler := &globalErrHandler{} buildState := &BuildState{} resourceSpec, err := resources.NewSpec(ps, fileCaches, buildState, logger, errorHandler, execHelper, cfg.OutputFormats, cfg.MediaTypes) if err != nil { return nil, err } contentSpec, err := helpers.NewContentSpec(cfg.Language, logger, ps.BaseFs.Content.Fs, execHelper) if err != nil { return nil, err } sp := source.NewSourceSpec(ps, nil, fs.Source) timeoutms := cfg.Language.GetInt("timeout") if timeoutms <= 0 { timeoutms = 3000 } ignoreErrors := cast.ToStringSlice(cfg.Cfg.Get("ignoreErrors")) ignorableLogger := loggers.NewIgnorableLogger(logger, ignoreErrors...) logDistinct := helpers.NewDistinctLogger(logger) d := &Deps{ Fs: fs, Log: ignorableLogger, LogDistinct: logDistinct, ExecHelper: execHelper, templateProvider: cfg.TemplateProvider, translationProvider: cfg.TranslationProvider, WithTemplate: cfg.WithTemplate, OverloadedTemplateFuncs: cfg.OverloadedTemplateFuncs, PathSpec: ps, ContentSpec: contentSpec, SourceSpec: sp, ResourceSpec: resourceSpec, Cfg: cfg.Language, Language: cfg.Language, Site: cfg.Site, FileCaches: fileCaches, BuildStartListeners: &Listeners{}, BuildClosers: &Closers{}, BuildState: buildState, Running: cfg.Running, Timeout: time.Duration(timeoutms) * time.Millisecond, globalErrHandler: errorHandler, } if cfg.Cfg.GetBool("templateMetrics") { d.Metrics = metrics.NewProvider(cfg.Cfg.GetBool("templateMetricsHints")) } return d, nil } func (d *Deps) Close() error { return d.BuildClosers.Close() } // ForLanguage creates a copy of the Deps with the language dependent // parts switched out. func (d Deps) ForLanguage(cfg DepsCfg, onCreated func(d *Deps) error) (*Deps, error) { l := cfg.Language var err error d.PathSpec, err = helpers.NewPathSpecWithBaseBaseFsProvided(d.Fs, l, d.Log, d.BaseFs) if err != nil { return nil, err } d.ContentSpec, err = helpers.NewContentSpec(l, d.Log, d.BaseFs.Content.Fs, d.ExecHelper) if err != nil { return nil, err } d.Site = cfg.Site // These are common for all sites, so reuse. // TODO(bep) clean up these inits. resourceCache := d.ResourceSpec.ResourceCache postBuildAssets := d.ResourceSpec.PostBuildAssets d.ResourceSpec, err = resources.NewSpec(d.PathSpec, d.ResourceSpec.FileCaches, d.BuildState, d.Log, d.globalErrHandler, d.ExecHelper, cfg.OutputFormats, cfg.MediaTypes) if err != nil { return nil, err } d.ResourceSpec.ResourceCache = resourceCache d.ResourceSpec.PostBuildAssets = postBuildAssets d.Cfg = l d.Language = l if onCreated != nil { if err = onCreated(&d); err != nil { return nil, err } } if err := d.translationProvider.Clone(&d); err != nil { return nil, err } if err := d.templateProvider.Clone(&d); err != nil { return nil, err } d.BuildStartListeners = &Listeners{} return &d, nil } // DepsCfg contains configuration options that can be used to configure Hugo // on a global level, i.e. logging etc. // Nil values will be given default values. type DepsCfg struct { // The Logger to use. Logger loggers.Logger // The file systems to use Fs *hugofs.Fs // The language to use. Language *langs.Language // The Site in use Site page.Site // The configuration to use. Cfg config.Provider // The media types configured. MediaTypes media.Types // The output formats configured. OutputFormats output.Formats // Template handling. TemplateProvider ResourceProvider WithTemplate func(templ tpl.TemplateManager) error // Used in tests OverloadedTemplateFuncs map[string]interface{} // i18n handling. TranslationProvider ResourceProvider // Whether we are in running (server) mode Running bool } // BuildState are flags that may be turned on during a build. type BuildState struct { counter uint64 } func (b *BuildState) Incr() int { return int(atomic.AddUint64(&b.counter, uint64(1))) } func NewBuildState() BuildState { return BuildState{} } type Closer interface { Close() error } type Closers struct { mu sync.Mutex cs []Closer } func (cs *Closers) Add(c Closer) { cs.mu.Lock() defer cs.mu.Unlock() cs.cs = append(cs.cs, c) } func (cs *Closers) Close() error { cs.mu.Lock() defer cs.mu.Unlock() for _, c := range cs.cs { c.Close() } cs.cs = cs.cs[:0] return nil } hugo-0.92.2/deps/deps_test.go000066400000000000000000000014711420147000300160140ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package deps import ( "testing" qt "github.com/frankban/quicktest" ) func TestBuildFlags(t *testing.T) { c := qt.New(t) var bf BuildState bf.Incr() bf.Incr() bf.Incr() c.Assert(bf.Incr(), qt.Equals, 4) } hugo-0.92.2/docs/000077500000000000000000000000001420147000300134655ustar00rootroot00000000000000hugo-0.92.2/docs/.editorconfig000066400000000000000000000004131420147000300161400ustar00rootroot00000000000000# https://editorconfig.org root = true [*] charset = utf-8 end_of_line = lf indent_size = 2 indent_style = space trim_trailing_whitespace = true [*.go] indent_size = 8 indent_style = tab [*.js] insert_final_newline = true [*.md] trim_trailing_whitespace = false hugo-0.92.2/docs/.github/000077500000000000000000000000001420147000300150255ustar00rootroot00000000000000hugo-0.92.2/docs/.github/SUPPORT.md000066400000000000000000000003121420147000300165170ustar00rootroot00000000000000### Asking Support Questions We have an active [discussion forum](https://discourse.gohugo.io) where users and developers can ask questions. Please don't use the GitHub issue tracker to ask questions. hugo-0.92.2/docs/.github/stale.yml000066400000000000000000000016001420147000300166550ustar00rootroot00000000000000# Number of days of inactivity before an issue becomes stale daysUntilStale: 120 # Number of days of inactivity before a stale issue is closed daysUntilClose: 30 # Issues with these labels will never be considered stale exemptLabels: - Keep - Security - UndocumentedFeature # Label to use when marking an issue as stale staleLabel: Stale # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help. If you still think this is important, please tell us why. This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: false hugo-0.92.2/docs/.gitignore000066400000000000000000000001521420147000300154530ustar00rootroot00000000000000/.idea /.vscode /public node_modules nohup.out .DS_Store trace.out .hugo_build.lock resources/_gen/images/hugo-0.92.2/docs/.markdownlint.yaml000066400000000000000000000001751420147000300171430ustar00rootroot00000000000000# https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md MD013: false # Line length MD033: false # Inline HTML hugo-0.92.2/docs/LICENSE.md000066400000000000000000000243601420147000300150760ustar00rootroot00000000000000Apache License ============== _Version 2.0, January 2004_ _<>_ ### Terms and Conditions for use, reproduction, and distribution #### 1. Definitions “License” shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. “Licensor” shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. “Legal Entity” shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, “control” means **(i)** the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the outstanding shares, or **(iii)** beneficial ownership of such entity. “You” (or “Your”) shall mean an individual or Legal Entity exercising permissions granted by this License. “Source” form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. “Object” form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. “Work” shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). “Derivative Works” shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. “Contribution” shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as “Not a Contribution.” “Contributor” shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. #### 2. Grant of Copyright License Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. #### 3. Grant of Patent License Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. #### 4. Redistribution You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: * **(a)** You must give any other recipients of the Work or Derivative Works a copy of this License; and * **(b)** You must cause any modified files to carry prominent notices stating that You changed the files; and * **(c)** You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and * **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. #### 5. Submission of Contributions Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. #### 6. Trademarks This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. #### 7. Disclaimer of Warranty Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. #### 8. Limitation of Liability In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. #### 9. Accepting Warranty or Additional Liability While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. _END OF TERMS AND CONDITIONS_ ### APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets `[]` replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same “printed page” as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. hugo-0.92.2/docs/README.md000066400000000000000000000054031420147000300147460ustar00rootroot00000000000000[![Netlify Status](https://api.netlify.com/api/v1/badges/e0dbbfc7-34f1-4393-a679-c16e80162705/deploy-status)](https://app.netlify.com/sites/gohugoio/deploys) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://gohugo.io/contribute/documentation/) # Hugo Docs Documentation site for [Hugo](https://github.com/gohugoio/hugo), the very fast and flexible static site generator built with love in Go. ## Contributing We welcome contributions to Hugo of any kind including documentation, suggestions, bug reports, pull requests etc. Also check out our [contribution guide](https://gohugo.io/contribute/documentation/). We would love to hear from you. Note that this repository contains solely the documentation for Hugo. For contributions that aren't documentation-related please refer to the [hugo](https://github.com/gohugoio/hugo) repository. *Pull requests shall **only** contain changes to the actual documentation. However, changes on the code base of Hugo **and** the documentation shall be a single, atomic pull request in the [hugo](https://github.com/gohugoio/hugo) repository.* Spelling fixes are most welcomed, and if you want to contribute longer sections to the documentation, it would be great if you had the following criteria in mind when writing: * Short is good. People go to the library to read novels. If there is more than one way to _do a thing_ in Hugo, describe the current _best practice_ (avoid "… but you can also do …" and "… in older versions of Hugo you had to …". * For example, try to find short snippets that teaches people about the concept. If the example is also useful as-is (copy and paste), then great. Don't list long and similar examples just so people can use them on their sites. * Hugo has users from all over the world, so easy to understand and [simple English](https://simple.wikipedia.org/wiki/Basic_English) is good. ## Branches * The `master` branch is where the site is automatically built from, and is the place to put changes relevant to the current Hugo version. * The `next` branch is where we store changes that are related to the next Hugo release. This can be previewed here: https://next--gohugoio.netlify.com/ ## Build To view the documentation site locally, you need to clone this repository: ```bash git clone https://github.com/gohugoio/hugoDocs.git ``` Also note that the documentation version for a given version of Hugo can also be found in the `/docs` sub-folder of the [Hugo source repository](https://github.com/gohugoio/hugo). Then to view the docs in your browser, run Hugo and open up the link: ```bash ▶ hugo server Started building sites ... . . Serving pages from memory Web Server is available at http://localhost:1313/ (bind address 127.0.0.1) Press Ctrl+C to stop ``` hugo-0.92.2/docs/_vendor/000077500000000000000000000000001420147000300151215ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/000077500000000000000000000000001420147000300171605ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/000077500000000000000000000000001420147000300210005ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/000077500000000000000000000000001420147000300236035ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/000077500000000000000000000000001420147000300251055ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/000077500000000000000000000000001420147000300256755ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_algolia.css000066400000000000000000000454051420147000300301660ustar00rootroot00000000000000.searchbox{display:inline-block;position:relative;width:200px;height:32px!important;white-space:nowrap;box-sizing:border-box;visibility:visible!important}.searchbox .algolia-autocomplete{display:block;width:100%;height:100%}.searchbox__wrapper{width:100%;height:100%;z-index:999;position:relative}.searchbox__input{display:inline-block;box-sizing:border-box;transition:box-shadow .4s ease,background .4s ease;border:0;border-radius:16px;box-shadow:inset 0 0 0 1px #ccc;background:#fff!important;padding:0 26px 0 32px;width:100%;height:100%;vertical-align:middle;white-space:normal;font-size:12px;-webkit-appearance:none;-moz-appearance:none;appearance:none}.searchbox__input::-webkit-search-cancel-button,.searchbox__input::-webkit-search-decoration,.searchbox__input::-webkit-search-results-button,.searchbox__input::-webkit-search-results-decoration{display:none}.searchbox__input:hover{box-shadow:inset 0 0 0 1px #b3b3b3}.searchbox__input:active,.searchbox__input:focus{outline:0;box-shadow:inset 0 0 0 1px #aaa;background:#fff}.searchbox__input::-webkit-input-placeholder{color:#aaa}.searchbox__input:-ms-input-placeholder{color:#aaa}.searchbox__input::-ms-input-placeholder{color:#aaa}.searchbox__input::placeholder{color:#aaa}.searchbox__submit{position:absolute;top:0;margin:0;border:0;border-radius:16px 0 0 16px;background-color:rgba(69,142,225,0);padding:0;width:32px;height:100%;vertical-align:middle;text-align:center;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;right:inherit;left:0}.searchbox__submit:before{display:inline-block;margin-right:-4px;height:100%;vertical-align:middle;content:""}.searchbox__submit:active,.searchbox__submit:hover{cursor:pointer}.searchbox__submit:focus{outline:0}.searchbox__submit svg{width:14px;height:14px;vertical-align:middle;fill:#6d7e96}.searchbox__reset{display:block;position:absolute;top:8px;right:8px;margin:0;border:0;background:none;cursor:pointer;padding:0;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;fill:rgba(0,0,0,.5)}.searchbox__reset.hide{display:none}.searchbox__reset:focus{outline:0}.searchbox__reset svg{display:block;margin:4px;width:8px;height:8px}.searchbox__input:valid~.searchbox__reset{display:block;-webkit-animation-name:sbx-reset-in;animation-name:sbx-reset-in;-webkit-animation-duration:.15s;animation-duration:.15s}@-webkit-keyframes sbx-reset-in{0%{-webkit-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0);opacity:0}to{-webkit-transform:none;transform:none;opacity:1}}@keyframes sbx-reset-in{0%{-webkit-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0);opacity:0}to{-webkit-transform:none;transform:none;opacity:1}}.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu{right:0!important;left:inherit!important}.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu:before{right:48px}.algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu{left:0!important;right:inherit!important}.algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu:before{left:48px}.algolia-autocomplete .ds-dropdown-menu{top:-6px;border-radius:4px;margin:6px 0 0;padding:0;text-align:left;height:auto;position:relative;background:transparent;border:none;z-index:999;max-width:600px;min-width:500px;box-shadow:0 1px 0 0 rgba(0,0,0,.2),0 2px 3px 0 rgba(0,0,0,.1)}.algolia-autocomplete .ds-dropdown-menu:before{display:block;position:absolute;content:"";width:14px;height:14px;background:#fff;z-index:1000;top:-7px;border-top:1px solid #d9d9d9;border-right:1px solid #d9d9d9;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);border-radius:2px}.algolia-autocomplete .ds-dropdown-menu .ds-suggestions{position:relative;z-index:1000;margin-top:8px}.algolia-autocomplete .ds-dropdown-menu .ds-suggestions a:hover{text-decoration:none}.algolia-autocomplete .ds-dropdown-menu .ds-suggestion{cursor:pointer}.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion.suggestion-layout-simple,.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion:not(.suggestion-layout-simple) .algolia-docsearch-suggestion--content{background-color:rgba(69,142,225,.05)}.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-]{position:relative;border:1px solid #d9d9d9;background:#fff;border-radius:4px;overflow:auto;padding:0 8px 8px}.algolia-autocomplete .ds-dropdown-menu *{box-sizing:border-box}.algolia-autocomplete .algolia-docsearch-suggestion{display:block;position:relative;padding:0 8px;background:#fff;color:#02060c;overflow:hidden}.algolia-autocomplete .algolia-docsearch-suggestion--highlight{color:#174d8c;background:rgba(143,187,237,.1);padding:.1em .05em}.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl0 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl1 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{padding:0 0 1px;background:inherit;box-shadow:inset 0 -2px 0 0 rgba(69,142,225,.8);color:inherit}.algolia-autocomplete .algolia-docsearch-suggestion--content{display:block;float:right;width:70%;position:relative;padding:5.33333px 0 5.33333px 10.66667px;cursor:pointer}.algolia-autocomplete .algolia-docsearch-suggestion--content:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ddd;left:-1px}.algolia-autocomplete .algolia-docsearch-suggestion--category-header{position:relative;border-bottom:1px solid #ddd;display:none;margin-top:8px;padding:4px 0;font-size:1em;color:#33363d}.algolia-autocomplete .algolia-docsearch-suggestion--wrapper{width:100%;float:left;padding:8px 0 0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column{float:left;width:30%;text-align:right;position:relative;padding:5.33333px 10.66667px;color:#a4a7ae;font-size:.9em;word-wrap:break-word}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ddd;right:0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-inline{display:none}.algolia-autocomplete .algolia-docsearch-suggestion--title{margin-bottom:4px;color:#02060c;font-size:.9em;font-weight:700}.algolia-autocomplete .algolia-docsearch-suggestion--text{display:block;line-height:1.2em;font-size:.85em;color:#63676d}.algolia-autocomplete .algolia-docsearch-suggestion--no-results{width:100%;padding:8px 0;text-align:center;font-size:1.2em}.algolia-autocomplete .algolia-docsearch-suggestion--no-results:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion code{padding:1px 5px;font-size:90%;border:none;color:#222;background-color:#ebebeb;border-radius:3px;font-family:Menlo,Monaco,Consolas,Courier New,monospace}.algolia-autocomplete .algolia-docsearch-suggestion code .algolia-docsearch-suggestion--highlight{background:none}.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--category-header,.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary{display:block}@media (min-width:768px){.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{display:block}}@media (max-width:768px){.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{display:inline-block;width:auto;float:left;padding:0;color:#02060c;font-size:.9em;font-weight:700;text-align:left;opacity:.5}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:after{content:"|"}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content{display:inline-block;width:auto;text-align:left;float:left;padding:0}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content:before{display:none}}.algolia-autocomplete .suggestion-layout-simple.algolia-docsearch-suggestion{border-bottom:1px solid #eee;padding:8px;margin:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content{width:100%;padding:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content:before{display:none}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header{margin:0;padding:0;display:block;width:100%;border:none}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl0,.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1{opacity:.6;font-size:.85em}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1:before{background-image:url('data:image/svg+xml;utf8,');content:"";width:10px;height:10px;display:inline-block}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--wrapper{width:100%;float:left;margin:0;padding:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--duplicate-content,.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--subcategory-inline{display:none!important}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title{margin:0;color:#458ee1;font-size:.9em;font-weight:400}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title:before{content:"#";font-weight:700;color:#458ee1;display:inline-block}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text{margin:4px 0 0;display:block;line-height:1.4em;padding:5.33333px 8px;background:#f8f8f8;font-size:.85em;opacity:.8}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{color:#3f4145;font-weight:700;box-shadow:none}.algolia-autocomplete .algolia-docsearch-footer{width:134px;height:20px;z-index:2000;margin-top:10.66667px;float:right;font-size:0;line-height:0}.algolia-autocomplete .algolia-docsearch-footer--logo{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='168' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath d='M78.988.938h16.594a2.968 2.968 0 0 1 2.966 2.966V20.5a2.967 2.967 0 0 1-2.966 2.964H78.988a2.967 2.967 0 0 1-2.966-2.964V3.897A2.961 2.961 0 0 1 78.988.938zm41.937 17.866c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 0 0-1.574-.199 5.7 5.7 0 0 0-.897.069 2.699 2.699 0 0 0-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874a32.5 32.5 0 0 1-1.868.314c-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 0 1-1.471-.636 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525a3.24 3.24 0 0 1 1.047-1.106c.445-.287.95-.492 1.532-.615a8.8 8.8 0 0 1 1.82-.185 8.404 8.404 0 0 1 1.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 0 0-.384-.73 1.784 1.784 0 0 0-.724-.493 3.164 3.164 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 0 0-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 0 1 2.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 0 0-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 0 0-.814.24 1.46 1.46 0 0 0-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483a6.8 6.8 0 0 1 .233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 0 1-1.471-.635 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 0 1 2.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 0 0-.109-.875 1.873 1.873 0 0 0-.384-.731 1.784 1.784 0 0 0-.724-.492 3.165 3.165 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.75 7.75 0 0 0-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 0 1 2.073-.177zm-8.034-1.271a1.626 1.626 0 0 1-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 0 1-1.128 1.906 4.986 4.986 0 0 1-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 0 1-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 0 1-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 0 1 1.15-1.892 5.133 5.133 0 0 1 1.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423a4.88 4.88 0 0 1 1.753 1.216 5.644 5.644 0 0 1 1.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 0 0-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 0 1-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 0 1-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 0 1 2.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17z' fill='%235468FF'/%3E%3Cpath d='M6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 0 0-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503a61.27 61.27 0 0 1-.582-.271 13.67 13.67 0 0 1-.55-.287 4.275 4.275 0 0 1-.567-.351 6.92 6.92 0 0 1-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 0 1-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 0 0-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 0 0-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 0 0-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104l-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 0 1-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z' fill='%235D6494'/%3E%3Cpath d='M89.632 5.967v-.772a.978.978 0 0 0-.978-.977h-2.28a.978.978 0 0 0-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 0 1 1.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01l-.39-.389a.977.977 0 0 0-1.382 0l-.465.465a.973.973 0 0 0 0 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 0 0-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 0 1-4.49-4.482 4.488 4.488 0 0 1 4.49-4.482 4.488 4.488 0 0 1 4.489 4.482 4.484 4.484 0 0 1-4.49 4.482m0-10.85a6.363 6.363 0 1 0 0 12.729 6.37 6.37 0 0 0 6.372-6.368 6.358 6.358 0 0 0-6.371-6.36' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E");background-repeat:no-repeat;background-position:50%;background-size:100%;overflow:hidden;text-indent:-9000px;padding:0!important;width:100%;height:100%;display:block} /*# sourceMappingURL=docsearch.min.css.map */ a.algolia-docsearch-suggestion { text-decoration: none !important; } .algolia-docsearch-suggestion--category-header { background: #0594cb; padding-left: .25rem !important; color: white !important; border-radius: 3px; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_animation.css000066400000000000000000000004311420147000300305230ustar00rootroot00000000000000.animated { animation-duration: .5s; animation-fill-mode: forwards; animation-timing-function: ease-in-out; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .fadeIn { animation-name: fadeIn; } .animated-delay-1 { animation-delay: 0.5s; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_carousel.css000066400000000000000000000011651420147000300303660ustar00rootroot00000000000000/* These styles enhance the home page carousel, located here: themes/gohugoioTheme/layouts/partials/home-page-sections/showcase.html */ .overflow-x-scroll{ -webkit-overflow-scrolling: touch; } .row { transition: 450ms transform; font-size: 0; } .tile { transition: 450ms all; } .details { background: -webkit-gradient(linear, left bottom, left top, from(rgba(0,0,0,0.9)), to(rgba(0,0,0,0))); background: linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0) 100%); transition: 450ms opacity; } .tile:hover .details { opacity: 1; } .row:hover .tile { opacity: 0.3; } .row:hover .tile:hover { opacity: 1; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_chroma.css000066400000000000000000000076221420147000300300260ustar00rootroot00000000000000/* Background */ .chroma { background-color: #ffffff } /* Error */ .chroma .err { color: #a61717; background-color: #e3d2d2 } /* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } /* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; } /* LineHighlight */ .chroma .hl { display: block; width: 100%;background-color: #ffffcc } /* LineNumbersTable */ .chroma .lnt { margin-right: 0.4em; padding: 0 0.4em 0 0.4em; } /* LineNumbers */ .chroma .ln { margin-right: 0.4em; padding: 0 0.4em 0 0.4em; } /* Keyword */ .chroma .k { font-weight: bold } /* KeywordConstant */ .chroma .kc { font-weight: bold } /* KeywordDeclaration */ .chroma .kd { font-weight: bold } /* KeywordNamespace */ .chroma .kn { font-weight: bold } /* KeywordPseudo */ .chroma .kp { font-weight: bold } /* KeywordReserved */ .chroma .kr { font-weight: bold } /* KeywordType */ .chroma .kt { color: #445588; font-weight: bold } /* NameAttribute */ .chroma .na { color: #008080 } /* NameBuiltin */ .chroma .nb { color: #999999 } /* NameClass */ .chroma .nc { color: #445588; font-weight: bold } /* NameConstant */ .chroma .no { color: #008080 } /* NameEntity */ .chroma .ni { color: #800080 } /* NameException */ .chroma .ne { color: #990000; font-weight: bold } /* NameFunction */ .chroma .nf { color: #990000; font-weight: bold } /* NameNamespace */ .chroma .nn { color: #555555 } /* NameTag */ .chroma .nt { color: #000080 } /* NameVariable */ .chroma .nv { color: #008080 } /* LiteralString */ .chroma .s { color: #bb8844 } /* LiteralStringAffix */ .chroma .sa { color: #bb8844 } /* LiteralStringBacktick */ .chroma .sb { color: #bb8844 } /* LiteralStringChar */ .chroma .sc { color: #bb8844 } /* LiteralStringDelimiter */ .chroma .dl { color: #bb8844 } /* LiteralStringDoc */ .chroma .sd { color: #bb8844 } /* LiteralStringDouble */ .chroma .s2 { color: #bb8844 } /* LiteralStringEscape */ .chroma .se { color: #bb8844 } /* LiteralStringHeredoc */ .chroma .sh { color: #bb8844 } /* LiteralStringInterpol */ .chroma .si { color: #bb8844 } /* LiteralStringOther */ .chroma .sx { color: #bb8844 } /* LiteralStringRegex */ .chroma .sr { color: #808000 } /* LiteralStringSingle */ .chroma .s1 { color: #bb8844 } /* LiteralStringSymbol */ .chroma .ss { color: #bb8844 } /* LiteralNumber */ .chroma .m { color: #009999 } /* LiteralNumberBin */ .chroma .mb { color: #009999 } /* LiteralNumberFloat */ .chroma .mf { color: #009999 } /* LiteralNumberHex */ .chroma .mh { color: #009999 } /* LiteralNumberInteger */ .chroma .mi { color: #009999 } /* LiteralNumberIntegerLong */ .chroma .il { color: #009999 } /* LiteralNumberOct */ .chroma .mo { color: #009999 } /* Operator */ .chroma .o { font-weight: bold } /* OperatorWord */ .chroma .ow { font-weight: bold } /* Comment */ .chroma .c { color: #999988; font-style: italic } /* CommentHashbang */ .chroma .ch { color: #999988; font-style: italic } /* CommentMultiline */ .chroma .cm { color: #999988; font-style: italic } /* CommentSingle */ .chroma .c1 { color: #999988; font-style: italic } /* CommentSpecial */ .chroma .cs { color: #999999; font-weight: bold; font-style: italic } /* CommentPreproc */ .chroma .cp { color: #999999; font-weight: bold } /* CommentPreprocFile */ .chroma .cpf { color: #999999; font-weight: bold } /* GenericDeleted */ .chroma .gd { color: #000000; background-color: #ffdddd } /* GenericEmph */ .chroma .ge { font-style: italic } /* GenericError */ .chroma .gr { color: #aa0000 } /* GenericHeading */ .chroma .gh { color: #999999 } /* GenericInserted */ .chroma .gi { color: #000000; background-color: #ddffdd } /* GenericOutput */ .chroma .go { color: #888888 } /* GenericPrompt */ .chroma .gp { color: #555555 } /* GenericStrong */ .chroma .gs { font-weight: bold } /* GenericSubheading */ .chroma .gu { color: #aaaaaa } /* GenericTraceback */ .chroma .gt { color: #aa0000 } /* TextWhitespace */ .chroma .w { color: #bbbbbb } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_code.css000066400000000000000000000027441420147000300274670ustar00rootroot00000000000000.chroma .lntable pre { padding: 0; margin: 0; border: 0; } .chroma .lntable pre code { padding: 0; margin: 0; } code { padding: 0.2em; margin: 0; font-size: 85%; background-color: rgba(27,31,35,0.05); border-radius: 3px; } pre code { display: block; padding: 1.5em 1.5em; font-size: .875rem; line-height: 2; overflow-x: auto; } pre { background-color: #fff; color: #333; white-space: pre; hyphens: none; position: relative; border-width: 1px; border-color: #ccc; border-style: solid; } /* The Pygments highlighter comes with its own styles. */ .highlight pre { background-color: inherit; color: inherit; padding: 0.5em; font-size: .875rem; } /*We are adding the copy button content here so we can change it with javascript. See the "Clipboard scripts"*/ .copy:after { content: "Copy" } .copied:after { content: "Copied" } @media (--breakpoint-large) { .full-width, pre.expand:hover { /*width: 100vw; position: relative; left: 50%; right: 50%; margin-left: -50vw; margin-right: -50vw;*/ /*width: 60vw;*/ /*position: relative; left: 50%; right: 50%;*/ /*margin-left: -30vw;*/ margin-right: -30vw; max-width: 100vw; } } .code-block .line-numbers-rows { background: #2f3a46; border: none; bottom: -50px; color: #98a4b3; left: -178px; padding: 50px 0; top: -50px; width: 138px } .code-block .line-numbers-rows>span:before { color: inherit; padding-right: 30px } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_color-scheme.css000066400000000000000000000035731420147000300311360ustar00rootroot00000000000000.primary-color {color: var(--primary-color)} .bg-primary-color {background-color: var(--primary-color)} .hover-bg-primary-color:hover {background-color: var(--primary-color)} .primary-color-dark {color: var(--primary-color-dark)} .bg-primary-color-dark {background-color: var(--primary-color-dark)} .hover-bg-primary-color-dark:hover {background-color: var(--primary-color-dark)} .primary-color-light {color: var(--primary-color-light)} .bg-primary-color-light {background-color: var(--primary-color-light)} .hover-bg-primary-color-light:hover {background-color: var(--primary-color-light)} .accent-color {color: var(--accent-color)} .bg-accent-color {background-color: var(--accent-color)} .hover-bg-accent-color:hover {background-color: var(--accent-color)} .accent-color-light {color: var(--accent-color-light)} .hover-accent-color-light:hover {color: var(--accent-color-light)} .bg-accent-color-light {background-color: var(--accent-color-light)} .hover-bg-accent-color-light:hover {background-color: var(--accent-color-light)} .accent-color-dark {color: var(--accent-color-dark)} .bg-accent-color-dark {background-color: var(--accent-color-dark)} .hover-bg-accent-color-dark:hover {background-color: var(--accent-color-dark)} .text-color-primary {color: var(--text-color-primary)} .text-on-primary-color {color: var(--text-on-primary-color)} .text-color-secondary {color: var(--text-color-secondary)} .text-color-disabled {color: var(--text-color-disabled)} .divider-color {color: var(--divider-color)} .warn-color {color: var(--warn-color)} .nested-links a { color: var(--primary-color); text-decoration: none; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_columns.css000066400000000000000000000004471420147000300302330ustar00rootroot00000000000000.column-count-2 {column-count: 1} .column-gap-1 {column-gap: 0} .break-inside-avoid {break-inside: auto} @media (--breakpoint-large) { .column-count-3-l {column-count: 3} .column-count-2-l {column-count: 2} .column-gap-1-l {column-gap: 1} .break-inside-avoid-l {break-inside: avoid} } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_content-tables.css000066400000000000000000000011231420147000300314650ustar00rootroot00000000000000.prose table { width: 100%; margin-bottom: 3em; border-collapse: collapse; border-spacing: 0; font-size: 1em; border: 1px solid var(--light-gray); & th { background-color: var(--primary-color); border-bottom: 1px solid var(--primary-color); color: white; font-weight: 400; text-align: left; padding: .375em .5em; } & td, & tc { padding: .75em .5em; text-align: left; border-right: 1px solid var(--light-gray); } } .prose table tr:nth-child(even) { background-color: var(--light-gray); } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_content.css000066400000000000000000000010421420147000300302150ustar00rootroot00000000000000.prose ul, .prose ol { margin-bottom: 2em; } .prose ul li, .prose ol li { margin-bottom: .5em; } .prose li:hover { background-color: var(--light-gray) } .prose ::selection { background: var(--primary-color); /* WebKit/Blink Browsers */ color: white; } body { line-height: 1.45; } p {margin-bottom: 1.3em;} h1, h2, h3, h4 { margin: 1.414em 0 0.5em; line-height: 1.2; } h1 { margin-top: 0; font-size: 2.441em; } h2 {font-size: 1.953em;} h3 {font-size: 1.563em;} h4 {font-size: 1.25em;} small, .font_small {font-size: 0.8em;} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_definition-lists.css000066400000000000000000000001441420147000300320310ustar00rootroot00000000000000 dl dt { font-weight: bold; font-size: 1.125rem; } dd { margin: .5em 0 2em 0; padding: 0; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_documentation-styles.css000066400000000000000000000017561420147000300327510ustar00rootroot00000000000000.note, .warning { border-left-width: 4px; border-left-style: solid; position: relative; border-color: var(--primary-color); display: block; } .note #exclamation-icon, .warning #exclamation-icon { fill: var(--primary-color); position: absolute; top: 35%; left: -12px; /*background-color: white;*/ } .admonition-content { display: block; margin: 0px; padding: .125em 1em; /*margin-left: 1em;*/ margin-top: 2em; margin-bottom: 2em; overflow-x: auto; /*font-size: .9375em;*/ background-color: var(--black-05); } .hide-child-menu .child-menu { display: none; } .hide-child-menu:hover .child-menu, .hide-child-menu:focus .child-menu, .hide-child-menu:active .child-menu { display: block; } /*documentation-copy headings exaggerate spacing and size to chunk content */ .documentation-copy h2 { margin-top: 3em; &.minor { font-size: inherit; margin-top: inherit; border-bottom: none; } } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_fluid-type.css000066400000000000000000000002551420147000300306320ustar00rootroot00000000000000.f2-fluid { font-size: 2.25rem; } @media (--breakpoint-large) { .f2-fluid { font-size: 1.25rem; font-size: calc(0.875rem + 0.5 * ((100vw - 20rem) / 60)); } } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_font-family.css000066400000000000000000000024021420147000300307710ustar00rootroot00000000000000/* From http://cssfontstack.com */ code, .code, pre code, .highlight pre { font-family: 'inconsolata',Menlo,Monaco,'Courier New',monospace; } .sans-serif { font-family: 'Muli', avenir, 'helvetica neue', helvetica, ubuntu, roboto, noto, 'segoe ui', arial, sans-serif; } .serif { font-family: Palatino,"Palatino Linotype","Palatino LT STD","Book Antiqua",Georgia,serif; } /* Monospaced Typefaces (for code) */ .courier { font-family: 'Courier Next', courier, monospace; } /* Sans-Serif Typefaces */ .helvetica { font-family: 'helvetica neue', helvetica, sans-serif; } .avenir { font-family: 'avenir next', avenir, sans-serif; } /* Serif Typefaces */ .athelas { font-family: athelas, georgia, serif; } .georgia { font-family: georgia, serif; } .times { font-family: times, serif; } .bodoni { font-family: "Bodoni MT", serif; } .calisto { font-family: "Calisto MT", serif; } .garamond { font-family: garamond, serif; } .baskerville { font-family: baskerville, serif; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_header-link.css000066400000000000000000000005051420147000300307310ustar00rootroot00000000000000.header-link:after { position: relative; left: 0.5em; opacity: 0; font-size: 0.8em; -moz-transition: opacity 0.2s ease-in-out 0.1s; -ms-transition: opacity 0.2s ease-in-out 0.1s; } h2:hover .header-link, h3:hover .header-link, h4:hover .header-link, h5:hover .header-link, h6:hover .header-link { opacity: 1; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_hljs.css000066400000000000000000000003631420147000300275100ustar00rootroot00000000000000/* modified from:*/ @import 'highlight.js/styles/atom-one-light.css'; /* hljs-template-variable covers the handlebars templating*/ .hljs-template-variable { color: var(--primary-color); } .hljs-attr { color: var(--accent-color-light); } _hugo-internal-template-styling.css000066400000000000000000000017051420147000300345460ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/* pagination.html: https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/template_embedded.go#L117 */ .pagination { margin: 3rem 0; } .pagination li { display: inline-block; margin-right: .375rem; font-size: .875rem; margin-bottom: 2.5em; } .pagination li a { padding: .5rem .625rem; background-color: white; color: #333; border: 1px solid #ddd; border-radius: 3px; text-decoration: none; } .pagination li.disabled { display: none; } .pagination li.active a:link, .pagination li.active a:active, .pagination li.active a:visited { background-color: #ddd; } /* Hides non-meaningful TOC items*/ #TableOfContents ul li ul li ul li{ display: none; } #TableOfContents ul li { color: black; display: block; margin-bottom: .375em; line-height: 1.375; } #TableOfContents ul li a{ width: 100%; padding: .25em .375em; margin-left: -.375em; } #TableOfContents ul li a:hover { background-color: #999; color: white; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_no-js.css000066400000000000000000000001461420147000300275750ustar00rootroot00000000000000.no-js .needs-js { opacity: 0 } .js .needs-js { opacity: 1; transition: opacity .15s ease-in; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_social-icons.css000066400000000000000000000003651420147000300311350ustar00rootroot00000000000000.facebook, .twitter, .instagram, .youtube { fill: #BABABA; } .facebook:hover { fill: #3b5998; } .twitter { fill: #55acee; } .twitter:hover { fill: #BABABA; } .instagram:hover { fill: #e95950; } .youtube:hover { fill: #bb0000; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_stickyheader.css000066400000000000000000000003221420147000300312220ustar00rootroot00000000000000 @media (min-width: 75em) { [data-scrolldir="down"] .sticky { position: fixed; top:100px; right:0; } [data-scrolldir="up"] .sticky { position: fixed; top:100px; right:0; } } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_svg.css000066400000000000000000000000461420147000300273450ustar00rootroot00000000000000.fill-current { fill: currentColor; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_tabs.css000066400000000000000000000011721420147000300275000ustar00rootroot00000000000000.tab-button{ margin-bottom:1px; position: relative; z-index: 1; color:#333; border-color:#ccc; outline: none; background-color:white; } .tab-pane code{ background:#f1f2f2; border-radius:0; } .tab-pane .chroma{ background:none; padding:0; } .tab-button.active{ border-bottom-color:#f1f2f2; background-color: #f1f2f2; } .tab-content .tab-pane{ display: none; } .tab-content .tab-pane.active{ display: block; } /* Treatment of copy buttons inside a tab module */ .tab-content .copy, .tab-content .copied{ display: none; } .tab-content .tab-pane.active + .copy, .tab-content .tab-pane.active + .copied{ display: block; }hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_tachyons.css000066400000000000000000000057341420147000300304070ustar00rootroot00000000000000/*! TACHYONS v4.7.0 | http://tachyons.io */ /* * NOTE: The Tachyons folder is for backup/reference only. This file references the module * ________ ______ * ___ __/_____ _________ /______ ______________________ * __ / _ __ `/ ___/_ __ \_ / / / __ \_ __ \_ ___/ * _ / / /_/ // /__ _ / / / /_/ // /_/ / / / /(__ ) * /_/ \__,_/ \___/ /_/ /_/_\__, / \____//_/ /_//____/ * /____/ * * TABLE OF CONTENTS * * 1. External Library Includes * - Normalize.css | http://normalize.css.github.io * 2. Tachyons Modules * 3. Variables * - Media Queries * - Colors * 4. Debugging * - Debug all * - Debug children * */ /* External Library Includes */ @import 'tachyons/src/_normalize'; /* Modules */ @import 'tachyons/src/_box-sizing'; /*@import 'tachyons/src/_aspect-ratios';*/ @import 'tachyons/src/_images'; @import 'tachyons/src/_background-size'; @import 'tachyons/src/_background-position'; /*@import 'tachyons/src/_outlines';*/ @import 'tachyons/src/_borders'; @import 'tachyons/src/_border-colors'; @import 'tachyons/src/_border-radius'; @import 'tachyons/src/_border-style'; @import 'tachyons/src/_border-widths'; @import 'tachyons/src/_box-shadow'; /*@import 'tachyons/src/_code';*/ @import 'tachyons/src/_coordinates'; @import 'tachyons/src/_clears'; @import 'tachyons/src/_display'; @import 'tachyons/src/_flexbox'; @import 'tachyons/src/_floats'; /*@import 'tachyons/src/_font-family';*/ @import 'tachyons/src/_font-style'; @import 'tachyons/src/_font-weight'; @import 'tachyons/src/_forms'; @import 'tachyons/src/_heights'; @import 'tachyons/src/_letter-spacing'; @import 'tachyons/src/_line-height'; @import 'tachyons/src/_links'; @import 'tachyons/src/_lists'; @import 'tachyons/src/_max-widths'; @import 'tachyons/src/_widths'; @import 'tachyons/src/_overflow'; @import 'tachyons/src/_position'; @import 'tachyons/src/_opacity'; /*@import 'tachyons/src/_rotations';*/ @import 'tachyons/src/_skins'; @import 'tachyons/src/_skins-pseudo'; @import 'tachyons/src/_spacing'; @import 'tachyons/src/_negative-margins'; @import 'tachyons/src/_tables'; @import 'tachyons/src/_text-decoration'; @import 'tachyons/src/_text-align'; @import 'tachyons/src/_text-transform'; @import 'tachyons/src/_type-scale'; @import 'tachyons/src/_typography'; @import 'tachyons/src/_utilities'; @import 'tachyons/src/_visibility'; @import 'tachyons/src/_white-space'; @import 'tachyons/src/_vertical-align'; @import 'tachyons/src/_hovers'; @import 'tachyons/src/_z-index'; @import 'tachyons/src/_nested'; /*@import 'tachyons/src/_styles';*/ /* Variables */ /* Importing here will allow you to override any variables in the modules */ @import 'tachyons/src/_colors'; @import 'tachyons/src/_media-queries'; /* Debugging */ /*@import 'tachyons/src/_debug-children'; @import 'tachyons/src/_debug-grid';*/ /* Uncomment out the line below to help debug layout issues */ /* @import 'tachyons/src/_debug'; */ hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/_variables.css000066400000000000000000000006741420147000300305250ustar00rootroot00000000000000:root { --primary-color: #0594CB; --primary-color-dark: #0A1922; --primary-color-light: #f9f9f9; --accent-color: #EBB951; --accent-color-light: #FF4088; --accent-color-dark: #33ba91; --text-color-primary: #373737; --text-on-primary-color: #fff; --text-color-secondary: #ccc; --text-color-disabled: #F7f7f7; --divider-color: #f6f6f6; --warn-color: red; --blue: var(--primary-color); } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/css/main.css000066400000000000000000000013711420147000300273350ustar00rootroot00000000000000/*Base Styles*/ @import '_tachyons'; /* purgecss start ignore */ @import '_header-link'; @import '_animation'; @import '_documentation-styles'; @import 'docsearch.js/dist/cdn/docsearch.min'; @import '_carousel'; @import '_code'; @import '_tabs'; @import '_color-scheme'; @import '_columns'; @import '_content'; @import '_content-tables'; @import '_definition-lists'; @import '_fluid-type'; @import '_font-family'; @import '_hugo-internal-template-styling'; @import '_no-js'; @import '_social-icons'; @import '_stickyheader'; @import '_svg'; @import '_chroma'; @import '_variables'; .nested-blockquote blockquote { border-left: 4px solid var(--primary-color); padding-left: 1em; /*margin: 0;*/ } .mw-90 { max-width:90%; } /* purgecss end ignore */ hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/index.js000066400000000000000000000005041420147000300265510ustar00rootroot00000000000000require("typeface-muli") import styles from './css/main.css'; import './js/clipboardjs.js' import './js/codeblocks.js' import './js/docsearch.js' import './js/hljs.js' import './js/lazysizes.js' import './js/menutoggle.js' import './js/scrolldir.js' import './js/smoothscroll.js' import './js/tabs.js' import './js/nojs.js' hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/000077500000000000000000000000001420147000300255215ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/clipboardjs.js000066400000000000000000000016351420147000300303600ustar00rootroot00000000000000var Clipboard = require('clipboard/dist/clipboard.js'); new Clipboard('.copy', { target: function(trigger) { if(trigger.classList.contains('copy-toggle')){ return trigger.previousElementSibling; } return trigger.nextElementSibling; } }).on('success', function(e) { successMessage(e.trigger, 'Copied!'); e.clearSelection(); }).on('error', function(e) { successMessage(e.trigger, fallbackMessage(e.action)); }); function successMessage(elem, msg) { elem.setAttribute('class', 'copied bg-primary-color-dark f6 absolute top-0 right-0 lh-solid hover-bg-primary-color-dark bn white ph3 pv2'); elem.setAttribute('aria-label', msg); } function fallbackMessage(elem, action) { var actionMsg = ''; var actionKey = (action === 'cut' ? 'X' : 'C'); if (isMac) { actionMsg = 'Press ⌘-' + actionKey; } else { actionMsg = 'Press Ctrl-' + actionKey; } return actionMsg; } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/codeblocks.js000066400000000000000000000005051420147000300301670ustar00rootroot00000000000000let article = document.getElementById('prose') if (article) { let codeBlocks = article.getElementsByTagName('code') for (let [key, codeBlock] of Object.entries(codeBlocks)){ var widthDif = codeBlock.scrollWidth - codeBlock.clientWidth if (widthDif > 0) codeBlock.parentNode.classList.add('expand') } } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/docsearch.js000066400000000000000000000003771420147000300300210ustar00rootroot00000000000000var docsearch = require('docsearch.js/dist/cdn/docsearch.js'); docsearch({ apiKey: '167e7998590aebda7f9fedcf86bc4a55', indexName: 'hugodocs', inputSelector: '#search-input', debug: true // Set debug to true if you want to inspect the dropdown }); hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/filesaver.js000066400000000000000000000000001420147000300300250ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/hljs.js000066400000000000000000000034721420147000300270250ustar00rootroot00000000000000var hljs = require('highlight.js/lib/highlight.js'); hljs.registerLanguage('bash', require('highlight.js/lib/languages/bash')); hljs.registerLanguage('css', require('highlight.js/lib/languages/css')); hljs.registerLanguage('markdown', require('highlight.js/lib/languages/markdown')); hljs.registerLanguage('diff', require('highlight.js/lib/languages/diff')); // hljs.registerLanguage('go', require('highlight.js/lib/languages/go')); hljs.registerLanguage('javascript', require('highlight.js/lib/languages/javascript')); hljs.registerLanguage('json', require('highlight.js/lib/languages/json')); hljs.registerLanguage('yaml', require('highlight.js/lib/languages/yaml')); hljs.registerLanguage('xml', require('highlight.js/lib/languages/xml')); hljs.registerLanguage('html', require('highlight.js/lib/languages/handlebars')); hljs.registerLanguage("go", function(e) { var t = { keyword: "code output note warning break default func interface select case map struct chan else goto package switch const fallthrough if range end type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune id autoplay Get", literal: "file download copy true false iota nil Pages with", built_in: "append cap close complex highlight copy imag len make new panic print println real recover delete Site Data tweet youtube ref relref vimeo instagram gist figure innershortcode" }; return { aliases: ["golang","hugo"], k: t, i: "Jquery is working

'); // hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/menutoggle.js000066400000000000000000000025731420147000300302340ustar00rootroot00000000000000// Grab any element that has the 'js-toggle' class and add an event listner for the toggleClass function var toggleBtns = document.getElementsByClassName('js-toggle') for (var i = 0; i < toggleBtns.length; i++) { toggleBtns[i].addEventListener('click', toggleClass, false) } function toggleClass() { // Define the data target via the dataset "target" (e.g. data-target=".docsmenu") var content = this.dataset.target.split(' ') // Find any menu items that are open var mobileCurrentlyOpen = document.querySelector('.mobilemenu:not(.dn)') var desktopCurrentlyOpen = document.querySelector('.desktopmenu:not(.dn)') var desktopActive = document.querySelector('.desktopmenu:not(.dn)') // Loop through the targets' divs for (var i = 0; i < content.length; i++) { var matches = document.querySelectorAll(content[i]); //for each, if the div has the 'dn' class (which is "display:none;"), remove it, otherwise, add that class [].forEach.call(matches, function(dom) { dom.classList.contains('dn') ? dom.classList.remove('dn') : dom.classList.add('dn'); return false; }); // close the currently open menu items if (mobileCurrentlyOpen) mobileCurrentlyOpen.classList.add('dn') if (desktopCurrentlyOpen) desktopCurrentlyOpen.classList.add('dn') if (desktopActive) desktopActive.classList.remove('db') } } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/nojs.js000066400000000000000000000001441420147000300270270ustar00rootroot00000000000000document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/, 'js'); hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/scrolldir.js000066400000000000000000000001011420147000300300440ustar00rootroot00000000000000var scrollDir = require('scrolldir/dist/scrolldir.auto.min.js'); hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/smoothscroll.js000066400000000000000000000044761420147000300306220ustar00rootroot00000000000000// query selector targets Hugo TOC (function() { 'use strict'; // Feature Test if ('querySelector' in document && 'addEventListener' in window && Array.prototype.forEach) { // Function to animate the scroll var smoothScroll = function(anchor, duration) { // Calculate how far and how fast to scroll var startLocation = window.pageYOffset; var endLocation = anchor.offsetTop; var distance = endLocation - startLocation; var increments = distance / (duration / 16); var stopAnimation; // Scroll the page by an increment, and check if it's time to stop var animateScroll = function() { window.scrollBy(0, increments); stopAnimation(); }; // If scrolling down if (increments >= 0) { // Stop animation when you reach the anchor OR the bottom of the page stopAnimation = function() { var travelled = window.pageYOffset; if ((travelled >= (endLocation - increments)) || ((window.innerHeight + travelled) >= document.body.offsetHeight)) { clearInterval(runAnimation); } }; } // If scrolling up else { // Stop animation when you reach the anchor OR the top of the page stopAnimation = function() { var travelled = window.pageYOffset; if (travelled <= (endLocation || 0)) { clearInterval(runAnimation); } }; } // Loop the animation function var runAnimation = setInterval(animateScroll, 16); }; // Define smooth scroll links var scrollToggle = document.querySelectorAll('#TableOfContents ul li a'); // For each smooth scroll link [].forEach.call(scrollToggle, function(toggle) { // When the smooth scroll link is clicked toggle.addEventListener('click', function(e) { // Prevent the default link behavior e.preventDefault(); // Get anchor link and calculate distance from the top var dataID = toggle.getAttribute('href'); var dataTarget = document.querySelector(dataID); var dataSpeed = toggle.getAttribute('data-speed'); // If the anchor exists if (dataTarget) { // Scroll to the anchor smoothScroll(dataTarget, dataSpeed || 500); } }, false); }); } })(); hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/js/tabs.js000066400000000000000000000024351420147000300270140ustar00rootroot00000000000000/** * Scripts which manages Code Toggle tabs. */ var i; // store tabs variable var allTabs = document.querySelectorAll("[data-toggle-tab]"); var allPanes = document.querySelectorAll("[data-pane]"); function toggleTabs(event) { if(event.target){ event.preventDefault(); var clickedTab = event.currentTarget; var targetKey = clickedTab.getAttribute("data-toggle-tab") }else { var targetKey = event } // We store the config language selected in users' localStorage if(window.localStorage){ window.localStorage.setItem("configLangPref", targetKey) } var selectedTabs = document.querySelectorAll("[data-toggle-tab='" + targetKey + "']"); var selectedPanes = document.querySelectorAll("[data-pane='" + targetKey + "']"); for (var i = 0; i < allTabs.length; i++) { allTabs[i].classList.remove("active"); allPanes[i].classList.remove("active"); } for (var i = 0; i < selectedTabs.length; i++) { selectedTabs[i].classList.add("active"); selectedPanes[i].classList.add("active"); } } for (i = 0; i < allTabs.length; i++) { allTabs[i].addEventListener("click", toggleTabs) } // Upon page load, if user has a preferred language in its localStorage, tabs are set to it. if(window.localStorage.getItem('configLangPref')) { toggleTabs(window.localStorage.getItem('configLangPref')) } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/opengraph/000077500000000000000000000000001420147000300270705ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/opengraph/gohugoio-card-base-1.png000066400000000000000000007323321420147000300334050ustar00rootroot00000000000000PNG  IHDR84 pHYs.#.#x?vIDATx[帪ȊOcjC#3Uu-K`@F?ok F_> gp"1WΉNFQ.+1U餪WUu3@s} ^Tu@LȁapfǦ$t>P-Y G#>Sh4)gϝt3CRQ8 /gDh3k}fP 0:Ui%*?aƕT95QCJnY3EjUBF>T4flk~Eu}R>׈74a5/L^ FKCI_cti9h^HFesBx35JU^U7(Dc>B,%uF⚂,Teet<[XRYB >%JZ' hMTM4٢6DXi!t-]SV0-vly#3$^n"s3{WؿdVQ<KO^|~?c9t@[J> e@tA4mdGs[B3<&:Mxnh.=&B %>-Q>8m1ZG#(79!ŽdZE ew'Ч^99eT9TV%G(]쳱1_=R/j3E+hb"#5O?kiC$Pi X2h·:X75)60vW=R۷JӧC10JdX{k l>a;p!0؎ (Øs M *KؠBY҃vKm4ns֖A ][32D"/TcE||xg޴.&ax7)-n}=*BϿx<5<`s5~b5Yα*8wo7?E`e/Mmiu.؁m|`pN!1I_!Z30(BE6('`*kH V^.:l͐fHC:z~tS1ӱBD SP;$o (=zf4>m@/6-krU+F-b W"CXI-݊kt4˱j?`)D8> q.E8TFQ1+\ -ݨbniu QrO$E.KWv,0UKbU] %D:\\Es[܍,].!\@౞@XkzbbKC % 5j |Rj5jH.HN$>skhѲkNr0Zo]Ƿ77J p+%գf(}Z&-m!A+Kĉ fPg,T_$taؤ8!C=/b !(7%= ),xt*J!hM>ħ詛+ D.͠Ϝc# ϸ[0*aJ߽(Y)JFU׍-+JWU}&=/u˹Sx̑+Z8zZʚnʐadr82nqگL%lN$\.$IaVd)y,;%%Q tF -P)*1X{Yłf~;9-($K* _>SUHࠉB8d>! Y$rׁ̟7SVƷGJ7 )qfliÊ^,;&f'?홈f=NɠHbIIe\7pFY-SyuFg*A R]Pr=VmQ G lf6wfXYhLD_QmOwn0TyeΉ$`96EҍHIE)q? X p9MyG9 W6WAKi1:<6$mG9nG 7iJ{P~0r>@ bKsg1H{kpuե䉕Iq~qje')GlVX3LmUx[~9y_&q 9aN=t*=M@IV({PlRӿ{&!H8Y.&R{:"s& 9de-031tvQ˜kB`P^g vwLR+ EsR0Q|aum) W"4 ڻ4L BĈ̹n<3D~6m3| cC$k1f<G1t~KD-(Qw+sb,l$ Fj6K; 4nLKӴnhC () es) /TR$(`]9~(z Y!wYBdLՙ4"cK:LͥH, QV8K'O6|.MoxWQ1W'}[}ÚQF/]-?} S@_@ 'Pv=(zɗ[G@l,2.u #?L]b@^,n9Tb\w >(y9JOA2CC`n*DM T G0f!ʺyU'(FՇ&s\>xEKbl_[XoB$ HA#tR?~ł5!fG@Rx|w՛#X8EUL5ihOWKEc,S?9T7sjOCiw{J{6B!A ]N Jrv7_6aA {J{p$!.>7,KpmZYzg5夹zԢNbx{\vo/B_;?xGoot7@%>F i+``NGqV0V=A=v>:8޸:1ii>`A| 7'sT4΀ծYT;* gIĵωz킹-yNpj&cgw!L|4(ytN:ntz{ps#͟E*65Ҩ+PT<fn>77; R|P;m_"3cTHY2K.0`E ;d0q2k^%cΨdRwyՃc_>g:g_(S>?7#? .IHSa'm@'=3*m$ž 6@kD3wU 7ㅸ( jUȕTCT>AQĘ |'>~pYe}ޒd>%Rt^]m17e˰:LIo<&?'x?S+&[kBŪ|}"Hq'9yZ.\ZƯ"w(J2w ٹ|Udɡ}5-VH_Yd߆DnEx硰 X$S(,-o>^+(8}Bw{q"cr@9R=Xs*@ķP&T=`Rl7ϙ>-̧\8k:R%OUA87cFąv(GS 8=iA%,Lj_Uh[FѰȁEg6Ў!6v|rՅh`İ O;7wӓJi aR>F*廞~1QVpmvKoܾ!@\ؘzI嬰͛<@}hW]!ct|ҰhՆPezA"+R;moj6>1J}'sj~xbWe1~N˰u u pp4! :=.z8 u=e zdvOAr=n.g'˻b<$A LVS*m9@cf\lǨ)yi|DVP6#dΣʱpx7<lrwRh}e4}s пLE56Tq/..# %I*uf ;'d'|i Mt'u?A(_[|U^v λM6|r)\j~JO?s1q+Kc $xÞH,7:Mt6M3xU/Hȷq4&߹|tg[B:.V9m#>&G9&I[ץ*l^Frn ;WV;^[=ǓOʭ?g r]d%E'HXN o\.0+IK( D)jU!=T1WOv܋T|p c8SW E1 NXpԩ ]~P(l,ctc+Ͼ} pYO"RlxD;y%cC9n1wrɬ:hpF ;Q_[i^RQP4;U-Z"1j`9?s(g$灶SQ1з ̣ 1m";!Mp*>< 'ф"pՓeAF+a;j) -ETc@. Y_2Gz-, I2 8<4OOo&#p=ą?ގnT:C(99{{ LF(>_0.!/.EJW8Y=8\-D A:)YF# 3 B6$\'u~˅Wg(- z`[:'%fR"J;.U=HX_|)/*;`qkuz6g3nqYaVj;#a,cdO2jՆQYǥ&cۅ.ƯcMG,5K\'6}P:Exafπ4d\LDRnAYi{ˣLyQNQG+ޡ*kҚ2OpEiqm34:hLJYhACnlU70*G]sI֍ o?7`pprBFB>$uv VKGH_ΆXr<& 1S _﮲Cĥޗ.b5uv)[?rO DzUvmcrګ Ea=?*i4Mw:Z.O7.\. h36a yqV{KJ[w+n"Z%<:#QM\2¼x샎|YѰ896il.#cWYTS3< ۄz}E2FjAҲ2t cb]({t @iC "2#kR\ ݲ ;Hl~u~\"JfYJF3RxH+A?bԤ(n̖(cqSΪ-af2(Z Gh7d}щ $UsZ$t6^ˌWGQn+Ɗuob;8M|KmEs vǝ F9{g#'$ǎ/ξ8TEફbz4QmGD9 ?:i~s!$'T]r~h)⁕WMi[^EF^"Q2XCQ޾5ڞ%S|47 Z>p:N0CNN~g;'d$~j\!$3W"+]sD^)ofK˘F==V?܅A6HG;"]".au<0iEU4:Ld8ڄɾ4xkԛ,t!tgc# g~"M8nyQj۝=GKw8;*+ca2e*璂9r-u(a6ip%ɨLUP:\CgFhrKF{2җ_T ^w`Lc^@ǢÁiĦ:crNv| &#ɚ]-2Q6G#Q!v\ʂ+(媣s'BiQ%;UBP%c?s5NeH/gGԼGA o϶\u v'slcmpv~qILC[\1|Q!-ШhW 7'_iN9 !J^1K[˽iEOaiMe$:׽@/3j->o;N_<nlTrX h9r bФX?͂y0=tq,%f З?͂P.*l9K=S1ι&kWQH<+ ׿#U1<$Y&0lɮI طW nw,8EBx4?<=H:{6'E-UҮgPA"(xئ{>[c Ɉm̙U Dg(Fi+eY|{mhmY.G!Ц8i"ؼ$#g K1Wb^޲l!.pJAb!gƑy)Z4j_ߗYw4KFՇC_P= 1ch⡙jKH%η'~>E)=|h%<`hL>ܦ¢vjnoR92pbA#xMw(J>1԰=T,%nIuJCk 硎jx!懴\:LDeY djyakmL8'לyQNV8vv9O s'q,Tɻ޼w^$6쳛G/SQ$t7v dp6VBv0dw6׎_ (~S_cUT>Xa+5,Ev?9y^?wy=V.V9lQ(Ƙ80 I״%g~-S[0F[5qj<} vl_N EFq$ؑ6#ʹ$'8nϼ&8,9 Fbݡ*+!nMp8v;y9NEf*/j ^[%̬1[VQTF;TdL–Ā+|]!qsgi5UOS-U ;Gi1M9dz5Os&p.12B, BꏫE@jU3j[MZ kOA:,際)% [n W] J1HI{rR:"#oϫRPtAy=njid$Ѣ7bQgu:YJ^|wn>?;%#O\_Md]sy݋\v<&#vׁdv0Kv忻?*.x N J Qh૜vYL'K2 YLѓ)<&$/`p1*6M17* ͟?oZ2߈=" 5.N52Ok׏:Y4^wxbőГ)iۑEƎs$znOFX=]~Ș?'<%0ҷ)y[! sf5[tqj>ՊR]WX_ۥ$u4ᙣfve( >Y2A@:a3C]ty$d|4W%AE3~+ͦ!Rw5I WX]>WLg /ڲ<{ ˑ+\(_4`~^^N:/_Ǔ|w_8piI(Z6N:`Swdl[MFi2xG1x> # ä v{DX :I)ywMvOBN"6IirZӆs3BE/%,:?֟nkr'Os0/ǭpº<0 d$GväP\F2Ftܗ\>1cOvhƧ.E/39=_}5ذ]-I)E) LNU&)b_L*?L`#F7jgDCbRGy8*mF'b}PT!΅>] 9ȃ H*9ׇ.O bi !!#O,v2200횡I`iIFbt̲\3"A[Mxz>Cڷ6bԌQk wp-$1"J 6K{v̂%NVE`*gn؛%lǠjoqEDSp©P:KmYѫ}C2a3Ev. XMFkד 5năTݫY G_꿪>!*9?ľST wjJN-I?֜8{#gչ9i*J$~òsHVenE5{o s46Ɩ*Z w&8=BA!cɢea[{= <8 Ϊo QXKxۑ,qh09W](-̳SvLh :ķJi9a4u"I.IV_;'7UĿ ᑞ9Ep G^2Ey]dyubdr׶;p`F-ss=O(pɓjflNr96y wY-O%uUGnUԮKU˾]Л+\̀I tM+cޘɌF+[e/K\; iڱ F~}Gq"Dq>5LR&'A Z(}RTbIY^AS$e,Kw]Х@*l/lb O4RC*'J_s;-[T:^4TNbsUUmb(:P֔w1Y7OSɎ6ISvP>YqY hiF _\OzrUU956S'3v&4#^E&,؉awgGzlZ,Q f^5ĵX,ѣ?W^[&[X#d~.Y) % +* ޸\&\Td5+u˳dn P ²:m,i@&_2lOLkZzh@qZ42\ Bqϡ5qUŷB_$DR0Uhz2s2a:t8Wn&V, Fq" \9hFj>( h%X `7fDrVs7iocohM77n(0"$l*sಚED;Of0YH؞D@ҐJ܊DN22#T7%|' w|"N9k)cMN;t=+ UpZ;GiRN Dk08k'li`7,ģT,Uk" cgW )Q:@lIj '`qnAyzc(9xʽcQVJ@ZDZTQOvq*;` 1Fz0|0^8jJV!RxsBP<^cEQV ;f\Q\m`ɝB:R ӎp^HQM@ ߀qqo";]GEYûR,~fV9RRGuUTf; ,_m݊:ҡUEO+y☴e$8A^iCMG$I W'D>׮kMU,6'hi^6ny*cJA{Rha4<؞UaD\p +*dӒlzU+w@.VtP8sY-V};oX#.`vde;z_13[fzI{e<ӵt l^^]L |?3u?=:c}!6"f D!`ԺWy4R^×=DG]㎰@#8pԶ]8~W?*:܁|,c(2ER:dp'@n h\.%q`VE+x3B3[kF ڞA[V*#hrힽEџ|C7^^[bGt׹_n9uUX.bXs|gfPE79逩RSaZV!܇-jZFgL ;ҝb4 أ$j, ,0P&-"#]z"P?s+a">6V*q]a~2ٮ:b-pHz4Bccgc8=(΂dߋѣ\mioGt %]NNy(2ɑ_JÈg$KT=y3&,7)vTs+QumI|:֥IAMy[|KShFeZ+ܫ;:9e-`C& H 1&Kx^vzh4 ZeR_[gD0|C#u,֧jE4_o!`;k2\X6>yU4(gX<~ |)|/OIo],좲u[0Y ٜPH*[ 3k, Q0 aiE_t^ϝc.a#"O1՛@V=#_1Iㄦs.gp[`bE(j&UbZG9lI!iAwh՛Xuui$ٻzKZ鞖>/"O*2yͯx>zCruJ?`MDN.x{@bwaGtDFIb `W4p<vmƤƐi+ ɟ_@o}Bzy7bW4ғRrm>K,zfgK\ΘA6v'rG>KD>Έ=gʃ4eHt@yhBzg埛ι~UZ Jwο/HpդߒHQrj3^ dbJ3>I>2~P'r\(O'zk]TƱjh 1Al$bN1cR+xtM2N8 MA `^RОO}`96$'0uBі$%[ NV0 F:%ne^[rBS>5lzJu<5(LÅy{ٽĈO , w<Jvz[Ƿdi?sSꭿz_CZUUS/"@KD g Nά'G׶gxsޠ8RzFVxnxKhѪrwɕ>²"&3\;BD٬ea3u_G9[6+DzX"=̒\iۋ0P:esVA(HэZ~X8$ϘirO0|Y΅dtg'M<ׁem|G "W2gcЛg"=bYndZc2-b5?Cu(Z,1,neٽ(:0ZX QdHic-Ap&̞OanOJ 305WD,aEf],kuĂ7I8U:.`R ^"GL)[& W;}fz_OT?q}uu ݧqm;3^dםİb= rZy=t3+A;I`@9K>ػ 5ífK'iWnEǼxZ%DJ_~ 3JPKظ٨vмZb =c!GY\7ڒbiԞ뤗+EGPj &;\^E} ?B1%wcb w S8]a{6V#XJ]чS8Ly#G3 =Ym_:qAz2zj%𱀩xG='j5J1BRT )Lz^W {cZ^93H:GݒCC5],qNnOx-^ ug qeȣnQ[|[$Cܕ[6$Ů1AI.:y3IOF:yWQ>>g=lI?"I|~]d3!<3mGC+MOM`zi3peW.`f0f"'L+7W3 ǂb)(Q+oM'n29j%9G9s3uq1N9_pY_Qv/ڳf۰H^x1hjnc# ҭt*mS9:Si$(VRFNET+92xw_ ȔՒk#ZK޶Qȡi j. NhsҨ:0yƺIPro,k~Nc@-_UCq=>/Τn g9_z6 ˿Wx*/|-Fq(n(b*uĞn3JH``|GM*;ӯ+#kkwd@9CN20Z~DL]z&0symIrQLC䣒<lbYęt0s[o| BT/06r:\W0^y@> 8\L$Stl=>܇Z{*}噖MRhw4,ĮgACN.'v㝅)urܫũ @a)ưg6~#B%*?$QTX4YsMX-PV>Ih=;ynQG/.qbve<&eC@xh}Fy&B5/'/#:ݲn0Umֆ m5'ጦhW1r=ك2h[5)a3rS5!l9I6iV·]7/Pvw./ zlNRˈ'9)!h*tkzs# uѥr9@q8v%%|qǎR0D͸݋J\WE x-T(ߪ,Z@LzmK_,`9:KvlISjs5gF+eoUpX"3kMɜkVyү_Zʅ҇bkv:EK,뗝aOk1'd/Sʔ¡wdP1v1!dKb$d'bYg!3䑗r>-!C Tioȧ5/2zkys^~. Dv[s3}w7]?Og=f#oF-Y[#A8J̵=µDʹIkm<"ۯ며vݒZr*v͟]fǜ2Bf\O1JX6/(!!}O(@ԝ9&M)*I~Qj6[2ʖ“Tٮ]/=VU|YU˻cfw.ZSr)7rqwd7.dDf=˲͟*@-R\ۣ͸ڣ i97y "jjuRRIb![&!Wz]S Y $qiŒFs*h\P`MA{l [fv'iʹvÕBD8@ Ф.)^ T EyGc+S'׎[!Ja!X<ڑ%9v{i6\Oq՝_X_Hȣ<(><ٹn@RM[;|Zڗo\I ǤZn{C{ekoV`G(}drzDAv8? * :ֆp] a]ҏcN"MA4|NifvS( w˥6?%Pbw^Ҟ`n"ǰoy_v-sw'=JpL,=njVGFDpez}P%ajvzRѱi9wY.2s_X9vהB.Ζt̫rgDSBUk*4Sm>f9ߥƽxx9.FGmX|&3z=Ot=$B&}y[ 尚gM1EIouoW{FGWsg;\}XVG4sTU SM[uAZ%bLC6 t)+nʊHx& qǎI!tzIO_% qqʊ#[LFV΋ %A])&`ͽgLuFJ 'tN5a×G*OKdٰTf0ڽO(a7`ڳ ZCvym 1y1_&B-M~|u/=."W bDe[(DXtAOR~cMJL]-_= `Tcbޭ C({T]fZ$e/.ƶڬmHB437#[R`26dz*PSqo 0"oxJ5'a{'~̦󆞾py!:XvUe(brJ# vG_ q2N>A t<}E -ho@͒>!~T[ۻTAUN3iWңŊ1v a\fPTÒEd f "ΌD#6 o(i؄* C9՜Q{U$Ww޷ϽLI 0;+pRhYBI7G =cp/qiICѧ|I姎"祫O;FL ')˱|8 Z| `;yϠ7IG{ǻdȇPژB!c0Q^ۡHz#<ftC&"p ϒSgQ@m-acrc9/1 1,@g:\sCʚᄁjnns2i͹YكEo*(ij㲮@WFU=yrd۝_1DJ40PUF9 uK%Jp2SdL­3y@q|D8CjbJLX5'|{v $Fw$D8nAY󧣔WWct ;S{ck}{3; yWZe$Xc=qb7&VNGj.,om]hG+kuC;y(jӗVb/^6 39ۖzk>l SUw:d>ҿ~>}~c_/vY+'y\8N5PDg .k.: ],ess[KZFtq;4~/cOJN :2وϙG9[#PBzv*Dn>?Ү +tQL"yI1 0Abrh88>.v$<.dt*^~6('p 5K|9.:;醝G>A2 $˃aB*J.:cO8Rea6\[vK=;ճn_sT@փ}SRjlՃ\)>̿&᧏P)YyĨ5cт} ӟJ!!aCL6U=Ho;"a@Bs%Hb!'rAL Z]S1g:ک_ )ti+rI}xViɐ_*LpEN\Hhɓ5XgKb l$;'>t:$zgk4.7LeVd+#0vÌ_1 ڣLceQ`h@P42OG4큜"р; x1&B[Pa31g"f7VNf'xI:Rlf1kCG=_neLJ  ۟Ј(d's6hD(Wos ^_bXbϸ-)߬˷1j86Si666U ٧-}2 H7yY=+$Tp5k#R)4}9+tQ{L7t]X 5S:#45 eLQ\ Fh n24*݂&ǻ.qM>>v;r3+~'9xzPRJ1gBY 2IwrRPeҿa&izD{J;*DzBq7QpِfkĮA*e@)2adCH^RH0HiBJ![q=H@l b#k)tӜ|v@m p2Wzlαmg2E[,4!W1c-f@V~:uD\Zע^:=nsĪ<W+r3`Z~!]uU8Ў;~BbwnB)^4T/؆PɊE4{t]j38??4? jzẼ< Jb01pz pSؔB) kf~{@)1M˜ _K" []VgE%. SBMmrG,p)~ap@ &չ Ж„[pzTYm[&ӽ.Pu;P,sgK9U;.ւ}R$+HͲp&7Ud.3c]#:d@V~IT}R̷:cnxCE~ao u),Җ>5R완 3 Rc[X&sMՖYè>$b1JhSGcfg_ڙEQpk)3s(P>g7 {pY#IIo8v+1liW#".M6`VSiHkZG 34lL,8踄n[ձ/kXø5L,ԝMZwКH5jSNRɹs6 *)ybpvG)|mbnxhҝ愤hjv>Ij<5Ϣ7uбHCV#8VatEﴋecˆȲR`2xs`3 0\M1qs?LO[ {OխnM)!)Zv\7B=Qof٩=6QV{hUU&Ϻ9|FFP=IE^@U\4|BK(܎=r۠kBd\MR;wm@ 1rCӹ笚ͮ]Ӛ(՛9A0[yc%A|wF.[7 a*uů/3'QLHt&V*춄3دP[ɮ# RkzIrzd@Z6ontˠ}8T~ 7BE]cYqE .EK8YVN2NOm X-ɶh֧@|hK䯵B`p GEd^]3-k]BY0Lu12DJAaȋX>f?l Ù}&vۤ41AWnڡEF'ĦKq+LD#A#<gݿ\%$%<-_g+ Z cSV,>ꕀ..c#%!}K5$;HfwCJLrOw|::_nn]Y:l(\Uuo+(P gp %@"Ey3"kӺp²B.da ½)YaaGN5qT3dU2 Po#j 6("&h_W1̪. FAO'sWvi[)\o(K͡6G>_`RǺcSp|: ?~|RU k@#\̔m^|LӠ:+MփAH9ɫSFT7,w.' ׈kc00K7ĠiBʶFT$6-0UeoDtC+qL7$ᣠIYv.ДPz Fh TWQv3q7L͋-pk϶jOM6BGE j 0h9U|wbx@¶`W1%42$(p }E?VOi-(eͼР[K̛ju\\j[9Le^t38Lpc^ԙRT -)8=cU0X8BmpPώ+ccy/o#gݨVhBN}'Dl< {aOCvA`O.zl =U) @;* ﱺL.vQwx7KXA^uzX=H=ɒ.k} %$;8+ᦃ.ѥUmlւH!Ț(a7UCoSl;0TG+<װ(a(/%2F>L^yݢC] N>3,Xx嚆37oJ\+tB>nK8VdRy&Sk3li_';&YI1py*CKemt?3tL9 UUYuڟ)dNZ~AT!r~48F@bEfQF%LW\:JY5'@CoNUrPMw >V:jHgɩX !XeRYPʫp Cb<|7Fܶn\1 &q\Y^s0=(_T;}%4BҜ~s k ]e,9w?JPA'y]CN^wU4TqLC9 3-`tuYή aVzltfP .)OkMW(e "S$}݀$3LUErqydu]˱~I4Hȸ&0/D(v7o 5bMS/uu|H8l^|0o,cCŇTP 41FJb"zە9"Z\hқWH 5Au-L19ի3 h"ԡƄ#*aj*_խ4,ٕXZpn\<9'ǵ5 /9 GsqoQk[1;m326'I׍YjS~r=$\>i ƃlqwGprӉĜwMCA3ŋO~+ 3x4KYU7n7 /pC;#(1F;};NK_C_nHzjʙFM dA_.HƮfa!|V=مRVJ'3 @\¥EwH?lu*SG]ܮg[aB4]_w=Hj-hxP.~v`$DRňRR6C*|mt:>>d:T?UyZz tl+4#XiSEsmBUS8Ң}. NO4PPy'M1~dL%(ҡ"84Hubܥt9n# {oVt(01Uf9d~C¿jl !!=mpu7I' ^uE3Έȣ]Te6|ʄF'2oP,G1jBH|8:phLrku|~5;-b'_3,"puxlpIJhO$ɬчsd^%#%4N ,cU1 VԊco;_S !(D3&pȓq@:ޜX=f~$#Wu-$|*'? }K:~7no\|M+>3y~mx|o>߷.|ak"RCW\w17lvX6'>}8::Mz:'᮹%DʁMRp:uz{{zn(697(MmPx)Kh]_o= K _R({[լFxmK-^[^I~:߳&T}L: o {yO3o,dBUi-;`Z[mqM/TELJ+K;bvJT2UE{Hs|erjz`> zB9KzvCfL(^@,9`+nZ;,&8>~◬@0ѓ؝qQ!x`)ɥ<f,$:9xynU8CJuf,'W&UGhǘM̌Gd,=9)6^DKd: 0`xyg 5hs!@ #}G9`ԌP0H]+ٱn3$4vlSQԘvQVB``ʠrxXlW$Dӳ-ͽ 3)246 e2E ֖T`.B5!Ix Fҁ7ǎd玿<^XȲ^rDevn8_83RQr=U,r&Qe@ =ɿMİ(arYV v-i$e< giTYwBYw1^f}Kxz:[܍<Ӫ:OEʘs &U\?n{2QSF~ FwO#_8~R;U{^hoGcUԂ۩v$ar:NrGY<·b϶r@sXyifQq -#m*!,E/}| ?$0k'[NmEA RVq):]c놸"0kHLYGke N`ˉ~e;#એҴHRB0yӭ3`o.\p#0PKM@>re9[+yzVo=9̢ʿZ\| JAR) -w' #^^ύMn^G[.'A MˍoPX4 79 [ۖfykږ}h𦆉lU鸒M4L[!(5-0KF핏.CB$T.Ĉ2Cݍ9gpa//\vW K)'EIpʭ }xck`o4%|~I ~4)BKϵ}d~G{WUj-h`keMaCyu|oFCX (1Yd)uCFgS̫}_ad1q4 2{KNpk|'SЙRz[Kvq(|%ż̀ӍǓC_e8:Y)`آSXi,!n /$[N7W~j%/r#F7W#tcV0hu;VAzA39ulqv` )1L1;0R gݵB);Wwz:Qv^sBOOUVeZhUDSЙʼn"$ t熇$L-ɰf d'yVH˯FtZ<]wZڡჃCp 쉌S*]s BP~s`< ?|&uy^~hHOOmA ' +hW4goW&G+ w͞c^(mA{B.L!mZё;g`Q׉NJ( q@N') ؑ#fXCN >@gU^+Uu*ple@XQ{IQGYQzUg=,ctu]*γTߵDH6cS'p(CR@\L2j#t HOΊ!XY"\yP[@53+$v6^ۓDҌZW4sEi6:޳#n &([{-n[>D%$T ?ck |!HE۸u,yiS/|p̛l^`/mɄ>EfWY`-6KL6v֏TꪛkϋMCW;O>A"82=,Qx7d"1ތ=z5㡍}2FYW@'÷.! zI=]RX{nҗ ɌKo15^Cqy]JasX{`6'Or:u<ث~#)kS.Gϵ2jmg 4S7Kmh΅Rog!lF~Xܷ&5R=e`22'knX3 k;nO;4'$\T13tRr #BX-cN}EW?œRO VϚ$ ?g ng1Z-S9:yp6cpa-SsiUUhoZ{8ITáOW͹Yݒ:7]-S1vhu*UBۍƤǹVZNI>I%L:ִ9_.fdYŸ'Jʂ>%vpH~]D̏IMU1]xxJU/:b 12y֌ҥ!U}{i!(y񅁜+;Uդw2#@F K=̿!a8yfy%6, ^?S~v TXn|p{5:ӡU6'\V^MۃĥoB/!ԈڍQ}pΌ>')ێ?H7j[,Wy0ZyMfpKuN58z9bHڹڼ>1>~Fs d'Q76[/@_dhPUʫ8Bзhez!(4F`3)W1ӼCFN!xwX WQDX,IWRz0 c ܅GWwx cŪCQ7,tBxQ>Ƥ '_c;S #籠s7aFF3G`GnˬB\p.o)ؕTMPP۬"l[y 4e=ì绥F-ůs~G!** &C~7( Hbs(Z{  gBs,@jDDZ!=Вt;mQ~ڂ^M5b{/v5rAv?o!d}_[:츀Bӥ~02?q|is"J?w,f iF5:"򰵓꧔Cj4RDLPOIs[eœưpM3R4t@WǷ0^TMbpuި ">ȈwC̡l`AJeEﵛdt VrasU|vDezzች D];Ob/O}%1)p]%2wq~c{.8k"l,F9uF@Mkk9+'ȡCe;#[!~TGxzb_$` ;pKit+\qTFORۢ)+V#'QHuݙжŤ&#&ҳg3f!H dJyM7E Җk9l4=I]>z~5xi/0?m~^:ӪEsnbG:sɞf A2IZrfC }>7nH,jgp$tbnaSOe%&3zSŘ8`!נ9hKƟ"Yg.p1Ognq?1_y$Z.3]?a4xb Bu mhxFePEP@}MLиSƾnjՕ Κ}]:v%`Bk1dUo+TOd9H AXb8}L98`[m]1QIRTk}PSʰs-Wr 9#N+Bfc\\ɇ@ 9c@P\|oML"Q?S#ú!=OHg1GFth2~ɂRb`Lwt("Ʀ|c\S=sm5cFl65P('3-0g@cZFF`wdtl[R#r=ō$£.W4tJ cOMy4h\TLvbdpQڮ m>ƀ$;H_yq[vGͬ+(W¥0&+>>KMo}BuFhM ׎/A!A!rg($)vuInkFϦD*NX}!f#w+\:RƖvR xx[+Oc4P#Z#6RL44K:Ult*`,keϼP'$92N*@+`*u?ayd$3Agdv15yY{̍fdg?$[џUDrݨ)su|:RrQk3}ᤙ,JTwFXXpٵwuߚxsB5%/vܫi*.YZCuu鵷!PGGD+J/<`67.Uk\nl3,Cw`83M#"L\Ll:'X)ܾw{Ț ʿ/L49E; C79 8B:ZgaUoQ[ݸ`W<~ [:g3b <pn{˻v1ӽen\o'9%8gvpFmZTWKnC`khFHekp˜q #5c7b<&T\\yG#QI [/(!PV;(UUz~]}t{}2csO׎(ԖHV_gy4Tn1'RDcϳ:n1;&͚wG3J]P |S76TE]|)pp#/׷6x(J]ޒ} =-j\r 4G]4#a3XOSg4,k{zzv 呍`,IPϤ&pPoRݱoO `4wx%YT舣w`wy=ȭ Ьat rXlfb"msa睩/c+=jN#Ӟ[}D.rh]+OыpiczG?UI 녬j#Dt(6~YzXׇsZv}:>WqWvPKbqygwY틘`IC.O>暖RO2.qztIޞUz`leE~͇mN>UBHvb=t#IӮ UQ< $%dB,TѼaXs]CSKA<Ascn}B8}UǞíl*DN5q4k ܔáЦoD)uH03đ9bIj4E؆@=Fًdjtbbζ)eH7iO~\idzn礨? wͭzv@&gd!aOB (!MW[݁nz2Qi+`6v5czJ:,!.ed "wgU2!& //8% A{Bn Cܥr?k.i J&Z]#'僑A 9>UuuT'Ɂী2){αlΩIe ؀,fw2=@G,AٸPrL#rN}ס$o},q>0Gt&`8Ijn 3QTmjjBdEFǔ8`G?[GKo̬DUxL#϶Zds|V)`x]/3P,+K8`hzdnԫϐLLﺌ*=>DEi^Ǽj016l-3}&)Vpl{#VMf:}ֱI([CL;-ڴ{4c|y!X57Xw$OaW?W/mϩUұ^pY~'?s+)~RG7j$*h}PtGmhY2.4&01S:<U(U kQ3S)A*RiqrΡQ@0Gbxœ'Lq.ĝ"Kz?7\[0 Cù`wxA|w#ulnĢçn`OV5-2B$QA>v%ۉjw30Pv2LIߣ@W*ɫQXǶuICK{$L]IarS }̮1CL씓oyt+zJO&pu&1ev6.*֊W9Bź! ~E oKŽVO?Me=H]>_T־ ڞ2NB<V#a5Mj#M=ٻ z >A9\V; !cM/=MR{QeOhxo>8Ouڟ|/'ָr+;(X5~YI5:mqUXÀǍ*5cJɽavK6g236#'lDێ^3줯L##'mW x/=ڝJ$ fC^cFM2kS5vZ8o"gX{fsb/Fazy aQ83 3޼P fiQ&f?=:/Z/L* )YXg =ku%8c܏HUaqpG*3qfշUoʄN֤ a[ MLkO@T= ۑ $jN<ۚ>T%jMkQ@hLbD]L7DqYJ#$\Z)"a4r8,zegKiprTJ=]yM}owKD\’dhfQw%ZɁ :2FXϑ~şW ^{SSU}sor:RFiRR2}0(Η!xy$.#dǒOwAj}MtW!f~/ioU7Q-@Ѭ]\ڡǻ߾"K$ȣ>;%9v<RtֺZTb1cÊ//CVR@-ƔO3EzEO,h1LgUGhGEx5tiVmBs 坽? #^0'Ҏjt0/E1ޣHŤKpL}L.P`a&Kg]?b^l V걚!xㆧzFlCV50|UŊrlx~L$kbv|뜎9OEFvA#v{!;F;zkq5>.'1wF!6KJ4|rCDc+Uarp<~L-- kiʡv)\8+?l]+^@76Þ ֌:mG@8i_/\8,0N7[眜!q#]v`pͩץ$ZEPU(n5ctJJz` 7g%W!f'gT͑U9U– b6ki]~ g /=gzyMcv5ޖ^a)0* كvTpϾM $gZCQ@j2 $uĽbΔyESYS_\WIX{ M1rWg0 Bnԁ#D0Wo;{Jc%%w5Xt .U'~$=.%1ww7ץG.!Ka`qjoJjts͐Zk`?tL/M9׿u{>zOӕAU>o `dEm=Gcң1rٺ(vn,S6yVrZ Xdn!~"ҏ) nả7$6'ū+0D9a0j4lD6_]ݭ'&Ү D4vГLk_fa=UqXs(5h.-ڷt &-B}5#KrԚm £(fȲ|uF6Zػn^DUtYF2yb_5LJ;qMRZ.J+9 XYc>#uv3d!;To-Ď1]2yCft3 ypmMG x `zfk]UzDE/4`'kapN#qmJpF'L9JE xȁ'<>ێ]ʷvI8B~zh=‡{@T;^?iCqmva30`$!*IdvX2$R ed}qn ;uCyh7lΕgrz@bvXg\իjzS&c\CJ`.KgKƠ厩WP,A(8\*`yރriQ}u8RuЩ0v *saW? mCT52 l{AO36-|xsT}g@P+[3 hXTCW8q.(+ڀr|Ng4<^_VЄoot;yf½m|WMq#pkD Q@2%Ι [$뙧츴Ϝu*/rtqu4ʃWLOMJp0[ɇ 9@3֥v,}p`0ұ|"O!Oj>}U\zgP ; Sߣե+=IoɊpC˨1jC1B<)#iG]l']G+.p$3YsPڎ5L;-g-9)`Ec k0^uvyCBp&rٲo sLA ca`= {XIjQ" a^O5=6!;%b%%a/~&M:yP$Z!J?Q$bD] 9lsI^Pˑ4=9R|󼯩)~іP0=@)6h̷du:E^aI;+̫[VxKdk׿9J[@k 9%Wf(.ۯTcy OTs_{|hԡ0OuT^k:"GPQ\'E~ut%v.[8Y+L) QИ{Zqg*aתs "jDK[6\-P*ey I)<>?#p=i;)4mbB&R&o,y5엢#z0Ek\o,k~d(D0}zM ?bEcaatQU\!ۍFҺ:%>Gq[3bd36!ͣ ?D[7;wbd(.DDuhۨ%x|b#w}@}&W09ej2e\v1%x29r$]`eBo9""9/@PvMYM3 J˵ Yӎo/3A A#L-S/%C\^C҈+=3ky IZ_EMTqO/Z2z0S̒4ap⋝1%92a2&|weʃ8؀3J2)N?qL23;}ecf( at ֶzrwOD H_X %l0!B$Jbb.$[|ͮVD#\n=|}$B-Ow%ݛOcOo ce櫈T\N2y)>bݳ?X6vPU`"9ZE1'ywVw9GUͅiH}ZȱMLOIZ$"C\K΍/y NfOYr?e};FOv7(N9\+{tFwds|nz Ѩ(na P<]/7>Vs3B/vDc3AujOgzYy  ?*ì 3[,e@ oQaڕ,d9@>ItH>jӍ֤Oa)H2.,ʛZUSTĚa<)?@ 96i%W EEMT%Ud&( kRYatR-iQ@A»'<{-6{}^/gI+ K_m4g_O*zs(No;\ҬOTۿ{+ݍlTif1B2qAЀg_OOY^oەCe7dWdrH86 q N->?}IipG6#?.N x57feMVTKO3>.|NnE~% X9͘! ܞjrQ9.,ii K,^rk|1=u3 h .iY9(2'ICב!h1(\8 lzը2c4оBt9 dF,V @=yrM[q|eˠ8.TkMND>]k-f3P~I#A5?_p;g , v*k2ͯyWTŇtWE kR_9=u8.uB{iS*UO4D;P?z\_W9y{͌QiY3/O`~'4lQ5 zۄnEj6qߛnUWHZ5#dVvˈMc8ɢC3f}G\yir)(2A{b35qU#6Zĸ\儇 (#t,< bZ3y (K)ga߂T[K"(̢^uJ |h1ӏ$nls|6|o?^g~X١@t*rPEȝ8έ_fYU!жb!u+[_጗4ҭ-'\  v0Olk< >=pWɶ>AqB4c, Ѝ(οY>ָAi7d r :Ah8'~H3R k6%ȥ鈱(cX,r"U6 a sOdMAry쮥Y;;;*J%"{y"bJ4X _K٣3Ëɧu%]XPj\?ZeB 3Q겻[\>u`C~is~{[Z”Q!EϜ.Tmvuaús_" Na,HI8[!|ǥv,5|gGRҠ{2],2=FvŴ9lٽ(ZV~##wPBb K)S{STߗJZ˟`:5p$(*T|m@Rfh&9:ID>Jg# ] i8&eǓZ.&[ox !8CjR#U = k3ssF6Dz¥e@^[eǨ}.GȬ7>J!ra%]H H^R7ǼρXd$ysK dOQ&uԷ{gD`Dq$a4/43批u^( Lh~ݣ/i;%ϼMa"_bǻcJV*Zi?Zsj} q8Gl!O7/ 8麓ꚐLɰ zh 1A"U]BD0fЇȏ[ QJ[co_tD9Y<w \ZUYnJɓŀQ0DJOY'*-9jL%bzJ78o/\ ,JͥݦuK*dS{^C9{ZrdaZF2lE6"fcߙ-\Pbpgg .M[L6LsR U҇j'sCrՏ]OxydaUJ0=/Ն!;× L^Y}xnbZ 13BQFlxbp10P6$Nd lU'nUᾂWYn):tNZYFZ'}|g%tn7"K`mbe Wu|ܒ]ܛƌt:XC%E VTOLV铻 :_i0**85yX&۸WOB;*Q*Y/җb^*xisc $eJ;>3ƒ7 jqF8bV/tA0Rrqhڲr)}葌D4oo}/k\?rꐦS\c<[T.d3S 2sq"ȼ<1l${|ԝ>@ ԁhや%6'cf6C1c0y-{Oi6R 3f—ԃq.nj^ _zh8Zsv,r:nK7fsuGb6$"ƘaԼ7ɸufw4oG b3" ̈́0l@}y=>_oG~dgy~]_{75JdHBtI/vh$BN',$}ܵyJ:pt-~9~t}šTH8˜ڒz(sը?嬶]y9Eg=tɈR|"<3A=(qP-R13y5&ϘѠbn85}FQv4+9] 7~jY#ҷje=)deInj3~?*>l]u4Aq8rK"Ug<;9MU _ ᝑ3{FK>7z;Z$69FM<3 фي)ljwo}^$UU?.'.ΡS=n F*t͖a9EB&X+d|.uniJ`zџMw_y7{ RB~F^f̒mv;zUu tFDXCUj\^^z,!\W@J3׸َW\%BDȏe0,=y@E&ڿV,CDʽ^y %J}%qd¦%D ^^qRrR3%Qa[';I+ T@At,:NDBHmʩSN %fuNb`ھ;"rއ1g܌+]'Z:zpy=Nqǁl0Sոݢ&'(-iWQ=VɉIw6 0N̩> BYQ񓔨C סA Bp:KED3z]9Wl1#_.EWajwYwoaxSJR@} ?owg_3'/ ؟lhQ,w'RPD&`kqKmWX67FRL(O - ؏hמpƋaDCEE2TG Rd')wH4]VZkfŚEJ3FuEkP;׈3t1ÚBTӖMbR۲eOSU*+ŠB"S7Xl^'֝]$KEHR3HRYck˘rIP bhU1'Wov`*e'r,roPl!j9Ofx{"&tIW`iΦT6Er43b8j ľ"I )g]h[bI'6/&G4iHU|~HU (T g>^EZ?v4wg:ʤM:dzOFͤüzK[8AmJt&[x;WהefjͪK 8 oL\Z7x 6 Ha,br5"e-}{(tnK阤(LAstkc$PΠ5>LYZ<:ayc]}60Mv(Jތ&ͮ9.6{~4dt')5DS wB`!xeﳜ5fU.v XKjPZwġfdkDZHDBp76wTIrc]7&#ê \ݵt&{M`гKLL3"^x!K5#9Ob 5g|riEfÍ9=Je'KbC<{gdqI#9R%zW'uwȿ~|Ƿz2yC=k;‚ @ 4:[!beaܐ2C;eP',[k-(9'm8 :gD3!h>3Js~chn$J;rga2>mfv{ְ.pU//Usc;%6*4gIѳV)Ye>f'(Qؔ @%g^cQ, &.BAzhLq85*K PwQDϤƗS?,7HE`ex(йnX,w3I[C)* @̰W5TPxbs/GUl7tY_ok i.PiNSR\5HoAw\1 KfYNN}r˖W]#>LjŮ-f=:K$&h5bKJYGClbFѽDl»GRR"tv;gHtavsvHavck]}9kYiL;I'ObjK:kvODNDH2aX_c2.tģvfz m@0lm +Y^K%eO,[ǓT'zOU dhѡ1|}u>i& tS [0:n7YČBcjD8cdL4rv+ O(>0FV-AjR~A*d ;M%Hz5[݉͋9߳1%}J\N:STlj`wPXIÂF"U(چv_U;A)eDBp-z#)vM/(XטҢT+?Ole' BP@Z Ϛ!v1qһ{V>NXkT#Y8ѸfR Ed'd'1/S>zU\Zohҷ(4Z[=՜k*CR7V:?|='2 "ouD(Gy9׹W//r㲓D& Oz{.Ƭ6"CVΣ_*3DY=?&I|xQMn=áDrggKB~7vJNԒpJ)շFIp2=46P$oﲟ9MHlrۙTT-U׭4}/[#R0=uha} ooK=G=÷82i$NE;ƈ 5bZM$s2}(YX2v>3)AU_0%5jv#kmrsfSZcb)\T(VB~%(8u\|DvF!J Y߆riw3dC]3l4ڒ6 7@Wj"qZ4a`/Npn%ƵDH]ymH"X&)$6{8և\x){໫R*b#j e*B܋z3 gy+m&}n16_Zh` TNwGRePB,&|'T<`Z OvGBí^cuu`QFOΠA-|>]0hmJǁH"򷔭.1E/'#Y rWR)nRzO$!tAþفZyw G b9Lm>l~8Cpൣp7+539!v WPs CټEB ^.PNJDU+6N{m$CMwUci@_4 }ُrː+8I}aV+yO{DsB g.*^yr2'Ki3> C.\NQn& p_Yt}5]Vd[C}5ENA _uHW?׾r?~|sߋe'`eZf-e'+yyp4J0mùž ٮnцsa]q!@y2hw`]t.gxڤqD?K5^5=L/V%lzg$ٳzj%S”yJ;ӂqc!$ϔ':%UWbO^-Xmrd6rÐHr N<{tMf+KYܫ6Ju&G"RCjz?7ڧoE!@|8Ud|c@M)&1TK[0GMECuL0?DZzoƳ M4&]!l) z'[4gu`15RE{.KyK.I&ɩ1yU 2o[G\Y]OOV-K@a@4R:mF E&? {^a>ߏ33/$ӽIޓkxgńEǟ9_ .XyӻDWªh\ܥ'vš.;e  Nuk?JLg z&; Bnr=Q;LvZcrOI%(ӓ&r3b3T[ ؑ2NK^9Rqx l"rivqX(Oª'Fb甀rsnxkg}3֨fr5y KۣSw9>q`3+R=Xql.Dl:PP Ը]G>W70>(wߡGQ 3M&K~xgv/bO1wYR9ɃQ=*-Hif)f|ON"ZH҈P[RUm?rrgZYg.R qNn7 ^9`-~>޾cPizUsF_;o7Y";x!T#jz8Nxһ @; uƻƍsۻb"g6!1{DҔ{>? 9N$dc2Ue Rgl`%m 6T@3D,SW[q|{E*_8EARYT~og?"M\ģ(>1OYwCߣYڃYʛ+QȊRrf{G" Q8b!l!CDE&SGy! cY01yb khD\L̞͐`#Mb;436sC}0~Kf6Uͭ'DS?=@B,Մ:fSQV505d;N-k$< <,`Apo{Ds+r{ Gdǧq|$jyIg1(N^N~IE!kЛ yxwZh.WM10\.vq.BCw|P;(#6<C`]y>1Zhځ`$Ш CyGg=O8>m!y`E(XeR4/=қ\n:mo}H`K:MSwraLFЅZ-qUKF8ǖT eľF.mA1A s~XE%V]ΜJl+( TֳLy$Ziq^X_Xbro[U' ݲ:+F8k{Nj\ä*ԬUbq! Dh#ZTdX0fOԡ*WPECBTyIx^w3JWD=@2ʈ4[qo*FYh9$Ѭ\4⮚+btD17BsuV#a8XÒ&oL_VΦ3g"zHՂ,dmw1gb|B=%-_3Oq|!?EO_nKeՖ^/67yB3EowVB, ~݇@s2#,EX3,LM0xFJDh-m&Kwܐ fK7buL1t_ JG#ݖfhĨQ dɎ.0ҬM䣡F%R\-Tj3W{(d`=3tӳ|M9ȃ\no!dZG^? t6YsֻwUKm68P#QMp"rZ+@4$ݐirUڬ˯,\L)sh bU`%i!Z@ LcHI hzn`HѰ\_=>{1 znL(zy:0.R08ϑp&Ij>Q:zѿM7d֨Ѯtzz%x ,5j KtX87/- VN;LiL!_D m;|wd1\Ͱp{#Orh{hߌ2=:'4kEZ|ɑz3{ u]Ӎ !2rn_>lїgm6'{͂ j;%sngj#rx#w*PH=sP.E_&1A0.IҥY&h wN|G%;I5)Z{o2@c/ u[Ç>K^*$ь5*Je!3F,hvrh[jHCjYG~YTU>_82JK 7w/e ȑ'Y+RIv]1kJ` (xƆ=35%&=YV:|PSƽ.Th-8 _&x*ř_$$^,z.R<*4 ,cZ=)(} \WZ4MgT*ހ=_dbFBVwofNש/bVK^_;> =}p$fߓ{@ |vkg8#)Aaɤ(e0?x0[>:>c'(a0-R00:}izIJ`:OPXvV?pޅtXJf V=䶃NcK? obBaLIî8C7 i;vi+TD|Mb! k<-[;m[c:U) 1[ kt3;!ڪ:pBJ R`:ЯOlmKy0\-TM%偤Im6+&U'YO"dz:(.$-N$Ӡ3U+MS!ip:/B>2g%p849M{L@1WDpFp!Ys"g'akafi,A w=nƇsյHPC&ͨl U5w>j}-g@]91eS` ZbޔPנ8yweDIIYg>Wm)FǾI_eaE5/ri{xs/qQowLMsH%U!+~0rd\Mj!@kj8,R7tU@6Ѿ 3ݻ,A/՝>D"]rV' 6F%;xdV7y(nX(4Ӛ2X36P"ڮ>O 5.=fJ Q6Jf(p]{jynoJɯ./ee#]FE]ݺ:%x+LnÅJ/-(+9V}_njWo7vrBYsJLNiuCƠu_UIMN1uG4WF0su$.7A>T(\ ΒNVQ_ld\;*WNqs'{.hH)-1W'gLKnor;xF~P?;NGX]+?/1d~{ q<'ALO*A~ _!eW bYA8ݜAV5"cm9"baN@d'8Bm7Y3;z=n vq;We0*h,Cx*d9BL4#E Il-qt"j{D@:h`<^g?Jy52IKk{`l%R-@'Ojܥ" Me CY5r{;w'U2]S2*XZJ158ݢK Z"c VյsHv-9QSäC:O%)^1\M0ڢ,w~+B(&h .:y.$1GKk ADzLDDhKE"C)$^M/| }UCfGO)MP%"bH8Essg:j8]PBkpF쮝%[e`\Pi7pa+g]‘4Tj"*.'Sv pBF2ad[L[]/EhTcsw'4 GurݺelxN"n@yc- Ӥao:C_ػC<bDQ%pJ0'9) |FbgeQXV׹ЮVגGfq5~ZCpȁS=ѩv`k7ϔ9[SD&\zN& =[7i:Dڿ0%,Z"svx`.aO'I;42&WMn%Ii01FP3JjS4aIW7+wM]#Hk -bgv KJK${5ŕ@+ K)\_S\Q8T޽`9[&s¨u[.b~nUznXe]94g֐ zprݑBFu3(eH>9J j̟%!h\fC=ʂVBᶼ$lE-m$+Mޙ]|~ͪF)0Z/P9ڝߴ5T+ǷY=> q v[AO'0Tm9fI@o '5tbV$|.@rzEaDEgawVÍ [*ì9- ѕw:aO`hYs:\q>я2D,6TFC,өkonH Ǧ'8^rHm\n\F4+Ku*:GJ9] z75:Bo+5,M,r}Y*+&K=1۰ Tm+ծ:5J" `gHwv.FpcgKa)uTFgWL7` ZVLː.OΗ(ٛ>wjoR/э0BE+EN L)Uq:Y3T)x=|zd>0Ƿ?T,/34wh`sڧƍJ\A"^uaŸ:S=MR"$B"/\o=&>`(a7-q%MIKtR"< PSU6Y:fg0~Ft1]I~"{m1''od4 s=@߉4SýyN\{JΜi^I ULӦaz[)(jл2{Xrw!*X-Z?'2ڧOt%J=0C\H_[CKJX1nTShI5HaR*\/h"&gSȥp&KfO#˛SHA#)]X S;rvz^vQ8_k)C=SG")4wo[&3! w0+xK(."OwuyjR9TY`_CVx_]PYߗA)I^֯I%vƘ&W;$nFWC?bXMģ<$t߼~6iyxp H2Lh;c)T[Llz<\7JពVLOJ73arF=FsGD3mS1<4afPu-%M`]B!NlD<=DL3oSQ6C3B~Zd>ȒL 8sа xR&TwHÂ"ca~@ ; Cݡ 陔 ʼnI$)UiZ6VF-G:ЕLk{d?yu)T$tXS`[F 'vncQmPd1Uy{V|FLJ3}NKX=Rv~0Db.yM4I1!JQt2uD3MuBAm\OH$abjdd4Kf?5 p3D&FEO64Y|/H=-2#N/\} ?t&K mfFܣ~裡@Oc Fn_=~L!$I틌\l{?ԃ<{1{ǫd71›@ezӲ3VUe_UeGrݵ{XuDkRQ6WT5AFt#D2#UUT0WO:|`n/Ȧ&"#}yC/][6"n_Uo)(yɫ qz("RYEs@yd:]h 82>(\DOgk 薞ju#^]_KZAhNJ .ȊQ9U ɊzPg)๺mGޅL"gJ,W^`b`cdj7O6yq Kv0ٷ^6 }L q<R+cC'|7yɏ_+Pʱؠi{*6O+ciڧ浩LUc1& `PILp APO'1bbzF@)#ءdaeSx|C9*\"TDi^@a kqraVhVzyxӔVlHi{$Z"*c6]/j($X^Q-Տ&8g8E:2ғvGѡG)9 M< 0+|Zt=5׷u([Y紗C^:A:9EÒr8jZ,Q[nu5;dx Kq8gtɜ0VDdS~>0* uYy!ՐwľrIO?nw0%Ng/J|Di7h}@ %L`Ε8 hUk'6|3xgI&ʭ|9{Ma}F-jr22~V9qq"J;7ZF;H$DǓ#&p$At69Kɛ>XrXSW.!i∈"? !O=oMj ߷hkN +5U +eXlպ5B}oP(%B|fQřWEP 9<|%ب΋ԔM4q懎xoo9?K@@! 6BwB4!<*$Iߒn8[[ΥNv Ԗ>c.3:V [˷m1=2f,,"㋼f鉒rGd4lFq<3ǭa &fҙ2ꢸ2)/ާrtr=舞 ~NPIΤtbG5c9bWlgN+diW__H< *%#EIEL)A?NJ˴ߤ$|{0^u܁  1lccQZ"- 5HTf:(c(# ?eu878gbhԑa:?l{fV[gmjwʓ D nXHhBXm.\iyXV*.AmE3z9Ngɯ2ǿ2{ݏOqyt@F`5j;nV6oNu ŨurUShtfT)4(zJ"madˉJrN4[bjemUՈv!`ܕ7?C|~(] 4w-֥!5)J"2y8FV$q{3)!g)}g݊1PKۜjt~Um*bIC]Vΐ1 Ӎ3M5t,?*.H b:=_yV3Z,]w䤻h;v);_Qj[MFZ 58PtӊBAv\C+<yɶ P$Q5cްYW) dtm2tЂWBNʉK{tdj؛NՋlS֞BCow(s TLo\BH^/vVvGϓx F?p|R8;y P"'Ri ex)aUɗY(|!M+Sq餃`GhUB(bV6\p~zdmgZZWkѐܚ^v3]4^JqB!LS`]3dxBJWWV TD]ŝLOָn-|Vщ8bЋwTKR&bMUPzT!]-=EYQ4ql|2u0 c:"jˉJ"G5IU9C7B*̺USє%V]!#ȱQ cNaݲ#b -pA'%Ӓ6eH>t6:NG xjS~ŕ]5Y!Qj:Yٗ !@Fl1P3pYC&>ٿ L?z''xmAEl Lb}n\>+`$A'* Z5Nqx-v ԻE#u"s'SwT"uSf5>Yu*8۫YKnZR%\͟q`AE||'fd=CCjm7N^6w+4{^>J_8=h\/<2h]gu`h 5eUy'O$cGD^<~A ơ󵄶#ٞav'e#6:p9/i~E9V9q[8,d";GuǣXn yu2]ZsZa̙ؓl*+IńNŵDrλb~L[lR -e-UjjTQV5j̯&=2#Dw0WlpAqXB4>l xѠ׎zIj OI.uyM%ЫFfR?4|Sqz9wa֮QlmiÄy'YRUb,rf7A)y#k):l  q*(ۡnWzӀ@}|gpĈ5jEz, +h`fj% 6o|@OG &scz?+Gr'HVEDX#dw y'8r]Tx?n `nWOeҞj\Ρ.>P zG6hӀvd7I#?-LGp.CHaOKg`fTFJcm):S5J#8M>mk/ͥn"-QqB Qsdʷ[R[9>Bmj́ z-v'ax!g?R %/,rDg69V[vz}Tޗ>z5yb麹-jpwX8pY*wbUs_ɖ#05V07EΟҹ 3=ʊjܾ3n<ꪇ0T!-4CL{3ۍI\PAalS蒎w4 ri:ig)rX>BK,<^j=/b;Gޘ8𱣤> As{9 +b̦S: 'c$WF$7 Eԡs6#$j;BK;5Y$0 ohb Ni!ְE6Ty64;hmAMRq%N31ӵ|eogx*6o:  G 1F0qL ֑m3R0хR{-4diiy?^Etu[K`陛!G])9je_v -dnqbMpCwІZ4Оqw&kF}?w*t*vGmEx~⸩ j=< 2iZO$ET,[Y\* GoYQԫMf_~6C,ʞ LQniKTGr̭k[ .w$Ɣѿvyj*Dh a{K*;R})-xMVξbs%c%(iNz▅m|3 !.SuWfo6+ؑa1"i3nƯds O*m~gkuqnKt MeIvvNX&iTfmG;?in3b`DBGx kxqD^3C^rNH=K'ti֚vniAOqQ욵Ÿ~ efn[.!gStߓAp} 2L ?3d4yyMi1OrϨ:"s+s._dVP *ێWi`Ir^k-'gYѬ&0v*-qziLҤĖ|69X'ݶ~,{?(>iJҥ&Te4HRU, T`CScLb1VQrE.fׇ-a SI|>*3MH~3"z<7%]v/ +:!7o>s};S˴ eD]@T`|;[zf/,'7Pe̘tpʴ Ր5zmL; OՒFr6Y@hdwj>Εn0:0T wHqAkbz`C1(}9(a ȈM9]{QN6؝Sp3YK9AxvIq3sx@noh E-1"a ?CcwR!K6GPk=Vϋ\k(OҮrM.׃#vRek:K'Q8lpbRlЫ(8=cE;Jd%b)LPO)"HYlO`v>(q:3|iQ^ћy`5o@8Ύ<&fslϒ^P"s5 a/"dj5P5:XtMtd쬐/\nh/ΒNJÑ_kܱ`u_Ǚ8lC!g Ό"cRR3pnň,L-ʐ[p(ŚEW8 ?-5v 8Lx -"9yz*~d}%V#'0DnDgv hS.j@^2;3FҞʅo8_h%:zGN} 8z\UW{/ϿqC|MLab )'q;/{>ͣSl t-jȢM ;NE@.Œǭp!]_6ʈGNdc*Ak2LŠ.L(hsV#K}qyԍM̫nb'<J"^='1 +{F|6?Ƀ5*N3v%`񣓚/\t kV_=? 9 nz@3“"~׍y з@Anz~ aX<ɘ.(!*V]Uo#/8%5 DOрF!Ȑf#%Yƀ4u70_3t⤒T-g3L lΊ}RpvA4):*(i0yRAY^.Rqf\",VgBr,; 0AVcVG˶Di K􈬦Ô2gH7HNtdW%dNtţ5bL^΃y|_r$ph,d {>4)N~6Z7gQ9a p \H}q<$lw}M8_rOW+#o3ʴ ]c]]$>e\=\R`'?Ubվi-.Y^O.t9^Z\ñ_ F_?u{d%]ᥫ>3y S6v'E}@;Pz'ܔ#O#O es8:!izc,!VmF^{b@'ōj-/;;Ncf{Eekī&G`шz$[$lQpxϱZ(Dѓ[q'Ƞ 70'N]T*v$s!Q= { qi8qk `gX=j<sm.9Fmǃ[Rekr&K'0 ZÄhQ}yk1>R ZqlipÎ%5 3<#F86r31+%*gܮvG TrE)1UQ!Dm%%emV5|~u9[8Q@<:Vgc"J-~UȻ.!qKLУKsBk+6y?}fvgdfXP/G8?8 5iVo%CK@=.Uo.nfх3t<{y+]2T;LN) L;:R򦪪>ept<%Ŗ͞L[V 5[:9M0jkkAbIP8XGA]}u\ ,:B!-dJmtN(BOSɩQM:msePA c*59( BC& Sg 4@98cMd9{w$\$9O Jޕӡ Rf1DL/Rsg@ШYXp,,!rR&G[* 8#{ɆzPX!< Ȓwu4Ut{aMI'goQ?sV̥9":6K{;D bSB0=E9d9⤤%%F#ŷhL~lbP yrj6?u‹`Y1q6bV=26ó`N63py(aba]!׸]yAw+\*Kf?a z Jh ;L;hg,/0ΡN4K( b/@k0Sj6HFX(HgZ2P% ӮdN"㬠 t$ގ* $Z?b # K&4#=rIEr!ۑ4 OB#\32v蜆sqk@ʞjf涀5R8="]w:fbKM\6F@!TJRl^|{$j -v{9S(ɩE4 7\Hn vf}dd߸α-pZ9שosCщL*4V:wu1Qu1m(Hkس A*P#*'M$P}]?u2i,'E2a5~GX 2dg8fmGAAbVl8` ?t]c0yE1ai ZjͶAAu-::BeZmR\:ڧr|zq#"ݫ߈HkB،-[wvbOH+valA u5,Ƅsb Ӌ8@ޒ_LyR-i=JoFOBӋAci}M12&Y,ڭ'QQZ3eIץ&q8d19ְCtU Wa򮓸70ug<%NgA5_/kMbD|dzcգq܏%z=ztnk;yU*BR3V}V}槏b:~Zݸb٭NGTEΌ`%iu~K%vJ 7R޷):RkV@)%)!vGgPg5&c~Nt{[(35KxO~{, Pzx wETXm:00:>,Y+m, }H5K fRNCG= dl9-kLŌaeC8ONx)h:+}9nt]fQ 0( ֒_hkȉ 9Ь90<0VH'h.(} /gar 3xj1h۹!~z`{oLH>t)D}k*gSi]6Ǜ =PUiшpy5 J>"od F-τpgkCE93#7ev wgh)%b?V_^xվu;58wJ$t;q.#zʦО/h2Fw:'N5:w$)7M=-eCOg*iBȝD5D/ހ,6!zvzVVG>@+ rTa'![%13Fl~Y|)1>++5bx W4"݂%0w%myUo̘E,;Aw-%1X,w_9mޞxQrl}M#1tc|*+%坒Ks_w-b^Lһ8;8 aA9)FAe9ph6[XQUd[,^yA#[,3\c i}!̓>Y" tSÆ_Zr-Qp:<5C!\~>RWGa{5HyQ[1Ce' a|!:O}y6!< +Lx*Hδ55d 4-!8]!mhPJ9P'7&=vfRŖvX64#Jo:OEc4(^;5&Jk{-^5ɓdoit)kb^-Yٰ})-0n9og 9,OO"m7``˜қ\l|zo={$`]a^0<L}BKRI`{S^DA8!<;krWrKw[/L{?:Єw%60!9d &sO܃5CwTgrSm0N64^4DJkl)x>5YF{bMs{~ꇕbIR4΂]\4'_s&N)}җhW$;@pEڕoa25;}bЩuY@w)+f$fah0l oK~9O~.O }%a>Ɖ}b;@Tԍ_b9Tc|<6`zgJ#3Tвy&.@u- gcW"0z$78$艓tEg\9zؕw3AӒ $e Ytm-<'Pp,xVbZټYO,t:p):Y$)J?G^E:I)Sμy ] m Rr: PyQOW !,,XNj^;[lݕ&%-1ךDWj]ZeW2qpm~8#x]m-U]dRѽh)z@Zg%/&YLH(Q~r8SU{SX/oyg,1z[Uq\y c2捅uԛ0MezYV0#.1 F!$(GNҐ">=ߗ1HwZ)w5; d*O,gy0~Au2_p2#5+t5"ewg<<Ŕd }[ ',zA)V &-:Ýg9/'d݅*\&>:v,\HZ\L!rc^Puǖ`9f1aŶ$ R+![K6{ǾK/Fށ$%vfoq^DD'G9h_$of }_u_ty)tMcNn{Nܣ@#rSheo5"c frc), hQWb ڌ@5&H?)RXmڗ szP ˡx ,cN@f`fSSmEZjV;q45xLw4{KY-aX uhHr˘4V)I9=-yRp@ M?nB/ӲrT"QB@pxrg*Cw=b)5/ϸa3CƥrOR%W'G/JE2eCploϠPr>D(C>HN^V̪VHrZ+|lM.NXb#j}o-އd^,f\m]3om߃o}¬žWm'ް&%ݩا |~*9~v2 癑,bє "HhfPxo eS|Dw[gw ዕJ(T ȱ|/ >yB UZBP~ڊ;,UG6+}`*UY\HNp6v$0|Ƹ6;Tz{ˋd'Y!1Ѿ)gT0WNSj4#}19EAEn.=#)8һh]+~\?'t2l8vG1,)0h"س١͟Ƿ2-1O;8a>9KBx4,ҪQ(">؃9 |ieK?C.'F /x[Kz:Xj{=!E+;O9 |i*ExUbe^_%C弯K1h$|0_]|2O?AwA@|Y/׈]R`d(M hhRM=i#ST-Q iZDIc X)-)Jł;=Y2UL$ U% .⹞!1643DJBŏI/fpAv%`$L2IWy^v341O\2' q>nG! OX4PaX\ggDh ]%S.z y\=זI!B4y$i)m5n Nz^g@DBhǏsSʁ#q~ Q*]ymSQc"='&3; ;c4c$M$}Nd9hs}QLhe+PdwN]ǗP j) YaP?s.T|]N웗b";*7P;)|!/ Imrs&vsns2f^6p`U TLrHlݝRbR -ғf' `k=QTx9itBRǛ ԥ*Xh@ת,kgńN#&ߤMĽƭSR8ˬP2 =iVƤw[H/M{}bmB:N(=_C\_d3s7Y "Lsfi y@Tv$`&Ϧ1LW񑢣TO.B|pզp8æq͝#LH4KWNԌz1"7 hX5u}>!5P1B9:'O GXLtBuG)".veqCرEf!@@5&Y3}3T,<1wHi?pR*fI Z T[6Q2p I2|qyj_WȽ3{ȍtl }{Qʚ͔_׺7>))LvO QBǿ2WBcw˗w91x.QA8 v>}PZڢt ,۴ܞ΁ʫG&z`Yx,{5#Owчg׺-K2#u?`x^;Un V[#=$@,?AzHX>xm`9e R~FVXPTF=2]sݹJP)+G)ܬ@j͵絪"gQw"qW(jޖFYyn(<' v&RFiԋ0jc+}}hw:]o7$z##7經vY!S׾fIBtk^#uJ.xۙ^j alMTQ7HYFX%ES^o{S=rS}2X/slUWj?<=l/|). *f!'emQ2#A)}|ey-_q jpUFu N T>ײ{9(q|ve'4XF[a-뎮 %_j"5B^D.GesA={˶r(̧;?e̟8 BA0Ā#&OzKOY`N T퐗o+}Q磌.>4$UE FDst$Pa/w""7[Y.ӚAW֭/AgV m_8LuXhj?wbxu؞&sJ% Zlf5W# uNXRb>O[KbC`E.jIlN|P-΍i=ӣ/V"l!1}BvSVto}./N%☡ȉ2篻K{a9}]+бKrtQb'Gaңr`Ul︩8wBc1i"],]܀A-tiBw&cgAKG+SiҲ@}~}U¼3Oz<<֙E $(kGN ,(gAI?%VmzZFnf gѰX9ZV32-& =Y)?o'ZN~~nOK\U*7X >Wrt:/|-OS"JtU[OA *g2 9iKfwL_c%fDFGRQK7Нrm̔ĞS A--(CMPCS9*> PFSMTB3"M3wg]3ϭ-Ԙ=1~S ҌycAֵMTs5+gFg=|LFaA"&+j#JQFMg|x:U" D\haݖIU |R[D'N `HhC[pkCK`La3Xݺ'2cuy%1Zޮ,PC4ٓTE g>1~M tq^;gvڽ䥣Xxn@щ}]~&o6xxoCQg.po8FoJr|T&ekQ.t~PrLZɡN~3pvSG1KCyEi '6 ycKյ9[ȏD_-ij KJ0)ko2K)]_0 3|XZuo5!{:PFBTUT@^A %2=cTQ.8]e0AK^zX򩫢_Ze'x@I[t%(wVS<ۄTnroiƩ$~ ]%̈́nz/R2276TU󃡲fBC̴d.IUxb~MlY%#vd] &2RqTU,-- #wrf]v5~D˾8>BIݟuspnPQMU2\rbz'Z, ǞD.Zݩp\wF}~eK_h0R_<']!gM_Tgv4$I|7G?8Џ)*?/=?3?~KW=7yfI? K-EZ.{0D)a;i 9 ^zB7y_q~-~9q)㴚)m/Pp:YH\,LWlMr#{7*^d3 59t]Դ3SkRf  #ywHs:9 PYfXu*<Ù՚bqwp)h @yN5#Zm'?`hRc{,7p*+2Wˎ |Ek_I*qEP?͏ABVC\ E?#,ܟW?gz) x@yz@,,]^x* XAf(U,5d7mVγȽf}D]$6޻>1:/:Nytݚ(?;Y|L|[?x{[<='=>RFQ$ Oj; 9o.1/f6Ep0A0OI H63/1n>v93W,\Dz,^{{{O4Bѣ(P5nj(xE]A=9XuRjل}LIģ!,c^]Cs>7+Ǒ3{w/I1rvMP)=q-xuiX.?GK2ScᏯ8g&}%>U]p8tM/Fs'mie371p`VZ?eB:Tkkة`ǩ!OJ7y1/LH|]Xc-:3u¥іXnbļ'1֥[b& y (s#΋evZ?F?- TBxdC^&"0k-Z yVԪ42[ NO] E NEe䥾 %!Ϝ0BP+7̩fpm(/xh]oE/##YmMЎR+:u`7n}  Eͅ|i Ibs .}=!f>/m y6/}d=VW;zSI'{Foe=3Mw\U<<4s;PBbZ*@#OxAFMl "*-06]rVW Lk@+3NAdz䈃hh=vn3*.Ȇ*E:5O̞rG`]ՆvD z5|z"ytJ =:ä[c\` Ŝ{)rK}B7̍2̚١PE4혖!v洧 ^F (tJH#jwULN{޲P>r^, xBnՑu cmE0 ry_J`#*>&H75MAZs3D&tgqLbBU^XԚp X;/nA'=Xi_'7՟yOe{MոJ]ba 11.dItD,Qso+T‡џ^y@?1ji`@a&cJA 3v)n PTu3,X ߷n:E䪃6ͽjO,Q &HGʈ< i L+Z81'D۞04%?4Nz;|Rf Zл ^+t{eUӕN5vQ m(/ )54-wSi,W}6hdSM9hd ]?((MBSZRXlyb(_"ydK `(R8ߢeD>+IVW%;g㨴PF8?f ƈ2sOŰ:drZlt$e~>|3:EtI}o??doZJփ2:IJβ2nAXK͇'g{9)3%70={w}n{Z*us& Op'XC1ι`|<aMPF#63twhkӂD5=2 zyTdc(` G L-: > &7*N!&^һA zVTkg Sgta䛖;{r(R8&*J!tzзfV:_GáCsL݀21[l1yD /矑JTѓuܱԂ8AF|0y/ѼHWZUW,wIݯi*فE*#(AM r V~2.GvQd'xjx<-9=Y0S-^&=ufevaQuB@nN@[ʝ3m׈YʏQrcRPљ Zr&Czeiw_DeNXia(SsӡmpjeYh͙/C:R,`a|wPe0DzGSs{ L+ç~U\udHmO ۱2٫xr- o,HשK9Xζԣl!lbwec(weM-z9FTAլI̥H?۱g'Opi`dԢcyW&aQ480O{qhls`~z:<)윘R<0Y {AΫ_`Пe({PUM'HJ3*jo *o7k?k]K[>6H/;U_7mgMz7V ntzLO!xq(2'RULJ>EAo8$!m,bTD=x֣ hG X Qs)O4.{V?̾ia< O#qjSddNZJMBH Ԏ O,yUΐk*(4OMafeub ?aJrRX IhV1vҋfNX/Ud74s\x˿sA8t(X[R4yRWVǔ' T-ED[ ¯^oGQ x~>;6wr+qӾΧ0Ǘv\?.ɥ]' LփZwXwP6׾Nu7_ٔlSo7x \Ot0QAx27%D*bԺL3~"jvKIS"\5100ˌn F4aRBh{qݘz3ݤ>w:.MG:}\;`&<ܚ-:@.HBvMRl9Dgn@M!=.'MOך]sU[@QʿSydDTŗh2[^ޱ4fK#s(Qff% QF czI~1R<iEk2Q/1lj6Ha4Ks]RH 3(j=yGeNs;6mwr J \Rk5=W,xgc2dM/-oW [<~.G)3CT/G_ؕ{H\ CgurG;>OOH+XY-D:-B8=mnڮ3c;ZV{ezus?5cך|Nz4W vOy^T1m}LFU>&*zqc#fvgy,6RMK6T7,%tmϞ;qu5KKbεXYeૣe/AM iJv}^&Dhq9kK4[GBRMTdzTpW5ʿMK2_]]ƲW"b95ѲsF_?Fjڗ0o-,i?ǍGefOg }EzRsY2n : T)VlKV.fO z`Bគ E.<T9ֵʙKE.ڇb,){iX _^Y1Sy1\0*ǣ\!?] "Fj,wVpBas w>=HޒQxRti4^ՈT:5ӊg0.[ h=b]v JcoJqNU囓ӧ65.e@v oƭׇ뒰AFc \LWj~! Y?tty!H#))!zҫqӰL:S82{Uwņ`9/x姎_ϯ"祫O}#E/c j8n0䡔\^Ym\o9]NN|wsQ'uFS_γ0^+]' bl$|NDӡh:]8 z#dcz#`Ti{8=  ŲUb1]%(QJ{aʙ#q! sF\`:'J!gKIh4r`pR Fu~綒NX3D*|hw)R9זV$\3!^Jߨ8  RriJlZxms(#8Fn>lVkjBknN!.K Dm,bm|_I`H=!u)j?17Ep onQzET^f_ZY<씘bУXXWN5SD]\-CN"? Fߤǯ~wswvY~|&F Uܝ5f֝oZXkRQýl2;o/Uo5f) 7 ;˰Օ^_^ʸ\;Ȓ_Dj 䶊K]rz*+f! vΒI*/)pgb6 APYBx8O"G1{nm'{,GsAA7Nuq'PB~cǚ [6iO-F׀ ρ iㇵ0#;?"Jc-{{b#:T̶ux|^ (v\C誵c;z6K9L6ul}̕K"s-37θ{H.IjJyfg-O , ZRZƴ 4ۋ!5De)JbuSQBy r6ehF6q{Y7`408@Lf+PX'g䧏fl[ 3y9j0D0eH .8^4SOpPra۹|Ɗ :n=z'Kc:o]&1̈́6ѤUT_XsP 3&yB0NxHHэUZ}aB4y92U)="FR,V2b= ulBHH'7 ,ڎꚸkD>87̞٥yZ)%aIV5m| ͯK3wxDo%C9y xI!'>?.`ϸI2q.^y<5ŽuFAl?z|-O{Ϙ |!^s4ؙ#a~G[cf<;d\bvTҚ?3HԮLF/0[+qb"ud"IJ*{"K&N c0וg}bڣ3(Pb/ kkncJ SZ*Qsɶo5%8i$*#U inNM4i`f8xIpfV"/RkI䥥kvS#c 04fʎ콱G$U\@HF=hlōޑG%E;łu6ㄜK`)܂lij2J`i6@u) kԻňUV\( "7.P] X7f65<jRh;m<̄7UJt\$爩зDP5nm6}rӮjI8f e9#kP^)Ģ/Y/=&?{ja5AzT*c5+͏Ca9([sm?޸F>5]E5v7.Yy;&N.IK˿=R2pM'g)k1DQUU U;X94ӫ4IΧߞM4XQ raXMłեj^cҘ=/;bI21 #AmH9)&UqĢq5 x%55tӞYey?:hsGyu&<л]&w7&P07@S90$n9͘z?@1ڱ*F9^Q5kOW{_\] BV kBZftrܘ8_[۰aKkH=8;\o]l&/mC`o iۓ/!ǏGJEɢX!`q`V# l7jFK|j>,g蠺`jDKӛMjy?KP#H' z FXtu2~_b$xd(]Ax~%+;_PfSKT_&qzSvoB"G-b# aI7 qpp⁝us<'-eW8vmoA#ρ{|}cRRGIf2[zr.zy2"E-߃ފQ[T gxQ{7Чz_P\1+QXoD)=}^j;4yRqIS) ,ʳֽ)h07\ ͖xTK9_ P)+Ev4dا0&[t'F'U"_ nv*lG쪩VVYCOsw"R#v49 Q,B$XxRCN'IO]ϩJqNܥPllE-}ZR!wz7$rZqF@{]:+lo S4#DSWl]]dz S<Dq ھuKNjx(A2-@7kkni0Vy3qS1*cR ᏦV[84v'G'/fyc?Tjvdr1>oF˗A@F.2󾦨)!:V >펍v1LVW3E*2+%̀=':D18P1[YM™ 4Om#-aJbٿ!j6.e֓=r*kp*`3vhvP:(np4cMŎFs*y2nUC;|eX_ (9 4|z;u>y䙮oz^hO98_Kcivv/@iKOt~ $?(/ DOs"O=S3#&#"Eiׇ]H~B-Ł$CɐԦI,L w.$WX0+I\F4qlK᤽q~9'HP`[ѕD 'l>!(k$a^lvvL|%Ij[7j4TCTbUT}>w ׎o+$0͐u Hz. AjGsE$Nӡ(LPb&M%}v8I)F4W<= :oF^c!qvŤXp go 1QӰ)a'fCS g I>nc )?S0UFrjs[Gɟ{ͷ~<"n0Zh W 8?j99'M+tOu`աv,DbMXrmD6yeoG^ [u"le2EPyz0~s uh\Kq)F$ػBPҖiH_F_LYn<So#NaQH\ϸ: GXj&WU4Z`FUA/ߐZk3xN:1LXSdX+:[8>Kg(*LsU~kqеđϩ1s!S7yܲ+Qz$dd'osяߓKz/,ڣ~խznfk.UsVU1 hˮLJCbuqn۹$=zMe哅psc^Ʃ47 \/do~*_̯Mn~oGvF}#JRfIz=_~[Dv~BwGRxHC'12h.W33D&-<)]UYe, SPȸ Mdtvw< Io#;n4)OO~:ƚT]IJYVsy1,;7:5NaJF~^53HBiӚȢi=`6i/2N"e5?2BYAym.*&ɹS";IltBx>҈)]hiZGiRN;M>e+qً"ٯ]&,I?"q)3jf~ *=YQտ6o7uǫ+G[¾eiU$Rp#'>n }ů9tF17sdheV<+%ErlU-1S+krcW'`Gr6-c;lMTt$2ۡw< ЛB@XUZ9O Yd&9Sa1' B;ڈ݋|6ND*/ČqVNrޥU= > LؑrO'HA%J(-7fVq<=]Z+k]N)Y@"ꏩV`V+F{~c4F85w"‚0%뫷`䲅%[Q;㈼^\G@iT@8bjZ& 55[Qz9voKůKo ^ևϏ3Bgq5+GX/ܳU%A\nÑ\YF#:991 ^BWq <+ !Ɉ-yM0v3$ 7e'jd[vo/!Иyo!7m 3s?~tO ~{/ډT}? u id\ve=j4\4NJ*Q ⌓EXċraj6009g&H3(p?bqv1P (,S_ov lT#݅pv| `A׮̪e%ƄhMefFϊ.v&ú+RGr\&W"ll-Av h)ehY_84 eb&lTŁGC~Zane}%xm<co^KNj]bX((6ڗq"Bbu (8MZ#^&F{$G^vxr:X/ݘ(SwK!u \9'Tr޽}.}2U|\=7,$u:燰fW-ocZ[V_>4J`!?|7uCsb}x1{ˆJէ׋d@tUh;ߓtxtn^PF wՎxqVAys?~$>7s6K&GGbG[vR9dk)EF8)/o^%^UȉpZ1˘n;rnd_bKਈbqy𯚙#a;hHSΆ=᳔xkTN&b[Z*򢔫UcLX4L̵)RN=K0t5UNCh4OERnN6fi R L+a>8qDx\(!}巸txr;]C=O-2+J3w/D/4y 5#rsMчp7TEtgc^=F*(}/מ(^TEWXb;:>3D 0M) &&>}:^cSE:x bS{1X /zs\X;hZ321.A0f j1F'YI^ݜ ;tN!zO_ʡjqGhdC`< V3GK%2%)cv dQ[? v&Ms !Q~KZ+j+MVC&Z@#޿})-ge2剚2   UŔsӷ-ʼ*~Ca!uoS_9gUPw_r d ouUe̶ fOb*yӈA/X`lFgIs2!,(撺;ͷE4^V@+i{o+fu?©Ix%2&zOOޟ߱GB}ޟ;Z0YS1b"xfu\}c,?lBCK3? f=e̮ hrm#N'Z5W\uS%+.Acˍ\S}$W6qx@ ^ E(I>2f s)S:gL*G+ۜE bVxb5IH`yF*f21ڒ[5*ᓦ mL*88]b`4.Vw|n5gלA5"* W]FL$ά)Qd$ܬC%q)#@hlx<=?y77?HIZc!ް<, 9wx20= aZM 'O;m)Rj4;~1#kLuѠ,} ˳=y1uz-Kb 6lܴY[.vw?)4ZMm?(uY@L"W} ͺ/+(^_auUv[xCq񴁯qڻ.S G2A3EBDrZ61p ,\IuNH8 J`w"("=HψKy<ֺ$cGLHVF5+,Nej1 BD!c-u V:@VM|C)c g HΒ ׮Q'QQ嚫J+ףH^{ĚI.ڞ4 {q:Ǐw>! `?pM,P#8WZ٪Bϧ+eڢwH,m"bb)mgtHWI>_N.tR?<@#\G PVU//{1Y2ht(/ȖPL j(/&yLbo _T-$ߝSKIՌnbڻץ>u2h|&Id?ؿW+6kO}\:|pș`@Ɓؑ>ƍn(g<rM!R]ӻ>K꣸pEbJwhpKbtp|C !NP%t ʀu ::ǾKe H[̏FŔh h }6^|N^ΎJYJrZ5'i R|D?P O|4[["kZ2plNEFb: #!ճ, } aDUfjźrº]QQ2;ǹ%UuwXl*A+q]_r,;T!c\GA+(Z H,F,cmqH0"^ȁVB@ZpƶpZړuKWczOkL~m QïEXo_}WBaPjxs9RkěwSO+ݐ2?>+&Ota5:hAm0&q4a -ՒS)=gR+G /5նાD'B >!h+ GO.WSE ,4qr`I /Pgl!alP"QD*o+`DԒ.Pg>aSЗ|Mp&/|S lZ>ꃕġ|rn'%N\b#us92D2v['xG(p$^g5mcFyǡ=zeKe=t#P3H7ur2`VnK $~IQ&DxGY7`1;\ 0R/GOf3 Sd!yaVYOe Ž\ Z*(1"9V | t$Nz+ܧ*og/,lnNAVHK䍚oO5 K_:_ZRsV(7^F5?GM~fc?w,?ӊ%ϐ~Rkل㪵mRStQ}3'5}b'g{jبwf6o.#%t]`UÒ_d't@]GM߭YƎq 8l)<2m)~7G dpSn!y)݊TepyƇEJF1&= !RZZ$)ñlQzQ"s#odA=X?+&#?k`D+,M*jiS S >sw4A^ZIpmD8\:X-Z%;F۴<ݩz2`=ZOf;1B$Y!* úL kY+//0C$N qbRP3hF$aOE$-rIXήn!u2['x6A/ïxr~b:|ͮ>s@`?kO^j(!-5 PQM++QJTFQ! 8~1"n\& 팊w6*+TCӞ Gײb08r $ڢ<_ (zbC?HR )4Uqz(<.EF.[Dl#]8ڈ>*6p Ku|OV*\RRб3`Y3ܛ9_`qq"]kzBA2#"2#_,ҍظj;z&EQvI".ڐ4#eoj F2965@,t`A۠\%)ޒ/GKt5=5}z ^+W.uQzaI/ɠXDT=*&A,-l 5%yuryXϾ.-r8Tդ]ꓛI AGEͳa!\LL4@$7&5zX!XGر_tKçW, _>8*S>"ْAHuG9d0U [ۛRAؙ73JOIfZJ5))I*Vwy]N-9M3.f":?Uzᄋ g8벯]zMK;f@.4FDA=+ EC܃^Pժ\lIDd2+[髐@sSKYLEhpi $@82- 2U >1}XS67\}p_3f^ɣTܛ"zp3K;*>ס >?tY>+MjfOVt/~j=7}ӿ}=(xKw>1T;Saz~H 4=S s)maa;K,IX<7a)uUI<‚ɧ7^n&@QYqH8ͤTM*Ȟa3Q6d"z~(ӟ)QUJTnf2Roc/Ι9Μjrj7,HiGcҶF A\@l3LU>1*ad_[N?-_Eb[R*˶RpROR/[THvnᮨi5g^`gMh7VW0Y{ SQsm9J^Yq &[O_)(}v>S7W q~[ȟMw~ZR {/8>_r ǟ\P3e+brIk=Z6 ğbSBfUUzw mP~1jQaLlSC4]7x9mle>0f*ˌ% 0L{*ekZ1oHi'KrET]1@edi/tL??}CeM$.8Xfҷ+"Df=}7@͝_KU>ŒjP$ @Π熎78y؅|cE,5̒vUY6IZI|qHDE(-IH{ϼrR0 @\10%kԼqQY(5łâ2nX5hzf=sƑ!19}(Pkoؿ &mqO^çS}|j4<(Ӕ 2;yyp ݀-pf8n|z{NTݴlgf𜺞'jȞm}+jEԤa:!\XMÏ|[H27G0"*fgj 3JjPtiΠ [)F&_F8Qޡ06lVڔ[JAS+pӁ\Q 2:֭^Bмr?c6qƾ bV':´`q$YL6_ )gtь? a0@yjdlZ%E[ \r uL~y x990 : .+UsҚ.rְnl9btx*5(;9BִclMM$A5&$0F$pS&(R%%4&]0Qm@h Vr,^hɃEj 7vi,2ʆu,zaL#2l8k'dΖ5{yַfJ^9FxȱH[p$`y/3G6/8%ť.q4ŴkT'##A"}/炁k+Cf7X8+9E=-3$KJmUܢ1]+Дpx$,.*"TK1d)0OT$^Ɋ]#C>osmYRQYu=̯oʅ}fi!OCa(-bSPΠI@f%Qn2.$on %Rsn8E$)ģrTy-LԜE%AH%# #Ln9"B@}m{(9IcMN[4`l15i}aiC Boh74&-$GXZoKtm63wݨ$'|0I V&/6 7nVZUK_fhȧ%l [,|PM%J0xc:Nd""Is+E@W;`}'&5Orh7:qqe㷤/M5OE|/0}/2P4΍ob㹪@au]ƮsS[nn9n`"SC3Tlm yȋ>`άV *Ѥ(x~8#{[x{h-B{!J #x]2a<[*k5Q&Ȯ<=-ji4ru ٜM=q@^o{;0)FL7 b9Y?ﲪAZs=ĂȌlq-p0XdJy^*w$& -WcvَK65_ hZ$?T\=4m=߻!ʓAV^vv7pvYQ%`26B%7ȠJR:65-6Ժ60f(X:uNҵNlf\PL)tzL3xuooxk+I7B q3tc|S6W>Pǟ %A&~o Vi>NŊ΅#_Tgz=/Q'1_)cXTvJ@3'wo:"SOuydvjs"\a5zuЗ1Ib;$l6VQƴ`zGŔ&"/s)5ij#Z!r>$/ `zST)dKR{yXK?qqwwG5ΎXhBS2!r Uc?tY4,D2F+pcK17jcЦN$ae]KWmۤ@aU.RЪ Z"ibCM `"5[ќlr`yn~ N9&ZD8 EnDu ~B$9Ŝ=p{8cuhʚnKoDۺ9Cm];y b󯬽-'Yq L,n$eg!; `v/ɺә|,x(K xvkN4R_n_-6@} :,.i={ X!ƺ2\MgB0%oGXEi ̲t6B\e&26YDl낐6.e<.ؿƳ'l:zS2U=C4y*K#|0ePiдɚ ;?ɤPǗ C-2+UZq[< Jmۓ2;sf)m6hEeyjtʝs#IK菈x~oGB RS;< ) q }DT|[>Pȗ,hRST7*d $K#R6O]q JZ$q̪0unI ;>LbjM{$9 uoYh.0q+ ) ;1N`tc̷=NmM c 6S'2^GخP6 "fG1C@v."}`rɪ3ѳɍh;@Y58O99OP,:W'`LQe;$M2^ r3YڽWػZ`Hˀt4d d\]S͢(ed ,΃2g#: ;mu՞])] $M#x,%@<^ꎩ])ަ'(p0mbrx7TtA=S X 0=JDy<ׇ8>~e;+Y}dZK}urm!)& '=5w۰uT119#,vYXQxNq"_]۶4Mn0q`f4eMX\aR9Uw]͂&Bw7b[Rٍn(sRA !JgRx2/VԮ//&+k4RgD"t ?)$"22ݮRӢ ^sX3ѡ|/H `PjF&dPr=d*X~AזH1XV߅!"'Q4-\b<~Yb?@2T`璡UhCg(z=uoGW?gP.fm㔬/첁44F0AǑ6e[ &z$1/ݎz]&H%8%@ JwvA *}]T$ waʿ1H\݈2F0{i+FgvtzRCM:o\YS(rOsڪjTV`5` J H2B$( ܨ`$w ܥm Ђ3iQ%]GX'w$ћRymP`T[@$>dZ1E}}%"rRJ]Bߢd#P*Q'֚aFasT--eC{CT́Rn!v`즽`:>}DN1t3 8~ǁXIkY45 Dzd. 3=USl'AL ڷf14rp~͇cM9j}%<qY㘐YaѺ2v[4 ÙO 2s& LblDb3"d,2f^ns,>6.713|0/=~X1pl0Pʀp 2pA$"hՎ}@(&hR‘]D0n}%c #ϓR# 5Mx:VՋ$e{s`;$g$kv =B)6l8ӱ3/fʌV6>7NN3Y/A v<: |cLp?c:DpH<2c$~ߦ sGh@(ڔ&1l+]BSa1'KӲ'N3Z3gEs >NLGB%܊u4y`:o(&AS15rUei-.hS%zCͮ L:>WFMVeH.40άVen p##f0az+fv!9md%XHѽYʞ/.X"l|B4ƿ*rD$AtlNHj|KarjmEyդMNX5>Ѵͱ԰H\FB&9M>g[I_fC%z"V{lIٱh0 js'թR3p1eվ~FڈW;`+!12h?Rt1l-P.l [D0Sb􆣙ylS EsmQۋǣ"~oӿc{Ԇo4A-,?(~рXGZkCRM&S*hvk ~4w*4_t8og`j=)qKtKybie3vmb AyX߄Smzg_ Ts5Vvk&ZN0Kt=,&㩩tQ `b;<6`G%J p#@6͠7%66Tխ$FBvfpqgS\!f,Y|]"j[Glǒj?+vF!m$Xb'\E.BT ,ziC!&WDv4HR,eR>v8"+u Qz:wu6E 5 Nm,,){eʩmJtL끏_(AEٙsR׼%`k0ٺ4q6J ];N(=ͺNE.>>bԢ{M] {rhLbgj`J"ĵ`#kBIhzc*m"j_+saVw?;6. MNB7'چr A? | B^[8I"s~ LQE:B-X:+v {٣|ҘRˌle%E˭V*V/2V2SQ5ysiva2 _4ctDw}44ģ1vz cf%`F#Huq}$'#2Oӻx3Rm#GO}uxm%9t!A}ESN e6D1@ C<߲ˏqLt'kF+ED^*ͦ\Ez:Zu =u SL`'DQ.l:; nD聡ANGqij:_7  A2w<xemӸdoQ"譈D.LMx}1Z?G;aCJj"35iU3sqG `n)pz4{4p#IF+ [Ky5/7vMF\ pe-%D*AuYmXiF i&nV"|f?#]LBF8Ylj,a(IyƘ7r^-mȦd /ELT=;JsniT5/^qܟ' ?iӍ^yml. hNhj #}OGLkNcD%k[BmfAj1`ٷ3c1Hp1V[/NZ=CKĜ'%$h:Go"'t{R#"]Zm7sv̓s<`;oUkocK^|< /zv/`E8~;^7*Ӡ8,^R͢D>PWj2Bb$&fr46)s3\brt=ơGU/FeYvV"kDݻ5sdv7F5X`Z; MI¸۔8Ph=sU̪I*A&?ɜS4=lg'*eB‘K%t kF X0F0Nh,xW @( +d"J Uv"ˏ>^_H@ +ȗ-I6RuRc/p'MLoϰ:vӢ_lqggK}+W$cKnLZɝ^`ɮhϰU/ 3k,a;,"aNf<hI@9~ =AԦ.adF<0,&vi(:BAy: a6Et+q$C<<Ʉrq@Q2vť8**XYabܟg! .#sEg% *x:AgРw<2b[l1[ MkA@ǯ؋pD͊egUˆ{u*<7'F?2-Wq iM#.:HQ.@w"B] l\ p)W<:A/dɪbpd" e"$Mkja3]0T9"xb/cbQN%P&Y[㈹4Bf=EH&M\S?ҩ }͟q .),jWZA,gx29m`a, AT/)Tv |j\vk&7  jH>Nr 1I((Ly15a7~=xl5#RϧuL?L:>ZYT^(9%z/pg?-pc!9+f\ .Rv pYR\jIV!wǸqB3k+"VJ7?Rx4ԫ±#0GGhҢ=6ƛifIֱnPٳږh6ebBЅb0Ԟ;'DƉ)— meZ [kcbzolN1M< WУ 64~/DRP^MQp81h<>+(9ďԖS&D~ɴ)L.fyv u'\D'?- `q!-`GX-4w*j(kF$ƫQ,l9͔32 i+;>$ywHrG2ܜ S PR* P}WSL+I˛I" B P(9XR\S;z#b;ݜ#K} d0o}@X;a߇%s1Fy w6x=~ߋNHsv:BnyEh;%*fE!wi%J -Ab trbѦp~u*@+߆.YOll"J_k &Z!O.s'lz*֮ i{s.qer/C5F[ݦblf@ ^ VYfӳ&:Ф[?]L+aM(\bx 4T.ޥMZ$dL=@ԬJ:[ت*^l!uC h0zy2bq[chɔ9M (t3;O6~7>tpn56l K|3:G!l" E VV"FӦk(R{Im|I aça+Cܥu`qӮg<@ܞ{7f<ÁvA>A=}T|leF6`7lLo߯_- pK(Ah)1he*s \xH}ZdztJ7X*H(N6}Ǔ:FFi7pK%減_J4,XW iDeA1ͲnC(~]WmPbSJ~4F^X 0?v&䪮mvtIV%n+iW6-͇H%cftcDX\u8*dl%D[Np tx_m'z3+ ТZ`wBD?^>YȦuS4tZq Z?[Q4vcTJ !d[{[wј8E֐a,OoM2+ C0iT>C'Sq&C0T9P8ic+; y|;F?_N*oeXI 16bzڱ"׫>5^j”8|*,rWi~u=!&:[*ziz`O{J~bnR=Dɠ9y´|tמG PO1xJpZY ;i*)q{dzBpP*] ,%e:Fn:~X|Ҽ3tHXCFmBfw Sގ,\,Y/? I[+HrȺ1"a0 .z}MoMX jm\c[d3$d317p/-ڶ\˦DU7zZ!ZPn ثR2h7$ǁقP1RׄyZ+24jofqb*zWf{h&LXDֺi_$$Ycr[D2E m&gNtP~|m-$r9Xlvjɳ8D==*sC 37@ou=>?O'. oGj4+_ݗq;*5]aq;>qyPs'v!e!# {oV31D}K4r&jyY{6Ĩ "EpUG򋅝1ob 9+KcSjJ!l}찱1H4f*f"/!\2wwtb;nIJS2u]7ai2)D `/Xrխ9DY uړrL`v]jǕ1UL *܎iK3"OUx5`U-|VgGԱwQ?t A3Ɣt$H趶:}/EnR0 e<([Cc>Y٤<͆)YA5S9HE#̛B0\e׷eZcsԏpOud[]vO䓬/0x8ݻ+&
    c;,vZI&Yw0hKwOvkxj2{{ Ӫ&fڦ7:$gx"9ۖDސ\LƊM<9tNQw"Tsl x*^;ёʢ$w%Bt%HppiFa \zwlK84²* הLnR2έelJEB%m2 @B7!aZh _6, 8̼2&mR^hKH aΓ~I`f}1f롘+|{|΂H 5R\' wVWyKcrKwz9V1lw (oQfVl])-nfRA˜"τ}$M@Bp)-x ;L!a BԷ[+xp`B cgITz5-ˮ;@usl?7.pXĻ'McMiJSc_k -2L '9PK;7Ïmpt ᆪ=oW9o`km<>=vK\U_thhٕ$IՇ[Ƹ4w9 ܩٸ-q"d8N)< ͺex.C|LU%ټEqja"e1`c28[Tw7d2Cf: H_DT@.RJ(0j5:"Mf-LfBgEUAS^>c|$clpKo#VСc'N#[g-ө8oQy$X.BJH$3:L` 9)8ްϧ*Ftn KBIjo!oᮆVC[x-7դW3F,NNk C>]n225_q9aLJ&&$19i<%9eX2|+qN+DJ ƂEt&H=CfB&N00 uB!ʤ6N47O'筭`l+l6TyG[?nh*h#)r؆ms>V؟tr ̀nd1-9vJ# !ݵM26cǩi7thD0\{4s;D :.1gH s5ȑO]"{=MWp̛QܞV,ofw}%XˈрG(+\D`21I"0(<8! "gt*U&]r[iO*Loǔw[P[+]:\~( BձIB|f͐pH]3bcsD&0_)DԮ̵w g z*TkB%'w-I(@;f 21p+^rx>{ځ<i::,+iT=H5qy! N\Ur˜`)f; 76qu ]Hj]X̏i?@`TL$(ڊHP,G[ѣkN|x6EiMVb؆]DZ(UW_aكv;I.n 7dd`dgs"o71&05ho joΙ5/doO O|qbC;TS7.u͝m6dϩD`ct_"Կ>ܮC-:oنP77uf[[%= JtMb4J ZH%z^u.wΥ`!G dn@qRXVb3B.-"bx҉^1TR7V̜ !.N+q"Nvf ~9JE ,cL:e/ $f=VQHօ0` W餸 n\3T ncjŴgS8w~0T 2QձZ G!-/L*sV !jUz3薤˸;(u'9F~*ʐ4"-Cs(Xd!_7۰ƘQq#`umx( 0Hz4IHǯ?!89L}I7M,KAƁPF9pPs ߍ_` lȶeɉA-=c/sUk74{܍+RUTsMLt} /"{6Ѐ" sL!KͿtϏ⊄HpζoT ˓>*EQ5p ;>8fY$69&6c!+z#n ]F:׊̀zV`˫]gEw@mM~,.bN!MvP`dI'OݒqChu E=`J & x?ZAAsx {cOQ(dW \[@ÖKr<37G@hA`-#}MeLi o., !(nzN[fIw*RWoC16f6Y# *Pi"Z5 V{3zB Ȣzd@W0g|@%n$N,椺b*T67j2%S3}}bF|ρ>2/%/āR#50T#%VSA'Ob{QtuUS2Iu\I)|#uIJ]=3ۣ #Y]7 < QEڣ4%wFq?5e-<+F@/ ŚjPƑy?OalfF M9E}= #bL*y 8n7%'i,|RŐ gTsVjₔ]^S 8!+#X̀SM !n8`OLR'%ϰ_uM`ny9u:me<݅#(H/̇;F_TCF2U 2'mI2@f FIqfo )+]rW[ k$#{=.L< }d8Sx%}CDKkl=˃lfgŅP\+C KvLC_u.s iQ 37n4(6dhA{ jcpQy~8fP'7L 5`t!+{14}#h5RB4#Dd[Jd-~U Zx)X091M;;7jb :axU؎[`Cawz N"ʤk)-'vX-}*I:]6s1bVjfc1 ysx BJ~+AU v~0;^l!<666G?D`$`&i /`}b4P1:{PF0IoX1p`!a|4prUlt:/Y6RĄqq4RrN{Fi{<*cf,( rɅl]4=b-We20( Qt=)`IT`Yw7LdvCHt#4X2+a޿%zE~RQ=GD!V&KehQ>H߮(c~C(#[AsbpMkr&iQ6 ¨>$QʟYDpW+,cQ-bFr~ 7U$^U&b3 |CQJτ,E%F[p26č^A4 Mzl +CX_Gx{zIښX,LdH [32y3eL  y,n%=U5XLNt`[gMdӂ 5U5Aqtqcf"O9Ye3֞xu 1+/PֳcsvS-S~1EH$G? -ax^i%2B>[ "vQmz$2b@ZP(g~2)@x1P"eX0Qd7RGKqbi-UF/}ײs:̿ȯ^p.ssG4yM[쒪9˳ ښ_#GRݸU[xF,ZRZ6%@lāvU.fHҍ4E@RJT: e`sdFͣù99)ݵџi1 5!ɼ{nP DFS'AМǒC PZ%#Ҝ6si  al5Vx^~_j*.PY]^-w@o Bv#Fk\;*IC) 71&:Bу O(!spB%ӯ UDDmD9y֚9/eǁH@d8bw ~ q4&(o_=#ІqໃxA]C߿;_ƫ+׼R|L -U ,1FW}WGpsiiDwe)Fܒ@:F2+C->],߰LGɈ 544ã v ۭ#knXU#'%`{YońRw?Múf70ץ,&#ǢKֆASmw`v(&d-V\QI".91(P9Y3ɣ1XU'K&10^[!ZBej=] ci4\xt(I5sa:X, .c C $D˭ ]F(n˶r~ҦhAjd j?m Vc ]"?^V4IKBy$=\ȧs<~k0ie#:/K7y9sl;y-vx@?]CqqBO>zzli:P-gR2Hfj2 D5U]@p+͉w.ɘ`q{Qʚ1F8f{0=8 (w!ƭ5Sms0Bk(BLظzֈ$iB맦\!rH# p tZ!Hx>[cQ=F@`$ЙB@EZMVv!. aR**[L24)b3HǷش`2((| T)XwG o ɳ K+32ۛI}SZ4M\bGB[Ei,m"-6# Kʺo]l ֲ7|P4; XqG6ρ8vu%j= ZVsMs:`MN)0f1X-+"+@0xG]85r)Q;aby5gU3X9<"uE __ͩ.a1CEtӠ/7BMZtzCv]hٳ|\BC>k7Xa|hzUk$ +A|0^ 6,͔J2-ҋ021s<$K9DZ AӢZK~TW!)j.9MrKiy(d7F/mhJ*ˠl*)Y.*PMCI0od: [r7 Xgy9.uLM#vf$U4hnm;F[/onPJrNGC ŜEஏm;7#^.ӟRݎh ^ӌŵrPw;o6ID @|OYE7jmn8\/ F!puӔgTSM ]60RWoN(z;֬ŔL5HN>BXiǂih{W79{GݹLK=NSow~` ]$$<)bR,E ^6>[n;x+](9g +A@$ZPrZ0 RQ?A%~t7 P}De/)D"΅mJ>S6Ad/$\J34v$ g0TQmԕc`x0EtbQ $AHZ`5(e4"䠆669H-թDaS?_6ЄfwM$d# PԜˮ;ĂJLu6 j٥aBqڻ IGs<߷ܢFVp +͈'-XfRb5ʿ-hrk.؛7Q}T]:Ί;/\uaREUPffstb#QNN,wfî-ƭKissWKH70KO)]lt6nH'uY:mfX4 kH+ѼS\SZr{:3!B @PŒM C(MyJ߹M'dзk>Gͯ^f^lm k.);B#`IqZL }|i yl[d+H9+VZq%M o;%a< U,BmATu=,A1RT4iA;eĒA%Ip_;Ucg8ssGs} n5>Hl!`~8{0ְ:lx1Gl =rc>^<'<󖋙$^M? w߶KG;r5$ dкk4{v@hEyk<,.ȌCӺLj{ڃ&DtXYG;WkY+FK`Hy%nЛz],s" y9P_R᧏cN=0] q',ƒf7 ^aieJWx' xgh6+h.gZ7su@e`Gt2,-F)+-+eSXv\4vp jS(*5hF4ODD2׎FD%zV+zԛ@4睦9.\;fEkl, bl \xLreo/%@,!.QTiwdXǘKWfYtכ\Lw3s #y׹>\[,f H-)p#&5PΤ69>Ҝw{AXE%}6{A`%}Za7QʤNCr)|k63M/ w-!Akb,tC0!.소#)̔FxHҟKН;U%ëFJ`\[t1d:X)#@QᇍKoC:J@Jᶃ g߼0W걻3bd&_ʉ>Ƀ_unȑ,7C`W)؏IpLDe:L;@N$4-6tgvlv. yv:sZ$C!`ԝgzU +ui <Ԙgl&k\b -p ctKNc!` t8{IN3"Zp569I<&eh'APq|Y?!cJ3MQirӀsƗQF(M]Vo}Xo穰xQ4^:6άEmlՌGYmSZ(5ATalO%I"L1T)é`-VœG Cv(Mii߰$`RM mɹυA&96EVЅ 6gl&zWּuv}jI=Xk4 X(٧JM-dR眚'^nm:Br3-;%юHz=dƝxG~c_qC;/#:YhRwO x,>T_"|b*$p\3*P͈u9$ ``8Sr (&_ު]0VHeܴYp͖);3Fʵh7+W_@ R@$HD%2 U3aKi!OpC"Ll d hj 92V y|MBm0/"٦d U6̨sdomma>Ei<'I+.7SqOCNcF:Ѭ\N<8j]URZ`lOɶ³f٠dluXCV2Np$ݜH4 !H!F\OݮZ>[a!_rohhD"Wa(([uӣ&h+jU@A+;" ludr3H QD>)쁈dqe,xZjpϘP91Qu_ZyR",3; 8u D. 7YډCŀGjaӻJ{x{k2.]c1 =,)豾}t)ჽ XND?NXW HsɑWAfX.rQ\c{a+v#Is'ME7h LHGHz)Ry"/TM,蔢 "le0ݣv#{+~n`%?^zBTun]N$kg8IxϡXs *DލBYShi8jo.H#Aˉ}A"E$2C2&&5TU޶~,c0e 4TVIL&֝7틬5CaO0hqdt*xap3eU]?&]ӡx3M(B*_X'>-Sm >`ZaDL[O+~dh[HCUT o\;F;hHɘvq0Ώ-= 9 K6"{ 644Alj"?H;c[xX#$$xjg")/'L)R+=95>lEOz|jo{lW~e4FW72MjU0U%Q؃>#XT'}NԗjM8+p 蘰nMWqF^JpE{6lvj̺zq=ΥcJ$_gUh2-$Ef~$J-E|A|So Sn=." ދPXIb] L> / R݀l* $ndm"k:0EluL mb8n$#! D04BI8 Ra2v{ )Kb klGLf?+솩 m*Tu09Ȕ& MKxD`P1dryz\&oQ*2){m aT3J3!P0u`E fW•%d9d=dnFHLBEʘ]uy 8fFĕ(J6I +٤p&iUKaQEvxߓsAI67Ήp`^r.[Ĭa޲f9.(br 3c9hc2 S"T$15T֕]UvluWMDo)d { JI{(4Mf0OH_qW\ ]BJD&}kl+ƚ#̺# hW\a"In[ܼXn1V Ýg m>4e;P#ʵoa,`75$# ŕ.*#Bh5 U Z)(thbi5t <9o+9Љza&v_4IG[eEkT 3\g|0OZXmy P2FEӬX|Ghd7I&3;j>&0 L5= sWɯg]HLみ]Y6S{YїϰhߩĠixa(s[SH [ #V]k;f;#vhaNьO+lqGvU7HQz?_]gWHv1K8;Vۡk& d+K"O`M(y6.l_HvFjWG#S!,a#8h0@-^q(uH5{0y%qV%~zhDdƔ3U"׊y( iҒf#5LDI ۠ljL-X>5&(u!]MA#?DnF`F&Z)@՟Q?HPgn%?qFѯWݫAD\6X>O 6=VrA> ͽUŢ=z(vhCf/a˚{ٽo-ݖ, _:\\z焧fiI+#Nb:Or6.J5̐M>T%xb"uA;;e&+_rKS:!kR)ȎnT2i;mF&1UÿFEPIkiLu)\Bq܎y^sLl [AmزƼGA@9@Os/Zx=aE|n1~e|ow| L{k$øK 92"([،zSI :6|%FxD_tBR@\hvVSk8U#T6jP ׊R"¢`E6*CM x#$'z9Z4*X(!b3f,*";/0 Wo*k6jkYPt$KqOVf/] &3eVD1GxQ4e抁ALU꼋 )["SXMIe2.Gd6td0u7&f+TyHi |4k qMhcí0=l ( gF[,d z ٓ^3/Dtc9lXbw`_\ŌFB,`e&9oo?$y4v,8fڭ1`? L[c8 'cZQ'gs ]8"5I7!yL6sm>O$8d;-9P4..vOmNRs~g"n#ǛKq:P0ՌPUKFڑf_&M4i6 $}OLŘzu^Q S**ЈYa޶&g.^I mF"eYV@ysmfu4ڍ d%E䒺Yc,Xhӧ%":+$_WE .]`&νHY AZu]{(0͎f \B6x[":C eS|lȃ/9 )ݍma0hAPX0s};i tP-JoGg4 XdMl!Rb1/Mȅ魀3M,.A(0ȁݬު &Zځ4nIICVіz6@ۓu&`qXxW$RfЉr9 ۈO83bΥaxi99q91zg.}%Agqy 界Bʼn1w͵Ɣyuʒ\vwgXߘy]q]ah&HTR:ݘUid*0{oZFpmv.@AgIVgH8+ ˈt(\QVa\;L|Pƌ]ஊ`f%lf@'-:Ȫr$Qw DΰsHdZ%tM5$̸¶ApݖYy˩í$Vn<]`+d.[*&F \◢7n$L < VTu3qM.] YrGĝyA(;Ԙ&"3dBZb:kHrs!U{|6'dué( ;e০`zE^)El^q/q7"JsA(d-YasHѦgo[A8ga:xkR 6-[grt-tH͠%6pcG]8 2c!h8phaƘ>vd `ꅾX$Ѐ2\Opu9 IzM'S<ϗm`l޶( g/W`1bO.Ϳ{5Rr66/: ;Zbck2gtݓiw΢Q$-cb| X 7WpgBnp^4A=jBvMAf{l?/& $zWӡ4 LX/vL> Yӆ OdYFxO7miL wȸ+#M? u]$^ Cwʀ1oVglu ɫ!8(lDsx"ś:z؜ﶩh@ZtJzeZ/2X좙0V!/ ,D Uwl.h"NkFґ  .!s +DxeP"!ZOPWA?׉ Ţ6Ss&հIl:q.4[T7i{0ovmF'O%Gs<]$? 4E`n0[maS`J;T%qeNVQjEdjmz8yؐ|I2*aؑ4k"-rfNyawEo歷Kst3P1' 96 og#]`z`0T/9d(<K~{ BⅩqG1ucD+fa@a o9zU'6fQQK+ù' :sesjݣ06_{ ǁB44g`nO0RAm;Щ d^c)@3 -z(^2+WI3:0I+-B %x$ lZ1 |V'`ch/M:@(qzA({(CQΰϯ A&U 0+Ҋ7\խ} eAT>3B5曹 ;?8P~0W)0&yW6:;xD% t¼MNCQ'|H}O~F> ҰQDt<$(G)$6~Zl#T1n3Tu#cB?U7tD=]l+*N>r.Cص$ /">&Vn xǚ{2q CрH魭acܚ}.QOKmM4A`C.llS9:NV5Bky3͂Mf-~].go1 L4x#IY͙7A29R#cu+¯uxzfD =h[95*Zp3Sexg|ejpY Ne;1/82EӨkGf$|vgb\VctQO"K)e 吖ȸBy5 /ݕ>ԋ9a.rnfyAf\ZDȰ:0CSxі;-dp2voxl26l(H$fE=`9Ne_BgYFREo=,7{Iw6FD#v?DTdUF]]} Xݹt)1U&-",](`ŸڤZe=T`27Bnh}cCvJTaǐtQl u0cfCIMofJgweS(af1RqAMo(:"Q?Ӥ) 5a%")!DO??Jޜ|Ę&z|p" +^6Ԧ`QgT]bc-"͚cƜ17RF{Xhurxza#)-x~\|j}ֳ|SM[},ؙDxqLs}} 6| ^RӲJ90de3c(?l5D `(Y;. nuaڃ>+?sڃHUKp"RwCxKд.<~^e !nbA;x\b+CcQu+:5HJo[BIIw²$1KR=2#F ԕʵ3ѷ-5kUeޫ|IPm${ '~ƣJ'RSeQ1ʑzD`6a+R FnhʻE*Px^4yyUYQ S< O@Q:m8Ο2onr:&[dd]W=fr/( LS2O2j'@a~oJ#TN궘YU0:=7@iuadC)jvګc^Ο NާDx8彺F d74Ś =!ǻa}<\>tS$oF ÷?6}3#BjWlhd]mV[2}5o{8j&Xv$Cq4 :nYB>0ThK^% @YjW'ˢې҈(#p+Q/_eɰnDNudnmy;|zݢ -f}d`Wk[s=Bu}K+n`?R6y#e2ݝ73^J< YwF,pGl?c(vLPSr9lXLg6%)_$_׼Q%jԸABTZ0RD&SIb[ZPvX>7yU֫R^3#f"* e|:! *s ĶZ!6'?hKrAl$qwRÊN>Fɩ}k4 s3H9ё9ً)cӉ\sA[,MyJ  FN0A :Q sȩv/̇.~gosG>Z# } ]2.eͷAo4\V CoBf @GKtZ&ia="cyg$Hw.y=5y&jg CEuv"cqZϬ@2N8GC@H^M!rK3W#_5o05gB"1MHEs8n]E`L pZX_G*WŊ;QOb@?d%ɮ65.K- c^K^ n[X*EoD< Z.TIyMfA92KqzS Ӧ _ǥi],}'圉 O}#fSmhtbb?.Tt! 2A&*^%') `$`14*d,!=X,y*ŗ f8jgmJp@k4AEfaWzrkMjlOaa5cLXv щzlLw)$FID~@B=L)+N8ں/Mw\Ak#MȢxgxhUZ3ni [234F8 ]s#Xܯmq `հwĦK͵C+D5iw %""n7Jm`FŸ5.20Н0q+$7m`pz#HV\.vLEd/o3ɷ[- a_$^lS'iR-)Fdݡ|c>GqRHK[3N:eX~N"ت6e.Z )cu:ŚD0b} e]ћY)dM;&M$!ej ;sM%*2dRY0#6N+d㡏լt ŒdSQhwhik'` _f;\{e}^ka[Ͷ06/)-o @ݟl `lMlsQ^5 j? nf6ߑz!C;&gCߜd:`#n%ELIfnAS?EN0LDtF6}lHvP<*;V/ByU@!t0Г Jۀ+ؖ3[ |W21(rXJ7o Q~@J9>b :~?Q ]0 o#*3#a]_ʉ Df 9:FS^w/ȓ$x r\)?Ԝ`6jHțm7\pzmeAE^,`IOBȅd˱Z# nrϿ+z@SzW'¹JӘCj[{ݹdyK`q&Q#7Lfj GPa(Kr캨[gyU&GRx&%A:AYE!*!K %lè-?LJy ` #7\5,s #`yn 2g,8~RI:i8,9~nbHq (v~1[F|֐:i o#|OFycLA72F~`AR `sCqe4A"ݽjk: vUd1uIQqG&ܰE}T"VAvCt]\o7Lˤ.BbI&o]eTѸK{]]ȧҗu*nmoZ<07FC"Rͥ\2Q%XSSbBPh^cq@ŀ'5:]S1p)`ҬeyiKڪHT%f=`7KT6!> i!*ˬ)x|:VW;aAX]j6E(?/lڍuq% FG"_`sS`d4g uoV:)p^&I/ʍ8 /M gWc l0# STƬ5d`)Qi7ܑ$6~*fzA;:i3ue5(`ڧe2h,5ь>,ݥ|P$Лo}ƒGK"v;kY7J"@0_B%B fDobQ+L1Đ+y(`xQOmϑk2%kn(]fn9ݲZ$onQ }#X,.:{Ւ9( e'tx׊W/tODS&^A j8lmfLQ->[kLZZq)ox {3`La{zfPEc!? teFTU3+"n&PWAe3:bIÀSI ]Vh,p@)N0̩D`A4AʋQW |-םuF4-W]Ę4̭}}.g_ Hmf{p`LK'a9Dc #o =mӄA=ϑcR/uc)>2m&B٘TVi6wC}5y{n<1ES sQv$0^h5A[qG0m˘$6KJZ[Xt§zFԽv d)|d݃ mOQYvgSڵ7O1+cELBAHMs6g:3&D̕/1x)kX4:`(JBI7[0z <=]f}ܬ(HjL SM{}>Z7\pMiY֭ҼN: 170]ڣ*k$ϩ =vWo/}X \w{ؖZ+)$/0- 8QjgL:7N[spoDô2SMvg6wAb"Ҫˏ_1[;h |ŝdސ{*@E&Q4D  +߀YHl"Ti847]ӚJRᄁUue/kd2ДT̤L'5iV,k@y^:,W[`@aaH,"s>B*5Omٶ+V^:Ns]U+4wSnȒGˮr al{ T6kV 2A)wq/㺔!T8lT\f.3G@9n]` حد4TKAUN{Q'| ؞:`1a C+>oa%sxiҋh=~@'~W07|۪/;7%ߏAKֆ,.WG=7Pb}Ns)mݎ0M&0%E7OedGEkuéىW0DGx&PU̪;,&i V2jͥnpSS7}3[ 'EEoPJܞ6S~Z2ܓiR"EVpt[>'64wv|.B4}w螗G"Pڗ9+ ~ =4Hhճ9SpO 7%rg'"` qkXܾ7_'wG#ғµx9ٲSmD=i#&<(eR6 0+ $JQwF+JI6:.zu*tX 3ט\ud:!x-HYq\ 'LYT6pw9Al8n}q|OY)Z0'QLYG<Ӥ+ O]*li0aTL U*QO 26غEn9/IQj5^e\K@],>*4Bׂw<3daB6fx4 ErtW+jgqfVqGK cYʩ Q{9J+yVfXl?[IfaOOǴ·{:n9@GW>lLWGz$V^eW%1]$huV}uUԣS &JmQ sUP9I&!il*Iݰ~E'Hbde/Ux(8fI675|!65PCY-'.A%3Z$m CѦYg'GKL%fT|F$as&SIXJǡ cmD#ĹBSKɳ'"1B |2x;ECгŽ6fJ3<lAi%2;^ u̠ 48nUsU?3('A`Q¨xD_-u}l_Us+Lm;y;먗i-;p=7a-; cswK2b?98rqVpjXf(Vv&(GiV涺@Ҍ|!ʧjښF[`^)9 53 7IҜXPOeRGGc5>,9aKDW1Zlrw ;F[ҙ-6s]X|2{utUEGϴg|wD~l@Y\K˛WM07>[KQ4B!X9U9 г7asbnúrEm,6r,X*Py2HA GƠ /FHsEiVyА tHIKZ O' ÜiY@)+pOal}'iTۆģ?޷yN`p5s=4Q*hU"qȎ1 5/<>(#Ҿ\90C749)Px ]Ύ=t/'$kgC8UB1,hh[7JlӒ,E?0D6FLȅ&0 ˴L$AT]jkA:ގh3ƪUӷeӋ0C>v7Ya5]_N ƅ{"{%i #T|_/ 4ܬqI4E ^륲ˡMβZ7Ḟ@sS+z{-b:r0<@OҎ*q"6;+W2 C]UD}aN}NnHfyOţ%PD(KWMuM &fm؃8]ȿGIZЫ=+WrCCawt)iw+(E.6xZhrp ޡ_iO%O6_`fe݄5&j.KK7b%xS1^dr+jE~ B/ex8cH+E$9lhaUh- 3yB%,چ[G72k$ 7y0 r,^m,7fnq*zj: ѦtyZJM0zJÆ f9+cBacX?Cu~c{c6yZ Ygɯb}>ffAyG]K2ߴ%۔P_+ Z=uTΥa10W `_Q UXj*ѴL/ȯH(CᗋՐ1cdRoIv/.Lh!Xŧ<*| c`r;]%(zNϊ+4I- ^F+wT"ŚBwսBm\kȓ#!kS@؎Jq!* 4k$b},CbT JrYE#iAPÕLuٰFja锭'JAK|hU@x@^]!C@} vt]4>ܜ̽'')Ǎ)>T]ᒪ= \h{ |Eb|h*7a r$bx$8^.6L1Ps2Wwf;pz>Y L?[F&RۘDONuJ73- t|7c [6[׷ Fo?^>_sv t=KEMi;@S C׵9)[XN-f*v`"D-4ȯYk3XpdD/^ŜlUF(-A^gǻK>\#l֟ B/Ҿn) V.fyΓXY/daKD2m@TB[a^2Mx̛Ti^'k.QD$ Lw C*ӎ  ,jP0B(* {U#+ "Yބ% eAJ,, !l^̣[W8a.^6SY6 2LVGn]R?GU}Maū@+Z-Xq={BE* nFEK t&l`hKhT9ua2`{0:W%s>o&o;k-.+,2G86wa)Ca 7\&T35{ )вE~BtXz8;U ? 0l`҄VttK]!VdOQfլ'%/6 U@\@ ֘0/HJQmך珔W+-hf}p0?oSV5y N⡙| l)ݩxq(=]"J4r-q%;Z#3"l۬[ ]Hu ÔEj@!*Vd^lKI"1z;K)ђ1-q-S"EжhJ)fLd4xTwv]Z%R+u}{/^믾vYS@+liަ {%8,"ʈ 9Qk3|A*Yy1 mTy\v:kG:/cٛ1jÞ#na+bJ}h+b9vSD[K'I7ԦwC|+(\Fyd'\\m0nOXlmgCsgŷ(ӟV> ڏlS \|[u15GF}D72ru,{a~=HҾvCD(po2P[ 'C h >ؠ?Ji%B=aECpq«]tP mE F[Ri giBWUzV<5y:3Z&/|Gܴ DN's󼳵7 #+%#'4ג Bu[:.;UDw\] DIx޻k  'EX )^|+ZqK3BIDyV.CMJ a`ol X+U"R(Jn[2cS(BtNu&(<(WފUi1B_oa8NMH΀xCaסx vˉIV Y+pO}u}脪nM=]qoXhO6B63|w%Ա2ċ,2ԭ w4MFFG|AO,׈O.qh4&xH=;tG$jN)75N&ح3 ;^H#Ee;A:Z'@/NWNWH"QF-(KSv sz;ņ̷nFS $l0-+>Jvn\ftD2"⾷$L2= D젏1C}u"HB ^-"eoDEg4#0NS**2G,uWhե蛤P;zôxҟ߲Ե5)\LFZqYg,eKlKg]4V@yFMG_E@LwA# Ax^fR\etM _{Xg0lLf夹ʾ he(s2h@M,/3hjq 6_=rGIN鼣Ov3Z[ B&22'K3Ly`d$˻ےiO5Ӽ tG##m6^=q3G鼶LL $LptB8pL)Ya5_=IN$PMf4T,H<(xg4 UuʮcόZӌ4y…6.W;aunx lLͶ#R%" (:W~dVSaZM|gm9q%l;f?5\iE^@Sb~VD+"`r4x&]D% ѻbdqս[|WVnʴRC-(=rQXgSCL[#5DU-Ne%-ت\;z):,YFK030Q_qpйhc)`PvRxyl,bЂn i*gh,U>#в% NdlrWxD욻(]7N . jM7߲/A*F9G3s=b^S>+$c8h/4:?G8)`L[0p57 ՌZP:8=j݊ɛ4YYsr{'מ~\L"'n`D&^EF5Rٯ"Pupb 2=Ur;5T%0(͗YUo+kyH~䳲-_O 3yd.ı"{E/편>~Y ǝ"U+B2n2ʕPgCXZ rj҈C@׬ nEYZ+'vk92QI=K²a#%r"󠽕tfbMZ(M`dۮ -hTX7 -KFci,̰t$l,'K 1cS+g"t %GغXĘikHj;1DHwɌZ0}C=;Nǀ$}lPOdıpyЪԝy19 φډ5١ dccɬsIyR>EE}iQv9rw-HݽZ2*i F9΂4Yo#\[F F~vEN8:]OnJfMc@)bEؠ!S NM{TyQAi]-c5bM]#Y]٘g\s[M)j][xתI_>N/t1y>h֊m.s\ocm/}Z9^P?w`P)۞4{ uVgFW $PUcFEK܍^T v[B[~Og./TrsQcJ`b*M"Dф.({ɰ? jHJ]PpBAbs_dNRbASrڤx>:u&gP5!R璙~};/85_7q0e0}:-50}㯛 GdsJkov ]O]^l39OA8qZ = ;9s.Q{y/ih.+-j3I/G AAьmzYcl "AAƱ!Lчqlq8Шcv>'p2z9F_#.h=zkx":P1scO~ 8,!ߪgfA!9c^ћʪn-gt-I>ĖyRY.,X舝k%%CB&JfafiFUb#XDFE2ZqQ4p *0նۃ{8SEg!U|'u, &߉JsX=ǹ#+1L)F'A{,rL[m?aǣ &8m@v̾ x1 va˘('6jI? r\05I2)&?#w|X_xK'k&}#$vwϷ1\,yG$zx]" 2Z)Xl?=^0^=h*Ze89-܂q4lMXnnڤ'DEc A*ycd Gͺm3*-!K kx)j>bnl`䚣voсu0RQѦrs{\(-Z|WDfF\m`Fq[m`ԥ?חS׵x6 ,kE!u}J""!:VAL6ݑXj& "4/ɿkT\"Z:7V=m,eL2WfY.NqmL,PRus,lUiS +va*"ri zKf9Kb841_TB(C-<4STdudBV\\2Q3k$Ot{=yOyX햺/^e'~q8aէۈaqt'ʚ`InGHA99^u~6oc y}Py>l(סZy'i=|G8/poR/Ee.Y1Tb*N!'nž5/:!PnJIo6Aa: Ap3\~JGBjeʚɨ}T3$ k~h"mˑ~|S;͘evU7L 8l!e@wի"@/f?kJE\>7`XKL1aX{~-C& E*V6ti~IYSI4Pr%da$YrH%S%]o4m8ȧCMӭni #m\FIewJ!9( cլZi %Phr7M_ka"DO.R;\zq^((N򅾓O󮍸`lܷݞdy&.I[-[\ GRM&f :ηMjD:%YinɎJ@7 mpo w"y}Ya[s#!ucɤ͟~:oݟ~0`(ZYWnaܖOԔΚߥvȸUd9]iPƕGw_Go+~gY_~v BbOP}$$)%?/u S8-FFC-dwO>?"^e}7 |2 z0f󳅮&`>K=tZ;3U`l2XB9st[8]tBI8;xlN?4ȱZT]uiFXTI*IxۺʵMkY{Dwh:Ni+GKŔe_+Pղ9* __w'kOo~~qro?gW7o`\#e?3>.`4tƫD`cJp) &3ׯ~'/㛼|SuGWhmzd,TִUZ_CUP' t<+tHYѯ^?_|⫪7qgI|7?ﲾR t4Tg`.K*=,`鉴t).zVD\?{_o:YTo~O~?ƛ7M $3Vr ̸e62Vr}|,_*+?T Bh+W 714TD.G('Imyԃ nJ*++|d4)vЧu"FAy'+Ճ!Õ?""t~A_{ bUƁjBTuRReεjҚy' 6,'`C8-Ls ^:\hD zJlTC!ZVX`q\WX?k_G?zSuE]Q ȼ?\$vWFb3 ~1|3%Ń҈P!|Fxl݂JFKWΠ1hoqgGw{?>Oܟzv})^u|U~u~>o`Ӥ%4 V S2zMh;Q1x}g?}[WqwbG_3*;?~7_o޼5y"|f8m xZZWz7v}qU.Ymz{'}' _EVNoc?O"‹Cg'oW?}}?z+x{z{_͛?O2vsTW m_zdT^lhFRcQS_N^7N2Ⲡ3"Xr$v0WMmP!` ^@qkEE⪀_reՐn@)j-cc,"- .}a(y=R_%MXS@LJ + {U9Y J\>-FFZ_p"NEX6]#'.w A{bw! L=z9v+^&K|@G775 } L7't<`@gpf>e_]_}_|teֿ~>jGc퇛'qlp2⒠[!:F#TD~G>w̷w* oFE֝yWu՛?㟧ƧwA .)-fpQ]LgՕ?W?_}*߾ 9|qU^wz7o??_~^^~՝9NDN`& +>!:K~oF^Wo_}W~ѫ7^}s]뾯o~_˯>{g?WNXM3;[;#9BnLTQV+_FPqOLX4FaSAi;i8 T9AnXI`)Y< 'O옃F[@HALc}.jyL3ZMd?#}:`+b BtR/X(gPgGͩ_V3lm;m:f:=b(q ; #1+Lpb"OQˋ<|W =ޕ[{h:A17J?ysX _H) HjA_j~`E ҭ=D[DM#!+GOٛoO?y[z8UoU~G^"k-G>mƵ_H!ÊIٺo7~eq_W]WE>}W6#̺ʪ~{E֧W_|kX&T뵣%e=UB0t 핂&JxO?x޾뺯XT]pyWV^u!Wo՛>yX]GZښ{-nXT{J˪?O쓏/>yѫ7^}u}sE ^u7o^yWo>O|{E9Wþ;`60Eue"9pq58Fi˸jRza͓3zZ@:3:(vs;#`k_n(hR`ORڤM,ЮhKEss ]hkQq:NN%:ΟAY^g szx9c:^'N!0<\ t8'}"AߝyXw# [K1}#zJߝ/?l0Z/BwҚbad bċ6o'?y?Oܟ޼o7z}߯*a7|*7ͫ/>~eӏ) IDs kDX/Wf0i?䫸WWEV^w3#tnr wܕW}}Ro~/zYAm}Xź.Xd'5ڵ {Zbz/.B?}_}z^u_weݯ"/7o_ggG_~W7uz^=ޯ޾}曏~W_ן~է_~ٿ(wSI lWxqg"dٵFь+#Tqpע ]b8^= ɻ.{)Q9]<TYJ+-MJ5Aq%o^2e>AXJ, I0ɠ±I8W{3@aik<$;*ZG]hfal0-ҦgexPs)G1Z{4nS1H~o7oiΩE(W r"'q-)t-˯_|W~ŧ}_~ǯ~DYq{Zy.I#[ʬ+k뮪h0#q4fF:Rw s #=8@03F Z*kˬʗ|{%"w37WUHQnfnn ssU3uv=]gVN{//_|[@|'#؅+A?8M^A(Θ1ے:E@ y!T*s23D𡅄$gTG@Xe*.l7chv} FQ@Y˜ b֑$}{G[oyOzn:_1Sӭzkw:٩i'h}r֞k+jܢqZTSg~翰^{-.I ɜ#0B[gz}u]-[qr_**BX yt^ ~X<|}3~u8`CfCKNjm1n7S7 7/_S_"Q&0<55jǕe1y0e~=}|uJ̜$%tcY#V`P)3*xlObڬۦi++癹[m*]մk!jMr=||բ&A'';4|ܶ a<;lD vrq|8$4[$S84$\5_iMSZK6HńK. >+UT?3gϭ3`(:PM6HMA|, d.hFb:ioFN[9'$X0tZ.%fâZ4lZEU1PwagS%?Lpr\;O0TiQ@6,C\^`["PtJ2,CXVP q|0inL%X()JC@:%<0ېQ-zАڱ#i= aY ~GK&6[:|7򭭞wzl|\\:nUgۻgk:?&y׏W%5+Z6t25m{z묮:HZ 7"fOz9%6y p*TծAR I`0üAS9 lٍ~{GL q:ɿmzw6M=Ajh+[( rLo[T>c&fɭ0g )ÃVo[ Ͻ% CջCn{\0k|(N֐YIL iΛYB\j+S{=ڙݞMVr6YNUӴMWU_UGWGO.\K!avuiޓ﫞ì]7lZ#_W^f{р0NN) m! *!XL:HTH4y$8P PWnZ),tږPLJUZbI r4D AX눀)(9%FFjT[-I狱+ NLE! t#q.\pY QBJ+ 8f]J]kJ26P>ډ-k65m5Z,S Y7P#Rer-pjX9<ؠL4('[q zĤ>+;~ck~{vtMnˁtpgUM-&nѸs>||`&^ b2 %VΗgb>B"[d힩⪊Q!fYY 璄#lX™{"γ պ 4UGHba=qoX!.)1[gK QGؿك0TlW{5/*Px։htur7m;Yz\roʋ|Y`ШNÖN%G.S<a+Q8d R J5nw**N % V'MY!*րèKz++ Df$K"DrvYrBD`Q  52Đ lE|i8)(CFtJrE$PS=9ɬ}sOb[ԁiPYWd#BxM H[CarFk+ؒaE+ZM# yDQ&1 "P(w2t g3-qL!U)} *{9g˩ ȕ"U@@`A {M~:ȵ3~ooznz<}avc[gE=o_]\{e_Q飼ܪuMN&q>3a{cbŔ*' ]c*bٚa y&+&v+Lx"&¤lڙ*NW=kx-^rYL'ITmUw5UcedC7jW`WC}k$گg˳/_z-Ƿ̡SbR} h7TftH (l=[M#G8nOqDx())phKOtL/PPXڙHX):)܀| ہAA)hǻԉ{Rjc a(*̀`JX .FC,}\:f ,fI^XblU4SB ԦiYaFf WFPحvhm)mNtzFk(Jfp7JpOE=SRh(C[yW2ѥPHJ& e^w1&!:GϦ̦Oo or8֪~iuk1y<~fœ %7\ϱL␣o^:Iǵ:GkºeS-ZLbR]zOk*֊h:1-b=WK^몙oh\U)Pn+Lj{1⢧ UeKދuY{va'+l}xވZY7䳙:Z)u~vf}kȼ|H>hV_WSfNsc\'}Eh[Y_om+=wb,%PzPIy2Š=|~g1=t9,z=mMչ\*W-o?>`:W`st=y:_j&l/Wv=y/]]3@..L%a`V5填(MJOp^˃¤S1zb`^Љ( J#H)"F:b`&˒i" b!%tBƨ6 Wbp /e2; YлB댭&y̲]ecv0F3(CR860lct5pn0_]Pr  K ]1QSoXERJ,Z9+ԋSn͈&5`S9!dXlSfa!N Crç J\ qXA3.nEQFeG*<]țhȤ*1mWo  8+EÕƔP|Rig[>s{z^aIgL{pT}UnbS`Ή g!DiٸEEN7||R~14B93<*h@0` GXF]"t5=[ɳ׵v^aJ|^$vw'{ͭ|m>9ĦfwVUK,&je(Q0OxŸN:x&v2:Oʣn}ݹ'nm߾Hf@2D *6/Sg>h:YmUJդY7UWU]|Uy-Wԋ24TEtޛUw}G뮫nҶu;[.l_=x/Ÿ2L@Cx" M.NKa^@cwI|R(6Q2GK27 Yb~^*qLE++%&"#$/%S~>>8w@q Q FBN0p!u g Ei(aIױ df :%]OrQ݀Vk)Op3m8 ^h8YzGEqnA<6CNģۋ!ZSMmʸCcbƑɅ$!#І%aІ:G9PSxgj(7rdN7i%#k>iz:ב0:MJ;E!)Ќ&MUaj>'M]SoZZzɍ5zG}e )Դpu~o;tE׋(RiH#ݭY!{G m]H0k0kgGf bS,ؑǢDR{1(kzyx ^}U,3!N'ǵ хH\#|(+'8ٻYКj[HQ+ XFYw.X?ۋXQ26KiXl- j+Q0rJUbXlx.;0vFyp9zSafW)&2zsοvŴ٪??3KVT : )Qdv"+'_9\W[;Î LcKGW|q67LE۞MJv%sM=ebP+F\k܃OUpȾS>ni1^ hJtub#*G;L;R }dۦX¹ܴj|m CH] :mѷ{ QhT|DGv׼Lsٯqmefu~>x> j6]nMI|[]Cs[-Y?~Fsǒ4B2Q|2WK1캮InlWz=;<?W[7@8"Y^Ĩ@oP+M 3"\'2ȏ,/.$b/>J+*-,jKMHLgsK2 %vhX"A&'Fb)B08%QK¨gz1^-;P$E  V@NJi<0;p^,tSBoy(k֎H M¹&ü!p QIF2(9< S2u:#ԃ1O-s C: rXbV=WH 7uBV@ ܦ;]ӲEǮ |?܇?}nH]7!=l9}UE )⊑tA~$we ʵk^ݮ5:GmEV -dB'[+8/w-^Kc%šsvU}] O.| O@]c>23j2+2sQN 41B.hH35l$KyV#J 0\ˇO:;t#QCDŽ[>xWH9L<]O% QvQ(1lY2ePٿbMm'#$eT^9nǛ!~A*v>4uZ5uX.gޭjn(zUF`3D+rQRQM?X!6F<*OUsuG'{z?ʓrurxۯqf`kܚ̧d5}Czh{<|[@1<~Q3{/Wp,YgRľrbt{훮k֫ٺVrk}G.a~T%QnB"$$+)~ (~QƘDɨN+-O҈f"J((nk1"jړA4)eyRK2رIf LXBI6`U辧(&ktoŠ j>re2QW7jF!?ˠewN՛ sObas;1\VnK.2m4vqhzq>t}G(0";7kͣL!pX>YthCJb,s!g9zsk ۾p_밿wW7o~\Jp#:^^:;>$޾vr僓kv+ mvw3C5^:~ =Yv~k;;:vpѱ{hwOfڞً}:+3u ER=qaj; Wi̻緶8h]UU읧sf{G/~`XW;X:njyWl21kTI pюre!Wz' iªE p{*TD}݃YqD@L[7pWWl5vԥ y>{;?rb+}OzW_}7qzf;ᴺڕ;v ]CqZ 폜_ٞmޙlMf5;繣͇VD{k·79j1rQfKgk.=iiN]>zsۈ_|׻v?.G#F lH5)I5Gc0d{l8GE!NQ."q鴲EX4 M30u$"uaDR!*3,XjD$mߎFN-n(+,䏫bH0PoY4DB MbS( J+.Zpf&! mw7p+n!O{w8+\>BjS pF_QECz>A\\_nw~sճkW;sN];߇{j*YL˙搣8'ΡLF^_{#n@h؃:ཿq뵏\G:Ȥ}eA\Wa˰vB-*yyƬqmO|.Pf E-Zɨ+zpwR=[ѕp%'AM͋5d*8`\Z?wZ/QAۓ7]ÝsakZݻU+0C%i[f|G{kf#SW?3G?7Ϋ񳗿|دUc= $=;;39frLA+{ B1q;d{v2CL*)nj55?Z? -9jv'>s~~Eנyוk޿Qd餹67B0[S83>m>]3~?Q w۞:7sOݳW0҃LvgX|&xyr=1Upw7zqZoWWqZm.L^rww}="y7GMg#//]eꊜxQyv^ǫcvrwZwmo`x+[d>]̚դ^Wu_w?rpmO֓n,jv&@s/ɋꙚd5H:;?[o8cv}_w]ÿt]G0b#`x_erq|JeDq9^79 yJ1(*ŧ$VgZ\<հqԦ{}[ԁhшEM=ugS3M@wciIj& N ,44mULdPBD…̉uɜP" Ԅ$URB}@"ш(39ȡ.2QʛKnƜsF5۴UqB!alD)X\Ou沌`'JQF5r˫]K)A$j^s~3_Mx$ј膰(t|ˇ[05MzB3CbD49ڮhٙ @yώD:$mgw~yƽWen֣[5=v[[ĵ& ݞY}b*w>J nJMNیRCܬW+=$>Or{z1 dR_||ž[IIZBt{ۿxG3Ol}7qeە{hnc]Z<:# =vI˕ͺ۪k']pL ~I;O?%WOY]Yr,I/Ȍ\+ھ'[G\w5AI=VjoxuYP xp1$i.MG1h=mMh^ ":`If+HՎ+v\\Hd nlS)4!nsӐgGqYFuN xC0UơTB\(,7!dώ3ϓpO8_OLue5SOrWĪ∄},bOzLZ2v.j0ÃYK4p%UP-4\ t2oeI0hݏ?гUOd[ ظܹj2!qX춰WDžLUm"܁O<=֑h8&>̗>*oxу; աSC؎|b3}ٺ4^7U[r}EɭE}j[/oo1܉tQ/G\Q_ۺZ5jR/ϟ}% R3@)@RÆa\CSp1Ɣ=a?/e4i,dq=Q0CIJbALŢfAVr񞡸Mt,MJ Ŕ4Dasp@) ,;/] x۷DhHgCl(RY@2: j*6[M~QZ Ҵ %8aȅve5lk\V.=&# gT,pDj:t4݌¼˭z1Y(t1YHi%+|#j #]hnY/ۧ@saƧ$jОpԘ4Gr0MZ?\1v'{$W |#uED# i$GsWMaģ~GQ1W'O=&f !r]]\.~;ڬmЦ;[S;.|e}6X L45Qc;ǎpzpHkI%xkn`]:jH;G S{>Siz0/N/j̏{NEU>W=y;;s"}I6UWW}#vJ0$;ޱfOw'f7\Q׷˛W\_m]{Fxt34Y@E%Xƒլcč8Bp#,#HBS3VEO-t_QXIMDŷ8(g%!fO,DVAlQ#JB@l¤og^eooi35AХxf=51{@f[7YS [XT<ٖ9o+ O䷌zd0M GmyeRfixP,-؁inNdN5WX8#4PF<}̎TEBB)0x,20kx- yP&'4k3=2}h8֐CV'TV`s aMUU51|r$k+oShXu&Ό:NiC20sngޭGaMQ{c̒!X{D5~ *R"voR:RI(.&`NvEqXů}ܼI1UtaV9gf73?[}cN@sSW7|`h;0~xk"@#Cz*nE࠹:֘tyUƓ87q $Ovh ŋi;yyUH P&0$e+YGC/dvB֌d^#˪uIL^!Ĩ)`6Nħ,nzʱj ñE"_wC $ՕineZc U$lbLf5; I%L(kYmd ^:34Z̆X̀4M ]uƵTeY% &VYIyhwFrFn"y dMKShw[ lț*s?PSpS[.+w?_كEm#sb8 2s|++vs٨d%Yt@+M)kc2O4?;9JN!BRx +XS%R@@re)b q: Cp7P1T:S-%ʊyIǁ+LU":.o#}|//~7^;S"q;?r;>{J%:_zgǥ+CBkw@P^nbث{')]["LMfw=?^ vϯ7_% Uj{?2{irJf[Wi 4w]## $ea0x"pk27)'$MPi̞ūQ@<"xf~U"HU,(5nK-("Ed"`IwbI)LՁlQв L"2 Iw0ihQ&d!Jr{3;J|x#HuETL{ȅ"uPgU^ZqQ5Q1d 9c|a㗰HAaN vTp qVI>Z dRktr"-%"5-kLTG;B%@EgAVʇSY7i5} zxkCf jR5ڂڔZw3X*cTZHT)1ۓ-a,^0fBԊ|3U6m關X8zlaUq840gS+DxuR9{1R2\~9KzyJav=ڭ+g#h"ԸjqB8̕#8BYѩI;ř|fD"\3Sz߯|)啓-r_Wi}壋?~h1 TMҰ O]Նo[33)Nw O2ͫH* -G,Ec&{Xs lP 0Xj(Ц[>أ)3A]L) ]>65SLd)M$!A;MʩL\eK: Fe/]he34JW :X'h^E#B݌Ý| fIXf9*"mr6QA ޺ty\ `hi7<$΍k@$%FY=bjZn!Y8v*?h̸C4g+@^a4u@f7ʡIMxJJASM`L'=Ъ턤.JJjs.ӭ0FЏ'T<'3SfrQ!o{u??IUMQ@;U/| GGkǗݪ!G͙q:P>D\% ߟ'8zC_6>2{wlbGo}-_/]׀*O*To׏n?gj_4~ƹF,++L>eF6J/ Eqptv#dӹƨ0GMH/Ї*$abjL,)+zB#پNoE7vFXHݤfx,OOK[fNyGB8Q4;D{ ֲKэj 7?؏-i"3i%وJE{..gQيdଭt+Gl1 6 Ȃ<Yml^P~v6R[!Ka sKsQy1["L$̆YK$zDjI(4.V %+%Ӵ$F*mRS0dfam̌JSb(/V⇫ŻP6BhToi\2I6܈5nȵ uc'Z!,=.ըuE߶=^xbS?^}v⪭qƽQ ƹz/^)jo>E7TjH7 %J&(@`OK''S|g [M,b$\7u/~OG/o#ͽ~5UzDB2(XPܮ,8 THԃEI.`TKȐEi\ eB$Iz$V1K2 IJT"62W J2d6.\kM}EHvY.,h#.I@iG(Xg#j mElD\ԀЇc WSRH75 E-vzsdKB#I3%G Ɉ1x!4srQh`CN$H d]l+=E4>z^P2a9C7wVpn*) ^Қ3!tlJ$0&@D([mzn鰌/`|=>&Xgo?+_ݯgn=۩'/Nx?[)KP!m њɗד֜}fY&B=z&fR>>憺iI<1uK=%#MX !~j%w JDEDzaޖնGf=l|F8A6y(UלHYDc+84XufTԌ>P ZLxӢ HVp^ð6`/}obpV-MLMȄLHQ{&fz8%iQ Csa]}Ǧu##ף]tc3+*d2V] n$όm.R-R}}G" ;Rh[pvZU܎gV0w" SBn!Vy#gD_ʯ_ٮ g"]CVռp|?K Qh\WJF֣ҰrPVA>Ût_{"3SM$TSɗ|Ы+(V-04-aFOhY[c,!)[)7iPg)_)rbQs#SHd,Z9u>w8}hT63@ XFXD, A(Bg=s{p2&Dl%b$*e)cC;ME:@)MMH1H3hFAQC3TȎ6y2*d{1Sgm{Q}W_x~*єcHNFn=jrph.R[G( 9 ۣƳN oiN\@q1{rwQ313>WվnDވ>& (Q(&U)s%E(1qDyueJ:Q>2 QT8azuņ2fPZMGpZ|(f^H Ix]TuL_R6ݕՋBD#X]}-_Z E̿[,9N^tD"i{fT(޲`csV KgTCÔG`uEKK7٨ZA-o֎2eAG\_= ض4Ž7[jU!C=2:R d$ tWeBV_9΋޴B%;i ېǜoNo:Coܽ6> ) Nqhp,fC#Z2P;L7VpDzgFܜZ;HF&GIÃ\˾cu;n'"1~t1;?8yr(5o\#ZN"H@M-EB&a F 3/ krܒ.G e._L$sEEh/IwǦaC7߯e8E1&?u'Ꙋm]QaY"U4cXI20uSLIFX[GܸMMD3fE ,ic`)B/]]EdFS }PQdV& dF|P!1S1R>}{ *N\ izҐ4ñ6pz$rv"x3|TdC?huM%HL[شuvHLLݩ-͉5 e瀋zN <ey7}d(X1_Ξp!'Kad@8b-؁o),ާG-hІK[cuO3aȄxT/2>\jqSɯ 0;F -USq Rת֒IR䓔Н}MۋЉxhU|򐰄 JHaZ߳t']TɝO 43B+h%H'fBʼnr*ՒidJ$R`Y$'G^Ln#I K<~}k#]O}ycs2&AY *<ȗa[ DO~!|>}eiDM7H6 v Z%S⌀۬#7$fi6CpQ fFdˊHoXqH%sIUO+QkQ$i%7/ePK8Ѿ@f=b"=j+sBkGˆU4ãBOeܤ{FV^֒6%F˨I&MHN:O#3P{]r&Zۖ 3<ʚKÐo1`&RUhPX!aYT-EF{}XhL1R')$:#&%N?3Kl 7c& Q}:)Գ81Dh{)ufe@ܸ;W,wHT]gQ:?}ҬaD{}%S w@EJSic8c@cvɫ(H6@1R?v(1kb>Rd;,K˼>2Sy0I 2LK3^5Rc0Uf6/mVND4<+V7b A7qB:LJU$\y #if fEK)&Ƕ[S'.!:EI.U*!]ظ`QuOk!IA0t([h"*(D'R 1TgL6Y"lsYD$40c^Ƃ. pyVų;lMW,y%D\tj9X`gFJkt $֭u<A!y47Ԓl VM3%3詢]{q]2h50Juޱo֚6$G4oW8!dD t4uV3ͣRهvk=;&K>PՕd3PKHg>?Rsm}ҩ61Lz"uhI0V:q6/+&I#x5Rhྚ*۰I*o0h]2@ 0_ٯnc`m[N[ETS2#%WCyK3#@ʻ 턹vLҒSh7F:{,CQbD㌠b@t |f<QÕ)jCI]cvF3)2tZ$j"Hʚ #M+MݩF7I1Lkg p\aj')a 9ՠ򴭨IIH*$&eY<0|s{21)nvDX0lR3AK;mhfʟeidf*9PExEFhQII`heNOi@/X7Gdi3דUg ayS:}2h7ВJɻIW2`&Ĕ9)L1遚eJIy 0{WFQt 00] OfBe5tyu>A}Ep1?{#tg2w^{xgUX e]()Nobg*fS5GgSFhgjK!Ъ T%2u2'jNJ@S5Q[G)>FD¯F"؈ȃ2ڊ%A9tۑ5eF!m`(QR0{<[a؊n࠰(>PK*1̩XӏSD*Ci @Mdf;Ny8XHSJ2ff",I>)uj*}n ,uI&A-b1n)2FfiNʯhBJ?#-y`v('Z+؆,g}& #!r[*=4N-n|~eA/Ʉ(fL;o88&-# t ,q-iX ۵$钃SpRGb0aX(;a;Nd\>Vlbma<)eI9ژ#%-S^36H8..u.`՟~2Rf 0fZ]d2-E2MP1ռ+pJpȲG2ebdbZTˏY ӑԏj%u0vW)85ة{3{V gc8:bpr& <΃vE3n峪SQua$GTȊmg1o~n hH#YWb@ Qox[)Y'XڿeS ьnaFws_HSub3HzĹvLFc Ղ 1LZ6dԺ*UR9ޝ3W {bMG1. fԳ 'ƍyj g2 L':[gbXz]JkÑL/𛪖W,8M~u?[:z$bIJ%,; LJLC*d&}؆Qd}|84.Ś`Fgiw[bHn'嗑&Х\kI2hzGvDÏ,A΅M9Hfre*Fhp`WRVf\XIf*q؉,`=HmR8`QHΈ D.dgEobL"Cf-;N$6*KD16.*pVF\2@\-/[y'1tD&)?bT,_8Y5JX$kYOv3S ,nmRMJ"2I- ivQuTTي"y$ZKsB/h?7jL|3ū>no@%m58V>R#q2gY,qT>mt[AмD^(opMxS>~*N*qR-_YqyVyx/6}oVk3Lίn_FT>>̢csU;xd/ibEl JɷIM&LlxdJ7dR *u"ҩܟCai>zڎ*J&X:vԨ3"OKl;g9&" %WL3ӃdUMDeIb#dWؑ {KM'[7)yHH/*n_z}EKZLrϹN':*Lj k| gd$Dsfꃉ'ƪnIV%/X))#C[`DSkVtܚ_db[bFɔ BS0B12#jc 87GIq#k߉J⳯aN厁MǕձLBQc~D`./.RR=]`24^[2H*Z'>nǷ."iV+vhKafT2%iʧZTP煉EVLJ #pkfq%-a-<)͹TlGXQ8(vÕב=EgH8g nn-3.FFLA t#H281>iP: Ml' ({]Ki0t%>WT9߅i xW2&LHyG N#l34:8JʼnTY3^_fyssk63؜iޑna2+ P Åd ਮܛn_gɿwNYߝzgſ¯(f|gȷ;]^_T^:l@Kڈ2)Ho`oo 9DZ >:.M0TVWkE:) sQS _x].56 ?sb0ʙt0Izf󌳴Y%Ml*45g.lH.9bEq14Um51C#]Ѽ 7sq%MWSO i̗p.s6CsG9}ol=,q(dC)`!v3'k Ւ̯bGTaŤc0Ü_<3DUQ`0([j fV͘ڜ1 ?qg'QJ fNCUy.# `( 6]ġHuyz};DΛ !Ir̪|-X`Z&";bMl< 3K w ɜyC,b*`Mpe'Gl),~d'2t*us:~htA"ԃur|wk-F]m?avk/ g+AHgP91UDo^8o|Wo|ʖ7}qŭ P#Ů $:a(fy[ʂ@V`ą]|ۃQz>c[X}tYTRAo1;jox_Uܴec9B ibLjv'׾d 3)/eH~&A!Is i"DOfzꉫ&U5>U+ݲ"gm#S1X},gFm>6/Tl{v?PkWo3r52>ΚBri&XxS5\4fizXE,xCYSsDi jSQ\" H ?hh_yGY~"g *COrdrX2%R1Q1HU$nXzN E$ d=mORLZJGh1yJl*eԈ$ ¥vKj( ntebXʒAǪ`##7b2>XR:x:xJf쇆ZS/CC,qF"iNbX0† yuN*!40J гq;Il3E$c(XcX&5; %w>Pxp1D'7~8;CEYҘdTΕ%/8ioO&BJ>wx.n=l}yls ݭW?[zSͿxņ*1uVʲ iZ07HW#fo~*srv)/g٣hW?~Ԑ F !DSl#"IDJ; d!$&y4.x4 _4&X͂dXl"+YNQC2(%:Ŏ"nlUQ3ޱHxlAnf1/*e+7#{b[,|њ<IrNhY^R;JkQh( ]VdCݔ 4k x`2<&cWy΁&{lfyx\FT̢M GMy27 o`~fMG:~Dxj94] )h\1.powܷ%$7N:P%10o%QqZSC蚢Z˟xSmwĹb rg߿n_Ka_};XsQ_PdɁ\ef7(7io<^&ªw?S;L FcE~ _on/}qfD$.؅ٓ=[Mfj"yKEhJ(sL d^RU1A<}`q%jX9b&DҖ2ca(LHa S)7Blуyo|V-e" 59mSU6H)26& 0ʌ Ј ,ˋ Gj?"3Ⱥ\aIN33.EWX*$}+!NӖ9\ Ë%S+hnix(˂mn"bEzq\jM1#6Nayn!oVNc_A\*Uẓ:ٳ2Q s?w$Ɏp%4iT&im :e F<cSk}Jw^~zog̏Y#Vr}};ކ@p@dpSa1OxQ"{}{n1dO?x?2'|F(vfdw\`rY໓/PYc ߐf| ^+H*R. @*)͞z蘤\~wT\Tݸȱ[57SZj=Y<'v?gs</;k_Q={w=oR_\:Kph8UG>Nz39nIb!Łt(.!33JD sS16Y )#36_T!ۙCMҡq,Kf.jx+@Ҍ"XS/}U'HҞ"a1'_DeM@7TL6\UP/͋Qd %0NI9Mn!G ҚkA$9YF=F(u @s]$!.+9;>6j3˃@3Fmt>uh^ˉA_A͘^R#|t5dXBGhЖ ?5ʩ! E9n)+bMNbxZ ըNo8E5)7| Ww% 2\&>zny{=ۙ"NEt{|:0tvzNu ƻҐOn-4@qz+d(X-{4UED5K{F }:ɫ'DE?j̪h63y4!ZR"v}6چ[$A ЍhN!urwNH{S^/ٷToQ[m=Ty·W;R WG_~u9Dŭ3sS57|_cM xk.LdܢpIEЃ"PҗlC-dFY3G!,R떖wB$@$}2N@WrJ&X,uGd؄ra% vgfxZf,>`i1E8xfKej}'hi_LE Ι-Ecr Oz,ىylS Rkd Eac !9(b/GVABйVHFG%"CMS:$\2y%n`%y6!+^h5ͦGl8D95S%fp6"7 0%2ulsdR}Ğ+{>ػ'`bbLdLt >Kt$bAY:I"e]8zJ̬ :TJror4I_iүyN"95x`禎Z^"VkldxF1}\Ŏ/i;auSAWʯ߳oNw~~].}YU\׌_oUM˘@%mE<ԑĺi$ De` jm*@R"6pe%2EΨպl['#sfafSJ$dd` Y$a1gq/iFY=!UE>Դތ#ԫ°v`$}(ѤqFذtNemN(L<26#*:'穢[˭3s}@dTX#0$" ے@zґ<1*OU'zfv붫>Q䉦{W}{d7GRzOg~rΠoD7&`=|G]׽P\R)& IhRDY:f҃\nx]Lj3JR .%L e_f2W 1(YQbfpZ4nh2mo$b\g cG'J"٘ݐQVHVZGxB& MV'VEcU5ftQ$$ OZ4yQӄUM,Tʐ l KsE.׶^0Ń2@ F➂A;\!:PG|*QS+5WF\waAӋNQNs ʎ CR!Q,h oZ< X¥߼ol6<MOe57M+][QȓݾRU( ~+ƭ!qPk6 OtZP*QR+/ rVq3mp8}ʝKۡ]_=\L?K_~aR0ucSr/w-G l+I}hED˿gM߬g~ ?9$lsX_>8PzT*O'.QKL7nUN6mt}{Ǟ*CJƮ_>qƿ2 /~?]VSM/G;U];iIշ/t4.d;#dP0 1$|RHsyf{n,k`! :htX:?d.D6cƆʪ~VUDe;=`^8T-}MKY#"/.dDe&<94Pw귕N)N5%) Jbj.Hh]Lx$Yڄ:h#pi±sükf?JQ歷]jd $]3k.<}c\u`jGS'_+~} `}'Vo4(j;;UMvҮ}79Y~v zc[; Er-d<BX@ b)0>7(rk}cA1"!YC2A&e"ߒ 8H[b`bq?nuz$N_|O|5o:FMi{!}})룶bK:OtO=2={u|YD#B 2j 5_=?|w;v+?.yT\9,zq>"SGmF^ ?K\Й6K8e-0d=~ng~aʳ<۟\x|ng=M,bsWUb :m~S4d Q/Sr}o~t墣u H N&?ͮSFWN9jSʻ:q1T7RyMs ?]η߅6㗏.CԔ)xM|mr}؉7+3 Rznjzw_ǯQULU\1Klyv}߄jk]$TQ& X4aиED!&(KĔ9'b a5> N,JbB+zȏiR&l/aRSTU8J Ln%-+}xqȦ(d Ǫ89_w9-khxkwTKO۶CZ2pG1U1 arTOP#bM΃܏>y揼=ݜX3>qo~7; 2ZwX Cc_+﫾fVqp9PhggraߠoW+x0yUSWg'T%}طo}n2??k5zvv2{mq虏vyeuܳo\U @0k'bՇ`1\*ɚW8wr%!`=HD O=rK۳t1.'ͺꪪs;,Y=N:c35nv`_s 7!+Wf_ich]_wdV[rut#^s`HhD.M"G!l)Mgϑ -h4T*"|D H"$w> Q I HERDAkdn= kPZkr)@~LJMOJxQ.8L@ p c%3CRͮs26!4aJ/Rr+D5IaGu4"2,&D! bM~zq󧡐 ScoB]&6lP& ]bCy\4=~771{J;'JY|z0*Eo9ҼAgNQQ#~z[Ų#`Zhyzͭ` Y602⚃|󕣧=~Gg깪ݙw=3u}R[bqfըpE̔Chb9ZrptcBM CW[6tĝ&_{~mo8b?'_Y;&cW1(/63;Yi#D!S.ftݿm¼TDD^Z\>7 ITx5}]X;}k5ڞu66ރ7v7WCN܅jvaՇ3$ŞgO"8r59=n]hsD.efb8&br*f͓=}xaN0[·t5&iNuUU_<~yzd?&s/$# ""GT rTn=}qkjlܾ|=/sxgĚ+ )&8jgxcLS,'rQXHCDUdxLC1%Vë.&AwL> dJF}3&՞ ~Wk|V۽^O[_0\hl:ޙw\*1KrZ"$&ӭ`B|f9׮޾Qv}ιºrO%Ѽ~}?vzʻN2uwhvsG}ofL*19޴Xt {aQW{,[Ww{}ɩ/ńV^h}fr|R}ocՇ=;ڟ jVϐHAډl-+:} DL.̇s懺n+-|)IEL x{d:YmrҬ'u[Wm]fx^߻:xoϓǩxW \֓g{/ yOs05?[|:x+W%hM<{X|C đՏQ151@CJ."6U$)@Ϥ4hl@Tv(]; %;,"! ꠈ;6Oy&*;&5֤Jtbt2;fx>].y) $!| wٙp6N JI*Lzb`TF0(ûfJNKv&h˂4[nflY%eEBЩi.:wC T90!.L3㴴Q<Fu iyBԓ2|vTsp(@6ч|o=m<_u[-OZ?\u\{޻?snFb$Y\A9Hܙn|<"v*jkZVlh1q'ċ W;LF-` uD`vg+j+1'1EP¤ƬA*LO1#ӲjM}Vx+fu}ۯVGI<+mGa"l3|;5;ᕅ@W% dQ|O06;JUtwWfcr8i?}O~glMjڬk9_hySgzF ~+c1ۿXϏ]߻V&mtr=_gjz+~K["F>AO2bqF> K)&Pօxu j GL6s4@y1J(HGSc''!V |+TInL~<+BCU%AHdUA6A2wBH( ]B$j!%Sb jOdrm#914 3)?YM,gJT1z)qIuwTC /Hsvry E`؄`8G:8xp}CS?ډq jtZ(0Gy/Qb O@a")=@k#P2U8 =VOwbl~ygQ1S+?7ߛ>}"%Gs嵗oW+&j+kТv'[o>5q =1ąּX:0wvL,ô?:TBǔ4\S׋XyO`p+gs ?^oa-B]&;U/ܤoŅ:qbQ7–;8M•+# +, n;>,qq=;y{z=--oOv\vm mKZ<&!A(I󛳆'\NVr,'մY׮z#WړHT o:;檚\y}#Njۦ'm;]f[Nί Y-OAL*wu @׿8v`6@'S勴LF#(D<#]_N%4zT2T` /H4pDڪ*!LNZG/|$uiY`$o:&$ &)!G $ȤI ̰Жe<1;"(LQ9 љZ Ph)EBM_>?i=ٺvh]fRyd܃Y;fK!Pk.yW;*[Whhٸ-G{͋Ϝӫ6ØHY56]<v+~zmv.,laaS 7*LVh ;Śֽ ʲdw޻OjѦ2j5=T@x*ΪiPoU{+[j++乊449[n+OJ$n4; ^t+PrT;ԝ;n:DwJnx˗PA*'Ԗ cӾonN't1.ͺMV"M$}G@ĐI5sdt=u]}uu7m;[flV7կ~w !&9ι$d%\'r&4:GY B=qN4a&w rr`f~{#|vkNr2YMUS뺯\gWn/$H`qWg{_&{2궝t>՗~. L6bz#YZ*B_@*E ĥ#<"V&Pq(#AE$Bk3EZh3t=HO_k~Y2/OUd@8PV†~DhoM,P$S栥."%ђ Pa:d$"H%Fiff/d, o m ώ DQ(-̓ʆS))ȶAk1 hco1B"`!f0?^q`/Y?QIL%10V퐀= hG{a[w/GY=S&})Y%, 2/mrqc^;VWqv-h(VMh踦KgØM~o^|틇w/׺ݯZH7?Ͽiaw/~~8qwOw^{׏o_}_|}?~J~t|xqY̫oxg2?}K/.[%y{^o UO@E$,MBʐu₏h2S"IPJTn2U9AO75=ThK6[1,LJ85.ˀr#HJ;(4iX,f4صc)8(" Sßoffrv.-6~FGt3I5v/XX+W"$ux[ewpgw {ٻ'L@8V8w_g~;1G=93gҲeY2$ O;hg55yw"+fn˗K*8"~z'{:2@YU_}|۸D$)n~Vc%5xu5m闿|7O_x/_}uw[vwwӧ_|KǻoOzm/^~rw]ᷧ#n/_{|wo^{|RҊk@uBSVW(!;] ۲-J~V.3lm.НNI9EY[p$DK4O>-> GQ2KHvd*(ҁ9:AN<5r6lu.$M-5z7 BmiA{-ڋ~?.ntw䉤2s,^0;̢z :}cowOo}e#ejƴ\j#2M3n2Kr`9ey E,Y06Cl͑VaRxeHdң3I%NiL &u-GS733c_Unm8`YJ ֣>0lCx6;o'W~tVl^1-6 q{gg簻$A\s`{}lz4qg8a_ByQ*?`qI%aWCOjZߴ#zE,ZD0*G|2w;'1W{o}};^?7;.8'vۇJ~vo~">Ҙ*F2cEcz,}^ʻ8Tш$htPq<&J ؐ {;~w?~ˇ>ܿx_Oip?YdȺQ?{o޼~go_oЬ6(YV!׫J7];*&>*q_yEzTa+Eͽ0{- fyC rvpXA;X< Y`µZŐIHz&t#D׸Ζނ뗡C{uLq' h"m-S9]cΟ#sx=eq!L{~Tà[y#n͞ƙ[c K߉Π=/4g4n3oyT1.c({2NkgT sx)3#`*[7;޿^}x/n;lV{܏{{>/֧s?~ŗ|Њ`[6 Y k~ r`eǗ_?0zh0+Y,Vu}v駷p]2:ql@I'O@Kl0o|u;PveG<_p9p[wpo& FƆ/(kjeh7{/?>?.|%B$L~:˷:Wo߾ˏo}/XWGOJwd.B*ڽT{AA*W\$ъ6r}r7ouҸյڄ6c!-Z$ #HeUqł%j`l֭Zً#doa\i Uk)D=@x1VYHxXDa`x3cQFok#Lu~ef[5ΗN}j(=Id}. :>[*~`^d6ހ<`[{pk0WL; ctI'L/ѡ fFme~?91Lsre[-Z_Îk .MC:mnr2l<ꥉnfxw?}O~/n/vb ;?=woV|ǯwsg@RE&`2eh?qл^|G#~koȄCw8/ݗ|ApkqގrvonIb@֐%C6+ \0s53{;w?|?nwg<τh1qGEfg<儧kc4#f8VGEm#jjyϛ}/߾|܏u`Ӌwo^}O/Gկ$WwY 1cr:rT-EjAOwPe a#|Ubne8[aamuI˸1v8d," ī 6+#SfdN;e >$6'Tc׻"52aD@ܩr#f{ݑE#0Ѵ%krup)SF&h :e,/L{Emynyvzd9D(Ddi _!e A=S  Lg  ;`S=5;W$:s8/ffs.I?޻r4kQ/˃;#8$!5K(Y(8 M0qO??WfGx͋ۛeo}6+h' ^WBe0$t$#Գ^{XuxZ G,eǺŊ/+w>Cc = *!/w +ƌeSi}PEECk+2_/}۽vwr;ۺS|x?|wJ,@%F|\D߈|# j#|Uwڗo^xûtW۱nǧǗ_>}?'g|A*)1!Ėg99XRwyp{՚WG-ry'%j. ٚ"wUG O|oIhu;&_$h!Ϥk9WQBbBm`-XTs shtP/* nKF~bk+Dg?糟 ښi4fop^+{ۿ7!D19n'^\Bmϐ^r,{yvsl/~nW_6dgM3f?ײѾ V)L3z>{EY@VE;vՌWg}fOo/򃟼{i7?j+m㽿]'˗9-%/ES/fT +fR;(0tٛwYO^~f*\ӧߎuįߺ?~OoѷsflnQ#SqB{|nHUwUЊVS<`ul>wZd9EEO0M% ?_(< p&Ivy?$ |>saNM6CޤbhkuN%!A8KCR EUmQ #jt0&FLF66izޞ9st3C {s'E绗Clisڿn#tnGȦN. Ad@ʥv$ Xůw{sq̏/߸O<>>RXdetnD}@wNAL#mWϚu?MfT֕ےWzɏX2,n {[O_|oj9I0bA%ĩ6W:%d{D!)6 jdf}{_7n* wݻ7;ŗX"YŽ>ƾ×{\N8uʗ>!<93#Y 3*CmN'.9uf + ۳ ع8|9]NgFBgѲ>0Y.Ӥ8ewCzriz}1{{|Ow/bstlwVʳs*!YG'I*BDn>z;#^=XxԸ@=KIh/qCTBeDe|/>{w>w??q (X(Wq[eb喭]rYQ@O0ی)%'I< :vkđ`@Q͊>TZ k-y6C|ٔ7;%0C"u@9U dN'JZzLĴHjax@Isy 2wDʹ4gذ0ڴ9Lps%+ FW!vQ-A{h-`Sk jmsq9si>0eNy a'>0Ljkf;{AmyzY8huͨ1m}gϗ_|0j;y} 34UG接qIS2u<<ײ=bN5<0ᗇT_|g3Oě~>Jjt f,Aj Ͻ&H]i@AmSOO nƬkϧ9st.:NdV)(:> K%0s] πeq7xv UДQҪeWR4RO 3Ae5T}hq>ir&7ZOyJ fʆ[Dzձ)\;3 ^iTmLGQ[.Y%xs|& u͊&+m44}n͆P(m(u|K-o}݊,Unܪ|mMTMB${ey/d'I&VݸIYZUI3&-ΟtŅRbm-ݻRPBչvEBis~|,~\=0zzl4?=rfk"o#'fk֧%u.3'{6^(%7*`vEyv ?TP臙""[^;"4-3LnW3mur6/2:,; YZ Ȝ(kra[y&C".!+%Ĭp:i=MY2EuH=Q;"K<{󎮸n!apHpfQI),kBRD<1(=sd])D!ܨ!2[MG*Z֨[Xh4Dq) s;#!Q'5㺋 ^!zU2"0iKwRPh&rH&|򊎁<8huױag?0wxa[G/A{Llr@D8<‰d!DL88Bd [3)obdti@6 ̖P ,7= ?AYDHU]{jBTY8Ga!+ :JF8j\|Jz*CN&}%}5PxfeP&==eK2Z@㲽^g4eh[ɾ35~@<@dHS]jT=Ezǔ!V 5 Oy:>01 t ڬzD \je)@ ]G! ]y;7JS b׿c 8 u&kv鄎@Vje }g8}GMipŒ8VǀM:6s @@Ja M_05UsmrYb8z)~=lj:V44Z*d~O=Ҟ˷Aϋ!Hqj ;=lXϥ`` HG-=^J.pc}ag6)/|8m#h `2|`X8Xk_Z[H{ĐTqSͼT*Zgˤtu)†1,]J)?5*Σ@Yhɼ 6ҷi ȒDk;4py(h{#lrE ߇ +_i' .L$5=\џVl]HbaC{ӏv#j(Q6.ZD.oxeYݗ6: ڷrkch)o4M.(pj q~_g)F/sA)Pp5ǀI,-ZW3h9"A#HCI ZcGQL0XA͟*㋉Wt'yEzmƣmBЛITi7Yp~|ָ;fPf,3y'7i``򢫝+, EchtB2uVr$[@ërE/68e/n+|KP\QyE[ WPLCk\wǚQ]0=IBۙU[WGAqwtDmzT}fWСB?f<6$44!-ʝQY0ttbOT/wz1#Z}&PVŶc> A=*a a.0u<ׁcY'DnW`.LftC 0~ fw;U;ط(|F S o]bنHaϭV"lsljI,dU1| *ʯ|R^∐z-%I 0]8oa#]#o-`۠*!OtAl%%7 Rļpv /vj\`ʉ½& nsX}UYnG r绔;>03ʐZi4;g8;;^/)<<>Gt?AEי!38Mn[/,UaXsHKԹF,$r>mT `z%B(SC 4 0,4.U` `lgt"`G%i %H2mM5T5(p$<&j A3L|$`_XV7JG؝DƦ/,%lh/1+Q(&~Ry=Ls`=[NH3l 'W$0JQ稁ynֶ4pE'&3}̌Qm2evQE_ivY1ꍢHӔ`L֝@RR}.l=lgKaYP,elovh$DAߵ+Զ[l5.qmd`t) _H.-zƹ>_6o\P4$]xZ? _p!E# ,3չ܎VfW4̵ő.&C>]endtڣ` Z|ȻA&y |Tʱb b3YVPD# @~/oZ܁ȬV_:"#wjf" g`c5u|`b×ُ2"B ՝tM$u o+všwJ9𴆐mis<p&<֊ uyץ$'`2.zL*yFXB(5*if,E7q%k8RPJO 5ތ<%N|YOdn@|ji'&@l6ԑ)6$i/uv: Jh^n9=x?fqȱ\Xe&Up-]Oz7,u0&J\JI1ۄJ1V]9c>6I%K(prm2whU/ }^ܸ|n=? Hcl7[ ߇q;,lvqgS%oܵE^Hj*UlyWUv$ ⨌rZmOuq8〣 I-X[( FdngVp"(7pf9"NKV G G<9@G̘sEVIqJ0.LS8BNtjŝ":A0ҿ R4tpěByEFcQ~o$3 ,[ V;EVsLB|2%B,(L+Rt3 L.pE}d"+H؎YD,."T->LflN[`FMVyv֛$dMES ׿Ǡl0 /uHXeƽa$]h2@b9IoPtB(:޵im:A?h]d4>Tpoծ@%|x d<0z-r|PtJ)."h&UfZ8Hg^5;)h> !T#Uك3>}N/@=iA뜙U[,T\4KjIP 7k%TGbqOB$;.fOns(N<-hͱ%pF=qÑ1d :ge;E0Zf0(Fz861tl*kaw8fnBrš;rV+gQ#][|g#Y+0@H:.UF7b$<X4 ỏVxK Y.K)TNܼJ.Yn0 lB4(P;3G$)ѶqE8!2>6<k):C{ M0PӠؘ_`{ mL^j=\t])(?rfGtΰ_Ȝ#shWD ~-;}׋['|ViϺ4p(:DCxG&Ë bAkKD)#~J#Ol"(^DtMU:+x _f 0l '΍(ll@bD^B{?f+Rp`5tƻ}K3=w|~䨢 'QAIMQh\MsU8.hӚ(WL(qվ[yM; *lP&kqILFVr>X^p#c]Ƴ@NX8B;i\Ae %X. ^rT5L.5%?]y& 1QI܊~@哰h"%%pDx?'uJ- 9z#;*Zn=(^Sh9:83ETWi}nA2dX˕IzQB$zŖXt.^kpy*~p&ф@"0`'2%]Q3m/mNaLĉ0Q!Ɇ(Ј&ӭ"xhn Z05͉AhӰqS PEQa."XxM!r`W(Dil=l' _yn&, ]>}`]B{$ң/&5q'my_Ri;k9Yn5jUw 9y`K>ک = "ZYUw=EU Kc -/3I0 9bBZ)VN;jv \AnB!cV-Q /+0L n\e`xb s/WVʢ-t QzyuƭhhY +&7+J|;%R kf;Ҙ\DDZ(?kSȜ!qn0;=(@8׸"61LXb!FţN7#I"ԸxY[fL7Yc-d>+ 2L},r3~-e.5_Wqb/f#*Bv3#j Rm R%LvJ$][u5C*wJPvCB7ʔy_(**IZSMY 5“-[Y «k- n9QgsX>Ȉ;ANbP4#1XC3tcq* ?wÀQLy4΍NiNt{|"rf^ 7_A0jWPplS>X(s-c|3Ne&1U ?jH`fØ+u괗}2H\h: ~)j5!_pVmӝI/lhEF|wM³r&IA5*b "P?Ŭ'߮8R$Ijr.sW=Sa ,9YɮsúpNUǍe Hdg s۪'_iځ%f0TUV&8%ƎJ0óh``3z=BMَ w(wŝсA)P0L?G09MF$jq1lZkt)aLփTy>d 5`"I3z}u0gQ" @b2Řdh#KU|?d,0sؙ5[ϡI2мTY_XfTHu%om;VnqRmi:H .s53^gĄ׿^--zQJ[P E[4*ԦȠ0AJ36@ de+錜fc ^y\S[QHaxo9Gr7V'hʂ,BLJJz`'9"7qpo:8%`_3_V_q]yat"P#%ǝn !D-R͋8<@B'_B#߅ [@majn j%Œ ?٪ iK7[A+/aBD2 kC -M#Kk"XbYǎ ]CIDvV,BUƲFZQ l.2G 9mtx~jw{Wᯂ[N;\[ qgηOy3K3,U ߛcf r![6Qt @:PG!, a,3n:Èbd H|>\0'- a6̍6#.LrV _΢wl3)!6-z9pR!֌MZ *|5CSƚŰW,IT@>qǙEgg%l(Jڼ&e_)8DǔLMmO3gI>۠j[I>UQg@?{pVɥdSW|<~ ad#v,vK)WϹ@ySyU6(i[1j͏'Z ĠuoyD,+rEakk+wf0 āfZm/[GnF E\ ?mB?0(DЁʘь ^NgK<g(iVj!MƊr9ԑk!1enV}Ni,+ <š҅>VaR5HH o GiIeQ2R)b[ꁔ!uc^ h,/ir`4 $n*01Aχw4ӨE/6RG3J%Œoಁ(J +" $BiJi)sdeXٕ׊-"FQ2Eh|pyd)Bmel$:;;݊RIgc05U&@@_o;[k:aFH4fBVEؤeXixo aKMPwo 0+<N䄅ֶiGIDȭԧ~F~E."! ԫ4!KzOs1mݢ/4~V"Ūs=dv5eڊ"eFbu8d\z"s.a%6ͺveHjJƄ v.I5LW$I ¹UPנwm/3]kQ :#ޢ}8C Φaʌ$>HGQȼi ̺B:㹻A'YRM&Ơzx:?=?g; 40l̑XI kT%AO^WiH"28"y` _cO,fkC􅳨֞%YLGآ\鎊ײwJXl01du45w(Hx0[vu@dy(T{A;0/"\Lb7c hLb's事**ҷzy'oS>I+fT۶Á]e] MF;x*2D0\v$ʷ%S%{0>UM 8%\D']Ūjk9)KnaDU$"l UWR>cC3!P9hzQiV-3:FFŔMkm6F | )mG| i[GljR; ݴ IC04Y*.&L ^f^; }VuvQ شn(َQ?O9O2د?7:Zs'Y㺈ОCrEy]Z^|7/|"\ۅ e3-?:e4;afhli[ 23#"忄5fd Cw :^hҞJbڤ*Yð#c53Ihmb<_ jbhi,,omjt@ 0[=D4-DK/6rgL1\`|wwj5=̛07`b)¥]dLeH 1Y)W9a*ZiERd]3:a IH W͌o*cG@qO"Bb ~7Wrs$yc%8yZ]iX} hO&pX{daꅄýE&EtW"eD@1ijd"gj+NVDBL+Ҭ| WyXa@-4k;*Mk[к@  "@((`~4Z;f*U8]aS֦' Fp7ްF>:CMBGHH.e#]ػF4D?m%`,@*:%) { ׁ]Q@$^>1:)ۤqYeϷ78oVmɑ#VJ)IeY@fwX$A5ɿ0YS2z÷ h1PG:LNsאUNQ +@\E݉yx Y4n㠶#݂d8ݡfsxp'F,"[Z07)~$VD%~:Dt%i"j!SC%YY),t8`]S&ynRⱬ,+(K>6[K"ѦqG9iEҸ]PShTk-WH!* =rLC"H0SiS߂1܋*>(<b  `WF{[$D|{VTi4 b(šR hLJi'vg ieBظ3>6 ,T㳙^тǫx1 5P6N෮`EOQ@ CI1m;Ζ08l:`h°KtަT~\쿱Aa)-9{elvL9⾞a"Fl]O7m"%zo`:Ert޷]eq$̺Uu/$ _ N͖)MDE'|cB2#O4k2ǝ]2kcG` #hꅿ#S/]aQ ҎotE"?? j.þ$=o]{I-iBbJuaAh-}ox6O`QJ*& ^"aL k1HLv{B=k0zaW<ƣЅb{^u"MfF"G\,D ~@7ATUF)P!@zX6GC]|^ "<͌oú"3ҫÊ=M䢃" PUrE#+H_Z̑$@˺V[XS$ "w~ç9(.> 5B(#cjj0f S\Isk!u0e؝QP㜻H+ (To$1 *_\}^ l['q{gXkLu3eErUkgD?"T۠(m\`ҷ9bشEz!Oxd8Xʚ5  tʎѲ:B& SN|BWj]~=gߙʘc5PHX)I"W1z| ~+0xSe6!qyDTpk6H-ON5@^QdHYzDkp նy_x1Z(עqaDnT:76];-n-3G>uŤ_У]1cd<egz\IGs{Is!ggWql/{,f^WJUs*W{skQh@*$Z|:ʱ: uؚՀ5 3FLWr"iμ=#8n{h ,0""-F yIjEbzs({G}XQ#+RH] BZܽ[sKC\d&K8XҷDx3s9ڱ ~0A e(c{~&!1Q^Sܢ2NfX)f0`DH[BO KqQgN 25jڍ65E>+3tv&(gTm9ރ\yOh%d|6%HARKˆlԨ vz`#"E鄲%(l-0(.ȻySzOQ>i3XN '.W~(pܘ<"hm="F qCTZ99"(|AN%b6吩i5NཧHV;a䌱s/qiW@ B;PWC!Z1ag!ĔI]O)lѺEC'vهQ/K*qZVb(]K,Pz9 WxE^">!5Fo8]D"1㡣J'O/M7,oh 4q5rq# 2閂!qO(>}v1P]qggĔj(ƕIɸK7 5_z0zҐo}!mk깄4LR>f^Gr=Ο:-_U, IUHlTƨx3bk~M(îTq6If^|0/aY44W[ Du:7L_i&ҶS!T^9JHldXMXlCfH7F9st ,`Cݓq'(Z].fh ecMpgp~q ` `zGj=:Bϐ5cfV?v}OLѱ $> I@|؋|Դ;:dݘFUA"lj 6d C^ey\a%iiVm323K6@!9[Z1G8=iЙDلE@h8_.͢a丧dd :A/<*P t~o(+/7oW/#[D$>:> qBm$F-6{s2ۉRv{=g)t`t !wz8o+ `;SѻoP657f3[>1GbB(Enǯ 33^iݬAtP7$ym g]Bd$3ၬ+=z`5Ɓr!(^A\;ͺяeh&8 iv}DZ\[x%dMG֓Gn *k2nж-8xMPł j@W"9Nr .4ePM4YYŐ.?H+݋^\0p'gX&D{Suu1;b!1\X,`(iu7Y)J2&y6 .hxNM`X9tI(ob֓\4ϝE裮zvޏPD6H[.v%d@eF6)*Egl* Ufai>yN٩_nՃs+cc[Zq<}C D.P]5vmdRӠ*sFG)Gi0|g;b0`Ta\Ϩ*6e s4=קEEXP ˫QrƋK+S9Y_zY7 Pn6N'|Ja`AOO@KVznf#e|*ivTN65>4 ipu}2xB+}DbuW%RR&bCW W(S8To &`bu2Ѱ#d[ NafF ,+m#Ik̡-ޚV2}sguGj%^ihŤt %$~;Lwc*WUYCp).X$VʛPPaLvYPɘS- KV4`:5LH2}1OY(P\5  7m$indxʳ"7)[A)@Ҩtn; @b]BI:VFF1i,8҅N:LiZTT.LncI0`b cوω*GIav`֗Q{N"dۀI]cD$fn_~z$%"~}pJ!h &M ( sJ3Mfv#lS*gmlMD+ZF Bsy׭'JfGcg50 h7erQ7U^=o|top_܎B6g 5 /EzG.nDAPԹ@ f' &Y!^_۪ThUQa ,nX>2PBTI5Sk,Lp?D qG8-501BJɐwsHPbj7OAHHU=:g܍S캗ĠN/KVhYmeĹlytLVBfySMskb*Z㴸6 8khآ&0hhɿzUWs2 id͆Ú,}0:êل]θHQ݁͢pФDK+2]IaŮA0Isxպu,-jĕbή>wzq 4g yP~6I! jPA x! <41Fˡ ٭bf4޵֒~`4w7a}+m29im>WF]RJF1~^Sf=z6 ,lZ++&8D㼙Q7Ɂ *V t4E=$~;p]iN+4 [PS 5 #ŷZG8O*゘UOg̪]UWy'u FVۣ*.D1_rߧ'0-rNL. 9+PSi((w: Y<2yNQ&ln!V¸9e{V^c,h!Ew2n)I1aNWyM  ,@5O}H1)XhXKcE'lUv a%-`ǍECi=00193B&UDGl lf4˭Mml+3#"@գL ge[JIZ! M1[f1r [fGv `1g"6"chW@"~⋊ho&îW?‹~nj6y70.`%5b~Tr-:V/-7:%ǥ y0!ԎڋG΍:!g-VWrQQf!0 ȕ˺5Ù`08M!IU qD'$ P%H9Nf p"FcūoV+0췀2f^gq½ߢ,g> Y G L¨EyBv[y+δ8-ڷgrRyr%i$M, 2AP IRp+ahӶ{_;9oA-q?)E(8A,tHwr7G36Z# OQrm ub^QfHdYN4)3%Gul wsj9%6g~zdGs(`4@ ׷CsO8iW1/*.tw~3(FK8]93:;t @JXiNIaiR_ #v WՌ-DĤf \ȒۜY2 SAn9cQ@@OH ]VUh G-'rn2$\d> #{fX Y]&JQ=RH,QyN ڨUr2@)(bWd\Qz\F'NY %L ׎,VhhZk CKM[lA#’v`(|ZN$)C+v%=lz]&ud*pزR_NN'7񙦟'5OÒ݃A !O=4WKS? ^\:,yØ7/+pIS㆟s yf}:@(Rjq>]Ytqw׶"Y''~M;{aG NFK5*R6ampb'0nKg26e}Nt1 [}T*6Jjش۸>@S״h ̅ _ld [ĆpRk^Iyʷ$?ᮌU="+渕_60g'RZa?*: }`j2RfKRw:u0av i:|2vHl-&J(+m_}.u!J7TӏDhiʯj(8i7p"Ђ(ՆtapnY0Tb0C+*8c|FRN)̦̾k^ʂC@`LS< a*McteQe3Zm9wpV}gnG22Μ;#eH`}. vhFgk"gjmp9\"|}h+U:[ftm$_29d;Ǚ7:p^]X+*Ϯ!hPq[ fpA(Z$wrXC?ϰg۪dZ:TLJ;3!rDM:)ث svi JmEC1O_11~_Nr 6CrPe1*{0A `V=IZZd[*.qYҚ)yyMM"s=s5+-=סi儂Fa]AU1;-0;ɆxX ƤqxEYy*b PioBg4g7:-) e''`b"ha@ uHFnV#P+\DS[126)oWat>^M՚6wfCUuC^mUhX 5hU!e܏NBn(QFo6ǻu+CAY^TWݞˑlqy 瀉ji:BtDQv3ŷ2qU+0JEJ046s9eTh+8W6Q*o [M`xtX%Z\+\a hhtFG0[6)YMHBK(c8Yr0*#%3j4 5/Nю#=D)(91-}(H#vX9ْε ʋn8 SnyN |kT$Mm@ MK{-gjH&}psiʦK/n"ѷ-.w!{>{q%6K?Z)t,ڕjË́fg$ǐ%vT I+~@3#}P;7j0Ϣ_N0* JQ BRof9Sh&%36l1:3JG L=Fe4zÆ,g'ǵ)NaL c$S5/gV &s|$aAh?Z G_Ƭ9j@GdzKbDb,gUtMaHq"W~"gBOü ͽ&ϑF-e :M٦U()IH#@|j})k Z2< Wʖ$v-[dDFI_7+?4%*9^ Pa9e\"bP om D4lKYa.iRƞcܖ$A"˛"`[;e8 u 2'\B95rkZ}^1OhE%: #2n6g/ɍpNfޚLSރ f$uqJ3]c61_jpV`x)$f$) 8KPg4yw KQ/yyKn3!.CEy։ƃ0THc}3Z4tP6mkZÕtoG8ʀ1|5Vp}\(+hjW0CZ nkF)H,~Y06Zn+p2Q$; PPjy4ҍ d;6]rܼ a1!=-tFffufG>:GµJ wk@p͡4S7/86Vhڴs9.PW KLTIaUk1':͐x 囶$nN D1S2Db:VQ$U$v6w]j>SVe&V]C,oG-N)&hmGi$ZA΄1uLrZ'3aKN px4"1jm䊝z}m77c (9#5}V?".[g$  (v&[󉄣7EP >G+vM0Ri,31/{ӳo`:^2z#n$H[.';NB2|'_>3diX;/߇HW`Kmԛ?'&PZE4ƫ1nXL։y,$푾"-3wc:? JarF36dwwJLdlpU'hYI]^[?Spi.{ۙTbh0%Ğ0jG^_^[t7[+lbIR@ 9ĘV 7FVq0+âxJMT@6dOJЖيu,GQ$@(BA7;rȰNsW_"95EEڽ MLoxs (śtMնL?k E`䢮6h5tT ndOgT$zh<Ė'"k @ŋkq(~Nm"H>w^W\yn7"R,LU=߲g+>hcϕ-NkPnv?c3,2pt>.tp 76 ,+ KV!*!g/>]Cϡ7G!G}Xc5Իߕ~> !KЛk 8(_&ii\u1O)XQ1+dt2dp`iA U϶"@Pu9U x+vYeu.)iho] Tg& g ~I`A3 t遐̍5.IG2.in/}7C*m H]8,^e.m]j !>pS!"z޾*(&:x.~d|Y*;l7(I.V5S{9s^ rHJ`eTfO&SZq~1tP1!XX_@!1*@JiZ+N04T5gBp\MFoLsk}Q | NR֑tаg0Њ =IbTu)s`w48>Ju?BφEm0na԰n?:W,?HYt$`Y1G٭U CLÔWB'hxb= w 3Rk\׍UtИ+;65^Us Gk,Ssð_gDQ ȮrF3M3LgȨ'+6.)w~ hxn(MG @d6}AcC}ű ' 2W!~W;\D]Dl2hqd%MQ,7:Aۓ++^M¥9A)= ,,<% VQplT]lg{[&LLCL0@vdP-Ɔ ^XlHQxc3r Tt֌D>[)Oˆ(EkIsxlHS&Ɏ֥EϤu(*[v0HnO"z$2e@\蟭=*%n+) < X`3?Ca5E;}K (TT}*vJVпڹ1քf -$+tٿI)3M۟X3:bm@NJ^ ZXTl`|U= eލw=XIT)^$5wGк;͢Kv''` dSDa:rRr .R !ZCȞh~:UMIìߠV99FMf{*+fլ|k[:6* B7 ~i-4ۤXW|gf˹09P*ii AִqX4PD2cR<,Bک8瀇[T /TQ/}(;2+ 4FFnbvfZU)$X `B(!Ƿ/1~ƀA[*G,[+6ҕM7 ۽͔&͓'6HF秄66މ#D} Ż['(7[t*zė͛\m+<+*g{^*_tEօha!,dWTB1j^ax2-Xe^Ej(W׊$${X%Ft1W_gP -K';7^xa yՂfYz@hTGt3xwdU9;iZf:Kfn`$Ÿ[X YG]k&()$$%%#Z"+s#"#5463!25#'32654&##532654&##,(vwetH?KQv51154114D',49dgbT>X ZF]k'''&$%%#.E"&&546632&&#"3267s[[sIx)7.M1ZaaZ1M.7)x ZnnZ'$!ibci!$'.& .& .:& .:& '.& .& A s!2#'32654&##A}YY}cWmiimWUnmVdghcAP&''?&'A&'&'A &'s#"#5463!2#'32654&##,(uu,ɹcXmiimXD',49dgdghcAQ&'A&'' "A; s!!!!!A1IA?&0SA;&0SA;&0SA:;&0SA:;&0'SSA;&0SA&0SA ;&0'SSAV&0SAd&0SA;&0 S4;&0SA;&0SA;&0SA ;&0SA;&0SA;&0SA;&0SA;}&0SA;&0SA;&0SA:O&0AD&0SA0 s!!!!A.!E"&&546632.#"32675#5!{W_}Mw+979%hg^fI&!)9 ZlpZ$" kgfh B.&I.&I.&I.&I.&I.}&IA s3!3#!A?Bs#5353!533##!!5!ePPPPKKKK WA)&PA&PA &PAs3A?AE&Ue;A&Ud&Ud&U~$&UO&UO&UA&UA &U&U'&Ud&UU}&U/:&U&UEPW"&'532653f6& -#/f28~Tp6E&eA s3335##Ai.Ii>A&gfA(s3!A.ؙAE&iejA(&iA(&i[A(&i?A(&i82(A (&i?A.&iVBAQ(&i?(&iD1s3#3#3#3D!桧+h.?PPD 1&sA s3#3#3AeE?EAEM&ueA&uA&uA&uA&uA &uA?E'766553#3#3 6! #e+eX}@CEE\J\/A&uVAQ&uA&u.S46632#"&&732654&#".VmnWWnmWPRRRRRRPanZZnm[[mcooccnm.&.&.&.&. &'.&.&.& .&.&.&.&. &.&.&.=&.&'. =&'.&'.&'.&'.&.&.}&.&.&.:&. 'S46632#"&&732654&#"'7777.VmnWWnmWPRRRRRRPJItJ;JsJ;anZZnm[[mcooccnmoDJJDI.&.&.&.&.&. (a!!!!!"&&546632&&#"3267'>iRQj'TE1RPPR1F4: [mnZ!#mdco  A s!2##32654&##AZz||z/../wfex)&&*A s332##32654&##Axx-00-lwfex(*&&).?$E.'746632#"&&732654&#"M#E:[2fVmnWWnmWPRRRRRRP9J'A3UnZZnm[[mcooccnmAs!2#732#'&&##32654&##AMzE"&5332653z@DD@ jMOOMk>&z>&z>&z>&z>&z> &z>&z>&z>/=&C>/&'C> /=&'C>/&'C>/&'C>/&'C>&z>&z>}&z>&z>:&>&z>&z>&za3#3,7?]a3#3#3#3 .,?5]&6]&6]&6]&6c3#35#3,׶;.ؽ;SySs s3#37%ճ$%Qf*f&H&H&H&H &I&Hs3#76632&&#"7%ճ$o%eH0 -%he75ze&H}&H&H/S s5!5!5!/eu3)3/S&A/S&A/S&A/ S&AAE&U''e;1 T#W"&&546632#73#'352654&#"Bd99dB;_  _-88--87 ?xRSw?8-Z"F"V,5?FF??FF? T&= T&= T(&= T&'9= T(&= T:&= T:&= T&= T&= (&= T&'9= T(&= T,&= T:&= T&= T&= T&= T&9 T&= T&= T&= T&= :r&* T&&= T3&= T&=>GW"&&546633#"3266554&#"'6632#6632!534&#"3267#"&'3=X.4zh14*6#!*),*M,.(v=Ec'&V8j{,%,0=@'J .&h8Wuf /M+7CT *z$v(,+)z%T87@D JCt?<:A>& 7d E"&'3#3#6632'2654&#":_ ]9Be99ez,99,-88 8.[,5@xRSv?>FF@?FF?7d ,E"&'3#4632&&#"#6632'2654&#";_ vu,  %& ]:Ae99ez,99,-88 8.[ew,*f,5?wSRx??FF??FF? E"&&546632&&#"32678T~FF~T4d2=7==7>2 c @wSSv?yB@@Cy &, &, :&, :&',, &, &, L E"&&546632#3#53'2654&#"Af:9gA:^ _,99,-99 ?xRSw?5,: [.8?FF??FF? R'3E"&&546632#4&''7&&'7'77'2654&#"0QzE@rJBX"=7"F&Q1}#d3@EW/320.45 ;iDCf:5=>s,]IIm0$9H..rw8\I6,.44..4 &m (W"&&546632#5#53533##53'2654&#"Ae99dB9\ VV ]+88+,99 >zX-6;>?9:>>; L&C !-E"&&546632#546632&&#"#53'2654&#"Af99fA:] 5hN.  , ^,88,-88 ?xRSw?5,n@a6%1[.8?FF??FF? QL&C z&'   E"&546632!534&#"3267C@tNMg4+'-/B>(G .&d |MxCCuM&T97CCC>t  &"  &"  &" : &'+"  &" z(&"  &'+" %(&" 3,&"  :&"  &"  &"  &"  &+  &"  &"  &"  &"  0&"  0&" : &  &"  E"&55!#7326554&#"'6632nzU,'-.BF"C!&&f>T|C@t r2T88?7J?y@wRNwDs#5354632&&#"'3#b_2no8$%zy.Eih  - U$0E"&'7326553#"&&546632'732654&#"0Ls.@E@> ^9De99eD;Z .66./66~ ;6Y,5=rNNr=4+R"F"q>;<==<;> U&8F U&8F U&8F U&8F U&8F U&8F !3?E"&'7327#5366553#"&&54663273'3#72654&#"/Ls/ BF` ^9Ce99eC8^ EOl.66./55> F  *28jHHj82*T"F"  F]a523553347;s3#6632#4&#"7\;YX!!+313jl).(6,;s#53533##6632#4&#"7VV\;ZW!!+3(z>>z03im.'4+7);&@:7;&@;7;&@;7 ;&@:3s3537D7s377d&GD&GJ&G&GB&GB0&G7&G3 &F&G&GD&G9&G!:&G' c&GW"&'532653530'cT !+il%W"&'5326531(c !+ilJ&W7p s33735#'#7׮O=7p&Y,7p&Y)7p s33735#'#7׮=7s37 7|&]7w&] 7&]7&]87 &]7 &]V Q9&]a&]/h's4&'3#6632#6632#4&#"#4&#"7 V:8O_;WV'+'+r"F"X.5594:io)/'81)/'81/ h&f/;s4&'3#6632#4&#"7 \:YY" *4r"F"X03io'1'7-/;&h9$&hR/;&h9/;&h9/;&h9/ ;&h9/;#s4&'3#6632#"&'532654&#"7 \:YYeo/)"+4r"F"X03ioim "+,1'7-/[&hVo/Q;&h9/;&h9 IE"&&546632'2654&#"5U|DD|UT|DD|T,44,-44 @wRSv@@wRQx@?FF??FF? I&s5 I&s5 I&s5 (&s5 I&s'55 I(&s5 I,&s5 I:&s5 I&s5 I&s5 I&&s5 I&&s5 I&s5 I&s5 I&s5 ]x&sq ]&s'q$ ]x&s'q4 ]&s'q$ ]&s'q$ ]&s'q $ I&s5 I&s5 I&s5 I0&s5 I0&s5 :I&sn I:E"&&546632'2654&#"'5U|DD|UT|DD|U:88:988JNVO @wRSv@@wRQx@E@@EDA@E/H/ I&6 I&s5 I0&s5 I'&s5 I&&s5 /;E"&&546632#6632!534&#"3267#"&'3'2654&#"2S|CC|SHc!""]Ai|+%..CA&C /A>Vu##"dE-45,-45 AxRRv?1102y&T87BDL?t 7346@FE??EF@/(d#W4&'3#6632#"&'32654&#"7 `;Bd99dB:^ c.77.-88J"F"Z-8?wSRx?5,Q?FF??FF?7(d W3#6632#"&'32654&#"7 _;Be99cC:^ c.77.-88-8?wSRx?5,Q?FF??FF? (T#E3#"&&546632#732654&#" _9Bd99dB;_ -88--87.,5?xRSw?8-Z"F"Q?FF??FF?/s4&'3#>32&&#"7 ,B- )4q#F"9J$ 54&#"7Mr@F[Mp<9gE.E7(&F*"#&]Q.70(>A“.X?8b% 5Q=8T- t-* '$+EJ$E"&55#53573#3267;lm__||(+ gix*, && >:&&]& &Q&42W"&5332653#53a]!"&1R km/('7-[1542&442&442&442&442&442&44 2&442&442&44x&4&'44 x&'44&'44&'44&' 442&442&442&442'&44:J&42&&442&4421&4@s3#3ݻ$Rs3#3#3#3ӵ~|q}|ѕDNNY&&&&Vc3#735#'3#~@ҋ@,MPҳ@W'>773#39*0A* ޼!=GS $:CQ=N.@&@&@&@&@&@&W'>773#76632&&#"9*0A* ޼!U]V1  ,=GS $:C=I%=N.@&@&@&. s5!5!5!. /s/)s-.&.&.&. &A+E"&'732654&##532654&#"#46325,R+2/)/;@M=1454Ms!!AA>&!A>gs!53!A_ Q7W36655!3#5!!# I-+$ga%;6ů;C|A;0A;&0VA;&0VI%c6673'3333'#'&&####""_IHȻCDII_"]8000/9^EK 0R-0 KE)##)Z*E"&'732654&##532654&#"'66325.Z55(nAGD36538=8k(50TI?JQB )$ ()#" # (#)lU?W ZG>_5A s3#3#3AcA?AA&{A&AR, E7#5!%3#3#3"&&'73267&;PmcAZ3S>45>QnĮA?A(D*/(,*EQAs333'#'&&##A\IJ_"\9/H-0 KE)#A&h W'>55!##f\+=&$!=X@WxP?-t[rRD1sAP.As!#!A?-A. q s73#3"3c?&\.'3E5#"&&5463353'32##7'#"33'326654&##7+nU++Un+#%BW)F*%$&*E)VB&$oEciicEoPZ;K$$K;ZP/a5#"&55332673K&GI= TI 1?AQ2 E5!3!33g-A s33333A߳--?AQE5!333333]߳g--AQ E5#3!3#7-?A s332#'32654&##Avv7117oghp'('% : s#5!32#'32654&##vv7007-ohgp''(&A s332#'32654&##3Avvx7117x߷ohgp''(&? w!W'>55!32#!#%32654&##f\+=& vv!=X-7117@WxPoghp-t[rR'('&Axs3!332#!!%32654&##Avvӗ7007ohgp''(&(v. E"&&546632&&#"'!!73267v[[vI)7-[1Vg,S.hV1[-7) ZnnZ+$"YU.-_[!$+  E"&'73267!5!&&#"'6632I)6.Z2Wh.S,dR2[46.Hs[[ +$![_-.UY#$+ZnnZAUO&UEPe Ss#5!#6632#54&#"eJ%LE:, TI A*"E"&&'##33>32'2654&#"^]no^]lYYkOYYONXX HYXEZnnZpddooddps76633"&5463!##"35#"rC+,|{[6& ~|q*)vfht?VW Ac$E"&'7326554&#"##5!#6632_&D*/5WL9eI&Bt <5OTI , MSu=s#53533#32#'32654&##uu7007GGMohgp''(&I%c>33!'32#'&&####"37!5Kd>F>dL^44..44_a2F$'D'$F2&&&&&&.N:a3#>3"$7:G`A5>,M=R1?8Yq s#53!!3#t__,AA"E"&'5326554&#"#!!6632 :*.6WL;K&Ar<6NTI  LSv=Rw+E5#53%6673'3333'#'&&####"="_IHȻCDII_"]8000/9^ĮEK 0R-0 KE)##)RZ.W3'"&'732654&##532654&#"'66325XZ55(nAGD36538=8k(50TI?JQB)$ ()#" # (#)lU?W ZG>_5ARE5#53%333'#'&&##j=9\IJ_"\9/HĮ-0 KE)#A-s335333'#'&&##7#5#A1cII`"^90c1堠0 KE)& 's#53533#33'#'&&##rr{(/*Q#]90GwHHw\%@5 @E)# sS5!333'#'&&## \HI_#]:/H--0 KE)#ARBE5#5!%3!3#!t䮮Į?A s3!!##!AAR0 E5#5!%!#!u㮮Į?-.;E"&&546632&&#"326654&#"3267#".546632qXYr   Z_adN_,"#+_N$I&)#`:Nh;8gDEe9=l WmuXrlsu(TD/440DU&z3[wDEe88eEDxZ3.RE3'"&&546632&&#"3267VHs[[sIx)7.M1ZaaZ1M.7)xZnnZ'$!ibci!$' Qq E5##5!#3bee,c& JRE5#53%3#35#3[=,׶;.ؽ;ĮSySs QE5!#5!#!33*,g-g-/RE5#5!%5#"&55332673fuK&GI=Į TI 1?/a57#5&&55353'26737d6;d"> EP 1?As36632#54&#"AK%HI< TI ARE5#5!%36632#54&#"yt*K%HI<Į TI &0E"&'#"&55333>32!732667"'!4&&p">nl Z`yJ)ap)D?"<%WfUHX)-E +mc42(!,iS_p8Cfi#Ebd2FJ`0:&8AUI&AA!E"&'5326554&###333' :*.6XNmr&uAr<555!##7;Pm\+=&$!=Xě@WxP?-t[rRAEE"&'532655!#3!36% -#乹/f27~Tp6ARJE7#5!%3!3#!D W5#5!%!!tĮA&DqW'7665##53!!3#3Y ?0/w__fnwt",jhkCE'6654&''3#3#35)&y;,׶;ٮ)!)SyS6S%M_& ['e+E"&&5467&&546632&&#"33#"3267JeBQK@IA~ZU/5'k8=82563CGBn(55 5_>GZ W?9W1)#( # "#)( $) EE"&'53265#'>55!6% -%!=X8\+=&$.g18t[rR@WxP~Tp6.?]s#53533#32#'32654&##uu7337GGMohgp''(&A!s!27'##3267'7'654##A[z{EA2MD -/JB2p{zmMlG4d E0];ZEW"&'532653!3#!6& -$.g27?Tp6 R4E5#5!%'>55!##u2\+=&$!=Xě@WxP?-t[rRA&UA0HRZ%.R.:Z&<.:& )] )S'E"&554677#>32'2654&#"E./? 2Q7=a9DyW/45//55 U#( 2F+D,G):lKOs?;<;<<:<<<?!s!25#'32654&##532654&##<.hZ?3E@ic|"##"|p pG=/@ C5CMgg<s!#<<&k<js!53#<n~W36655!3#5!35#?VDx*nU64h) )& +)& +'c7>73353373'#'.###5#" m$.!))~ -%mN &' O)99)̓)E"&'732654&##532654&#"'66325 H~-+%k642 # +84V%**Mlx=5AD oujKE-A A9HS<B s3#3#3<#$HH<B&t;<B&t?<~ E7#5!%3#3#3"&&'73267-GY#$q55!##@2* °r0a/E.v;bR<s33#3#'3<P4<F s3353#5#<)Rs <Cs!##<v8(m )  s#5!#sI I& )(h%1=E3#"&&546632#3#6632#"&'32654&#"!2654&#"p K29Y22Y93L K3:Y22Y:2K "*+"#*+f#*+"#)))-/AxPRw@0+4+0@wRPxA/-NAHH@AGHAAHGA@HHA_ (%a5#"&553326753y3uu*3 qo}5/<~ E5!3333EVv<: s33333<vv<~E5!333333BUvv<~C W5#333#v</ s332#'32654&##55!32#!#%32654&##@2* nil4`Ar0aQ')((Q/E.WU6R-v;bRu"!"<s335332#!5#%32654&##$K/"n @wSSv?l3'r >;l !W"&'73267#53.#"'6632K%;*%I/%n9XGH l;> r'3l?vSSx?<F K&G V DA <Q E"&'##336632'2654&#"554&#"##53533##6632i8(*!!+2WW\:ZX'_ /&.'4+(z>>z.4in=aH s#53533#32#'32654&##y^kl]yV%''%VppIQPPRd !'c7>33'!'32#'.###5#"37!5 l2E34 !54D3lM () N׹,5335+~ ~ 00)Rhs3#7>3&ݺ$R:]I199@"+ s5#535!#3#[WW싋x[x554&#"#!##6632n9(+*-6_@[Z'^ /&*/)6,ax28jn173353373'#'.###5#" )Qm$.!))~ -%mN &' O)99)̓~-W53'"&'732654&##532654&#"'66325ՉQH~-+%k642 # +84V%**Mlx=5ADwoujKE-A A9HS<~E5#53%3373'#'.##*4~ -& nN 29)̓<s3353373'#'.##7#5#<.d ~!.%mO  d.mm9)̓yqs#53533#373'#'.##AWW7u'!mN 0(z>>z8( s#5!373'#'.##=4~ -%mN 1s9)̓<~E5#53%3353#5#e<  s335!##5#<vư<~ E5#53%!##ev)6E"&546632&&#"32654&#"3267#".54632eG~U) 8DUQ\R"L?'MCZ@sX4gSTf3[w ~Ru?vIBJO6=##*3w%BV0M\\M1VA%)~W53'"&&546632&&#"32679T~FF~T4d2=7==7>2 cw@wSSv?yB@@Cy ~ E5#53%#5!#fs(F W53#3й#T&/FW5#533#353#ćѹ#҇ѓy!T%y~E5#53%3#735#'3*P~@~ҋ@,MPҳ ~ E5!#5!#333xrVsv(~|E5#53%5#"&553326753e3uu*3 qo}5/([a57#5"&55353'26753*d0."d( ttql4+@D@ @~E5#53%3#6632#4&#"e\;YX!!+313jl).(6,$.E"&7#"&55333>32!73267"'34&ۊ XHBqKMg4:F(F!.&dX)+ |$II!!!Ho>CuM&(K@t:,!97:&.@] &r554&###3373'2j8(*62?4~Qs~'^ /&71Jvj=`H~E7#5!%'>55!##,FY2* °r0aq/E.v;bR)RE"&&546632'2654&#"'5!>U|DD|UT|DD|U9999988hD @wRSv@@wRQx@E@@EDA@EOmm)R&> &H&H&H&(%&(<~ W5#53%!#e삂<&DW'7665#5#535!#3#3P G hWW싋TeYu$qوQqT:hlCNE'6654&''3#3#735O/&`;~<~ /hy"|,MN!1+-E,_&  ")E"&5467&&54632&&#"33#"3267 {E@4=pC{++#W37-" 146l$++ SH9@ @.EKluo??E'7665#'>55!* 3!r0aL2* +eW} s;bR /E. I\/)(]  8(l/W4&'3#66327'#"&'3"367'7654&@ `;Bd8704=<!,:^ b,88,E55!##e2* °r0aq/E.v;bR@G < s!#3#<\y~)~:&s&:&1  s535! le\e]++0LGW55!!55!0RT4S%[%'$s53&&54663253!56654&#"'vg[mMc8gvE;`NWW7#5!#'.55##agV)( 4DW0MN}r<$#5U\\w?w*.>"E"&&'732654&#"#!!#6632'/^P8,`1396.":r)N/Df9D} ",((.9fDHm;$@.E"&546632&&#"#>32'26654&&#"HOf:q+9$R)KM 0I,;\7?nR(((( uX$$]]4+= ;hBHn?,++,'2s!5!6O `8?%1E"&5467&&546325'2654&#"2654&#",ZE>NvwL=EV67765885+//++// l`Lc _DZggZE`  cJ`l)'((((')+)##))##)4.W"&'7326553#"&&54663226654&&#";p,9$R)LL 1H-9^6>oGM:'''' &#]]4*> ;iAHn?tX,,,,AE"&&546632'26654&&#",R}EE}RS}EE}R++ ++ CxNOwCCwONxC ;*+: :+*; ?+ s53535733?FϸfX,&s5>54&#"'66325!Ci}8-&*_)00Fp}It3L>}#UOUy-A1,E"&&'732654&##532654&#"'663251`S6.f/4786wi253.*]'0/FKp=F;EQD{"~"!)&'(*%#&}#,U<;V \E>[1LB E5!533#535DIVVo7.A7"E"&&'732654&#"#!!#6632'/^Q5-c*395-9n#N*>d:Cz"~"!1,./2bIGh9!A.E"&546632&&#"#>32'26654&&#"CNf;r-8%U(NO 2I+>_6>qP**)) uX$$ca0&8:c@Gn?.--.+L-W!5!6RʴP*B%1E"&5467&&546325'2654&#"2654&#",YE>MxxK=EV8<<88<<8.22.-33 l`Kb _C[fgZC`  bJ`l*)*))*)*,,$%**%$,A7.W"&'7326553#"&&54663226654&&#":r-8%V'NO 2I+>_6>qKN=))**%#`U.&89e?Go>mVx.--. p$i!e k w n p h r o p W"&54632'2654&#"S__ST^^Tolllllloe7??55??7$i s53535733$e7dTqF@q!es576654#"'663253's.5L/KV!&Ken $ iD:!>"D qk)W"&'732654&##532654&#"'663253S B%[M>R2LW9+4;ae b e=5(9719C w s5#533#'535Ļt55y j?\ d?n W"&'732654&#"#!##66324IB# ' >-(&>&cg  eH ;+GM p&W"&54632&&#"#6632'2654&#"[azc";8,3 ;";J[Nl`mxb -2E8CQZhs#5! UY#qi r%1W"&5467&&546325'2654&#"72654&#"Qb5-&1]KM[0%,6bS""""D:'8 5%5??5%5 8':D[ o'W"&'7326553#"&54632'2654&#"(>8+3 ;";J[L[a6`$b -2E8CPmfEc6 p$i!e k  w n  p h r o p$i!e k  w n  p h r oLG#3  $''% `$''% ,' '% ,+s53++e W'665#53C'!&-5&D'+s?g+S5353+F+e W'665#5353C'!(-5&D'+s?g+')') )w353R78-LW3537k8ʹ><!w54676654&#"5663253&$#'P#%e.?d:+1#6*E%'!J=">4#3 <!W"&&54667667733267#5?d:*$1!i&%"'P$$fD%M; 73$2)*E%',pw53,RYe"&&546632 1T2/S51R31SY/R2.R3/P41R0KS'7'7'37'_V&} x }%WaHKGg!r32riGr.*s7#537#53733733#3##7#37#D5I&Xms^r4J%Yn s ]3]$\jjjj {W#3r ?4{W3 ?4;S53;bMW.5466736@@65115HQRHwllwL/W#6654&'352256@@wllwHRQ#L'E"&554&''5766554633#"#5233 EJ"33"JE9//9MD'"!(EL :#"8!L'W5326554663"&&554&##532#:00:EJ!33!JE!9#"9!LE'""(DMaL{W!#3akkuL.W53#5!kko=Yw5!=Gϊ=Y?Gu5!eeGu5!ee=Gw5!=eeGu5!ee=Y?W5!eee,e W'665#53B%#'.5%D(+s?h,e&GG+y&KK,p&LL+y S5467'3+.7D'"'yr?h85'C(,,p S'665#53B&"'-p5&D'+s?gT&OOT&PPT+w'73TT.w#7'3T &RR S3K+*3a3DwwGuua`s3vvGwwa`$<4'E5.5466753'&&#"32677"TzBBzT"#G<:!E%JJJJ%E!:fE '"yA13Dx$#$<46W&&5466773'673'&&#"3267#"'7#7&&'7(@ %(6eE&n!9"n*):"F%IIPB%F":#r=+ n% 0+s*.}LX^ f]e_ $( >#3W'7&&5467'766327'#"&'726654&&'&VZ/.Z?0OBB O#,,$#-- BvMLq@,3gRRgU2.gg:CD;;DC:H5E"&&'#53&47#53>32&&#"'3#7'3#73267JyQf`an QyJ8i 6 > )??) > 6 i 54&#"'6632'3#7'3!732671iw W/OA0 "#L$13Bad P!O 0**)S93~ RG2b Ob  |!$HE5bR b"~'"]s#5333353#5##N88-g-$g &'K,s56655#535#53546632&&#"'3#3#5!'!"CCCX9uZ@p):)C#3-Lx  b8f..Fj;#-+!a=b$6Fs5575575377326553#v@@@@5kn#k$?$l$TkU?TkT";Gea@!s54>753'#54&&'7#6X@@W6# j "HjD  DjHLf: ) :fLCs5#535#5353#33#3##3aKKKKLLLLb>bDb>bDB s#53532'3#7##326654&&##aKKAd; ]];c@  g9fE"g#Ch9M6338C*s#535#53532'3#7'3#7##326654&&##aKKKKFm$xM  Nw!kG  Kc=btE?b )c>FM6338P!s5#535#5332##3#32654&##aKKKKPm88lOD.0550.b>b47^b)0/)W+a'.##53267!5!&&##5!#7'3#7#532y47I 670 libb>bus5#535#533#7353#3#Бtė%uc=b<b=chw53и0* W#35353əa -YW#3 -7(! w5#53533#|(vv7!Zw5!7vvB4 w'7'77'TTSS4TUUT7!! w5!53537}}}vv~~~~7!S5!5!7Hvvvv7!>W'7#537#5373#3#m#m#6n#x".SvRv-SvRv8!!w5%%58CW7!!e%5%5!BW7!! w5%%55!7.||U{{ww7!! e%5%55!!/ꈊ{{U|ww7! w5#53533#5!|Ꙃxxww8c!/A"&'&&#"'6632327"&'&&#"'66323272%!),VM05#!( -XO02%!),VM05#!( -XO+::2?9;1> ::2?9;1>7!xe"&'&&#"'66323272%!),WM05#!( -XO ::2?9;1>7!e5!5!w*.tw3#3*VDT&1W'7&&54>327#"&''&&#"26654&'P8P-7-Pl@)M"Q7Q(0.Qk=%G!3:\7!7]8,%f&m@8fP.g*g&g=:fN,j9 4X8*IQ2Y9&C d?#/w"&546326632#"&''267&&#"32654&#"GUSI@@ISUG@@( (( (d`XVb,,bVX`,,e)++'0##00##0'++)iAW"&'532654632&&#"2 (dg1 *c 'at'atD%s53&&54663253#56654&&#"TK?yWXx?JU%++%#+b^ON_b+#*GDR$%QDG*H s535!؉tMt|++7L!W!##7꣣u0LGLU W#53#3΁U_ٴ>V.E$W332653#5##"&'1. %/6" $$4+Z149*E"&&546632#.##56632'2654&&#"Ls@:fB;K9lM + S]1D~P'0'&00 =lGDj<,0Hj9?r[hP?5 .:13='3a#3"&54632'2654&#""&54632'2654&#"_ZdeYYddY*YdeXZccZ\wbcsv`bwl1<<.,>>/lwbcsv`bwl1<<.-=>/F '3?KE"&54632'2654&#"3"&54632'2654&#""&54632'2654&#"ZcdYYddYZdZdeYYddY*YdeXZccZ wbcsv`bwl1<<.-=>/a?wbcsv`bwl1<<.,>>/lwbcsv`bwl1<<.-=>/+8. W3'꿿B!!GGS w7'373''3537'35#3'#GJMGA"#-.?W@@WVV.YCQE".54>32#"&'7#"&546632#73326654&&#"326726654&#"bw@B{j{d2Z<>K -\;T[6`>5B}'(F`kUQdEs//.o/ # /%>r_hx@\tU~EA=NMiYIqA35] -S5[{?VmeO""X&+K%F/&)$@+--,:HE&&'#"&&54677&&5466327#6673'%267'"6654&.[)$1yCSzBPA$')8dDYkB1$2,B&[&=J#9@" '51! 1!)03[=D_#""R,6R.[M(F: )b5Q:%! & !'&," ."L^E"&&54663!##Eh:;iF[{i9gEFf8AG:OE"&'732654&''.5467&&546632&&#"7654&''&&'7I|).AI *. /=67 >sOFq$,%a*). /=58>s#& &$& % t@4?%6T.9$&6T.<";V.*9 *9,-AE".54>32'"&54632&&#"32672>54.#"Nc77cNMb77b6h{{h(R(0+33+0(R?@lP++Pl@AlP++Pl 7cMMb77bMMc7tddsf7016gT-Rm@@mQ--Qm@@mR-,'=FE".54>32'2>54.#"'32#72#'&&##7'32654&##Nc77cNMb77bM@lP++Pl@AlP++PlgIPMD"#* *00 7cMMb77bMMc7@-Rm@@mQ--Qm@@mR-YJ6:> #5dw S#5!#33#73#53#'3}lxm|{]@\%[喖iS"&&546632'2654&#"0K,,L/0L++L0&&&&+J./H+*I//J*[**** S3K+*3 &RR?KW3?w?KS33?sOO` w#53533#ycceeDpppp8*E"&55'754663232676676654#"TR`K5j0T6FI=K!"-Z:! ]Q8=:[8U0GF=rLc")f" E$.bw5#535#53533#3#yggggffffpoiqmmqiop2L 2E".54>32!"32673!2554'.#"_f56g]s['}(|NU{3G'Yu "XX#:5 8b~FFg=BoD01:1/>o ))*5 Ad +s3#3#3%5!'"&&546632'2654&#"Ae081M--M11M,,M2E?Eii'F/0E%%E0/F'T$$$$#%$$j1 S'665#53<$v1)&L-I0N S5467'3%<$v0L.H)( &RRR]S5!RQ]aa'-3S'3e- % S"&5463"30@@0%@/.AC%k S5265440AA%BCA./@-S73e-/S53jQ/S53jQ S"&5463"30@@0@//?Ak S5265440AABA?//@NFS53!53FN-0 C735335349r:yyiiiiN3& C5!53353R:aaiiiiGPC53PGW3&C5!53Raaii--9C'39e--C739e-k-SC73'539nΕ-ͽiiy-S73!73',^,^-jQ53jG-C73#'ookNN-qqG-C'373JokNNko-qqG-S C'373'53JokNNko-EEiiL)Q"&&'732675Q-_,%&+_.Q)1Y; 3663 ;Y1y!&Q"&&546632'2654&#"&=$$=&'<$$<' !!!"<$%;##;%%;"I   3Q"&&54663273'2654&#"#:"":#:} "9$ !! 7##7 5n#7 @!!-AC'6632327#"&'&&#"RK8(1 RL7(APU ;OV C)'!C'66323267#"&'&&#"'53353sJC2% JC2) D:)9: :: iiiiC)0C'66323267#"&'&&#"773sJC2% JC2) :9r)9: :: }yyC)&C5!'66323267#"&'&&#"RJC2% JC2) aa9: :: W]C5!R]aaN3& C5!%53353R:3aaiiiiW10C5!''3Rr91aayyW10C5!'73R9r1aayy-~C54>54&#"'66323@&8>- D '$ -S'3!'3,^,^,-L)C'>32&&#"U_-Q55Q._+&%,)553kk%!9A *)0(C, PG53PN3W53!53͕T S'665#53=$v('}K.J:}G"&'732654#"'73'6632!>'$  U )  /4G F VM($*1b:H0G"&54673267?F=10 ,<3.H0 P L) U"&'73267Pc_,%&+_cVG $$ GVWQG5!Raa"C5!yy/g'%B`Buvz2G'8NVOE/H/HFGJ'-3-s-A-A-F)s!&'AQ]:w\:B0C'66323267#"&'&&#"QL9(QL9) OV PU p=S'3266553#% %%@(pU*)0(H-NS53!53N C735335349r:yyjjjjN C5!53353R:aaiiii PC53P WC5!53Raaii=C'3=vC73=vkC5373=viiyC73373UHeQ539C73#'~~wPPVV9C'373I~wPPw~VVG$ C'373'53JokNNkoFFii9 Q"&'73267Vl_5--8_k]O '..' O]yQ"&&546632'2654&#"&=$$=&'<$$<' !!"<%%;"";&$<"I! ! Q"&&54663273'2654&#"#:"":#:} "9$ !! 8"#7 5o"8 A!  C'66323267#"&'&&#"QS?1 $  QT?1"!OV PU C!S"&'&&#"'66323267%53353D( JC2$ JCؕ: 9: 9:iiiiCC73"&'&&#"'6632326749r( JC2$ JCyy 9: 9:CC5!"&'&&#"'66323267Re( JC2$ JCaa 9: 9:H}C5!paaN C5!%53353R:aaiiiiWC'35!4r9RyyaaWC5!'73R9raayy~C54>54&#"'63232O6=  C# S'3!'3$Ue9 C'6632&&#"h_lVWk_8--5 O]]O (--T C5467'3U$=$vK.J((~p= S'5266553kk%!9pB*)0(C,#C5!#:g'ABvv g'7777bJsJ;JsJ;4DJJDIvC5!bbA^C53^A/AC'6632327#"&'&&#"QC2! - QD2! ,APU  ;OV jQ53jR2g5![ff;'S"&&'7326745>Qn(D*/(,*EQD)0 Q"&'73267'73PeO 3//3 Of9r)UH #''# HUyyD)0 Q"&'73267''3PeO 3//3 Of~r9)UH #''# HUyyD)B %Q"&'73267'4>54&#"'6632PeO 3//3 Of}   3'/3)UH #''# HU : C)B 'Q"&'73267''66323267#"&'&&#"HfO 4--4 OeJC2% JD2)  )?66?:: 9: G-X0 C73#'773ookNNR|-MMmG-0 C73#'7'3ookNN|Q-MMmG-4C73#'74>54&#"'6632ookNN    3'/4-MMm: C-B C73#'''66323267#"&'&&#"oohQQ"JC2% JD2)  -88:: 9: D Q"&'73267'73PeO 3//3 Of9rVH#''#HVzzD Q"&'73267''3PeO 3//3 Of~r9VH#''#HVzzD %Q"&'73267'4>54&#"'6632PeO 3//3 Of}   3'/3VH#''#HV ; C 'Q"&'73267''66323267#"&'&&#"HfO 4--4 OeJC2% JD2)  @66@9; 9: GX C73#'773ookNNR|NNnG C73#'7'3ookNN|QNNnGC73#'74>54&#"'6632ookNN    3'/4NNn; C C73#'''66323267#"&'&&#"oohQQ"JC2% JD2)  999; 9: "RN".:FVbnz&2>JVb<HT`p|.DP\ht $0<HT`t+7CO[gs,8Uap|)5AMYe )5AMYeq}  ! - 9 y  3 n 2 > J V b n z ! 2 > J V b n z   $ 4 D T ` l x  :T`lx %1Ez*6BNZfr~'YD%1Ar~ ".:FR^jv".:FR^j'3?Q]iu +GSlx BNs>JVbn~"2BR^jv ]!-9EQ]iu 0t %1=IUamy)5Hgs    R ^ j v !!@!L!X!d!!!!!"""$"I"Q"]"i"""###N#s##########$$K$S$s$$$$$%%=%o%%%& &&&'&K&&&' 'G'O'o''((F(t((())4)P))))**+*G*p***+-+9+A+M++++,,C,O,[,c,o,w,,,,,,,--*-6-B-N-Z-f-----.-.\.d.l...//#/+/3/;/G/S/[/////00 0,080s000011:1F1c1~11111111292A2`2w222233+3]333344 444M4{4455565L5y556+6X666667E7v777788.8Z8b8888899C9e9999999::::):W:c:o:{:::::::; ;;=;m;y;;;;;#>@>u>>??X???@@#@X@@@ADTDfDDDDDE"E.EJEhEEEEEEF.FeFvFFFFFFFFFFGG GG0GGGSG_GoG~GGGGGGGGGGGGGH0HHI!I`IIIJ;JJJKKJKpKKL LJL{LLLM MM1M>MRM^MwMMMMMNNN7NNNNOO`OOOOOP P0PnPQ)QCQmQRLRiRS:SSSSTTT)T>TTTU(U?UVUbUoU|UUUUUUUV VV3VKVWViVvVVVVVVVW W7WhWWWX(X5XMX`XsXXXXXYYY/Y\YYYYYYYYYYYZZ ZZZ(Z1Z:ZCZnZZZZZZZ[[[*[6[G[X[o[[[\\G\y\\\\\]]/]J]a]y]]]]]]]^^$^A^b^^^__,_\___` `L`d`|```^ E_<H\I{ Aw....... AlA  A  A A#A[A[A[A[A[A[A[A[A[A[A[A[A[4[A[A[A[A[A[A[A[A[A[A[AGA.......AWAAA;AA;A;;;~;;;A;A;;';;;/;AABAABABABABABAbABABtDtDAAAAAAAAAAA$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$..AA$.AAAAAAAA(((((((((((A.~ ~ ~ ~ ~ ~ ~ >>>>>>>>>>>>>>>>>>>>>>>kkkkko/o/o/o/o/A                           ]]77        r       ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (        o7oo7o7o7o7 3 7 7      7 3     !    T7T7T7T7 7 7 7 7 7 7?7  //o/o/$o/o/o/o/o//o/o/i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i  /7 ////"//7j4j4j4j4j4j4j4j4j4j4j4j4j4j4j4j4j4j4j4j4j4j4j4j4/6.......c........A@7A@3fvAAPAPAPAM [A[A[ADxAAA"AAA tDA$. AA.~ ./IA\AA AAU A A(. ;A; XA E$.7A_x A)A)o EAABA..~  //AA;ADA5 A5A/D[A..DxxAA$.$.$. /PAAx $.kAF ;AGAx.x.)|)\<<<<:):):),~<~<~<<a<a<{<<{)<8) @@)Gb(<v<<<G< K<< !4)12<22z<S~ {)h h<,<<d <<< )) == b((@@2@h<<<(<))n%:):(:(,)~<~<{){){)1<<<b(<K< GG,{) 8|2@<,),& q0@'j4XX[X"XXX.X$X'XXXX?X,XXX.X!X+XX| |$|!|| || || | | |$|!|| || || | | |$|!|| || || | | |$|!|| || || | L$$++++0+<,RX.``/;b#a==X==,,+,+,11CC  XXXe!!!X$XGX$XXX XXX XX&XX'X6XXXXXXX&XXXXXX0XYX7X7XBX7X7X7X8X7X7X7X7X8X7X7X*XXXiXXX7q0XQ.XbX+.[/,/,  0?0?u^8u~2A~j R' NNNW-kyGGGLy-CCCWNWW LNbLW"/zH'sAAFs'Q\NNNWky99G9yCCCHNWW9/R;-DDDCGGGCDDDCGGGC,EXKX^,,P KNONE))    /9~2~(-37SWY $(.158#:C_cku)/ !%+/7;IS[io{     " & 0 3 : D R p y !!!"!&!.""""""""+"H"`"e%' 0:4&*07SWY#&.157$;Dbjr$.  $*.6:BLZ^lx      & 0 2 9 D R p t !!!"!&!.""""""""+"H"`"d%'!O+$ PB=+(?5cl%}zew~ck_<k PRTVhlp*`bdjNTZdfhntvxz|~~~X.Q5aR9:4y*?)6+,}0 '0HIPUegisu=7>F78@FVY]fhs;<Y/^q`uM@2N'&(1 #@16=_WY[){   . $+PHJLrtv}|!%&"*+C12!>,F43"L;J9N=M<SDQAdUbSXIcT]GVfXh[\k^m`l_narewiylxkj|ou(/jpcv}p ?K:Z  <*B0ZKaR|4~     hijknorstuxpqlyv !w^_m"#$%&'()*+-./012345689:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\],7`a$,.E3D25#O>TERB\Mobqdtgzm{n~q  ?-A/G57%9':(;)8&`Q^Owyz{xUWZV[CABDKLGIJH3eibchsnfg]rpjkozv    .    ( ( 2@ 2@  r 4              Copyright 2016 The Mulish Project Authors (https://github.com/googlefonts/mulish)Mulish BlackRegular3.603;NONE;Mulish-BlackVersion 3.603Mulish-BlackVernon Adamshttp://www.sansoxygen.comThis Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: http://scripts.sil.org/OFLhttp://scripts.sil.org/OFLMulishBlackMulishRomanWeightItalicRoman,"$     bc%&d' !(e"#$%&'()*+,-./01234)*56789+:;<=,>?@ABCDEFG-H.I/JKLMNOPQ0R1STUVWXYZ[f2\]^_`abgcdefghijklmnopqrstuv345wxyz{|}6~78h9:;<=DikljnmEFoGHprsqIJKLtvwuMNOPQ   xRy { |z !"#}$%&STU'()*+,-V./012345W6789:;<X~=>?@ABCDEFGHIJKLMNOYZPQRS[\TUVWXYZ[]\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~" ? ^`>@B  !aA# _C      !"#$%&'()*+Abreveuni1EAEuni1EB6uni1EB0uni1EB2uni1EB4uni01CDuni1EA4uni1EACuni1EA6uni1EA8uni1EAAuni0200uni0226uni1EA0uni1EA2uni0202AmacronAogonek AringacuteAEacuteuni0181uni1E08 Ccircumflex Cdotaccentuni01C4DcaronDcroatuni1E0Cuni018Auni1E0Euni01C5EbreveEcaronuni0228uni1E1Cuni1EBEuni1EC6uni1EC0uni1EC2uni1EC4uni0204 Edotaccentuni1EB8uni1EBAuni0206Emacronuni1E16uni1E14Eogonekuni1EBCGcaron Gcircumflexuni0122 Gdotaccentuni1E20Hbaruni1E2A Hcircumflexuni1E24IJIbreveuni0208uni1E2Euni1ECAuni1EC8uni020AImacronIogonekItilde Jcircumflexuni0136uni01C7LacuteLcaronuni013BLdotuni1E36uni01C8uni1E3Auni1E42uni01CANacuteNcaronuni0145uni1E44uni1E46Enguni01CBuni1E48Obreveuni1ED0uni1ED8uni1ED2uni1ED4uni1ED6uni020Cuni022Auni0230uni1ECCuni1ECEOhornuni1EDAuni1EE2uni1EDCuni1EDEuni1EE0 Ohungarumlautuni020EOmacronuni1E52uni1E50uni01EA Oslashacuteuni1E4Cuni1E4Euni022CRacuteRcaronuni0156uni0210uni1E5Auni0212uni1E5ESacuteuni1E64uni1E66 Scircumflexuni0218uni1E60uni1E62uni1E68uni1E9Euni018FTbarTcaronuni0162uni021Auni1E6Cuni1E6EUbreveuni0214uni1EE4uni1EE6Uhornuni1EE8uni1EF0uni1EEAuni1EECuni1EEE Uhungarumlautuni0216Umacronuni1E7AUogonekUringUtildeuni1E78Wacute Wcircumflex WdieresisWgrave Ycircumflexuni1E8Euni1EF4Ygraveuni01B3uni1EF6uni0232uni1EF8Zacute Zdotaccentuni1E92Iacute_J.loclNLDabreveuni1EAFuni1EB7uni1EB1uni1EB3uni1EB5uni01CEuni1EA5uni1EADuni1EA7uni1EA9uni1EABuni0201uni0227uni1EA1uni1EA3uni0203amacronaogonek aringacuteaeacuteuni0253uni1E09 ccircumflex cdotaccentdcaronuni1E0Duni0257uni1E0Funi01C6ebreveecaronuni1E1Duni1EBFuni1EC7uni1EC1uni1EC3uni1EC5uni0205 edotaccentuni1EB9uni1EBBuni0207emacronuni1E17uni1E15eogonekuni1EBDuni0259gcaron gcircumflexuni0123 gdotaccentuni1E21uni01E5hbaruni1E2Buni021F hcircumflexuni1E25ibreveuni0209uni1E2F i.loclTRKuni1ECBuni1EC9uni020Bimacroniogonekitildeuni0237 jcircumflexuni01E9uni0137 kgreenlandiclacutelcaronuni013Cldotuni1E37uni01C9uni1E3Buni1E43nacute napostrophencaronuni0146uni1E45uni1E47enguni01CCuni1E49obreveuni1ED1uni1ED9uni1ED3uni1ED5uni1ED7uni020Duni022Buni0231uni1ECDuni1ECFohornuni1EDBuni1EE3uni1EDDuni1EDFuni1EE1 ohungarumlautuni020Fomacronuni1E53uni1E51uni01EB oslashacuteuni1E4Duni1E4Funi022Dracutercaronuni0157uni0211uni1E5Buni0213uni1E5Fsacuteuni1E65uni1E67 scircumflexuni0219uni1E61uni1E63uni1E69tbartcaronuni0163uni021Buni1E97uni1E6Duni1E6Fubreveuni01D4uni0215uni1EE5uni1EE7uhornuni1EE9uni1EF1uni1EEBuni1EEDuni1EEF uhungarumlautuni0217umacronuni1E7Buogonekuringutildeuni1E79wacute wcircumflex wdieresiswgrave ycircumflexuni1E8Funi1EF5ygraveuni01B4uni1EF7uni0233uni1EF9zacute zdotaccentuni1E93germandbls.caltiacute_j.loclNLD I_J.loclNLD i_j.loclNLDuni0410uni0411uni0412uni0413uni0403uni0490uni0414uni0415uni0400uni0401uni0416uni0417uni0418uni0419uni040Duni048Auni041Auni040Cuni041Buni041Cuni041Duni041Euni041Funi0420uni0421uni0422uni0423uni040Euni0424uni0425uni0427uni0426uni0428uni0429uni040Funi042Cuni042Auni042Buni0409uni040Auni0405uni0404uni042Duni0406uni0407uni0408uni040Buni042Euni042Funi0402uni0462uni046Auni0472uni0474uni0492uni0494uni0496uni0498uni049Auni049Cuni049Euni04A0uni04A2uni04A4uni0524uni04A8uni04AAuni04ACuni04AEuni04B0uni04B2uni04B4uni04B6uni04B8uni04BAuni0526uni04BCuni04BEuni04C0uni04C1uni04C3uni04C5uni04C7uni04C9uni04CBuni04CDuni04D0uni04D2uni04D4uni04D6uni04D8uni04DAuni04DCuni04DEuni04E0uni04E2uni04E4uni04E6uni04E8uni04EAuni04ECuni04EEuni04F0uni04F2uni04F4uni04F6uni04F8uni04FAuni04FCuni04FEuni0510uni0512uni051Auni051Cuni048Cuni048Euni0528uni052Euni0406.loclBSHuni0492.loclBSHuni0498.loclBSHuni04AA.loclBSHuni0498.loclCHUuni04AA.loclCHUuni0430uni0431uni0432uni0433uni0453uni0491uni0434uni0435uni0450uni0451uni0436uni0437uni0438uni0439uni045Duni048Buni043Auni045Cuni043Buni043Cuni043Duni043Euni043Funi0440uni0441uni0442uni0443uni045Euni0444uni0445uni0447uni0446uni0448uni0449uni045Funi044Cuni044Auni044Buni0459uni045Auni0455uni0454uni044Duni0456uni0457uni0458uni045Buni044Euni044Funi0452uni0463uni046Buni0473uni0475uni0493uni0495uni0497uni0499uni049Buni049Duni049Funi04A1uni04A3uni04A5uni0525uni04A9uni04ABuni04ADuni04AFuni04B1uni04B3uni04B5uni04B7uni04B9uni04BBuni0527uni04BDuni04BFuni04CFuni04C2uni04C4uni04C6uni04C8uni04CAuni04CCuni04CEuni04D1uni04D3uni04D5uni04D7uni04D9uni04DBuni04DDuni04DFuni04E1uni04E3uni04E5uni04E7uni04E9uni04EBuni04EDuni04EFuni04F1uni04F3uni04F5uni04F7uni04F9uni04FBuni04FDuni04FFuni0511uni0513uni051Buni051Duni048Duni048Funi0529uni052Funi0456.loclBSHuni0493.loclBSHuni0499.loclBSHuni04AB.loclBSHuni0499.loclCHUuni04AB.loclCHUuni0394Sigmauni03A9uni03BC zero.tosfone.tosftwo.tosf three.tosf four.tosf five.tosfsix.tosf seven.tosf eight.tosf nine.tosfuni2080uni2081uni2082uni2083uni2084uni2085uni2086uni2087uni2088uni2089 zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnom zero.numrone.numrtwo.numr three.numr four.numr five.numrsix.numr seven.numr eight.numr nine.numruni2070uni00B9uni00B2uni00B3uni2074uni2075uni2076uni2077uni2078uni2079periodcentered.loclCATuni00AD figuredashuni2015uni2010uni27E8uni27E9uni2007uni200Auni2008uni00A0uni2009uni200BCRuni20B5 colonmonetarydongEurouni20B2uni20B4uni20ADlirauni20BAuni20BCuni20A6pesetauni20B1uni20BDuni20B9uni20B8uni20AEuni20A9uni2219uni2052uni2215emptysetuni2126uni2206uni00B5uniF8FFminuteseconduni2113 estimateduni2116uni02BCuni02BBuni02BAuni02C9uni02CBuni02B9uni02BFuni02BEuni02CAuni02CCuni02C8 uni02BF.case uni02BE.caseuni0308 uni03080301 uni03080304uni0307 uni03070304 gravecomb acutecomb uni03010307uni030B uni030C.altuni0302uni030C uni030C0307uni0306uni030A uni030A0301 tildecomb uni03030308tildecomb_acutecomb uni03030304uni0304 uni03040308 uni03040300 uni03040301 hookabovecombuni030Funi0311uni0312uni031B dotbelowcombuni0324uni0326uni0327uni0328uni032Euni0331uni0335uni0337uni0338tildecomb.case.Ouni031B.O.case uni0308.caseuni03080301.caseuni03080304.case uni0307.caseuni03070304.casegravecomb.caseacutecomb.caseuni03010307.case uni030B.caseuni030C.alt.case uni0302.case uni030C.caseuni030C0307.case uni0306.case uni030A.caseuni030A0301.casetildecomb.caseuni03030308.casetildecomb_acutecomb.caseuni03030304.case uni0304.caseuni03040308.caseuni03040300.caseuni03040301.casehookabovecomb.case uni030F.case uni0311.case uni0312.case uni031B.case uni0335.case uni0337.case uni0338.case uni0335.cy uni0307.i tildecomb.o uni030C.alt.t uni0335.t brevecombcybrevecombcy.case uni03060301 uni03060300 uni03060309 uni03060303 uni03020301 uni03020300 uni03020309 uni03020303uni03060301.caseuni03060300.caseuni03060309.caseuni03060303.caseuni03020301.caseuni03020300.caseuni03020309.caseuni03020303.caseuni0000D ,.PR57>@@Bnp    $&)*,,..02446;==?IKVYY\]ahklo  o  $ 6 .XDFLTcyrllatnkernmarkmkmk" S{}~ _&&&&&&&&&& 0 0 0 0,,2 0<^ B 0 L 0  0 0 0 0 0 0 0 0 0  " " " " " " " " " " " " " " " " " 0 0 : : : : : : : @ F z z z T Z d d d z z z_Ql%'7FHIJKLMNOPQRSTUVWX]^`abcdep"+UW%)*-019;=FGH(-(VWQ37777777>>>>>>0Q30'A@-+!!@!A!B!C!D!E!F!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!X!Y!Z![!]!^!_!`!a!b!c!d!e!!!!0:><>>>,!!@!A!B!C!D!E!F!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!X!Y!Z![!]!^!_!`!a!b!c!d!e!!!!04:4<4>40!!@!A!B!C!D!E!F!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!X!Y!Z![!]!^!_!`!a!b!c!d!e!!!!042:$<$>$IJKL0@ABCDEFHIJKLMNOPQRSTUXYZ[]^_`abcde0!4: < > IJKL0  @ A B C D E F H I J K L M N O P Q R S T U X Y Z [ ] ^ _ ` a b c d e    04+:8<8>8I0J0K0L00@ABCDEFHIJKLMNOPQRSTUXYZ[]^_`abcde04::7<7>7I2J2K2L2'@ABCDEFHIJKLMNOPQRSTUXYZ[]^_`abcde'@ABCDEFHIJKLMNOPQRSTUXYZ[]^_`abcde*@ABCDEFHIJKLMNOPQRSTUXYZ[]^_`abcde:<>0@ABCDEFHIJKLMNOPQRSTUXYZ[]^_`abcde04<:.<.>.I J K L 0@ABCDEFHIJKLMNOPQRSTUXYZ[]^_`abcde04*:4<4>4I2J2K2L20@ABCDEFHIJKLMNOPQRSTUXYZ[]^_`abcde04<:H<H>HI2J2K2L20!!@!A!B!C!D!E!F!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!X!Y!Z![!]!^!_!`!a!b!c!d!e!!!!0:42:#<#>#IJKLNQ:<> 7,NQ44444444,,0404: < > 04:<>:<>'@ABCDEFHIJKLMNOPQRSTUXYZ[]^_`abcde7.%(...................%(NQ% VdW]TVCW)d73V!W!9;2ABaL !   )   1 &,B,2   {(k) $'  P2 z  (2   ~   (&$  $<  ( 2   & > &* .EHXf@(        &(& (1 & $(0  # !4BB&D   ,* *(    &2 ( & 2  *   $  (      826F82< (&(U<( (((  (( 22?UT?SnO[     *7A UWoSq|l~x EGG#Y\$__(fo)q3      #%%',.13469;=??AJMSUUWZ\_aacqswz ./2367?FQp$q)46799;=?R 9 &(((// 0GHHFIOPUWdef%gh:iijj%koqrsuvv%w|~GH_ & 'I(%  <V 56677P8?@EGGY\1__<foqrsRQ* `  %?6["! ." ZAB/  7    ++XY44+  !!D""!##4%%"')** ++!,, ..//B01E34 66477 89;<== ?? AA BC6DE.FGHHIJ"MPQS/UU!WW!XY7ZZ\\]]D^^+__Aaa cc]dd"eeff"gghh0ii jj#kmnnoq$ss#tvwwz|}} ~~ ,C8--\, 0 - # ,C0$0$ # 8,^- #,#,W$ )*)+,;--)..N//O00S11T2344K66U77L995;;5<<==5?EFH)IL3MM=NN>OO=PP>QR2J@M2@ 1 &',--1.HIOPUWdef+gqs  6""  "677*8?@FGGHUVW/X[\\]efikrs K !*0%E    &  C 2DF  !!4%%))-. //01522&3345==@@BD%FG IJMO PP2QSTTXY&[[\\ ]]4aaddee ffgg hh'iiGjmnnHoq sstyzz{|}} ~ ( J 3I  (  '  3 (   B%%=)*+,,--..;//<00>11?2344866@779::);;<<)>>)?EFHIL$MM-NN.OO-PP.QR#7A:# .8 & / EB ,.P+RuNw|r~x57>*@@2Bn3q`    $&)*..02448;?IKV YY\]bhkl"oy$}}/024678<=@ABCDJKS_`bcghjmU****************************(X(X(X(X(X(X(XV\b****************************hnt****************UgLfao2!!<!!<!!2!!<6!2!!2!!2!!<!!<!!2!!<6!2!!2!!2!!<!!<!!<!!26!<!!<!!<!!<!!2!!<!!2!!<!!"" B" !2!8"@H@H@"@H@H@H@ZTffZTfNTfZTfZ`fZ`ff!\""r""r""r""!\""r""r""!\""rl"!\""!\""!\""r""r""r""!\l"r""r""r""r""!\""!\"""""r""""xx~!!!!!!!&V&\"""&\""&\""&\""&\""&\"&V&\""&\"&V""&\""&\""&\""&\"&V&\""&\"!!!&V">""">&V">&V"D&V">&V"D"&V"D&V">!!P\\P\PPP\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""L""""R""""L""""R""""R""""R"""""""""""""""""""""""""""""""""""""""""""""""""""""""""!\!b"""""  & & &"!z!D!z"!z!D!z"!z"!z!D!z",!D!z",!D,2".!h>!n!h>!n8>!n!h>!n!hD!n!hD!n!hD!nntzhtzhtzhtzhtzhtzntJhtzhtzPtb\tbPtV\tb\tb\tbhtzhtzhtzntzntzhtzhtzntz"""""""!!!!!!!!!!!####"                        X"^"^  $>:@4:@4:@4:@4:@4:@$>:@4"@$>:@$>:@$>:@4:@4:@4:@$>"@4:@4:@(:@4:@$>:@$>:@.:@4:@&4&:FLLLLLL^dXpv^djpvRdXpvRdXpv^djpv&x&~!,&x x!, x!, x!, x!, x!, x!,&x x!, x!,&x|!, x!, x!, x!, x!, x!, x!,&x x x x x x  x   x     $t 0$z 6 < * 0$z 6 < * 0$z 6 < * 0$z 6 <$t 0$z 6 < * 0  6 <$t 0$z 6 <$t 0$z 6 <$t 0$z 6 < * 0$z 6 < * 0$z 6 <$t 0$z 6 <$t 0$z 6 <$t 0  6 < * 0$z 6 < * 0$z 6 < 0# 6 <  0# 6 < 0 6 <  0# 6 <  0# 6 <  0# 6 < * 0$z 6 <  0$z 6 < * 0$z 6 <$t 0$z 6 <$t 0$z 6 < 0$z 6 <  < $ < * 0$z 6 <$t 0$z 6 <$t 0$z 6 <$t 0$z 6 < B H N T Z# ` f ~ x l x l x ~ l x ~ r x ~ #$ #$ #$ #$ #$ # # # # # # # # # # # # # # # # # # # # # # $ $ !!!!!!!!! !!!!!!!!!! !!!!!!!! !&!,!!!!2!8"p"v!>"v"""!D""!D""!""!J!J"@!J!!!P!!!!!V""""!\!b""!h!n!!""!"j!t"!z!!!"^&V&\""&\"!!"L""""!""!!!!!!""!!!!!!""!"j!!&V&\"!!!!"j!!!!!!!"" """"""."("."4":""@"@"F"""""L"""""R"""""X"^"d"d"d"d"j"p"v"|""""""""""&\"""""""""""$J###$,$2"$2###"##"###$$""#"#H#N"#N####$##$t$z# ## #$>$D#$&###$#*$b#0$n#6$h$n#<#B#$#$$#H#N$t$z#T$>$D#$&#Z#`#f#l#Z#`#f#l#r#r#x#~$h###$&$J################$##$###$#$$$$$$$$$$$ $&$,$2$8$>$D$J$P$V$\$b$h$n$$$t$z$$$$$$$$$$$$Va aaaVfSVSaVaaVVafffVVVVVann^_lamlmVPV?a??VzVVazazCz||6a[IVHaAaAAV===*5K,,,CCVml;+V"*"+FF;{:;:VY:V,{,)V)){ wV99V995V$$5665qn588B<DVV&>V4V444VVee!aVahaST??fPBhva aHIJ,":aa  VSa"a4aaaaBaCaa;'!fa[[ka66a<74<+?LAA L)C YC.w(EB3>+4?z>w>>>((""EM5522a :Dv !* <L*L $$ 11   *J V  .n $ 6F                          ,,,,,,,,,,,,,,,,,,,,,,,,,,,&&&&&&&&,,,,,,,,>>>>>>>>>>>>>>>DDDDDDDDDDDDDDDa xDFLTcyrllatnlBSH CHU 2 : AZE CAT ZCRT KAZ MOL |NLD ROM TAT TRK      aaltzcaltcaseccmpccmpdnomfracligaloclloclloclloclloclloclnumronumordnsinfsubssups"   !    %LhB**&P, ,:xx* < <CNbc     8%  FFss  ""   2266%8;"(.4:FR^jvdfeg      !"#$%. n&>,FV gj\+GW  FFVV  #22N  "4>HR\v  0Rt     F6",eeVVUWFH<]]ii2bcde"%.fg%.*26( "B%* $lsss)u X)   ! F]7n: g#$8$wghtitalhugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/output/000077500000000000000000000000001420147000300264455ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/output/css/000077500000000000000000000000001420147000300272355ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/output/css/app.css000066400000000000000000004775221420147000300305500ustar00rootroot00000000000000/* muli-200normal - latin */ @font-face { font-family: 'Muli'; font-style: normal; font-display: swap; font-weight: 200; src: local('Muli Extra Light '), local('Muli-Extra Light'), url(/fonts/muli-latin-200.woff2) format('woff2'), url(/fonts/muli-latin-200.woff) format('woff'); /* Modern Browsers */ } /* muli-200italic - latin */ @font-face { font-family: 'Muli'; font-style: italic; font-display: swap; font-weight: 200; src: local('Muli Extra Light italic'), local('Muli-Extra Lightitalic'), url(/fonts/muli-latin-200italic.woff2) format('woff2'), url(/fonts/muli-latin-200italic.woff) format('woff'); /* Modern Browsers */ } /* muli-300normal - latin */ @font-face { font-family: 'Muli'; font-style: normal; font-display: swap; font-weight: 300; src: local('Muli Light '), local('Muli-Light'), url(/fonts/muli-latin-300.woff2) format('woff2'), url(/fonts/muli-latin-300.woff) format('woff'); /* Modern Browsers */ } /* muli-300italic - latin */ @font-face { font-family: 'Muli'; font-style: italic; font-display: swap; font-weight: 300; src: local('Muli Light italic'), local('Muli-Lightitalic'), url(/fonts/muli-latin-300italic.woff2) format('woff2'), url(/fonts/muli-latin-300italic.woff) format('woff'); /* Modern Browsers */ } /* muli-400normal - latin */ @font-face { font-family: 'Muli'; font-style: normal; font-display: swap; font-weight: 400; src: local('Muli Regular '), local('Muli-Regular'), url(/fonts/muli-latin-400.woff2) format('woff2'), url(/fonts/muli-latin-400.woff) format('woff'); /* Modern Browsers */ } /* muli-400italic - latin */ @font-face { font-family: 'Muli'; font-style: italic; font-display: swap; font-weight: 400; src: local('Muli Regular italic'), local('Muli-Regularitalic'), url(/fonts/muli-latin-400italic.woff2) format('woff2'), url(/fonts/muli-latin-400italic.woff) format('woff'); /* Modern Browsers */ } /* muli-600normal - latin */ @font-face { font-family: 'Muli'; font-style: normal; font-display: swap; font-weight: 600; src: local('Muli SemiBold '), local('Muli-SemiBold'), url(/fonts/muli-latin-600.woff2) format('woff2'), url(/fonts/muli-latin-600.woff) format('woff'); /* Modern Browsers */ } /* muli-600italic - latin */ @font-face { font-family: 'Muli'; font-style: italic; font-display: swap; font-weight: 600; src: local('Muli SemiBold italic'), local('Muli-SemiBolditalic'), url(/fonts/muli-latin-600italic.woff2) format('woff2'), url(/fonts/muli-latin-600italic.woff) format('woff'); /* Modern Browsers */ } /* muli-700normal - latin */ @font-face { font-family: 'Muli'; font-style: normal; font-display: swap; font-weight: 700; src: local('Muli Bold '), local('Muli-Bold'), url(/fonts/muli-latin-700.woff2) format('woff2'), url(/fonts/muli-latin-700.woff) format('woff'); /* Modern Browsers */ } /* muli-700italic - latin */ @font-face { font-family: 'Muli'; font-style: italic; font-display: swap; font-weight: 700; src: local('Muli Bold italic'), local('Muli-Bolditalic'), url(/fonts/muli-latin-700italic.woff2) format('woff2'), url(/fonts/muli-latin-700italic.woff) format('woff'); /* Modern Browsers */ } /* muli-800normal - latin */ @font-face { font-family: 'Muli'; font-style: normal; font-display: swap; font-weight: 800; src: local('Muli ExtraBold '), local('Muli-ExtraBold'), url(/fonts/muli-latin-800.woff2) format('woff2'), url(/fonts/muli-latin-800.woff) format('woff'); /* Modern Browsers */ } /* muli-800italic - latin */ @font-face { font-family: 'Muli'; font-style: italic; font-display: swap; font-weight: 800; src: local('Muli ExtraBold italic'), local('Muli-ExtraBolditalic'), url(/fonts/muli-latin-800italic.woff2) format('woff2'), url(/fonts/muli-latin-800italic.woff) format('woff'); /* Modern Browsers */ } /* muli-900normal - latin */ @font-face { font-family: 'Muli'; font-style: normal; font-display: swap; font-weight: 900; src: local('Muli Black '), local('Muli-Black'), url(/fonts/muli-latin-900.woff2) format('woff2'), url(/fonts/muli-latin-900.woff) format('woff'); /* Modern Browsers */ } /* muli-900italic - latin */ @font-face { font-family: 'Muli'; font-style: italic; font-display: swap; font-weight: 900; src: local('Muli Black italic'), local('Muli-Blackitalic'), url(/fonts/muli-latin-900italic.woff2) format('woff2'), url(/fonts/muli-latin-900italic.woff) format('woff'); /* Modern Browsers */ } /*Base Styles*/ /*! TACHYONS v4.7.0 | http://tachyons.io */ /* * NOTE: The Tachyons folder is for backup/reference only. This file references the module * ________ ______ * ___ __/_____ _________ /______ ______________________ * __ / _ __ `/ ___/_ __ \_ / / / __ \_ __ \_ ___/ * _ / / /_/ // /__ _ / / / /_/ // /_/ / / / /(__ ) * /_/ \__,_/ \___/ /_/ /_/_\__, / \____//_/ /_//____/ * /____/ * * TABLE OF CONTENTS * * 1. External Library Includes * - Normalize.css | http://normalize.css.github.io * 2. Tachyons Modules * 3. Variables * - Media Queries * - Colors * 4. Debugging * - Debug all * - Debug children * */ /* External Library Includes */ /*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */ /* Document ========================================================================== */ /** * 1. Correct the line height in all browsers. * 2. Prevent adjustments of font size after orientation changes in iOS. */ html { line-height: 1.15; /* 1 */ -webkit-text-size-adjust: 100%; /* 2 */ } /* Sections ========================================================================== */ /** * Remove the margin in all browsers. */ body { margin: 0; } /** * Correct the font size and margin on `h1` elements within `section` and * `article` contexts in Chrome, Firefox, and Safari. */ h1 { font-size: 2em; margin: 0.67em 0; } /* Grouping content ========================================================================== */ /** * 1. Add the correct box sizing in Firefox. * 2. Show the overflow in Edge and IE. */ hr { -webkit-box-sizing: content-box; box-sizing: content-box; /* 1 */ height: 0; /* 1 */ overflow: visible; /* 2 */ } /** * 1. Correct the inheritance and scaling of font size in all browsers. * 2. Correct the odd `em` font sizing in all browsers. */ pre { font-family: monospace, monospace; /* 1 */ font-size: 1em; /* 2 */ } /* Text-level semantics ========================================================================== */ /** * Remove the gray background on active links in IE 10. */ a { background-color: transparent; } /** * 1. Remove the bottom border in Chrome 57- * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. */ abbr[title] { border-bottom: none; /* 1 */ text-decoration: underline; /* 2 */ -webkit-text-decoration: underline dotted; text-decoration: underline dotted; /* 2 */ } /** * Add the correct font weight in Chrome, Edge, and Safari. */ b, strong { font-weight: bolder; } /** * 1. Correct the inheritance and scaling of font size in all browsers. * 2. Correct the odd `em` font sizing in all browsers. */ code, kbd, samp { font-family: monospace, monospace; /* 1 */ font-size: 1em; /* 2 */ } /** * Add the correct font size in all browsers. */ small { font-size: 80%; } /** * Prevent `sub` and `sup` elements from affecting the line height in * all browsers. */ sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } /* Embedded content ========================================================================== */ /** * Remove the border on images inside links in IE 10. */ img { border-style: none; } /* Forms ========================================================================== */ /** * 1. Change the font styles in all browsers. * 2. Remove the margin in Firefox and Safari. */ button, input, optgroup, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 1 */ line-height: 1.15; /* 1 */ margin: 0; /* 2 */ } /** * Show the overflow in IE. * 1. Show the overflow in Edge. */ button, input { /* 1 */ overflow: visible; } /** * Remove the inheritance of text transform in Edge, Firefox, and IE. * 1. Remove the inheritance of text transform in Firefox. */ button, select { /* 1 */ text-transform: none; } /** * Correct the inability to style clickable types in iOS and Safari. */ button, [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } /** * Remove the inner border and padding in Firefox. */ button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { border-style: none; padding: 0; } /** * Restore the focus styles unset by the previous rule. */ button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring { outline: 1px dotted ButtonText; } /** * Correct the padding in Firefox. */ fieldset { padding: 0.35em 0.75em 0.625em; } /** * 1. Correct the text wrapping in Edge and IE. * 2. Correct the color inheritance from `fieldset` elements in IE. * 3. Remove the padding so developers are not caught out when they zero out * `fieldset` elements in all browsers. */ legend { -webkit-box-sizing: border-box; box-sizing: border-box; /* 1 */ color: inherit; /* 2 */ display: table; /* 1 */ max-width: 100%; /* 1 */ padding: 0; /* 3 */ white-space: normal; /* 1 */ } /** * Add the correct vertical alignment in Chrome, Firefox, and Opera. */ progress { vertical-align: baseline; } /** * Remove the default vertical scrollbar in IE 10+. */ textarea { overflow: auto; } /** * 1. Add the correct box sizing in IE 10. * 2. Remove the padding in IE 10. */ [type="checkbox"], [type="radio"] { -webkit-box-sizing: border-box; box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } /** * Correct the cursor style of increment and decrement buttons in Chrome. */ [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } /** * 1. Correct the odd appearance in Chrome and Safari. * 2. Correct the outline style in Safari. */ [type="search"] { -webkit-appearance: textfield; /* 1 */ outline-offset: -2px; /* 2 */ } /** * Remove the inner padding in Chrome and Safari on macOS. */ [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * 1. Correct the inability to style clickable types in iOS and Safari. * 2. Change font properties to `inherit` in Safari. */ ::-webkit-file-upload-button { -webkit-appearance: button; /* 1 */ font: inherit; /* 2 */ } /* Interactive ========================================================================== */ /* * Add the correct display in Edge, IE 10+, and Firefox. */ details { display: block; } /* * Add the correct display in all browsers. */ summary { display: list-item; } /* Misc ========================================================================== */ /** * Add the correct display in IE 10+. */ template { display: none; } /** * Add the correct display in IE 10. */ [hidden] { display: none; } /* Modules */ /* BOX SIZING */ html, body, div, article, aside, section, main, nav, footer, header, form, fieldset, legend, pre, code, a, h1,h2,h3,h4,h5,h6, p, ul, ol, li, dl, dt, dd, blockquote, figcaption, figure, textarea, table, td, th, tr, input[type="email"], input[type="number"], input[type="password"], input[type="tel"], input[type="text"], input[type="url"], .border-box { -webkit-box-sizing: border-box; box-sizing: border-box; } /*@import 'tachyons/src/_aspect-ratios';*/ /* IMAGES Docs: http://tachyons.io/docs/elements/images/ */ /* Responsive images! */ img { max-width: 100%; } /* BACKGROUND SIZE Docs: http://tachyons.io/docs/themes/background-size/ Media Query Extensions: -ns = not-small -m = medium -l = large */ /* Often used in combination with background image set as an inline style on an html element. */ .cover { background-size: cover!important; } .contain { background-size: contain!important; } @media screen and (min-width: 30em) { .cover-ns { background-size: cover!important; } .contain-ns { background-size: contain!important; } } @media screen and (min-width: 30em) and (max-width: 60em) { .cover-m { background-size: cover!important; } .contain-m { background-size: contain!important; } } @media screen and (min-width: 60em) { .cover-l { background-size: cover!important; } .contain-l { background-size: contain!important; } } /* BACKGROUND POSITION Base: bg = background Modifiers: -center = center center -top = top center -right = center right -bottom = bottom center -left = center left Media Query Extensions: -ns = not-small -m = medium -l = large */ .bg-center { background-repeat: no-repeat; background-position: center center; } .bg-top { background-repeat: no-repeat; background-position: top center; } .bg-right { background-repeat: no-repeat; background-position: center right; } .bg-bottom { background-repeat: no-repeat; background-position: bottom center; } .bg-left { background-repeat: no-repeat; background-position: center left; } @media screen and (min-width: 30em) { .bg-center-ns { background-repeat: no-repeat; background-position: center center; } .bg-top-ns { background-repeat: no-repeat; background-position: top center; } .bg-right-ns { background-repeat: no-repeat; background-position: center right; } .bg-bottom-ns { background-repeat: no-repeat; background-position: bottom center; } .bg-left-ns { background-repeat: no-repeat; background-position: center left; } } @media screen and (min-width: 30em) and (max-width: 60em) { .bg-center-m { background-repeat: no-repeat; background-position: center center; } .bg-top-m { background-repeat: no-repeat; background-position: top center; } .bg-right-m { background-repeat: no-repeat; background-position: center right; } .bg-bottom-m { background-repeat: no-repeat; background-position: bottom center; } .bg-left-m { background-repeat: no-repeat; background-position: center left; } } @media screen and (min-width: 60em) { .bg-center-l { background-repeat: no-repeat; background-position: center center; } .bg-top-l { background-repeat: no-repeat; background-position: top center; } .bg-right-l { background-repeat: no-repeat; background-position: center right; } .bg-bottom-l { background-repeat: no-repeat; background-position: bottom center; } .bg-left-l { background-repeat: no-repeat; background-position: center left; } } /*@import 'tachyons/src/_outlines';*/ /* BORDERS Docs: http://tachyons.io/docs/themes/borders/ Base: b = border Modifiers: a = all t = top r = right b = bottom l = left n = none Media Query Extensions: -ns = not-small -m = medium -l = large */ .ba { border-style: solid; border-width: 1px; } .bt { border-top-style: solid; border-top-width: 1px; } .br { border-right-style: solid; border-right-width: 1px; } .bb { border-bottom-style: solid; border-bottom-width: 1px; } .bl { border-left-style: solid; border-left-width: 1px; } .bn { border-style: none; border-width: 0; } @media screen and (min-width: 30em) { .ba-ns { border-style: solid; border-width: 1px; } .bt-ns { border-top-style: solid; border-top-width: 1px; } .br-ns { border-right-style: solid; border-right-width: 1px; } .bb-ns { border-bottom-style: solid; border-bottom-width: 1px; } .bl-ns { border-left-style: solid; border-left-width: 1px; } .bn-ns { border-style: none; border-width: 0; } } @media screen and (min-width: 30em) and (max-width: 60em) { .ba-m { border-style: solid; border-width: 1px; } .bt-m { border-top-style: solid; border-top-width: 1px; } .br-m { border-right-style: solid; border-right-width: 1px; } .bb-m { border-bottom-style: solid; border-bottom-width: 1px; } .bl-m { border-left-style: solid; border-left-width: 1px; } .bn-m { border-style: none; border-width: 0; } } @media screen and (min-width: 60em) { .ba-l { border-style: solid; border-width: 1px; } .bt-l { border-top-style: solid; border-top-width: 1px; } .br-l { border-right-style: solid; border-right-width: 1px; } .bb-l { border-bottom-style: solid; border-bottom-width: 1px; } .bl-l { border-left-style: solid; border-left-width: 1px; } .bn-l { border-style: none; border-width: 0; } } /* BORDER COLORS Docs: http://tachyons.io/docs/themes/borders/ Border colors can be used to extend the base border classes ba,bt,bb,br,bl found in the _borders.css file. The base border class by default will set the color of the border to that of the current text color. These classes are for the cases where you desire for the text and border colors to be different. Base: b = border Modifiers: --color-name = each color variable name is also a border color name */ .b--black { border-color: #000; } .b--near-black { border-color: #111; } .b--dark-gray { border-color: #333; } .b--mid-gray { border-color: #555; } .b--gray { border-color: #777; } .b--silver { border-color: #999; } .b--light-silver { border-color: #aaa; } .b--moon-gray { border-color: #ccc; } .b--light-gray { border-color: #eee; } .b--near-white { border-color: #f4f4f4; } .b--white { border-color: #fff; } .b--white-90 { border-color: rgba(255, 255, 255, .9); } .b--white-80 { border-color: rgba(255, 255, 255, .8); } .b--white-70 { border-color: rgba(255, 255, 255, .7); } .b--white-60 { border-color: rgba(255, 255, 255, .6); } .b--white-50 { border-color: rgba(255, 255, 255, .5); } .b--white-40 { border-color: rgba(255, 255, 255, .4); } .b--white-30 { border-color: rgba(255, 255, 255, .3); } .b--white-20 { border-color: rgba(255, 255, 255, .2); } .b--white-10 { border-color: rgba(255, 255, 255, .1); } .b--white-05 { border-color: rgba(255, 255, 255, .05); } .b--white-025 { border-color: rgba(255, 255, 255, .025); } .b--white-0125 { border-color: rgba(255, 255, 255, .0125); } .b--black-90 { border-color: rgba(0, 0, 0, .9); } .b--black-80 { border-color: rgba(0, 0, 0, .8); } .b--black-70 { border-color: rgba(0, 0, 0, .7); } .b--black-60 { border-color: rgba(0, 0, 0, .6); } .b--black-50 { border-color: rgba(0, 0, 0, .5); } .b--black-40 { border-color: rgba(0, 0, 0, .4); } .b--black-30 { border-color: rgba(0, 0, 0, .3); } .b--black-20 { border-color: rgba(0, 0, 0, .2); } .b--black-10 { border-color: rgba(0, 0, 0, .1); } .b--black-05 { border-color: rgba(0, 0, 0, .05); } .b--black-025 { border-color: rgba(0, 0, 0, .025); } .b--black-0125 { border-color: rgba(0, 0, 0, .0125); } .b--dark-red { border-color: #e7040f; } .b--red { border-color: #ff4136; } .b--light-red { border-color: #ff725c; } .b--orange { border-color: #ff6300; } .b--gold { border-color: #ffb700; } .b--yellow { border-color: #ffd700; } .b--light-yellow { border-color: #fbf1a9; } .b--purple { border-color: #5e2ca5; } .b--light-purple { border-color: #a463f2; } .b--dark-pink { border-color: #d5008f; } .b--hot-pink { border-color: #ff41b4; } .b--pink { border-color: #ff80cc; } .b--light-pink { border-color: #ffa3d7; } .b--dark-green { border-color: #137752; } .b--green { border-color: #19a974; } .b--light-green { border-color: #9eebcf; } .b--navy { border-color: #001b44; } .b--dark-blue { border-color: #00449e; } .b--blue { border-color: #0594CB; } .b--light-blue { border-color: #96ccff; } .b--lightest-blue { border-color: #cdecff; } .b--washed-blue { border-color: #f6fffe; } .b--washed-green { border-color: #e8fdf5; } .b--washed-yellow { border-color: #fffceb; } .b--washed-red { border-color: #ffdfdf; } .b--transparent { border-color: transparent; } .b--inherit { border-color: inherit; } /* BORDER RADIUS Docs: http://tachyons.io/docs/themes/border-radius/ Base: br = border-radius Modifiers: 0 = 0/none 1 = 1st step in scale 2 = 2nd step in scale 3 = 3rd step in scale 4 = 4th step in scale Literal values: -100 = 100% -pill = 9999px Media Query Extensions: -ns = not-small -m = medium -l = large */ .br0 { border-radius: 0; } .br1 { border-radius: .125rem; } .br2 { border-radius: .25rem; } .br3 { border-radius: .5rem; } .br4 { border-radius: 1rem; } .br-100 { border-radius: 100%; } .br-pill { border-radius: 9999px; } .br--bottom { border-top-left-radius: 0; border-top-right-radius: 0; } .br--top { border-bottom-left-radius: 0; border-bottom-right-radius: 0; } .br--right { border-top-left-radius: 0; border-bottom-left-radius: 0; } .br--left { border-top-right-radius: 0; border-bottom-right-radius: 0; } @media screen and (min-width: 30em) { .br0-ns { border-radius: 0; } .br1-ns { border-radius: .125rem; } .br2-ns { border-radius: .25rem; } .br3-ns { border-radius: .5rem; } .br4-ns { border-radius: 1rem; } .br-100-ns { border-radius: 100%; } .br-pill-ns { border-radius: 9999px; } .br--bottom-ns { border-top-left-radius: 0; border-top-right-radius: 0; } .br--top-ns { border-bottom-left-radius: 0; border-bottom-right-radius: 0; } .br--right-ns { border-top-left-radius: 0; border-bottom-left-radius: 0; } .br--left-ns { border-top-right-radius: 0; border-bottom-right-radius: 0; } } @media screen and (min-width: 30em) and (max-width: 60em) { .br0-m { border-radius: 0; } .br1-m { border-radius: .125rem; } .br2-m { border-radius: .25rem; } .br3-m { border-radius: .5rem; } .br4-m { border-radius: 1rem; } .br-100-m { border-radius: 100%; } .br-pill-m { border-radius: 9999px; } .br--bottom-m { border-top-left-radius: 0; border-top-right-radius: 0; } .br--top-m { border-bottom-left-radius: 0; border-bottom-right-radius: 0; } .br--right-m { border-top-left-radius: 0; border-bottom-left-radius: 0; } .br--left-m { border-top-right-radius: 0; border-bottom-right-radius: 0; } } @media screen and (min-width: 60em) { .br0-l { border-radius: 0; } .br1-l { border-radius: .125rem; } .br2-l { border-radius: .25rem; } .br3-l { border-radius: .5rem; } .br4-l { border-radius: 1rem; } .br-100-l { border-radius: 100%; } .br-pill-l { border-radius: 9999px; } .br--bottom-l { border-top-left-radius: 0; border-top-right-radius: 0; } .br--top-l { border-bottom-left-radius: 0; border-bottom-right-radius: 0; } .br--right-l { border-top-left-radius: 0; border-bottom-left-radius: 0; } .br--left-l { border-top-right-radius: 0; border-bottom-right-radius: 0; } } /* BORDER STYLES Docs: http://tachyons.io/docs/themes/borders/ Depends on base border module in _borders.css Base: b = border-style Modifiers: --none = none --dotted = dotted --dashed = dashed --solid = solid Media Query Extensions: -ns = not-small -m = medium -l = large */ .b--dotted { border-style: dotted; } .b--dashed { border-style: dashed; } .b--solid { border-style: solid; } .b--none { border-style: none; } @media screen and (min-width: 30em) { .b--dotted-ns { border-style: dotted; } .b--dashed-ns { border-style: dashed; } .b--solid-ns { border-style: solid; } .b--none-ns { border-style: none; } } @media screen and (min-width: 30em) and (max-width: 60em) { .b--dotted-m { border-style: dotted; } .b--dashed-m { border-style: dashed; } .b--solid-m { border-style: solid; } .b--none-m { border-style: none; } } @media screen and (min-width: 60em) { .b--dotted-l { border-style: dotted; } .b--dashed-l { border-style: dashed; } .b--solid-l { border-style: solid; } .b--none-l { border-style: none; } } /* BORDER WIDTHS Docs: http://tachyons.io/docs/themes/borders/ Base: bw = border-width Modifiers: 0 = 0 width border 1 = 1st step in border-width scale 2 = 2nd step in border-width scale 3 = 3rd step in border-width scale 4 = 4th step in border-width scale 5 = 5th step in border-width scale Media Query Extensions: -ns = not-small -m = medium -l = large */ .bw0 { border-width: 0; } .bw1 { border-width: .125rem; } .bw2 { border-width: .25rem; } .bw3 { border-width: .5rem; } .bw4 { border-width: 1rem; } .bw5 { border-width: 2rem; } /* Resets */ .bt-0 { border-top-width: 0; } .br-0 { border-right-width: 0; } .bb-0 { border-bottom-width: 0; } .bl-0 { border-left-width: 0; } @media screen and (min-width: 30em) { .bw0-ns { border-width: 0; } .bw1-ns { border-width: .125rem; } .bw2-ns { border-width: .25rem; } .bw3-ns { border-width: .5rem; } .bw4-ns { border-width: 1rem; } .bw5-ns { border-width: 2rem; } .bt-0-ns { border-top-width: 0; } .br-0-ns { border-right-width: 0; } .bb-0-ns { border-bottom-width: 0; } .bl-0-ns { border-left-width: 0; } } @media screen and (min-width: 30em) and (max-width: 60em) { .bw0-m { border-width: 0; } .bw1-m { border-width: .125rem; } .bw2-m { border-width: .25rem; } .bw3-m { border-width: .5rem; } .bw4-m { border-width: 1rem; } .bw5-m { border-width: 2rem; } .bt-0-m { border-top-width: 0; } .br-0-m { border-right-width: 0; } .bb-0-m { border-bottom-width: 0; } .bl-0-m { border-left-width: 0; } } @media screen and (min-width: 60em) { .bw0-l { border-width: 0; } .bw1-l { border-width: .125rem; } .bw2-l { border-width: .25rem; } .bw3-l { border-width: .5rem; } .bw4-l { border-width: 1rem; } .bw5-l { border-width: 2rem; } .bt-0-l { border-top-width: 0; } .br-0-l { border-right-width: 0; } .bb-0-l { border-bottom-width: 0; } .bl-0-l { border-left-width: 0; } } /* BOX-SHADOW Docs: http://tachyons.io/docs/themes/box-shadow/ Media Query Extensions: -ns = not-small -m = medium -l = large */ .shadow-1 { -webkit-box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, .2); box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, .2); } .shadow-2 { -webkit-box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, .2); box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, .2); } .shadow-3 { -webkit-box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2); box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2); } .shadow-4 { -webkit-box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, .2); box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, .2); } .shadow-5 { -webkit-box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, .2); box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, .2); } @media screen and (min-width: 30em) { .shadow-1-ns { -webkit-box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, .2); box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, .2); } .shadow-2-ns { -webkit-box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, .2); box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, .2); } .shadow-3-ns { -webkit-box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2); box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2); } .shadow-4-ns { -webkit-box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, .2); box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, .2); } .shadow-5-ns { -webkit-box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, .2); box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, .2); } } @media screen and (min-width: 30em) and (max-width: 60em) { .shadow-1-m { -webkit-box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, .2); box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, .2); } .shadow-2-m { -webkit-box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, .2); box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, .2); } .shadow-3-m { -webkit-box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2); box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2); } .shadow-4-m { -webkit-box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, .2); box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, .2); } .shadow-5-m { -webkit-box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, .2); box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, .2); } } @media screen and (min-width: 60em) { .shadow-1-l { -webkit-box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, .2); box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, .2); } .shadow-2-l { -webkit-box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, .2); box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, .2); } .shadow-3-l { -webkit-box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2); box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2); } .shadow-4-l { -webkit-box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, .2); box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, .2); } .shadow-5-l { -webkit-box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, .2); box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, .2); } } /*@import 'tachyons/src/_code';*/ /* COORDINATES Docs: http://tachyons.io/docs/layout/position/ Use in combination with the position module. Base: top bottom right left Modifiers: -0 = literal value 0 -1 = literal value 1 -2 = literal value 2 --1 = literal value -1 --2 = literal value -2 Media Query Extensions: -ns = not-small -m = medium -l = large */ .top-0 { top: 0; } .right-0 { right: 0; } .bottom-0 { bottom: 0; } .left-0 { left: 0; } .top-1 { top: 1rem; } .right-1 { right: 1rem; } .bottom-1 { bottom: 1rem; } .left-1 { left: 1rem; } .top-2 { top: 2rem; } .right-2 { right: 2rem; } .bottom-2 { bottom: 2rem; } .left-2 { left: 2rem; } .top--1 { top: -1rem; } .right--1 { right: -1rem; } .bottom--1 { bottom: -1rem; } .left--1 { left: -1rem; } .top--2 { top: -2rem; } .right--2 { right: -2rem; } .bottom--2 { bottom: -2rem; } .left--2 { left: -2rem; } .absolute--fill { top: 0; right: 0; bottom: 0; left: 0; } @media screen and (min-width: 30em) { .top-0-ns { top: 0; } .left-0-ns { left: 0; } .right-0-ns { right: 0; } .bottom-0-ns { bottom: 0; } .top-1-ns { top: 1rem; } .left-1-ns { left: 1rem; } .right-1-ns { right: 1rem; } .bottom-1-ns { bottom: 1rem; } .top-2-ns { top: 2rem; } .left-2-ns { left: 2rem; } .right-2-ns { right: 2rem; } .bottom-2-ns { bottom: 2rem; } .top--1-ns { top: -1rem; } .right--1-ns { right: -1rem; } .bottom--1-ns { bottom: -1rem; } .left--1-ns { left: -1rem; } .top--2-ns { top: -2rem; } .right--2-ns { right: -2rem; } .bottom--2-ns { bottom: -2rem; } .left--2-ns { left: -2rem; } .absolute--fill-ns { top: 0; right: 0; bottom: 0; left: 0; } } @media screen and (min-width: 30em) and (max-width: 60em) { .top-0-m { top: 0; } .left-0-m { left: 0; } .right-0-m { right: 0; } .bottom-0-m { bottom: 0; } .top-1-m { top: 1rem; } .left-1-m { left: 1rem; } .right-1-m { right: 1rem; } .bottom-1-m { bottom: 1rem; } .top-2-m { top: 2rem; } .left-2-m { left: 2rem; } .right-2-m { right: 2rem; } .bottom-2-m { bottom: 2rem; } .top--1-m { top: -1rem; } .right--1-m { right: -1rem; } .bottom--1-m { bottom: -1rem; } .left--1-m { left: -1rem; } .top--2-m { top: -2rem; } .right--2-m { right: -2rem; } .bottom--2-m { bottom: -2rem; } .left--2-m { left: -2rem; } .absolute--fill-m { top: 0; right: 0; bottom: 0; left: 0; } } @media screen and (min-width: 60em) { .top-0-l { top: 0; } .left-0-l { left: 0; } .right-0-l { right: 0; } .bottom-0-l { bottom: 0; } .top-1-l { top: 1rem; } .left-1-l { left: 1rem; } .right-1-l { right: 1rem; } .bottom-1-l { bottom: 1rem; } .top-2-l { top: 2rem; } .left-2-l { left: 2rem; } .right-2-l { right: 2rem; } .bottom-2-l { bottom: 2rem; } .top--1-l { top: -1rem; } .right--1-l { right: -1rem; } .bottom--1-l { bottom: -1rem; } .left--1-l { left: -1rem; } .top--2-l { top: -2rem; } .right--2-l { right: -2rem; } .bottom--2-l { bottom: -2rem; } .left--2-l { left: -2rem; } .absolute--fill-l { top: 0; right: 0; bottom: 0; left: 0; } } /* CLEARFIX http://tachyons.io/docs/layout/clearfix/ */ /* Nicolas Gallaghers Clearfix solution Ref: http://nicolasgallagher.com/micro-clearfix-hack/ */ .cf:before, .cf:after { content: " "; display: table; } .cf:after { clear: both; } .cf { *zoom: 1; } .cl { clear: left; } .cr { clear: right; } .cb { clear: both; } .cn { clear: none; } @media screen and (min-width: 30em) { .cl-ns { clear: left; } .cr-ns { clear: right; } .cb-ns { clear: both; } .cn-ns { clear: none; } } @media screen and (min-width: 30em) and (max-width: 60em) { .cl-m { clear: left; } .cr-m { clear: right; } .cb-m { clear: both; } .cn-m { clear: none; } } @media screen and (min-width: 60em) { .cl-l { clear: left; } .cr-l { clear: right; } .cb-l { clear: both; } .cn-l { clear: none; } } /* DISPLAY Docs: http://tachyons.io/docs/layout/display Base: d = display Modifiers: n = none b = block ib = inline-block it = inline-table t = table tc = table-cell t-row = table-row t-columm = table-column t-column-group = table-column-group Media Query Extensions: -ns = not-small -m = medium -l = large */ .dn { display: none; } .di { display: inline; } .db { display: block; } .dib { display: inline-block; } .dit { display: inline-table; } .dt { display: table; } .dtc { display: table-cell; } .dt-row { display: table-row; } .dt-row-group { display: table-row-group; } .dt-column { display: table-column; } .dt-column-group { display: table-column-group; } /* This will set table to full width and then all cells will be equal width */ .dt--fixed { table-layout: fixed; width: 100%; } @media screen and (min-width: 30em) { .dn-ns { display: none; } .di-ns { display: inline; } .db-ns { display: block; } .dib-ns { display: inline-block; } .dit-ns { display: inline-table; } .dt-ns { display: table; } .dtc-ns { display: table-cell; } .dt-row-ns { display: table-row; } .dt-row-group-ns { display: table-row-group; } .dt-column-ns { display: table-column; } .dt-column-group-ns { display: table-column-group; } .dt--fixed-ns { table-layout: fixed; width: 100%; } } @media screen and (min-width: 30em) and (max-width: 60em) { .dn-m { display: none; } .di-m { display: inline; } .db-m { display: block; } .dib-m { display: inline-block; } .dit-m { display: inline-table; } .dt-m { display: table; } .dtc-m { display: table-cell; } .dt-row-m { display: table-row; } .dt-row-group-m { display: table-row-group; } .dt-column-m { display: table-column; } .dt-column-group-m { display: table-column-group; } .dt--fixed-m { table-layout: fixed; width: 100%; } } @media screen and (min-width: 60em) { .dn-l { display: none; } .di-l { display: inline; } .db-l { display: block; } .dib-l { display: inline-block; } .dit-l { display: inline-table; } .dt-l { display: table; } .dtc-l { display: table-cell; } .dt-row-l { display: table-row; } .dt-row-group-l { display: table-row-group; } .dt-column-l { display: table-column; } .dt-column-group-l { display: table-column-group; } .dt--fixed-l { table-layout: fixed; width: 100%; } } /* FLEXBOX Media Query Extensions: -ns = not-small -m = medium -l = large */ .flex { display: -webkit-box; display: -ms-flexbox; display: flex; } .inline-flex { display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; } /* 1. Fix for Chrome 44 bug. * https://code.google.com/p/chromium/issues/detail?id=506893 */ .flex-auto { -webkit-box-flex: 1; -ms-flex: 1 1 auto; flex: 1 1 auto; min-width: 0; /* 1 */ min-height: 0; /* 1 */ } .flex-none { -webkit-box-flex: 0; -ms-flex: none; flex: none; } .flex-column { -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; } .flex-row { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; } .flex-wrap { -ms-flex-wrap: wrap; flex-wrap: wrap; } .flex-nowrap { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .flex-wrap-reverse { -ms-flex-wrap: wrap-reverse; flex-wrap: wrap-reverse; } .flex-column-reverse { -webkit-box-orient: vertical; -webkit-box-direction: reverse; -ms-flex-direction: column-reverse; flex-direction: column-reverse; } .flex-row-reverse { -webkit-box-orient: horizontal; -webkit-box-direction: reverse; -ms-flex-direction: row-reverse; flex-direction: row-reverse; } .items-start { -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; } .items-end { -webkit-box-align: end; -ms-flex-align: end; align-items: flex-end; } .items-center { -webkit-box-align: center; -ms-flex-align: center; align-items: center; } .items-baseline { -webkit-box-align: baseline; -ms-flex-align: baseline; align-items: baseline; } .items-stretch { -webkit-box-align: stretch; -ms-flex-align: stretch; align-items: stretch; } .self-start { -ms-flex-item-align: start; align-self: flex-start; } .self-end { -ms-flex-item-align: end; align-self: flex-end; } .self-center { -ms-flex-item-align: center; align-self: center; } .self-baseline { -ms-flex-item-align: baseline; align-self: baseline; } .self-stretch { -ms-flex-item-align: stretch; align-self: stretch; } .justify-start { -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .justify-end { -webkit-box-pack: end; -ms-flex-pack: end; justify-content: flex-end; } .justify-center { -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; } .justify-between { -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; } .justify-around { -ms-flex-pack: distribute; justify-content: space-around; } .content-start { -ms-flex-line-pack: start; align-content: flex-start; } .content-end { -ms-flex-line-pack: end; align-content: flex-end; } .content-center { -ms-flex-line-pack: center; align-content: center; } .content-between { -ms-flex-line-pack: justify; align-content: space-between; } .content-around { -ms-flex-line-pack: distribute; align-content: space-around; } .content-stretch { -ms-flex-line-pack: stretch; align-content: stretch; } .order-0 { -webkit-box-ordinal-group: 1; -ms-flex-order: 0; order: 0; } .order-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-last { -webkit-box-ordinal-group: 100000; -ms-flex-order: 99999; order: 99999; } .flex-grow-0 { -webkit-box-flex: 0; -ms-flex-positive: 0; flex-grow: 0; } .flex-grow-1 { -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; } .flex-shrink-0 { -ms-flex-negative: 0; flex-shrink: 0; } .flex-shrink-1 { -ms-flex-negative: 1; flex-shrink: 1; } @media screen and (min-width: 30em) { .flex-ns { display: -webkit-box; display: -ms-flexbox; display: flex; } .inline-flex-ns { display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; } .flex-auto-ns { -webkit-box-flex: 1; -ms-flex: 1 1 auto; flex: 1 1 auto; min-width: 0; /* 1 */ min-height: 0; /* 1 */ } .flex-none-ns { -webkit-box-flex: 0; -ms-flex: none; flex: none; } .flex-column-ns { -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; } .flex-row-ns { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; } .flex-wrap-ns { -ms-flex-wrap: wrap; flex-wrap: wrap; } .flex-nowrap-ns { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .flex-wrap-reverse-ns { -ms-flex-wrap: wrap-reverse; flex-wrap: wrap-reverse; } .flex-column-reverse-ns { -webkit-box-orient: vertical; -webkit-box-direction: reverse; -ms-flex-direction: column-reverse; flex-direction: column-reverse; } .flex-row-reverse-ns { -webkit-box-orient: horizontal; -webkit-box-direction: reverse; -ms-flex-direction: row-reverse; flex-direction: row-reverse; } .items-start-ns { -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; } .items-end-ns { -webkit-box-align: end; -ms-flex-align: end; align-items: flex-end; } .items-center-ns { -webkit-box-align: center; -ms-flex-align: center; align-items: center; } .items-baseline-ns { -webkit-box-align: baseline; -ms-flex-align: baseline; align-items: baseline; } .items-stretch-ns { -webkit-box-align: stretch; -ms-flex-align: stretch; align-items: stretch; } .self-start-ns { -ms-flex-item-align: start; align-self: flex-start; } .self-end-ns { -ms-flex-item-align: end; align-self: flex-end; } .self-center-ns { -ms-flex-item-align: center; align-self: center; } .self-baseline-ns { -ms-flex-item-align: baseline; align-self: baseline; } .self-stretch-ns { -ms-flex-item-align: stretch; align-self: stretch; } .justify-start-ns { -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .justify-end-ns { -webkit-box-pack: end; -ms-flex-pack: end; justify-content: flex-end; } .justify-center-ns { -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; } .justify-between-ns { -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; } .justify-around-ns { -ms-flex-pack: distribute; justify-content: space-around; } .content-start-ns { -ms-flex-line-pack: start; align-content: flex-start; } .content-end-ns { -ms-flex-line-pack: end; align-content: flex-end; } .content-center-ns { -ms-flex-line-pack: center; align-content: center; } .content-between-ns { -ms-flex-line-pack: justify; align-content: space-between; } .content-around-ns { -ms-flex-line-pack: distribute; align-content: space-around; } .content-stretch-ns { -ms-flex-line-pack: stretch; align-content: stretch; } .order-0-ns { -webkit-box-ordinal-group: 1; -ms-flex-order: 0; order: 0; } .order-1-ns { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-2-ns { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-3-ns { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-4-ns { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-5-ns { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-6-ns { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-7-ns { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-8-ns { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-last-ns { -webkit-box-ordinal-group: 100000; -ms-flex-order: 99999; order: 99999; } .flex-grow-0-ns { -webkit-box-flex: 0; -ms-flex-positive: 0; flex-grow: 0; } .flex-grow-1-ns { -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; } .flex-shrink-0-ns { -ms-flex-negative: 0; flex-shrink: 0; } .flex-shrink-1-ns { -ms-flex-negative: 1; flex-shrink: 1; } } @media screen and (min-width: 30em) and (max-width: 60em) { .flex-m { display: -webkit-box; display: -ms-flexbox; display: flex; } .inline-flex-m { display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; } .flex-auto-m { -webkit-box-flex: 1; -ms-flex: 1 1 auto; flex: 1 1 auto; min-width: 0; /* 1 */ min-height: 0; /* 1 */ } .flex-none-m { -webkit-box-flex: 0; -ms-flex: none; flex: none; } .flex-column-m { -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; } .flex-row-m { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; } .flex-wrap-m { -ms-flex-wrap: wrap; flex-wrap: wrap; } .flex-nowrap-m { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .flex-wrap-reverse-m { -ms-flex-wrap: wrap-reverse; flex-wrap: wrap-reverse; } .flex-column-reverse-m { -webkit-box-orient: vertical; -webkit-box-direction: reverse; -ms-flex-direction: column-reverse; flex-direction: column-reverse; } .flex-row-reverse-m { -webkit-box-orient: horizontal; -webkit-box-direction: reverse; -ms-flex-direction: row-reverse; flex-direction: row-reverse; } .items-start-m { -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; } .items-end-m { -webkit-box-align: end; -ms-flex-align: end; align-items: flex-end; } .items-center-m { -webkit-box-align: center; -ms-flex-align: center; align-items: center; } .items-baseline-m { -webkit-box-align: baseline; -ms-flex-align: baseline; align-items: baseline; } .items-stretch-m { -webkit-box-align: stretch; -ms-flex-align: stretch; align-items: stretch; } .self-start-m { -ms-flex-item-align: start; align-self: flex-start; } .self-end-m { -ms-flex-item-align: end; align-self: flex-end; } .self-center-m { -ms-flex-item-align: center; align-self: center; } .self-baseline-m { -ms-flex-item-align: baseline; align-self: baseline; } .self-stretch-m { -ms-flex-item-align: stretch; align-self: stretch; } .justify-start-m { -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .justify-end-m { -webkit-box-pack: end; -ms-flex-pack: end; justify-content: flex-end; } .justify-center-m { -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; } .justify-between-m { -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; } .justify-around-m { -ms-flex-pack: distribute; justify-content: space-around; } .content-start-m { -ms-flex-line-pack: start; align-content: flex-start; } .content-end-m { -ms-flex-line-pack: end; align-content: flex-end; } .content-center-m { -ms-flex-line-pack: center; align-content: center; } .content-between-m { -ms-flex-line-pack: justify; align-content: space-between; } .content-around-m { -ms-flex-line-pack: distribute; align-content: space-around; } .content-stretch-m { -ms-flex-line-pack: stretch; align-content: stretch; } .order-0-m { -webkit-box-ordinal-group: 1; -ms-flex-order: 0; order: 0; } .order-1-m { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-2-m { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-3-m { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-4-m { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-5-m { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-6-m { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-7-m { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-8-m { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-last-m { -webkit-box-ordinal-group: 100000; -ms-flex-order: 99999; order: 99999; } .flex-grow-0-m { -webkit-box-flex: 0; -ms-flex-positive: 0; flex-grow: 0; } .flex-grow-1-m { -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; } .flex-shrink-0-m { -ms-flex-negative: 0; flex-shrink: 0; } .flex-shrink-1-m { -ms-flex-negative: 1; flex-shrink: 1; } } @media screen and (min-width: 60em) { .flex-l { display: -webkit-box; display: -ms-flexbox; display: flex; } .inline-flex-l { display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; } .flex-auto-l { -webkit-box-flex: 1; -ms-flex: 1 1 auto; flex: 1 1 auto; min-width: 0; /* 1 */ min-height: 0; /* 1 */ } .flex-none-l { -webkit-box-flex: 0; -ms-flex: none; flex: none; } .flex-column-l { -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; } .flex-row-l { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; } .flex-wrap-l { -ms-flex-wrap: wrap; flex-wrap: wrap; } .flex-nowrap-l { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .flex-wrap-reverse-l { -ms-flex-wrap: wrap-reverse; flex-wrap: wrap-reverse; } .flex-column-reverse-l { -webkit-box-orient: vertical; -webkit-box-direction: reverse; -ms-flex-direction: column-reverse; flex-direction: column-reverse; } .flex-row-reverse-l { -webkit-box-orient: horizontal; -webkit-box-direction: reverse; -ms-flex-direction: row-reverse; flex-direction: row-reverse; } .items-start-l { -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; } .items-end-l { -webkit-box-align: end; -ms-flex-align: end; align-items: flex-end; } .items-center-l { -webkit-box-align: center; -ms-flex-align: center; align-items: center; } .items-baseline-l { -webkit-box-align: baseline; -ms-flex-align: baseline; align-items: baseline; } .items-stretch-l { -webkit-box-align: stretch; -ms-flex-align: stretch; align-items: stretch; } .self-start-l { -ms-flex-item-align: start; align-self: flex-start; } .self-end-l { -ms-flex-item-align: end; align-self: flex-end; } .self-center-l { -ms-flex-item-align: center; align-self: center; } .self-baseline-l { -ms-flex-item-align: baseline; align-self: baseline; } .self-stretch-l { -ms-flex-item-align: stretch; align-self: stretch; } .justify-start-l { -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .justify-end-l { -webkit-box-pack: end; -ms-flex-pack: end; justify-content: flex-end; } .justify-center-l { -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; } .justify-between-l { -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; } .justify-around-l { -ms-flex-pack: distribute; justify-content: space-around; } .content-start-l { -ms-flex-line-pack: start; align-content: flex-start; } .content-end-l { -ms-flex-line-pack: end; align-content: flex-end; } .content-center-l { -ms-flex-line-pack: center; align-content: center; } .content-between-l { -ms-flex-line-pack: justify; align-content: space-between; } .content-around-l { -ms-flex-line-pack: distribute; align-content: space-around; } .content-stretch-l { -ms-flex-line-pack: stretch; align-content: stretch; } .order-0-l { -webkit-box-ordinal-group: 1; -ms-flex-order: 0; order: 0; } .order-1-l { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-2-l { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-3-l { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-4-l { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-5-l { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-6-l { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-7-l { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-8-l { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-last-l { -webkit-box-ordinal-group: 100000; -ms-flex-order: 99999; order: 99999; } .flex-grow-0-l { -webkit-box-flex: 0; -ms-flex-positive: 0; flex-grow: 0; } .flex-grow-1-l { -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; } .flex-shrink-0-l { -ms-flex-negative: 0; flex-shrink: 0; } .flex-shrink-1-l { -ms-flex-negative: 1; flex-shrink: 1; } } /* FLOATS http://tachyons.io/docs/layout/floats/ 1. Floated elements are automatically rendered as block level elements. Setting floats to display inline will fix the double margin bug in ie6. You know... just in case. 2. Don't forget to clearfix your floats with .cf Base: f = float Modifiers: l = left r = right n = none Media Query Extensions: -ns = not-small -m = medium -l = large */ .fl { float: left; _display: inline; } .fr { float: right; _display: inline; } .fn { float: none; } @media screen and (min-width: 30em) { .fl-ns { float: left; _display: inline; } .fr-ns { float: right; _display: inline; } .fn-ns { float: none; } } @media screen and (min-width: 30em) and (max-width: 60em) { .fl-m { float: left; _display: inline; } .fr-m { float: right; _display: inline; } .fn-m { float: none; } } @media screen and (min-width: 60em) { .fl-l { float: left; _display: inline; } .fr-l { float: right; _display: inline; } .fn-l { float: none; } } /*@import 'tachyons/src/_font-family';*/ /* FONT STYLE Docs: http://tachyons.io/docs/typography/font-style/ Media Query Extensions: -ns = not-small -m = medium -l = large */ .i { font-style: italic; } .fs-normal { font-style: normal; } @media screen and (min-width: 30em) { .i-ns { font-style: italic; } .fs-normal-ns { font-style: normal; } } @media screen and (min-width: 30em) and (max-width: 60em) { .i-m { font-style: italic; } .fs-normal-m { font-style: normal; } } @media screen and (min-width: 60em) { .i-l { font-style: italic; } .fs-normal-l { font-style: normal; } } /* FONT WEIGHT Docs: http://tachyons.io/docs/typography/font-weight/ Base fw = font-weight Modifiers: 1 = literal value 100 2 = literal value 200 3 = literal value 300 4 = literal value 400 5 = literal value 500 6 = literal value 600 7 = literal value 700 8 = literal value 800 9 = literal value 900 Media Query Extensions: -ns = not-small -m = medium -l = large */ .normal { font-weight: normal; } .b { font-weight: bold; } .fw1 { font-weight: 100; } .fw2 { font-weight: 200; } .fw3 { font-weight: 300; } .fw4 { font-weight: 400; } .fw5 { font-weight: 500; } .fw6 { font-weight: 600; } .fw7 { font-weight: 700; } .fw8 { font-weight: 800; } .fw9 { font-weight: 900; } @media screen and (min-width: 30em) { .normal-ns { font-weight: normal; } .b-ns { font-weight: bold; } .fw1-ns { font-weight: 100; } .fw2-ns { font-weight: 200; } .fw3-ns { font-weight: 300; } .fw4-ns { font-weight: 400; } .fw5-ns { font-weight: 500; } .fw6-ns { font-weight: 600; } .fw7-ns { font-weight: 700; } .fw8-ns { font-weight: 800; } .fw9-ns { font-weight: 900; } } @media screen and (min-width: 30em) and (max-width: 60em) { .normal-m { font-weight: normal; } .b-m { font-weight: bold; } .fw1-m { font-weight: 100; } .fw2-m { font-weight: 200; } .fw3-m { font-weight: 300; } .fw4-m { font-weight: 400; } .fw5-m { font-weight: 500; } .fw6-m { font-weight: 600; } .fw7-m { font-weight: 700; } .fw8-m { font-weight: 800; } .fw9-m { font-weight: 900; } } @media screen and (min-width: 60em) { .normal-l { font-weight: normal; } .b-l { font-weight: bold; } .fw1-l { font-weight: 100; } .fw2-l { font-weight: 200; } .fw3-l { font-weight: 300; } .fw4-l { font-weight: 400; } .fw5-l { font-weight: 500; } .fw6-l { font-weight: 600; } .fw7-l { font-weight: 700; } .fw8-l { font-weight: 800; } .fw9-l { font-weight: 900; } } /* FORMS */ .input-reset { -webkit-appearance: none; -moz-appearance: none; } .button-reset::-moz-focus-inner, .input-reset::-moz-focus-inner { border: 0; padding: 0; } /* HEIGHTS Docs: http://tachyons.io/docs/layout/heights/ Base: h = height min-h = min-height min-vh = min-height vertical screen height vh = vertical screen height Modifiers 1 = 1st step in height scale 2 = 2nd step in height scale 3 = 3rd step in height scale 4 = 4th step in height scale 5 = 5th step in height scale -25 = literal value 25% -50 = literal value 50% -75 = literal value 75% -100 = literal value 100% -auto = string value of auto -inherit = string value of inherit Media Query Extensions: -ns = not-small -m = medium -l = large */ /* Height Scale */ .h1 { height: 1rem; } .h2 { height: 2rem; } .h3 { height: 4rem; } .h4 { height: 8rem; } .h5 { height: 16rem; } /* Height Percentages - Based off of height of parent */ .h-25 { height: 25%; } .h-50 { height: 50%; } .h-75 { height: 75%; } .h-100 { height: 100%; } .min-h-100 { min-height: 100%; } /* Screen Height Percentage */ .vh-25 { height: 25vh; } .vh-50 { height: 50vh; } .vh-75 { height: 75vh; } .vh-100 { height: 100vh; } .min-vh-100 { min-height: 100vh; } /* String Properties */ .h-auto { height: auto; } .h-inherit { height: inherit; } @media screen and (min-width: 30em) { .h1-ns { height: 1rem; } .h2-ns { height: 2rem; } .h3-ns { height: 4rem; } .h4-ns { height: 8rem; } .h5-ns { height: 16rem; } .h-25-ns { height: 25%; } .h-50-ns { height: 50%; } .h-75-ns { height: 75%; } .h-100-ns { height: 100%; } .min-h-100-ns { min-height: 100%; } .vh-25-ns { height: 25vh; } .vh-50-ns { height: 50vh; } .vh-75-ns { height: 75vh; } .vh-100-ns { height: 100vh; } .min-vh-100-ns { min-height: 100vh; } .h-auto-ns { height: auto; } .h-inherit-ns { height: inherit; } } @media screen and (min-width: 30em) and (max-width: 60em) { .h1-m { height: 1rem; } .h2-m { height: 2rem; } .h3-m { height: 4rem; } .h4-m { height: 8rem; } .h5-m { height: 16rem; } .h-25-m { height: 25%; } .h-50-m { height: 50%; } .h-75-m { height: 75%; } .h-100-m { height: 100%; } .min-h-100-m { min-height: 100%; } .vh-25-m { height: 25vh; } .vh-50-m { height: 50vh; } .vh-75-m { height: 75vh; } .vh-100-m { height: 100vh; } .min-vh-100-m { min-height: 100vh; } .h-auto-m { height: auto; } .h-inherit-m { height: inherit; } } @media screen and (min-width: 60em) { .h1-l { height: 1rem; } .h2-l { height: 2rem; } .h3-l { height: 4rem; } .h4-l { height: 8rem; } .h5-l { height: 16rem; } .h-25-l { height: 25%; } .h-50-l { height: 50%; } .h-75-l { height: 75%; } .h-100-l { height: 100%; } .min-h-100-l { min-height: 100%; } .vh-25-l { height: 25vh; } .vh-50-l { height: 50vh; } .vh-75-l { height: 75vh; } .vh-100-l { height: 100vh; } .min-vh-100-l { min-height: 100vh; } .h-auto-l { height: auto; } .h-inherit-l { height: inherit; } } /* LETTER SPACING Docs: http://tachyons.io/docs/typography/tracking/ Media Query Extensions: -ns = not-small -m = medium -l = large */ .tracked { letter-spacing: .1em; } .tracked-tight { letter-spacing: -.05em; } .tracked-mega { letter-spacing: .25em; } @media screen and (min-width: 30em) { .tracked-ns { letter-spacing: .1em; } .tracked-tight-ns { letter-spacing: -.05em; } .tracked-mega-ns { letter-spacing: .25em; } } @media screen and (min-width: 30em) and (max-width: 60em) { .tracked-m { letter-spacing: .1em; } .tracked-tight-m { letter-spacing: -.05em; } .tracked-mega-m { letter-spacing: .25em; } } @media screen and (min-width: 60em) { .tracked-l { letter-spacing: .1em; } .tracked-tight-l { letter-spacing: -.05em; } .tracked-mega-l { letter-spacing: .25em; } } /* LINE HEIGHT / LEADING Docs: http://tachyons.io/docs/typography/line-height Media Query Extensions: -ns = not-small -m = medium -l = large */ .lh-solid { line-height: 1; } .lh-title { line-height: 1.25; } .lh-copy { line-height: 1.5; } @media screen and (min-width: 30em) { .lh-solid-ns { line-height: 1; } .lh-title-ns { line-height: 1.25; } .lh-copy-ns { line-height: 1.5; } } @media screen and (min-width: 30em) and (max-width: 60em) { .lh-solid-m { line-height: 1; } .lh-title-m { line-height: 1.25; } .lh-copy-m { line-height: 1.5; } } @media screen and (min-width: 60em) { .lh-solid-l { line-height: 1; } .lh-title-l { line-height: 1.25; } .lh-copy-l { line-height: 1.5; } } /* LINKS Docs: http://tachyons.io/docs/elements/links/ */ .link { text-decoration: none; -webkit-transition: color .15s ease-in; transition: color .15s ease-in; } .link:link, .link:visited { -webkit-transition: color .15s ease-in; transition: color .15s ease-in; } .link:hover { -webkit-transition: color .15s ease-in; transition: color .15s ease-in; } .link:active { -webkit-transition: color .15s ease-in; transition: color .15s ease-in; } .link:focus { -webkit-transition: color .15s ease-in; transition: color .15s ease-in; outline: 1px dotted currentColor; } /* LISTS http://tachyons.io/docs/elements/lists/ */ .list { list-style-type: none; } /* MAX WIDTHS Docs: http://tachyons.io/docs/layout/max-widths/ Base: mw = max-width Modifiers 1 = 1st step in width scale 2 = 2nd step in width scale 3 = 3rd step in width scale 4 = 4th step in width scale 5 = 5th step in width scale 6 = 6st step in width scale 7 = 7nd step in width scale 8 = 8rd step in width scale 9 = 9th step in width scale -100 = literal value 100% -none = string value none Media Query Extensions: -ns = not-small -m = medium -l = large */ /* Max Width Percentages */ .mw-100 { max-width: 100%; } /* Max Width Scale */ .mw1 { max-width: 1rem; } .mw2 { max-width: 2rem; } .mw3 { max-width: 4rem; } .mw4 { max-width: 8rem; } .mw5 { max-width: 16rem; } .mw6 { max-width: 32rem; } .mw7 { max-width: 48rem; } .mw8 { max-width: 64rem; } .mw9 { max-width: 96rem; } /* Max Width String Properties */ .mw-none { max-width: none; } @media screen and (min-width: 30em) { .mw-100-ns { max-width: 100%; } .mw1-ns { max-width: 1rem; } .mw2-ns { max-width: 2rem; } .mw3-ns { max-width: 4rem; } .mw4-ns { max-width: 8rem; } .mw5-ns { max-width: 16rem; } .mw6-ns { max-width: 32rem; } .mw7-ns { max-width: 48rem; } .mw8-ns { max-width: 64rem; } .mw9-ns { max-width: 96rem; } .mw-none-ns { max-width: none; } } @media screen and (min-width: 30em) and (max-width: 60em) { .mw-100-m { max-width: 100%; } .mw1-m { max-width: 1rem; } .mw2-m { max-width: 2rem; } .mw3-m { max-width: 4rem; } .mw4-m { max-width: 8rem; } .mw5-m { max-width: 16rem; } .mw6-m { max-width: 32rem; } .mw7-m { max-width: 48rem; } .mw8-m { max-width: 64rem; } .mw9-m { max-width: 96rem; } .mw-none-m { max-width: none; } } @media screen and (min-width: 60em) { .mw-100-l { max-width: 100%; } .mw1-l { max-width: 1rem; } .mw2-l { max-width: 2rem; } .mw3-l { max-width: 4rem; } .mw4-l { max-width: 8rem; } .mw5-l { max-width: 16rem; } .mw6-l { max-width: 32rem; } .mw7-l { max-width: 48rem; } .mw8-l { max-width: 64rem; } .mw9-l { max-width: 96rem; } .mw-none-l { max-width: none; } } /* WIDTHS Docs: http://tachyons.io/docs/layout/widths/ Base: w = width Modifiers 1 = 1st step in width scale 2 = 2nd step in width scale 3 = 3rd step in width scale 4 = 4th step in width scale 5 = 5th step in width scale -10 = literal value 10% -20 = literal value 20% -25 = literal value 25% -30 = literal value 30% -33 = literal value 33% -34 = literal value 34% -40 = literal value 40% -50 = literal value 50% -60 = literal value 60% -70 = literal value 70% -75 = literal value 75% -80 = literal value 80% -90 = literal value 90% -100 = literal value 100% -third = 100% / 3 (Not supported in opera mini or IE8) -two-thirds = 100% / 1.5 (Not supported in opera mini or IE8) -auto = string value auto Media Query Extensions: -ns = not-small -m = medium -l = large */ /* Width Scale */ .w1 { width: 1rem; } .w2 { width: 2rem; } .w3 { width: 4rem; } .w4 { width: 8rem; } .w5 { width: 16rem; } .w-10 { width: 10%; } .w-20 { width: 20%; } .w-25 { width: 25%; } .w-30 { width: 30%; } .w-33 { width: 33%; } .w-34 { width: 34%; } .w-40 { width: 40%; } .w-50 { width: 50%; } .w-60 { width: 60%; } .w-70 { width: 70%; } .w-75 { width: 75%; } .w-80 { width: 80%; } .w-90 { width: 90%; } .w-100 { width: 100%; } .w-third { width: 33.33333%; } .w-two-thirds { width: 66.66667%; } .w-auto { width: auto; } @media screen and (min-width: 30em) { .w1-ns { width: 1rem; } .w2-ns { width: 2rem; } .w3-ns { width: 4rem; } .w4-ns { width: 8rem; } .w5-ns { width: 16rem; } .w-10-ns { width: 10%; } .w-20-ns { width: 20%; } .w-25-ns { width: 25%; } .w-30-ns { width: 30%; } .w-33-ns { width: 33%; } .w-34-ns { width: 34%; } .w-40-ns { width: 40%; } .w-50-ns { width: 50%; } .w-60-ns { width: 60%; } .w-70-ns { width: 70%; } .w-75-ns { width: 75%; } .w-80-ns { width: 80%; } .w-90-ns { width: 90%; } .w-100-ns { width: 100%; } .w-third-ns { width: 33.33333%; } .w-two-thirds-ns { width: 66.66667%; } .w-auto-ns { width: auto; } } @media screen and (min-width: 30em) and (max-width: 60em) { .w1-m { width: 1rem; } .w2-m { width: 2rem; } .w3-m { width: 4rem; } .w4-m { width: 8rem; } .w5-m { width: 16rem; } .w-10-m { width: 10%; } .w-20-m { width: 20%; } .w-25-m { width: 25%; } .w-30-m { width: 30%; } .w-33-m { width: 33%; } .w-34-m { width: 34%; } .w-40-m { width: 40%; } .w-50-m { width: 50%; } .w-60-m { width: 60%; } .w-70-m { width: 70%; } .w-75-m { width: 75%; } .w-80-m { width: 80%; } .w-90-m { width: 90%; } .w-100-m { width: 100%; } .w-third-m { width: 33.33333%; } .w-two-thirds-m { width: 66.66667%; } .w-auto-m { width: auto; } } @media screen and (min-width: 60em) { .w1-l { width: 1rem; } .w2-l { width: 2rem; } .w3-l { width: 4rem; } .w4-l { width: 8rem; } .w5-l { width: 16rem; } .w-10-l { width: 10%; } .w-20-l { width: 20%; } .w-25-l { width: 25%; } .w-30-l { width: 30%; } .w-33-l { width: 33%; } .w-34-l { width: 34%; } .w-40-l { width: 40%; } .w-50-l { width: 50%; } .w-60-l { width: 60%; } .w-70-l { width: 70%; } .w-75-l { width: 75%; } .w-80-l { width: 80%; } .w-90-l { width: 90%; } .w-100-l { width: 100%; } .w-third-l { width: 33.33333%; } .w-two-thirds-l { width: 66.66667%; } .w-auto-l { width: auto; } } /* OVERFLOW Media Query Extensions: -ns = not-small -m = medium -l = large */ .overflow-visible { overflow: visible; } .overflow-hidden { overflow: hidden; } .overflow-scroll { overflow: scroll; } .overflow-auto { overflow: auto; } .overflow-x-visible { overflow-x: visible; } .overflow-x-hidden { overflow-x: hidden; } .overflow-x-scroll { overflow-x: scroll; } .overflow-x-auto { overflow-x: auto; } .overflow-y-visible { overflow-y: visible; } .overflow-y-hidden { overflow-y: hidden; } .overflow-y-scroll { overflow-y: scroll; } .overflow-y-auto { overflow-y: auto; } @media screen and (min-width: 30em) { .overflow-visible-ns { overflow: visible; } .overflow-hidden-ns { overflow: hidden; } .overflow-scroll-ns { overflow: scroll; } .overflow-auto-ns { overflow: auto; } .overflow-x-visible-ns { overflow-x: visible; } .overflow-x-hidden-ns { overflow-x: hidden; } .overflow-x-scroll-ns { overflow-x: scroll; } .overflow-x-auto-ns { overflow-x: auto; } .overflow-y-visible-ns { overflow-y: visible; } .overflow-y-hidden-ns { overflow-y: hidden; } .overflow-y-scroll-ns { overflow-y: scroll; } .overflow-y-auto-ns { overflow-y: auto; } } @media screen and (min-width: 30em) and (max-width: 60em) { .overflow-visible-m { overflow: visible; } .overflow-hidden-m { overflow: hidden; } .overflow-scroll-m { overflow: scroll; } .overflow-auto-m { overflow: auto; } .overflow-x-visible-m { overflow-x: visible; } .overflow-x-hidden-m { overflow-x: hidden; } .overflow-x-scroll-m { overflow-x: scroll; } .overflow-x-auto-m { overflow-x: auto; } .overflow-y-visible-m { overflow-y: visible; } .overflow-y-hidden-m { overflow-y: hidden; } .overflow-y-scroll-m { overflow-y: scroll; } .overflow-y-auto-m { overflow-y: auto; } } @media screen and (min-width: 60em) { .overflow-visible-l { overflow: visible; } .overflow-hidden-l { overflow: hidden; } .overflow-scroll-l { overflow: scroll; } .overflow-auto-l { overflow: auto; } .overflow-x-visible-l { overflow-x: visible; } .overflow-x-hidden-l { overflow-x: hidden; } .overflow-x-scroll-l { overflow-x: scroll; } .overflow-x-auto-l { overflow-x: auto; } .overflow-y-visible-l { overflow-y: visible; } .overflow-y-hidden-l { overflow-y: hidden; } .overflow-y-scroll-l { overflow-y: scroll; } .overflow-y-auto-l { overflow-y: auto; } } /* POSITIONING Docs: http://tachyons.io/docs/layout/position/ Media Query Extensions: -ns = not-small -m = medium -l = large */ .static { position: static; } .relative { position: relative; } .absolute { position: absolute; } .fixed { position: fixed; } @media screen and (min-width: 30em) { .static-ns { position: static; } .relative-ns { position: relative; } .absolute-ns { position: absolute; } .fixed-ns { position: fixed; } } @media screen and (min-width: 30em) and (max-width: 60em) { .static-m { position: static; } .relative-m { position: relative; } .absolute-m { position: absolute; } .fixed-m { position: fixed; } } @media screen and (min-width: 60em) { .static-l { position: static; } .relative-l { position: relative; } .absolute-l { position: absolute; } .fixed-l { position: fixed; } } /* OPACITY Docs: http://tachyons.io/docs/themes/opacity/ */ .o-100 { opacity: 1; } .o-90 { opacity: .9; } .o-80 { opacity: .8; } .o-70 { opacity: .7; } .o-60 { opacity: .6; } .o-50 { opacity: .5; } .o-40 { opacity: .4; } .o-30 { opacity: .3; } .o-20 { opacity: .2; } .o-10 { opacity: .1; } .o-05 { opacity: .05; } .o-025 { opacity: .025; } .o-0 { opacity: 0; } /*@import 'tachyons/src/_rotations';*/ /* SKINS Docs: http://tachyons.io/docs/themes/skins/ Classes for setting foreground and background colors on elements. If you haven't declared a border color, but set border on an element, it will be set to the current text color. */ /* Text colors */ .black-90 { color: rgba(0, 0, 0, .9); } .black-80 { color: rgba(0, 0, 0, .8); } .black-70 { color: rgba(0, 0, 0, .7); } .black-60 { color: rgba(0, 0, 0, .6); } .black-50 { color: rgba(0, 0, 0, .5); } .black-40 { color: rgba(0, 0, 0, .4); } .black-30 { color: rgba(0, 0, 0, .3); } .black-20 { color: rgba(0, 0, 0, .2); } .black-10 { color: rgba(0, 0, 0, .1); } .black-05 { color: rgba(0, 0, 0, .05); } .white-90 { color: rgba(255, 255, 255, .9); } .white-80 { color: rgba(255, 255, 255, .8); } .white-70 { color: rgba(255, 255, 255, .7); } .white-60 { color: rgba(255, 255, 255, .6); } .white-50 { color: rgba(255, 255, 255, .5); } .white-40 { color: rgba(255, 255, 255, .4); } .white-30 { color: rgba(255, 255, 255, .3); } .white-20 { color: rgba(255, 255, 255, .2); } .white-10 { color: rgba(255, 255, 255, .1); } .black { color: #000; } .near-black { color: #111; } .dark-gray { color: #333; } .mid-gray { color: #555; } .gray { color: #777; } .silver { color: #999; } .light-silver { color: #aaa; } .moon-gray { color: #ccc; } .light-gray { color: #eee; } .near-white { color: #f4f4f4; } .white { color: #fff; } .dark-red { color: #e7040f; } .red { color: #ff4136; } .light-red { color: #ff725c; } .orange { color: #ff6300; } .gold { color: #ffb700; } .yellow { color: #ffd700; } .light-yellow { color: #fbf1a9; } .purple { color: #5e2ca5; } .light-purple { color: #a463f2; } .dark-pink { color: #d5008f; } .hot-pink { color: #ff41b4; } .pink { color: #ff80cc; } .light-pink { color: #ffa3d7; } .dark-green { color: #137752; } .green { color: #19a974; } .light-green { color: #9eebcf; } .navy { color: #001b44; } .dark-blue { color: #00449e; } .blue { color: #0594CB; } .light-blue { color: #96ccff; } .lightest-blue { color: #cdecff; } .washed-blue { color: #f6fffe; } .washed-green { color: #e8fdf5; } .washed-yellow { color: #fffceb; } .washed-red { color: #ffdfdf; } .color-inherit { color: inherit; } .bg-black-90 { background-color: rgba(0, 0, 0, .9); } .bg-black-80 { background-color: rgba(0, 0, 0, .8); } .bg-black-70 { background-color: rgba(0, 0, 0, .7); } .bg-black-60 { background-color: rgba(0, 0, 0, .6); } .bg-black-50 { background-color: rgba(0, 0, 0, .5); } .bg-black-40 { background-color: rgba(0, 0, 0, .4); } .bg-black-30 { background-color: rgba(0, 0, 0, .3); } .bg-black-20 { background-color: rgba(0, 0, 0, .2); } .bg-black-10 { background-color: rgba(0, 0, 0, .1); } .bg-black-05 { background-color: rgba(0, 0, 0, .05); } .bg-white-90 { background-color: rgba(255, 255, 255, .9); } .bg-white-80 { background-color: rgba(255, 255, 255, .8); } .bg-white-70 { background-color: rgba(255, 255, 255, .7); } .bg-white-60 { background-color: rgba(255, 255, 255, .6); } .bg-white-50 { background-color: rgba(255, 255, 255, .5); } .bg-white-40 { background-color: rgba(255, 255, 255, .4); } .bg-white-30 { background-color: rgba(255, 255, 255, .3); } .bg-white-20 { background-color: rgba(255, 255, 255, .2); } .bg-white-10 { background-color: rgba(255, 255, 255, .1); } /* Background colors */ .bg-black { background-color: #000; } .bg-near-black { background-color: #111; } .bg-dark-gray { background-color: #333; } .bg-mid-gray { background-color: #555; } .bg-gray { background-color: #777; } .bg-silver { background-color: #999; } .bg-light-silver { background-color: #aaa; } .bg-moon-gray { background-color: #ccc; } .bg-light-gray { background-color: #eee; } .bg-near-white { background-color: #f4f4f4; } .bg-white { background-color: #fff; } .bg-transparent { background-color: transparent; } .bg-dark-red { background-color: #e7040f; } .bg-red { background-color: #ff4136; } .bg-light-red { background-color: #ff725c; } .bg-orange { background-color: #ff6300; } .bg-gold { background-color: #ffb700; } .bg-yellow { background-color: #ffd700; } .bg-light-yellow { background-color: #fbf1a9; } .bg-purple { background-color: #5e2ca5; } .bg-light-purple { background-color: #a463f2; } .bg-dark-pink { background-color: #d5008f; } .bg-hot-pink { background-color: #ff41b4; } .bg-pink { background-color: #ff80cc; } .bg-light-pink { background-color: #ffa3d7; } .bg-dark-green { background-color: #137752; } .bg-green { background-color: #19a974; } .bg-light-green { background-color: #9eebcf; } .bg-navy { background-color: #001b44; } .bg-dark-blue { background-color: #00449e; } .bg-blue { background-color: #0594CB; } .bg-light-blue { background-color: #96ccff; } .bg-lightest-blue { background-color: #cdecff; } .bg-washed-blue { background-color: #f6fffe; } .bg-washed-green { background-color: #e8fdf5; } .bg-washed-yellow { background-color: #fffceb; } .bg-washed-red { background-color: #ffdfdf; } .bg-inherit { background-color: inherit; } /* SKINS:PSEUDO Customize the color of an element when it is focused or hovered over. */ .hover-black:hover, .hover-black:focus { color: #000; } .hover-near-black:hover, .hover-near-black:focus { color: #111; } .hover-dark-gray:hover, .hover-dark-gray:focus { color: #333; } .hover-mid-gray:hover, .hover-mid-gray:focus { color: #555; } .hover-gray:hover, .hover-gray:focus { color: #777; } .hover-silver:hover, .hover-silver:focus { color: #999; } .hover-light-silver:hover, .hover-light-silver:focus { color: #aaa; } .hover-moon-gray:hover, .hover-moon-gray:focus { color: #ccc; } .hover-light-gray:hover, .hover-light-gray:focus { color: #eee; } .hover-near-white:hover, .hover-near-white:focus { color: #f4f4f4; } .hover-white:hover, .hover-white:focus { color: #fff; } .hover-black-90:hover, .hover-black-90:focus { color: rgba(0, 0, 0, .9); } .hover-black-80:hover, .hover-black-80:focus { color: rgba(0, 0, 0, .8); } .hover-black-70:hover, .hover-black-70:focus { color: rgba(0, 0, 0, .7); } .hover-black-60:hover, .hover-black-60:focus { color: rgba(0, 0, 0, .6); } .hover-black-50:hover, .hover-black-50:focus { color: rgba(0, 0, 0, .5); } .hover-black-40:hover, .hover-black-40:focus { color: rgba(0, 0, 0, .4); } .hover-black-30:hover, .hover-black-30:focus { color: rgba(0, 0, 0, .3); } .hover-black-20:hover, .hover-black-20:focus { color: rgba(0, 0, 0, .2); } .hover-black-10:hover, .hover-black-10:focus { color: rgba(0, 0, 0, .1); } .hover-white-90:hover, .hover-white-90:focus { color: rgba(255, 255, 255, .9); } .hover-white-80:hover, .hover-white-80:focus { color: rgba(255, 255, 255, .8); } .hover-white-70:hover, .hover-white-70:focus { color: rgba(255, 255, 255, .7); } .hover-white-60:hover, .hover-white-60:focus { color: rgba(255, 255, 255, .6); } .hover-white-50:hover, .hover-white-50:focus { color: rgba(255, 255, 255, .5); } .hover-white-40:hover, .hover-white-40:focus { color: rgba(255, 255, 255, .4); } .hover-white-30:hover, .hover-white-30:focus { color: rgba(255, 255, 255, .3); } .hover-white-20:hover, .hover-white-20:focus { color: rgba(255, 255, 255, .2); } .hover-white-10:hover, .hover-white-10:focus { color: rgba(255, 255, 255, .1); } .hover-inherit:hover, .hover-inherit:focus { color: inherit; } .hover-bg-black:hover, .hover-bg-black:focus { background-color: #000; } .hover-bg-near-black:hover, .hover-bg-near-black:focus { background-color: #111; } .hover-bg-dark-gray:hover, .hover-bg-dark-gray:focus { background-color: #333; } .hover-bg-mid-gray:hover, .hover-bg-mid-gray:focus { background-color: #555; } .hover-bg-gray:hover, .hover-bg-gray:focus { background-color: #777; } .hover-bg-silver:hover, .hover-bg-silver:focus { background-color: #999; } .hover-bg-light-silver:hover, .hover-bg-light-silver:focus { background-color: #aaa; } .hover-bg-moon-gray:hover, .hover-bg-moon-gray:focus { background-color: #ccc; } .hover-bg-light-gray:hover, .hover-bg-light-gray:focus { background-color: #eee; } .hover-bg-near-white:hover, .hover-bg-near-white:focus { background-color: #f4f4f4; } .hover-bg-white:hover, .hover-bg-white:focus { background-color: #fff; } .hover-bg-transparent:hover, .hover-bg-transparent:focus { background-color: transparent; } .hover-bg-black-90:hover, .hover-bg-black-90:focus { background-color: rgba(0, 0, 0, .9); } .hover-bg-black-80:hover, .hover-bg-black-80:focus { background-color: rgba(0, 0, 0, .8); } .hover-bg-black-70:hover, .hover-bg-black-70:focus { background-color: rgba(0, 0, 0, .7); } .hover-bg-black-60:hover, .hover-bg-black-60:focus { background-color: rgba(0, 0, 0, .6); } .hover-bg-black-50:hover, .hover-bg-black-50:focus { background-color: rgba(0, 0, 0, .5); } .hover-bg-black-40:hover, .hover-bg-black-40:focus { background-color: rgba(0, 0, 0, .4); } .hover-bg-black-30:hover, .hover-bg-black-30:focus { background-color: rgba(0, 0, 0, .3); } .hover-bg-black-20:hover, .hover-bg-black-20:focus { background-color: rgba(0, 0, 0, .2); } .hover-bg-black-10:hover, .hover-bg-black-10:focus { background-color: rgba(0, 0, 0, .1); } .hover-bg-white-90:hover, .hover-bg-white-90:focus { background-color: rgba(255, 255, 255, .9); } .hover-bg-white-80:hover, .hover-bg-white-80:focus { background-color: rgba(255, 255, 255, .8); } .hover-bg-white-70:hover, .hover-bg-white-70:focus { background-color: rgba(255, 255, 255, .7); } .hover-bg-white-60:hover, .hover-bg-white-60:focus { background-color: rgba(255, 255, 255, .6); } .hover-bg-white-50:hover, .hover-bg-white-50:focus { background-color: rgba(255, 255, 255, .5); } .hover-bg-white-40:hover, .hover-bg-white-40:focus { background-color: rgba(255, 255, 255, .4); } .hover-bg-white-30:hover, .hover-bg-white-30:focus { background-color: rgba(255, 255, 255, .3); } .hover-bg-white-20:hover, .hover-bg-white-20:focus { background-color: rgba(255, 255, 255, .2); } .hover-bg-white-10:hover, .hover-bg-white-10:focus { background-color: rgba(255, 255, 255, .1); } .hover-dark-red:hover, .hover-dark-red:focus { color: #e7040f; } .hover-red:hover, .hover-red:focus { color: #ff4136; } .hover-light-red:hover, .hover-light-red:focus { color: #ff725c; } .hover-orange:hover, .hover-orange:focus { color: #ff6300; } .hover-gold:hover, .hover-gold:focus { color: #ffb700; } .hover-yellow:hover, .hover-yellow:focus { color: #ffd700; } .hover-light-yellow:hover, .hover-light-yellow:focus { color: #fbf1a9; } .hover-purple:hover, .hover-purple:focus { color: #5e2ca5; } .hover-light-purple:hover, .hover-light-purple:focus { color: #a463f2; } .hover-dark-pink:hover, .hover-dark-pink:focus { color: #d5008f; } .hover-hot-pink:hover, .hover-hot-pink:focus { color: #ff41b4; } .hover-pink:hover, .hover-pink:focus { color: #ff80cc; } .hover-light-pink:hover, .hover-light-pink:focus { color: #ffa3d7; } .hover-dark-green:hover, .hover-dark-green:focus { color: #137752; } .hover-green:hover, .hover-green:focus { color: #19a974; } .hover-light-green:hover, .hover-light-green:focus { color: #9eebcf; } .hover-navy:hover, .hover-navy:focus { color: #001b44; } .hover-dark-blue:hover, .hover-dark-blue:focus { color: #00449e; } .hover-blue:hover, .hover-blue:focus { color: #0594CB; } .hover-light-blue:hover, .hover-light-blue:focus { color: #96ccff; } .hover-lightest-blue:hover, .hover-lightest-blue:focus { color: #cdecff; } .hover-washed-blue:hover, .hover-washed-blue:focus { color: #f6fffe; } .hover-washed-green:hover, .hover-washed-green:focus { color: #e8fdf5; } .hover-washed-yellow:hover, .hover-washed-yellow:focus { color: #fffceb; } .hover-washed-red:hover, .hover-washed-red:focus { color: #ffdfdf; } .hover-bg-dark-red:hover, .hover-bg-dark-red:focus { background-color: #e7040f; } .hover-bg-red:hover, .hover-bg-red:focus { background-color: #ff4136; } .hover-bg-light-red:hover, .hover-bg-light-red:focus { background-color: #ff725c; } .hover-bg-orange:hover, .hover-bg-orange:focus { background-color: #ff6300; } .hover-bg-gold:hover, .hover-bg-gold:focus { background-color: #ffb700; } .hover-bg-yellow:hover, .hover-bg-yellow:focus { background-color: #ffd700; } .hover-bg-light-yellow:hover, .hover-bg-light-yellow:focus { background-color: #fbf1a9; } .hover-bg-purple:hover, .hover-bg-purple:focus { background-color: #5e2ca5; } .hover-bg-light-purple:hover, .hover-bg-light-purple:focus { background-color: #a463f2; } .hover-bg-dark-pink:hover, .hover-bg-dark-pink:focus { background-color: #d5008f; } .hover-bg-hot-pink:hover, .hover-bg-hot-pink:focus { background-color: #ff41b4; } .hover-bg-pink:hover, .hover-bg-pink:focus { background-color: #ff80cc; } .hover-bg-light-pink:hover, .hover-bg-light-pink:focus { background-color: #ffa3d7; } .hover-bg-dark-green:hover, .hover-bg-dark-green:focus { background-color: #137752; } .hover-bg-green:hover, .hover-bg-green:focus { background-color: #19a974; } .hover-bg-light-green:hover, .hover-bg-light-green:focus { background-color: #9eebcf; } .hover-bg-navy:hover, .hover-bg-navy:focus { background-color: #001b44; } .hover-bg-dark-blue:hover, .hover-bg-dark-blue:focus { background-color: #00449e; } .hover-bg-blue:hover, .hover-bg-blue:focus { background-color: #0594CB; } .hover-bg-light-blue:hover, .hover-bg-light-blue:focus { background-color: #96ccff; } .hover-bg-lightest-blue:hover, .hover-bg-lightest-blue:focus { background-color: #cdecff; } .hover-bg-washed-blue:hover, .hover-bg-washed-blue:focus { background-color: #f6fffe; } .hover-bg-washed-green:hover, .hover-bg-washed-green:focus { background-color: #e8fdf5; } .hover-bg-washed-yellow:hover, .hover-bg-washed-yellow:focus { background-color: #fffceb; } .hover-bg-washed-red:hover, .hover-bg-washed-red:focus { background-color: #ffdfdf; } .hover-bg-inherit:hover, .hover-bg-inherit:focus { background-color: inherit; } /* Variables */ /* SPACING Docs: http://tachyons.io/docs/layout/spacing/ An eight step powers of two scale ranging from 0 to 16rem. Base: p = padding m = margin Modifiers: a = all h = horizontal v = vertical t = top r = right b = bottom l = left 0 = none 1 = 1st step in spacing scale 2 = 2nd step in spacing scale 3 = 3rd step in spacing scale 4 = 4th step in spacing scale 5 = 5th step in spacing scale 6 = 6th step in spacing scale 7 = 7th step in spacing scale Media Query Extensions: -ns = not-small -m = medium -l = large */ .pa0 { padding: 0; } .pa1 { padding: .25rem; } .pa2 { padding: .5rem; } .pa3 { padding: 1rem; } .pa4 { padding: 2rem; } .pa5 { padding: 4rem; } .pa6 { padding: 8rem; } .pa7 { padding: 16rem; } .pl0 { padding-left: 0; } .pl1 { padding-left: .25rem; } .pl2 { padding-left: .5rem; } .pl3 { padding-left: 1rem; } .pl4 { padding-left: 2rem; } .pl5 { padding-left: 4rem; } .pl6 { padding-left: 8rem; } .pl7 { padding-left: 16rem; } .pr0 { padding-right: 0; } .pr1 { padding-right: .25rem; } .pr2 { padding-right: .5rem; } .pr3 { padding-right: 1rem; } .pr4 { padding-right: 2rem; } .pr5 { padding-right: 4rem; } .pr6 { padding-right: 8rem; } .pr7 { padding-right: 16rem; } .pb0 { padding-bottom: 0; } .pb1 { padding-bottom: .25rem; } .pb2 { padding-bottom: .5rem; } .pb3 { padding-bottom: 1rem; } .pb4 { padding-bottom: 2rem; } .pb5 { padding-bottom: 4rem; } .pb6 { padding-bottom: 8rem; } .pb7 { padding-bottom: 16rem; } .pt0 { padding-top: 0; } .pt1 { padding-top: .25rem; } .pt2 { padding-top: .5rem; } .pt3 { padding-top: 1rem; } .pt4 { padding-top: 2rem; } .pt5 { padding-top: 4rem; } .pt6 { padding-top: 8rem; } .pt7 { padding-top: 16rem; } .pv0 { padding-top: 0; padding-bottom: 0; } .pv1 { padding-top: .25rem; padding-bottom: .25rem; } .pv2 { padding-top: .5rem; padding-bottom: .5rem; } .pv3 { padding-top: 1rem; padding-bottom: 1rem; } .pv4 { padding-top: 2rem; padding-bottom: 2rem; } .pv5 { padding-top: 4rem; padding-bottom: 4rem; } .pv6 { padding-top: 8rem; padding-bottom: 8rem; } .pv7 { padding-top: 16rem; padding-bottom: 16rem; } .ph0 { padding-left: 0; padding-right: 0; } .ph1 { padding-left: .25rem; padding-right: .25rem; } .ph2 { padding-left: .5rem; padding-right: .5rem; } .ph3 { padding-left: 1rem; padding-right: 1rem; } .ph4 { padding-left: 2rem; padding-right: 2rem; } .ph5 { padding-left: 4rem; padding-right: 4rem; } .ph6 { padding-left: 8rem; padding-right: 8rem; } .ph7 { padding-left: 16rem; padding-right: 16rem; } .ma0 { margin: 0; } .ma1 { margin: .25rem; } .ma2 { margin: .5rem; } .ma3 { margin: 1rem; } .ma4 { margin: 2rem; } .ma5 { margin: 4rem; } .ma6 { margin: 8rem; } .ma7 { margin: 16rem; } .ml0 { margin-left: 0; } .ml1 { margin-left: .25rem; } .ml2 { margin-left: .5rem; } .ml3 { margin-left: 1rem; } .ml4 { margin-left: 2rem; } .ml5 { margin-left: 4rem; } .ml6 { margin-left: 8rem; } .ml7 { margin-left: 16rem; } .mr0 { margin-right: 0; } .mr1 { margin-right: .25rem; } .mr2 { margin-right: .5rem; } .mr3 { margin-right: 1rem; } .mr4 { margin-right: 2rem; } .mr5 { margin-right: 4rem; } .mr6 { margin-right: 8rem; } .mr7 { margin-right: 16rem; } .mb0 { margin-bottom: 0; } .mb1 { margin-bottom: .25rem; } .mb2 { margin-bottom: .5rem; } .mb3 { margin-bottom: 1rem; } .mb4 { margin-bottom: 2rem; } .mb5 { margin-bottom: 4rem; } .mb6 { margin-bottom: 8rem; } .mb7 { margin-bottom: 16rem; } .mt0 { margin-top: 0; } .mt1 { margin-top: .25rem; } .mt2 { margin-top: .5rem; } .mt3 { margin-top: 1rem; } .mt4 { margin-top: 2rem; } .mt5 { margin-top: 4rem; } .mt6 { margin-top: 8rem; } .mt7 { margin-top: 16rem; } .mv0 { margin-top: 0; margin-bottom: 0; } .mv1 { margin-top: .25rem; margin-bottom: .25rem; } .mv2 { margin-top: .5rem; margin-bottom: .5rem; } .mv3 { margin-top: 1rem; margin-bottom: 1rem; } .mv4 { margin-top: 2rem; margin-bottom: 2rem; } .mv5 { margin-top: 4rem; margin-bottom: 4rem; } .mv6 { margin-top: 8rem; margin-bottom: 8rem; } .mv7 { margin-top: 16rem; margin-bottom: 16rem; } .mh0 { margin-left: 0; margin-right: 0; } .mh1 { margin-left: .25rem; margin-right: .25rem; } .mh2 { margin-left: .5rem; margin-right: .5rem; } .mh3 { margin-left: 1rem; margin-right: 1rem; } .mh4 { margin-left: 2rem; margin-right: 2rem; } .mh5 { margin-left: 4rem; margin-right: 4rem; } .mh6 { margin-left: 8rem; margin-right: 8rem; } .mh7 { margin-left: 16rem; margin-right: 16rem; } @media screen and (min-width: 30em) { .pa0-ns { padding: 0; } .pa1-ns { padding: .25rem; } .pa2-ns { padding: .5rem; } .pa3-ns { padding: 1rem; } .pa4-ns { padding: 2rem; } .pa5-ns { padding: 4rem; } .pa6-ns { padding: 8rem; } .pa7-ns { padding: 16rem; } .pl0-ns { padding-left: 0; } .pl1-ns { padding-left: .25rem; } .pl2-ns { padding-left: .5rem; } .pl3-ns { padding-left: 1rem; } .pl4-ns { padding-left: 2rem; } .pl5-ns { padding-left: 4rem; } .pl6-ns { padding-left: 8rem; } .pl7-ns { padding-left: 16rem; } .pr0-ns { padding-right: 0; } .pr1-ns { padding-right: .25rem; } .pr2-ns { padding-right: .5rem; } .pr3-ns { padding-right: 1rem; } .pr4-ns { padding-right: 2rem; } .pr5-ns { padding-right: 4rem; } .pr6-ns { padding-right: 8rem; } .pr7-ns { padding-right: 16rem; } .pb0-ns { padding-bottom: 0; } .pb1-ns { padding-bottom: .25rem; } .pb2-ns { padding-bottom: .5rem; } .pb3-ns { padding-bottom: 1rem; } .pb4-ns { padding-bottom: 2rem; } .pb5-ns { padding-bottom: 4rem; } .pb6-ns { padding-bottom: 8rem; } .pb7-ns { padding-bottom: 16rem; } .pt0-ns { padding-top: 0; } .pt1-ns { padding-top: .25rem; } .pt2-ns { padding-top: .5rem; } .pt3-ns { padding-top: 1rem; } .pt4-ns { padding-top: 2rem; } .pt5-ns { padding-top: 4rem; } .pt6-ns { padding-top: 8rem; } .pt7-ns { padding-top: 16rem; } .pv0-ns { padding-top: 0; padding-bottom: 0; } .pv1-ns { padding-top: .25rem; padding-bottom: .25rem; } .pv2-ns { padding-top: .5rem; padding-bottom: .5rem; } .pv3-ns { padding-top: 1rem; padding-bottom: 1rem; } .pv4-ns { padding-top: 2rem; padding-bottom: 2rem; } .pv5-ns { padding-top: 4rem; padding-bottom: 4rem; } .pv6-ns { padding-top: 8rem; padding-bottom: 8rem; } .pv7-ns { padding-top: 16rem; padding-bottom: 16rem; } .ph0-ns { padding-left: 0; padding-right: 0; } .ph1-ns { padding-left: .25rem; padding-right: .25rem; } .ph2-ns { padding-left: .5rem; padding-right: .5rem; } .ph3-ns { padding-left: 1rem; padding-right: 1rem; } .ph4-ns { padding-left: 2rem; padding-right: 2rem; } .ph5-ns { padding-left: 4rem; padding-right: 4rem; } .ph6-ns { padding-left: 8rem; padding-right: 8rem; } .ph7-ns { padding-left: 16rem; padding-right: 16rem; } .ma0-ns { margin: 0; } .ma1-ns { margin: .25rem; } .ma2-ns { margin: .5rem; } .ma3-ns { margin: 1rem; } .ma4-ns { margin: 2rem; } .ma5-ns { margin: 4rem; } .ma6-ns { margin: 8rem; } .ma7-ns { margin: 16rem; } .ml0-ns { margin-left: 0; } .ml1-ns { margin-left: .25rem; } .ml2-ns { margin-left: .5rem; } .ml3-ns { margin-left: 1rem; } .ml4-ns { margin-left: 2rem; } .ml5-ns { margin-left: 4rem; } .ml6-ns { margin-left: 8rem; } .ml7-ns { margin-left: 16rem; } .mr0-ns { margin-right: 0; } .mr1-ns { margin-right: .25rem; } .mr2-ns { margin-right: .5rem; } .mr3-ns { margin-right: 1rem; } .mr4-ns { margin-right: 2rem; } .mr5-ns { margin-right: 4rem; } .mr6-ns { margin-right: 8rem; } .mr7-ns { margin-right: 16rem; } .mb0-ns { margin-bottom: 0; } .mb1-ns { margin-bottom: .25rem; } .mb2-ns { margin-bottom: .5rem; } .mb3-ns { margin-bottom: 1rem; } .mb4-ns { margin-bottom: 2rem; } .mb5-ns { margin-bottom: 4rem; } .mb6-ns { margin-bottom: 8rem; } .mb7-ns { margin-bottom: 16rem; } .mt0-ns { margin-top: 0; } .mt1-ns { margin-top: .25rem; } .mt2-ns { margin-top: .5rem; } .mt3-ns { margin-top: 1rem; } .mt4-ns { margin-top: 2rem; } .mt5-ns { margin-top: 4rem; } .mt6-ns { margin-top: 8rem; } .mt7-ns { margin-top: 16rem; } .mv0-ns { margin-top: 0; margin-bottom: 0; } .mv1-ns { margin-top: .25rem; margin-bottom: .25rem; } .mv2-ns { margin-top: .5rem; margin-bottom: .5rem; } .mv3-ns { margin-top: 1rem; margin-bottom: 1rem; } .mv4-ns { margin-top: 2rem; margin-bottom: 2rem; } .mv5-ns { margin-top: 4rem; margin-bottom: 4rem; } .mv6-ns { margin-top: 8rem; margin-bottom: 8rem; } .mv7-ns { margin-top: 16rem; margin-bottom: 16rem; } .mh0-ns { margin-left: 0; margin-right: 0; } .mh1-ns { margin-left: .25rem; margin-right: .25rem; } .mh2-ns { margin-left: .5rem; margin-right: .5rem; } .mh3-ns { margin-left: 1rem; margin-right: 1rem; } .mh4-ns { margin-left: 2rem; margin-right: 2rem; } .mh5-ns { margin-left: 4rem; margin-right: 4rem; } .mh6-ns { margin-left: 8rem; margin-right: 8rem; } .mh7-ns { margin-left: 16rem; margin-right: 16rem; } } @media screen and (min-width: 30em) and (max-width: 60em) { .pa0-m { padding: 0; } .pa1-m { padding: .25rem; } .pa2-m { padding: .5rem; } .pa3-m { padding: 1rem; } .pa4-m { padding: 2rem; } .pa5-m { padding: 4rem; } .pa6-m { padding: 8rem; } .pa7-m { padding: 16rem; } .pl0-m { padding-left: 0; } .pl1-m { padding-left: .25rem; } .pl2-m { padding-left: .5rem; } .pl3-m { padding-left: 1rem; } .pl4-m { padding-left: 2rem; } .pl5-m { padding-left: 4rem; } .pl6-m { padding-left: 8rem; } .pl7-m { padding-left: 16rem; } .pr0-m { padding-right: 0; } .pr1-m { padding-right: .25rem; } .pr2-m { padding-right: .5rem; } .pr3-m { padding-right: 1rem; } .pr4-m { padding-right: 2rem; } .pr5-m { padding-right: 4rem; } .pr6-m { padding-right: 8rem; } .pr7-m { padding-right: 16rem; } .pb0-m { padding-bottom: 0; } .pb1-m { padding-bottom: .25rem; } .pb2-m { padding-bottom: .5rem; } .pb3-m { padding-bottom: 1rem; } .pb4-m { padding-bottom: 2rem; } .pb5-m { padding-bottom: 4rem; } .pb6-m { padding-bottom: 8rem; } .pb7-m { padding-bottom: 16rem; } .pt0-m { padding-top: 0; } .pt1-m { padding-top: .25rem; } .pt2-m { padding-top: .5rem; } .pt3-m { padding-top: 1rem; } .pt4-m { padding-top: 2rem; } .pt5-m { padding-top: 4rem; } .pt6-m { padding-top: 8rem; } .pt7-m { padding-top: 16rem; } .pv0-m { padding-top: 0; padding-bottom: 0; } .pv1-m { padding-top: .25rem; padding-bottom: .25rem; } .pv2-m { padding-top: .5rem; padding-bottom: .5rem; } .pv3-m { padding-top: 1rem; padding-bottom: 1rem; } .pv4-m { padding-top: 2rem; padding-bottom: 2rem; } .pv5-m { padding-top: 4rem; padding-bottom: 4rem; } .pv6-m { padding-top: 8rem; padding-bottom: 8rem; } .pv7-m { padding-top: 16rem; padding-bottom: 16rem; } .ph0-m { padding-left: 0; padding-right: 0; } .ph1-m { padding-left: .25rem; padding-right: .25rem; } .ph2-m { padding-left: .5rem; padding-right: .5rem; } .ph3-m { padding-left: 1rem; padding-right: 1rem; } .ph4-m { padding-left: 2rem; padding-right: 2rem; } .ph5-m { padding-left: 4rem; padding-right: 4rem; } .ph6-m { padding-left: 8rem; padding-right: 8rem; } .ph7-m { padding-left: 16rem; padding-right: 16rem; } .ma0-m { margin: 0; } .ma1-m { margin: .25rem; } .ma2-m { margin: .5rem; } .ma3-m { margin: 1rem; } .ma4-m { margin: 2rem; } .ma5-m { margin: 4rem; } .ma6-m { margin: 8rem; } .ma7-m { margin: 16rem; } .ml0-m { margin-left: 0; } .ml1-m { margin-left: .25rem; } .ml2-m { margin-left: .5rem; } .ml3-m { margin-left: 1rem; } .ml4-m { margin-left: 2rem; } .ml5-m { margin-left: 4rem; } .ml6-m { margin-left: 8rem; } .ml7-m { margin-left: 16rem; } .mr0-m { margin-right: 0; } .mr1-m { margin-right: .25rem; } .mr2-m { margin-right: .5rem; } .mr3-m { margin-right: 1rem; } .mr4-m { margin-right: 2rem; } .mr5-m { margin-right: 4rem; } .mr6-m { margin-right: 8rem; } .mr7-m { margin-right: 16rem; } .mb0-m { margin-bottom: 0; } .mb1-m { margin-bottom: .25rem; } .mb2-m { margin-bottom: .5rem; } .mb3-m { margin-bottom: 1rem; } .mb4-m { margin-bottom: 2rem; } .mb5-m { margin-bottom: 4rem; } .mb6-m { margin-bottom: 8rem; } .mb7-m { margin-bottom: 16rem; } .mt0-m { margin-top: 0; } .mt1-m { margin-top: .25rem; } .mt2-m { margin-top: .5rem; } .mt3-m { margin-top: 1rem; } .mt4-m { margin-top: 2rem; } .mt5-m { margin-top: 4rem; } .mt6-m { margin-top: 8rem; } .mt7-m { margin-top: 16rem; } .mv0-m { margin-top: 0; margin-bottom: 0; } .mv1-m { margin-top: .25rem; margin-bottom: .25rem; } .mv2-m { margin-top: .5rem; margin-bottom: .5rem; } .mv3-m { margin-top: 1rem; margin-bottom: 1rem; } .mv4-m { margin-top: 2rem; margin-bottom: 2rem; } .mv5-m { margin-top: 4rem; margin-bottom: 4rem; } .mv6-m { margin-top: 8rem; margin-bottom: 8rem; } .mv7-m { margin-top: 16rem; margin-bottom: 16rem; } .mh0-m { margin-left: 0; margin-right: 0; } .mh1-m { margin-left: .25rem; margin-right: .25rem; } .mh2-m { margin-left: .5rem; margin-right: .5rem; } .mh3-m { margin-left: 1rem; margin-right: 1rem; } .mh4-m { margin-left: 2rem; margin-right: 2rem; } .mh5-m { margin-left: 4rem; margin-right: 4rem; } .mh6-m { margin-left: 8rem; margin-right: 8rem; } .mh7-m { margin-left: 16rem; margin-right: 16rem; } } @media screen and (min-width: 60em) { .pa0-l { padding: 0; } .pa1-l { padding: .25rem; } .pa2-l { padding: .5rem; } .pa3-l { padding: 1rem; } .pa4-l { padding: 2rem; } .pa5-l { padding: 4rem; } .pa6-l { padding: 8rem; } .pa7-l { padding: 16rem; } .pl0-l { padding-left: 0; } .pl1-l { padding-left: .25rem; } .pl2-l { padding-left: .5rem; } .pl3-l { padding-left: 1rem; } .pl4-l { padding-left: 2rem; } .pl5-l { padding-left: 4rem; } .pl6-l { padding-left: 8rem; } .pl7-l { padding-left: 16rem; } .pr0-l { padding-right: 0; } .pr1-l { padding-right: .25rem; } .pr2-l { padding-right: .5rem; } .pr3-l { padding-right: 1rem; } .pr4-l { padding-right: 2rem; } .pr5-l { padding-right: 4rem; } .pr6-l { padding-right: 8rem; } .pr7-l { padding-right: 16rem; } .pb0-l { padding-bottom: 0; } .pb1-l { padding-bottom: .25rem; } .pb2-l { padding-bottom: .5rem; } .pb3-l { padding-bottom: 1rem; } .pb4-l { padding-bottom: 2rem; } .pb5-l { padding-bottom: 4rem; } .pb6-l { padding-bottom: 8rem; } .pb7-l { padding-bottom: 16rem; } .pt0-l { padding-top: 0; } .pt1-l { padding-top: .25rem; } .pt2-l { padding-top: .5rem; } .pt3-l { padding-top: 1rem; } .pt4-l { padding-top: 2rem; } .pt5-l { padding-top: 4rem; } .pt6-l { padding-top: 8rem; } .pt7-l { padding-top: 16rem; } .pv0-l { padding-top: 0; padding-bottom: 0; } .pv1-l { padding-top: .25rem; padding-bottom: .25rem; } .pv2-l { padding-top: .5rem; padding-bottom: .5rem; } .pv3-l { padding-top: 1rem; padding-bottom: 1rem; } .pv4-l { padding-top: 2rem; padding-bottom: 2rem; } .pv5-l { padding-top: 4rem; padding-bottom: 4rem; } .pv6-l { padding-top: 8rem; padding-bottom: 8rem; } .pv7-l { padding-top: 16rem; padding-bottom: 16rem; } .ph0-l { padding-left: 0; padding-right: 0; } .ph1-l { padding-left: .25rem; padding-right: .25rem; } .ph2-l { padding-left: .5rem; padding-right: .5rem; } .ph3-l { padding-left: 1rem; padding-right: 1rem; } .ph4-l { padding-left: 2rem; padding-right: 2rem; } .ph5-l { padding-left: 4rem; padding-right: 4rem; } .ph6-l { padding-left: 8rem; padding-right: 8rem; } .ph7-l { padding-left: 16rem; padding-right: 16rem; } .ma0-l { margin: 0; } .ma1-l { margin: .25rem; } .ma2-l { margin: .5rem; } .ma3-l { margin: 1rem; } .ma4-l { margin: 2rem; } .ma5-l { margin: 4rem; } .ma6-l { margin: 8rem; } .ma7-l { margin: 16rem; } .ml0-l { margin-left: 0; } .ml1-l { margin-left: .25rem; } .ml2-l { margin-left: .5rem; } .ml3-l { margin-left: 1rem; } .ml4-l { margin-left: 2rem; } .ml5-l { margin-left: 4rem; } .ml6-l { margin-left: 8rem; } .ml7-l { margin-left: 16rem; } .mr0-l { margin-right: 0; } .mr1-l { margin-right: .25rem; } .mr2-l { margin-right: .5rem; } .mr3-l { margin-right: 1rem; } .mr4-l { margin-right: 2rem; } .mr5-l { margin-right: 4rem; } .mr6-l { margin-right: 8rem; } .mr7-l { margin-right: 16rem; } .mb0-l { margin-bottom: 0; } .mb1-l { margin-bottom: .25rem; } .mb2-l { margin-bottom: .5rem; } .mb3-l { margin-bottom: 1rem; } .mb4-l { margin-bottom: 2rem; } .mb5-l { margin-bottom: 4rem; } .mb6-l { margin-bottom: 8rem; } .mb7-l { margin-bottom: 16rem; } .mt0-l { margin-top: 0; } .mt1-l { margin-top: .25rem; } .mt2-l { margin-top: .5rem; } .mt3-l { margin-top: 1rem; } .mt4-l { margin-top: 2rem; } .mt5-l { margin-top: 4rem; } .mt6-l { margin-top: 8rem; } .mt7-l { margin-top: 16rem; } .mv0-l { margin-top: 0; margin-bottom: 0; } .mv1-l { margin-top: .25rem; margin-bottom: .25rem; } .mv2-l { margin-top: .5rem; margin-bottom: .5rem; } .mv3-l { margin-top: 1rem; margin-bottom: 1rem; } .mv4-l { margin-top: 2rem; margin-bottom: 2rem; } .mv5-l { margin-top: 4rem; margin-bottom: 4rem; } .mv6-l { margin-top: 8rem; margin-bottom: 8rem; } .mv7-l { margin-top: 16rem; margin-bottom: 16rem; } .mh0-l { margin-left: 0; margin-right: 0; } .mh1-l { margin-left: .25rem; margin-right: .25rem; } .mh2-l { margin-left: .5rem; margin-right: .5rem; } .mh3-l { margin-left: 1rem; margin-right: 1rem; } .mh4-l { margin-left: 2rem; margin-right: 2rem; } .mh5-l { margin-left: 4rem; margin-right: 4rem; } .mh6-l { margin-left: 8rem; margin-right: 8rem; } .mh7-l { margin-left: 16rem; margin-right: 16rem; } } /* NEGATIVE MARGINS Base: n = negative Modifiers: a = all t = top r = right b = bottom l = left 1 = 1st step in spacing scale 2 = 2nd step in spacing scale 3 = 3rd step in spacing scale 4 = 4th step in spacing scale 5 = 5th step in spacing scale 6 = 6th step in spacing scale 7 = 7th step in spacing scale Media Query Extensions: -ns = not-small -m = medium -l = large */ .na1 { margin: -0.25rem; } .na2 { margin: -0.5rem; } .na3 { margin: -1rem; } .na4 { margin: -2rem; } .na5 { margin: -4rem; } .na6 { margin: -8rem; } .na7 { margin: -16rem; } .nl1 { margin-left: -0.25rem; } .nl2 { margin-left: -0.5rem; } .nl3 { margin-left: -1rem; } .nl4 { margin-left: -2rem; } .nl5 { margin-left: -4rem; } .nl6 { margin-left: -8rem; } .nl7 { margin-left: -16rem; } .nr1 { margin-right: -0.25rem; } .nr2 { margin-right: -0.5rem; } .nr3 { margin-right: -1rem; } .nr4 { margin-right: -2rem; } .nr5 { margin-right: -4rem; } .nr6 { margin-right: -8rem; } .nr7 { margin-right: -16rem; } .nb1 { margin-bottom: -0.25rem; } .nb2 { margin-bottom: -0.5rem; } .nb3 { margin-bottom: -1rem; } .nb4 { margin-bottom: -2rem; } .nb5 { margin-bottom: -4rem; } .nb6 { margin-bottom: -8rem; } .nb7 { margin-bottom: -16rem; } .nt1 { margin-top: -0.25rem; } .nt2 { margin-top: -0.5rem; } .nt3 { margin-top: -1rem; } .nt4 { margin-top: -2rem; } .nt5 { margin-top: -4rem; } .nt6 { margin-top: -8rem; } .nt7 { margin-top: -16rem; } @media screen and (min-width: 30em) { .na1-ns { margin: -0.25rem; } .na2-ns { margin: -0.5rem; } .na3-ns { margin: -1rem; } .na4-ns { margin: -2rem; } .na5-ns { margin: -4rem; } .na6-ns { margin: -8rem; } .na7-ns { margin: -16rem; } .nl1-ns { margin-left: -0.25rem; } .nl2-ns { margin-left: -0.5rem; } .nl3-ns { margin-left: -1rem; } .nl4-ns { margin-left: -2rem; } .nl5-ns { margin-left: -4rem; } .nl6-ns { margin-left: -8rem; } .nl7-ns { margin-left: -16rem; } .nr1-ns { margin-right: -0.25rem; } .nr2-ns { margin-right: -0.5rem; } .nr3-ns { margin-right: -1rem; } .nr4-ns { margin-right: -2rem; } .nr5-ns { margin-right: -4rem; } .nr6-ns { margin-right: -8rem; } .nr7-ns { margin-right: -16rem; } .nb1-ns { margin-bottom: -0.25rem; } .nb2-ns { margin-bottom: -0.5rem; } .nb3-ns { margin-bottom: -1rem; } .nb4-ns { margin-bottom: -2rem; } .nb5-ns { margin-bottom: -4rem; } .nb6-ns { margin-bottom: -8rem; } .nb7-ns { margin-bottom: -16rem; } .nt1-ns { margin-top: -0.25rem; } .nt2-ns { margin-top: -0.5rem; } .nt3-ns { margin-top: -1rem; } .nt4-ns { margin-top: -2rem; } .nt5-ns { margin-top: -4rem; } .nt6-ns { margin-top: -8rem; } .nt7-ns { margin-top: -16rem; } } @media screen and (min-width: 30em) and (max-width: 60em) { .na1-m { margin: -0.25rem; } .na2-m { margin: -0.5rem; } .na3-m { margin: -1rem; } .na4-m { margin: -2rem; } .na5-m { margin: -4rem; } .na6-m { margin: -8rem; } .na7-m { margin: -16rem; } .nl1-m { margin-left: -0.25rem; } .nl2-m { margin-left: -0.5rem; } .nl3-m { margin-left: -1rem; } .nl4-m { margin-left: -2rem; } .nl5-m { margin-left: -4rem; } .nl6-m { margin-left: -8rem; } .nl7-m { margin-left: -16rem; } .nr1-m { margin-right: -0.25rem; } .nr2-m { margin-right: -0.5rem; } .nr3-m { margin-right: -1rem; } .nr4-m { margin-right: -2rem; } .nr5-m { margin-right: -4rem; } .nr6-m { margin-right: -8rem; } .nr7-m { margin-right: -16rem; } .nb1-m { margin-bottom: -0.25rem; } .nb2-m { margin-bottom: -0.5rem; } .nb3-m { margin-bottom: -1rem; } .nb4-m { margin-bottom: -2rem; } .nb5-m { margin-bottom: -4rem; } .nb6-m { margin-bottom: -8rem; } .nb7-m { margin-bottom: -16rem; } .nt1-m { margin-top: -0.25rem; } .nt2-m { margin-top: -0.5rem; } .nt3-m { margin-top: -1rem; } .nt4-m { margin-top: -2rem; } .nt5-m { margin-top: -4rem; } .nt6-m { margin-top: -8rem; } .nt7-m { margin-top: -16rem; } } @media screen and (min-width: 60em) { .na1-l { margin: -0.25rem; } .na2-l { margin: -0.5rem; } .na3-l { margin: -1rem; } .na4-l { margin: -2rem; } .na5-l { margin: -4rem; } .na6-l { margin: -8rem; } .na7-l { margin: -16rem; } .nl1-l { margin-left: -0.25rem; } .nl2-l { margin-left: -0.5rem; } .nl3-l { margin-left: -1rem; } .nl4-l { margin-left: -2rem; } .nl5-l { margin-left: -4rem; } .nl6-l { margin-left: -8rem; } .nl7-l { margin-left: -16rem; } .nr1-l { margin-right: -0.25rem; } .nr2-l { margin-right: -0.5rem; } .nr3-l { margin-right: -1rem; } .nr4-l { margin-right: -2rem; } .nr5-l { margin-right: -4rem; } .nr6-l { margin-right: -8rem; } .nr7-l { margin-right: -16rem; } .nb1-l { margin-bottom: -0.25rem; } .nb2-l { margin-bottom: -0.5rem; } .nb3-l { margin-bottom: -1rem; } .nb4-l { margin-bottom: -2rem; } .nb5-l { margin-bottom: -4rem; } .nb6-l { margin-bottom: -8rem; } .nb7-l { margin-bottom: -16rem; } .nt1-l { margin-top: -0.25rem; } .nt2-l { margin-top: -0.5rem; } .nt3-l { margin-top: -1rem; } .nt4-l { margin-top: -2rem; } .nt5-l { margin-top: -4rem; } .nt6-l { margin-top: -8rem; } .nt7-l { margin-top: -16rem; } } /* TABLES Docs: http://tachyons.io/docs/elements/tables/ */ .collapse { border-collapse: collapse; border-spacing: 0; } .striped--light-silver:nth-child(odd) { background-color: #aaa; } .striped--moon-gray:nth-child(odd) { background-color: #ccc; } .striped--light-gray:nth-child(odd) { background-color: #eee; } .striped--near-white:nth-child(odd) { background-color: #f4f4f4; } .stripe-light:nth-child(odd) { background-color: rgba(255, 255, 255, .1); } .stripe-dark:nth-child(odd) { background-color: rgba(0, 0, 0, .1); } /* TEXT DECORATION Docs: http://tachyons.io/docs/typography/text-decoration/ Media Query Extensions: -ns = not-small -m = medium -l = large */ .strike { text-decoration: line-through; } .underline { text-decoration: underline; } .no-underline { text-decoration: none; } @media screen and (min-width: 30em) { .strike-ns { text-decoration: line-through; } .underline-ns { text-decoration: underline; } .no-underline-ns { text-decoration: none; } } @media screen and (min-width: 30em) and (max-width: 60em) { .strike-m { text-decoration: line-through; } .underline-m { text-decoration: underline; } .no-underline-m { text-decoration: none; } } @media screen and (min-width: 60em) { .strike-l { text-decoration: line-through; } .underline-l { text-decoration: underline; } .no-underline-l { text-decoration: none; } } /* TEXT ALIGN Docs: http://tachyons.io/docs/typography/text-align/ Base t = text-align Modifiers l = left r = right c = center j = justify Media Query Extensions: -ns = not-small -m = medium -l = large */ .tl { text-align: left; } .tr { text-align: right; } .tc { text-align: center; } .tj { text-align: justify; } @media screen and (min-width: 30em) { .tl-ns { text-align: left; } .tr-ns { text-align: right; } .tc-ns { text-align: center; } .tj-ns { text-align: justify; } } @media screen and (min-width: 30em) and (max-width: 60em) { .tl-m { text-align: left; } .tr-m { text-align: right; } .tc-m { text-align: center; } .tj-m { text-align: justify; } } @media screen and (min-width: 60em) { .tl-l { text-align: left; } .tr-l { text-align: right; } .tc-l { text-align: center; } .tj-l { text-align: justify; } } /* TEXT TRANSFORM Docs: http://tachyons.io/docs/typography/text-transform/ Base: tt = text-transform Modifiers c = capitalize l = lowercase u = uppercase n = none Media Query Extensions: -ns = not-small -m = medium -l = large */ .ttc { text-transform: capitalize; } .ttl { text-transform: lowercase; } .ttu { text-transform: uppercase; } .ttn { text-transform: none; } @media screen and (min-width: 30em) { .ttc-ns { text-transform: capitalize; } .ttl-ns { text-transform: lowercase; } .ttu-ns { text-transform: uppercase; } .ttn-ns { text-transform: none; } } @media screen and (min-width: 30em) and (max-width: 60em) { .ttc-m { text-transform: capitalize; } .ttl-m { text-transform: lowercase; } .ttu-m { text-transform: uppercase; } .ttn-m { text-transform: none; } } @media screen and (min-width: 60em) { .ttc-l { text-transform: capitalize; } .ttl-l { text-transform: lowercase; } .ttu-l { text-transform: uppercase; } .ttn-l { text-transform: none; } } /* TYPE SCALE Docs: http://tachyons.io/docs/typography/scale/ Base: f = font-size Modifiers 1 = 1st step in size scale 2 = 2nd step in size scale 3 = 3rd step in size scale 4 = 4th step in size scale 5 = 5th step in size scale 6 = 6th step in size scale 7 = 7th step in size scale Media Query Extensions: -ns = not-small -m = medium -l = large */ /* * For Hero/Marketing Titles * * These generally are too large for mobile * so be careful using them on smaller screens. * */ .f-6, .f-headline { font-size: 6rem; } .f-5, .f-subheadline { font-size: 5rem; } /* Type Scale */ .f1 { font-size: 3rem; } .f2 { font-size: 2.25rem; } .f3 { font-size: 1.5rem; } .f4 { font-size: 1.25rem; } .f5 { font-size: 1rem; } .f6 { font-size: .875rem; } .f7 { font-size: .75rem; } /* Small and hard to read for many people so use with extreme caution */ @media screen and (min-width: 30em){ .f-6-ns, .f-headline-ns { font-size: 6rem; } .f-5-ns, .f-subheadline-ns { font-size: 5rem; } .f1-ns { font-size: 3rem; } .f2-ns { font-size: 2.25rem; } .f3-ns { font-size: 1.5rem; } .f4-ns { font-size: 1.25rem; } .f5-ns { font-size: 1rem; } .f6-ns { font-size: .875rem; } .f7-ns { font-size: .75rem; } } @media screen and (min-width: 30em) and (max-width: 60em) { .f-6-m, .f-headline-m { font-size: 6rem; } .f-5-m, .f-subheadline-m { font-size: 5rem; } .f1-m { font-size: 3rem; } .f2-m { font-size: 2.25rem; } .f3-m { font-size: 1.5rem; } .f4-m { font-size: 1.25rem; } .f5-m { font-size: 1rem; } .f6-m { font-size: .875rem; } .f7-m { font-size: .75rem; } } @media screen and (min-width: 60em) { .f-6-l, .f-headline-l { font-size: 6rem; } .f-5-l, .f-subheadline-l { font-size: 5rem; } .f1-l { font-size: 3rem; } .f2-l { font-size: 2.25rem; } .f3-l { font-size: 1.5rem; } .f4-l { font-size: 1.25rem; } .f5-l { font-size: 1rem; } .f6-l { font-size: .875rem; } .f7-l { font-size: .75rem; } } /* TYPOGRAPHY http://tachyons.io/docs/typography/measure/ Media Query Extensions: -ns = not-small -m = medium -l = large */ /* Measure is limited to ~66 characters */ .measure { max-width: 30em; } /* Measure is limited to ~80 characters */ .measure-wide { max-width: 34em; } /* Measure is limited to ~45 characters */ .measure-narrow { max-width: 20em; } /* Book paragraph style - paragraphs are indented with no vertical spacing. */ .indent { text-indent: 1em; margin-top: 0; margin-bottom: 0; } .small-caps { -webkit-font-feature-settings: "c2sc"; font-feature-settings: "c2sc"; font-variant: small-caps; } /* Combine this class with a width to truncate text (or just leave as is to truncate at width of containing element. */ .truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } @media screen and (min-width: 30em) { .measure-ns { max-width: 30em; } .measure-wide-ns { max-width: 34em; } .measure-narrow-ns { max-width: 20em; } .indent-ns { text-indent: 1em; margin-top: 0; margin-bottom: 0; } .small-caps-ns { -webkit-font-feature-settings: "c2sc"; font-feature-settings: "c2sc"; font-variant: small-caps; } .truncate-ns { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } @media screen and (min-width: 30em) and (max-width: 60em) { .measure-m { max-width: 30em; } .measure-wide-m { max-width: 34em; } .measure-narrow-m { max-width: 20em; } .indent-m { text-indent: 1em; margin-top: 0; margin-bottom: 0; } .small-caps-m { -webkit-font-feature-settings: "c2sc"; font-feature-settings: "c2sc"; font-variant: small-caps; } .truncate-m { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } @media screen and (min-width: 60em) { .measure-l { max-width: 30em; } .measure-wide-l { max-width: 40em; } .measure-narrow-l { max-width: 20em; } .indent-l { text-indent: 1em; margin-top: 0; margin-bottom: 0; } .small-caps-l { -webkit-font-feature-settings: "c2sc"; font-feature-settings: "c2sc"; font-variant: small-caps; } .truncate-l { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } /* UTILITIES Media Query Extensions: -ns = not-small -m = medium -l = large */ /* Equivalent to .overflow-y-scroll */ .overflow-container { overflow-y: scroll; } .center { margin-right: auto; margin-left: auto; } .mr-auto { margin-right: auto; } .ml-auto { margin-left: auto; } @media screen and (min-width: 30em){ .center-ns { margin-right: auto; margin-left: auto; } .mr-auto-ns { margin-right: auto; } .ml-auto-ns { margin-left: auto; } } @media screen and (min-width: 30em) and (max-width: 60em){ .center-m { margin-right: auto; margin-left: auto; } .mr-auto-m { margin-right: auto; } .ml-auto-m { margin-left: auto; } } @media screen and (min-width: 60em){ .center-l { margin-right: auto; margin-left: auto; } .mr-auto-l { margin-right: auto; } .ml-auto-l { margin-left: auto; } } /* VISIBILITY Media Query Extensions: -ns = not-small -m = medium -l = large */ /* Text that is hidden but accessible Ref: http://snook.ca/archives/html_and_css/hiding-content-for-accessibility */ .clip { position: fixed !important; _position: absolute !important; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px, 1px, 1px, 1px); } @media screen and (min-width: 30em) { .clip-ns { position: fixed !important; _position: absolute !important; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px, 1px, 1px, 1px); } } @media screen and (min-width: 30em) and (max-width: 60em) { .clip-m { position: fixed !important; _position: absolute !important; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px, 1px, 1px, 1px); } } @media screen and (min-width: 60em) { .clip-l { position: fixed !important; _position: absolute !important; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px, 1px, 1px, 1px); } } /* WHITE SPACE Media Query Extensions: -ns = not-small -m = medium -l = large */ .ws-normal { white-space: normal; } .nowrap { white-space: nowrap; } .pre { white-space: pre; } @media screen and (min-width: 30em) { .ws-normal-ns { white-space: normal; } .nowrap-ns { white-space: nowrap; } .pre-ns { white-space: pre; } } @media screen and (min-width: 30em) and (max-width: 60em) { .ws-normal-m { white-space: normal; } .nowrap-m { white-space: nowrap; } .pre-m { white-space: pre; } } @media screen and (min-width: 60em) { .ws-normal-l { white-space: normal; } .nowrap-l { white-space: nowrap; } .pre-l { white-space: pre; } } /* VERTICAL ALIGN Media Query Extensions: -ns = not-small -m = medium -l = large */ .v-base { vertical-align: baseline; } .v-mid { vertical-align: middle; } .v-top { vertical-align: top; } .v-btm { vertical-align: bottom; } @media screen and (min-width: 30em) { .v-base-ns { vertical-align: baseline; } .v-mid-ns { vertical-align: middle; } .v-top-ns { vertical-align: top; } .v-btm-ns { vertical-align: bottom; } } @media screen and (min-width: 30em) and (max-width: 60em) { .v-base-m { vertical-align: baseline; } .v-mid-m { vertical-align: middle; } .v-top-m { vertical-align: top; } .v-btm-m { vertical-align: bottom; } } @media screen and (min-width: 60em) { .v-base-l { vertical-align: baseline; } .v-mid-l { vertical-align: middle; } .v-top-l { vertical-align: top; } .v-btm-l { vertical-align: bottom; } } /* HOVER EFFECTS Docs: http://tachyons.io/docs/themes/hovers/ - Dim - Glow - Hide Child - Underline text - Grow - Pointer - Shadow */ /* Dim element on hover by adding the dim class. */ .dim { opacity: 1; -webkit-transition: opacity .15s ease-in; transition: opacity .15s ease-in; } .dim:hover, .dim:focus { opacity: .5; -webkit-transition: opacity .15s ease-in; transition: opacity .15s ease-in; } .dim:active { opacity: .8; -webkit-transition: opacity .15s ease-out; transition: opacity .15s ease-out; } /* Animate opacity to 100% on hover by adding the glow class. */ .glow { -webkit-transition: opacity .15s ease-in; transition: opacity .15s ease-in; } .glow:hover, .glow:focus { opacity: 1; -webkit-transition: opacity .15s ease-in; transition: opacity .15s ease-in; } /* Hide child & reveal on hover: Put the hide-child class on a parent element and any nested element with the child class will be hidden and displayed on hover or focus.
    Hidden until hover or focus
    Hidden until hover or focus
    Hidden until hover or focus
    Hidden until hover or focus
    */ .hide-child .child { opacity: 0; -webkit-transition: opacity .15s ease-in; transition: opacity .15s ease-in; } .hide-child:hover .child, .hide-child:focus .child, .hide-child:active .child { opacity: 1; -webkit-transition: opacity .15s ease-in; transition: opacity .15s ease-in; } .underline-hover:hover, .underline-hover:focus { text-decoration: underline; } /* Can combine this with overflow-hidden to make background images grow on hover * even if you are using background-size: cover */ .grow { -moz-osx-font-smoothing: grayscale; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-transform: translateZ(0); transform: translateZ(0); -webkit-transition: -webkit-transform 0.25s ease-out; transition: -webkit-transform 0.25s ease-out; transition: transform 0.25s ease-out; transition: transform 0.25s ease-out, -webkit-transform 0.25s ease-out; } .grow:hover, .grow:focus { -webkit-transform: scale(1.05); transform: scale(1.05); } .grow:active { -webkit-transform: scale(.90); transform: scale(.90); } .grow-large { -moz-osx-font-smoothing: grayscale; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-transform: translateZ(0); transform: translateZ(0); -webkit-transition: -webkit-transform .25s ease-in-out; transition: -webkit-transform .25s ease-in-out; transition: transform .25s ease-in-out; transition: transform .25s ease-in-out, -webkit-transform .25s ease-in-out; } .grow-large:hover, .grow-large:focus { -webkit-transform: scale(1.2); transform: scale(1.2); } .grow-large:active { -webkit-transform: scale(.95); transform: scale(.95); } /* Add pointer on hover */ .pointer:hover { cursor: pointer; } /* Add shadow on hover. Performant box-shadow animation pattern from http://tobiasahlin.com/blog/how-to-animate-box-shadow/ */ .shadow-hover { cursor: pointer; position: relative; -webkit-transition: all 0.5s cubic-bezier(0.165, 0.84, 0.44, 1); transition: all 0.5s cubic-bezier(0.165, 0.84, 0.44, 1); } .shadow-hover::after { content: ''; -webkit-box-shadow: 0px 0px 16px 2px rgba(0, 0, 0, .2); box-shadow: 0px 0px 16px 2px rgba(0, 0, 0, .2); border-radius: inherit; opacity: 0; position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; -webkit-transition: opacity 0.5s cubic-bezier(0.165, 0.84, 0.44, 1); transition: opacity 0.5s cubic-bezier(0.165, 0.84, 0.44, 1); } .shadow-hover:hover::after, .shadow-hover:focus::after { opacity: 1; } /* Combine with classes in skins and skins-pseudo for * many different transition possibilities. */ .bg-animate, .bg-animate:hover, .bg-animate:focus { -webkit-transition: background-color .15s ease-in-out; transition: background-color .15s ease-in-out; } /* Z-INDEX Base z = z-index Modifiers -0 = literal value 0 -1 = literal value 1 -2 = literal value 2 -3 = literal value 3 -4 = literal value 4 -5 = literal value 5 -999 = literal value 999 -9999 = literal value 9999 -max = largest accepted z-index value as integer -inherit = string value inherit -initial = string value initial -unset = string value unset MDN: https://developer.mozilla.org/en/docs/Web/CSS/z-index Spec: http://www.w3.org/TR/CSS2/zindex.html Articles: https://philipwalton.com/articles/what-no-one-told-you-about-z-index/ Tips on extending: There might be a time worth using negative z-index values. Or if you are using tachyons with another project, you might need to adjust these values to suit your needs. */ .z-0 { z-index: 0; } .z-1 { z-index: 1; } .z-2 { z-index: 2; } .z-3 { z-index: 3; } .z-4 { z-index: 4; } .z-5 { z-index: 5; } .z-999 { z-index: 999; } .z-9999 { z-index: 9999; } .z-max { z-index: 2147483647; } .z-inherit { z-index: inherit; } .z-initial { z-index: auto; z-index: initial; } .z-unset { z-index: unset; } /* NESTED Tachyons module for styling nested elements that are generated by a cms. */ .nested-copy-line-height p, .nested-copy-line-height ul, .nested-copy-line-height ol { line-height: 1.5; } .nested-headline-line-height h1, .nested-headline-line-height h2, .nested-headline-line-height h3, .nested-headline-line-height h4, .nested-headline-line-height h5, .nested-headline-line-height h6 { line-height: 1.25; } .nested-list-reset ul, .nested-list-reset ol { padding-left: 0; margin-left: 0; list-style-type: none; } .nested-copy-indent p+p { text-indent: 1em; margin-top: 0; margin-bottom: 0; } .nested-copy-separator p+p { margin-top: 1.5em; } .nested-img img { width: 100%; max-width: 100%; display: block; } .nested-links a { color: #0594CB; -webkit-transition: color .15s ease-in; transition: color .15s ease-in; } .nested-links a:hover, .nested-links a:focus { color: #96ccff; -webkit-transition: color .15s ease-in; transition: color .15s ease-in; } /*@import 'tachyons/src/_styles';*/ /* Variables */ /* Importing here will allow you to override any variables in the modules */ /* Tachyons COLOR VARIABLES Grayscale - Solids - Transparencies Colors */ /* CUSTOM MEDIA QUERIES Media query values can be changed to fit your own content. There are no magic bullets when it comes to media query width values. They should be declared in em units - and they should be set to meet the needs of your content. You can also add additional media queries, or remove some of the existing ones. These media queries can be referenced like so: @media (--breakpoint-not-small) { .medium-and-larger-specific-style { background-color: red; } } @media (--breakpoint-medium) { .medium-screen-specific-style { background-color: red; } } @media (--breakpoint-large) { .large-and-larger-screen-specific-style { background-color: red; } } */ /* Media Queries */ /* Debugging */ /*@import 'tachyons/src/_debug-children'; @import 'tachyons/src/_debug-grid';*/ /* Uncomment out the line below to help debug layout issues */ /* @import 'tachyons/src/_debug'; */ /* purgecss start ignore */ .header-link:after { position: relative; left: 0.5em; opacity: 0; font-size: 0.8em; -moz-transition: opacity 0.2s ease-in-out 0.1s; -ms-transition: opacity 0.2s ease-in-out 0.1s; } h2:hover .header-link, h3:hover .header-link, h4:hover .header-link, h5:hover .header-link, h6:hover .header-link { opacity: 1; } .animated { -webkit-animation-duration: .5s; animation-duration: .5s; -webkit-animation-fill-mode: forwards; animation-fill-mode: forwards; -webkit-animation-timing-function: ease-in-out; animation-timing-function: ease-in-out; } @-webkit-keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .fadeIn { -webkit-animation-name: fadeIn; animation-name: fadeIn; } .animated-delay-1 { -webkit-animation-delay: 0.5s; animation-delay: 0.5s; } .note, .warning { border-left-width: 4px; border-left-style: solid; position: relative; border-color: #0594CB; display: block; } .note #exclamation-icon, .warning #exclamation-icon { fill: #0594CB; position: absolute; top: 35%; left: -12px; /*background-color: white;*/ } .admonition-content { display: block; margin: 0px; padding: .125em 1em; /*margin-left: 1em;*/ margin-top: 2em; margin-bottom: 2em; overflow-x: auto; /*font-size: .9375em;*/ background-color: rgba(0, 0, 0, .05); } .hide-child-menu .child-menu { display: none; } .hide-child-menu:hover .child-menu, .hide-child-menu:focus .child-menu, .hide-child-menu:active .child-menu { display: block; } /*documentation-copy headings exaggerate spacing and size to chunk content */ .documentation-copy h2 { margin-top: 3em } .documentation-copy h2.minor { font-size: inherit; margin-top: inherit; border-bottom: none; } .searchbox{display:inline-block;position:relative;width:200px;height:32px!important;white-space:nowrap;-webkit-box-sizing:border-box;box-sizing:border-box;visibility:visible!important} .searchbox .algolia-autocomplete{display:block;width:100%;height:100%} .searchbox__wrapper{width:100%;height:100%;z-index:999;position:relative} .searchbox__input{display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:background .4s ease,-webkit-box-shadow .4s ease;transition:background .4s ease,-webkit-box-shadow .4s ease;transition:box-shadow .4s ease,background .4s ease;transition:box-shadow .4s ease,background .4s ease,-webkit-box-shadow .4s ease;border:0;border-radius:16px;-webkit-box-shadow:inset 0 0 0 1px #ccc;box-shadow:inset 0 0 0 1px #ccc;background:#fff!important;padding:0 26px 0 32px;width:100%;height:100%;vertical-align:middle;white-space:normal;font-size:12px;-webkit-appearance:none;-moz-appearance:none;appearance:none} .searchbox__input::-webkit-search-cancel-button,.searchbox__input::-webkit-search-decoration,.searchbox__input::-webkit-search-results-button,.searchbox__input::-webkit-search-results-decoration{display:none} .searchbox__input:hover{-webkit-box-shadow:inset 0 0 0 1px #b3b3b3;box-shadow:inset 0 0 0 1px #b3b3b3} .searchbox__input:active,.searchbox__input:focus{outline:0;-webkit-box-shadow:inset 0 0 0 1px #aaa;box-shadow:inset 0 0 0 1px #aaa;background:#fff} .searchbox__input::-webkit-input-placeholder{color:#aaa} .searchbox__input:-ms-input-placeholder{color:#aaa} .searchbox__input::-ms-input-placeholder{color:#aaa} .searchbox__input::placeholder{color:#aaa} .searchbox__submit{position:absolute;top:0;margin:0;border:0;border-radius:16px 0 0 16px;background-color:rgba(69, 142, 225, 0);padding:0;width:32px;height:100%;vertical-align:middle;text-align:center;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;right:inherit;left:0} .searchbox__submit:before{display:inline-block;margin-right:-4px;height:100%;vertical-align:middle;content:""} .searchbox__submit:active,.searchbox__submit:hover{cursor:pointer} .searchbox__submit:focus{outline:0} .searchbox__submit svg{width:14px;height:14px;vertical-align:middle;fill:#6d7e96} .searchbox__reset{display:block;position:absolute;top:8px;right:8px;margin:0;border:0;background:none;cursor:pointer;padding:0;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;fill:rgba(0, 0, 0, .5)} .searchbox__reset.hide{display:none} .searchbox__reset:focus{outline:0} .searchbox__reset svg{display:block;margin:4px;width:8px;height:8px} .searchbox__input:valid~.searchbox__reset{display:block;-webkit-animation-name:sbx-reset-in;animation-name:sbx-reset-in;-webkit-animation-duration:.15s;animation-duration:.15s} @-webkit-keyframes sbx-reset-in{0%{-webkit-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0);opacity:0}to{-webkit-transform:none;transform:none;opacity:1}} @keyframes sbx-reset-in{0%{-webkit-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0);opacity:0}to{-webkit-transform:none;transform:none;opacity:1}} .algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu{right:0!important;left:inherit!important} .algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu:before{right:48px} .algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu{left:0!important;right:inherit!important} .algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu:before{left:48px} .algolia-autocomplete .ds-dropdown-menu{top:-6px;border-radius:4px;margin:6px 0 0;padding:0;text-align:left;height:auto;position:relative;background:transparent;border:none;z-index:999;max-width:600px;min-width:500px;-webkit-box-shadow:0 1px 0 0 rgba(0, 0, 0, .2),0 2px 3px 0 rgba(0, 0, 0, .1);box-shadow:0 1px 0 0 rgba(0, 0, 0, .2),0 2px 3px 0 rgba(0, 0, 0, .1)} .algolia-autocomplete .ds-dropdown-menu:before{display:block;position:absolute;content:"";width:14px;height:14px;background:#fff;z-index:1000;top:-7px;border-top:1px solid #d9d9d9;border-right:1px solid #d9d9d9;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);border-radius:2px} .algolia-autocomplete .ds-dropdown-menu .ds-suggestions{position:relative;z-index:1000;margin-top:8px} .algolia-autocomplete .ds-dropdown-menu .ds-suggestions a:hover{text-decoration:none} .algolia-autocomplete .ds-dropdown-menu .ds-suggestion{cursor:pointer} .algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion.suggestion-layout-simple,.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion:not(.suggestion-layout-simple) .algolia-docsearch-suggestion--content{background-color:rgba(69, 142, 225, .05)} .algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-]{position:relative;border:1px solid #d9d9d9;background:#fff;border-radius:4px;overflow:auto;padding:0 8px 8px} .algolia-autocomplete .ds-dropdown-menu *{-webkit-box-sizing:border-box;box-sizing:border-box} .algolia-autocomplete .algolia-docsearch-suggestion{display:block;position:relative;padding:0 8px;background:#fff;color:#02060c;overflow:hidden} .algolia-autocomplete .algolia-docsearch-suggestion--highlight{color:#174d8c;background:rgba(143, 187, 237, .1);padding:.1em .05em} .algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl0 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl1 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{padding:0 0 1px;background:inherit;-webkit-box-shadow:inset 0 -2px 0 0 rgba(69, 142, 225, .8);box-shadow:inset 0 -2px 0 0 rgba(69, 142, 225, .8);color:inherit} .algolia-autocomplete .algolia-docsearch-suggestion--content{display:block;float:right;width:70%;position:relative;padding:5.33333px 0 5.33333px 10.66667px;cursor:pointer} .algolia-autocomplete .algolia-docsearch-suggestion--content:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ddd;left:-1px} .algolia-autocomplete .algolia-docsearch-suggestion--category-header{position:relative;border-bottom:1px solid #ddd;display:none;margin-top:8px;padding:4px 0;font-size:1em;color:#33363d} .algolia-autocomplete .algolia-docsearch-suggestion--wrapper{width:100%;float:left;padding:8px 0 0} .algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column{float:left;width:30%;text-align:right;position:relative;padding:5.33333px 10.66667px;color:#a4a7ae;font-size:.9em;word-wrap:break-word} .algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ddd;right:0} .algolia-autocomplete .algolia-docsearch-suggestion--subcategory-inline{display:none} .algolia-autocomplete .algolia-docsearch-suggestion--title{margin-bottom:4px;color:#02060c;font-size:.9em;font-weight:700} .algolia-autocomplete .algolia-docsearch-suggestion--text{display:block;line-height:1.2em;font-size:.85em;color:#63676d} .algolia-autocomplete .algolia-docsearch-suggestion--no-results{width:100%;padding:8px 0;text-align:center;font-size:1.2em} .algolia-autocomplete .algolia-docsearch-suggestion--no-results:before{display:none} .algolia-autocomplete .algolia-docsearch-suggestion code{padding:1px 5px;font-size:90%;border:none;color:#222;background-color:#ebebeb;border-radius:3px;font-family:Menlo,Monaco,Consolas,Courier New,monospace} .algolia-autocomplete .algolia-docsearch-suggestion code .algolia-docsearch-suggestion--highlight{background:none} .algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--category-header,.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary{display:block} @media (min-width:768px){.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{display:block}} @media (max-width:768px){.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{display:inline-block;width:auto;float:left;padding:0;color:#02060c;font-size:.9em;font-weight:700;text-align:left;opacity:.5}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:after{content:"|"}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content{display:inline-block;width:auto;text-align:left;float:left;padding:0}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content:before{display:none}} .algolia-autocomplete .suggestion-layout-simple.algolia-docsearch-suggestion{border-bottom:1px solid #eee;padding:8px;margin:0} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content{width:100%;padding:0} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content:before{display:none} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header{margin:0;padding:0;display:block;width:100%;border:none} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl0,.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1{opacity:.6;font-size:.85em} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1:before{background-image:url('data:image/svg+xml;utf8,');content:"";width:10px;height:10px;display:inline-block} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--wrapper{width:100%;float:left;margin:0;padding:0} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--duplicate-content,.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--subcategory-inline{display:none!important} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title{margin:0;color:#458ee1;font-size:.9em;font-weight:400} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title:before{content:"#";font-weight:700;color:#458ee1;display:inline-block} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text{margin:4px 0 0;display:block;line-height:1.4em;padding:5.33333px 8px;background:#f8f8f8;font-size:.85em;opacity:.8} .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{color:#3f4145;font-weight:700;-webkit-box-shadow:none;box-shadow:none} .algolia-autocomplete .algolia-docsearch-footer{width:134px;height:20px;z-index:2000;margin-top:10.66667px;float:right;font-size:0;line-height:0} .algolia-autocomplete .algolia-docsearch-footer--logo{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='168' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath d='M78.988.938h16.594a2.968 2.968 0 0 1 2.966 2.966V20.5a2.967 2.967 0 0 1-2.966 2.964H78.988a2.967 2.967 0 0 1-2.966-2.964V3.897A2.961 2.961 0 0 1 78.988.938zm41.937 17.866c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 0 0-1.574-.199 5.7 5.7 0 0 0-.897.069 2.699 2.699 0 0 0-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874a32.5 32.5 0 0 1-1.868.314c-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 0 1-1.471-.636 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525a3.24 3.24 0 0 1 1.047-1.106c.445-.287.95-.492 1.532-.615a8.8 8.8 0 0 1 1.82-.185 8.404 8.404 0 0 1 1.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 0 0-.384-.73 1.784 1.784 0 0 0-.724-.493 3.164 3.164 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 0 0-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 0 1 2.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 0 0-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 0 0-.814.24 1.46 1.46 0 0 0-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483a6.8 6.8 0 0 1 .233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 0 1-1.471-.635 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 0 1 2.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 0 0-.109-.875 1.873 1.873 0 0 0-.384-.731 1.784 1.784 0 0 0-.724-.492 3.165 3.165 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.75 7.75 0 0 0-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 0 1 2.073-.177zm-8.034-1.271a1.626 1.626 0 0 1-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 0 1-1.128 1.906 4.986 4.986 0 0 1-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 0 1-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 0 1-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 0 1 1.15-1.892 5.133 5.133 0 0 1 1.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423a4.88 4.88 0 0 1 1.753 1.216 5.644 5.644 0 0 1 1.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 0 0-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 0 1-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 0 1-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 0 1 2.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17z' fill='%235468FF'/%3E%3Cpath d='M6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 0 0-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503a61.27 61.27 0 0 1-.582-.271 13.67 13.67 0 0 1-.55-.287 4.275 4.275 0 0 1-.567-.351 6.92 6.92 0 0 1-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 0 1-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 0 0-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 0 0-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 0 0-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104l-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 0 1-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z' fill='%235D6494'/%3E%3Cpath d='M89.632 5.967v-.772a.978.978 0 0 0-.978-.977h-2.28a.978.978 0 0 0-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 0 1 1.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01l-.39-.389a.977.977 0 0 0-1.382 0l-.465.465a.973.973 0 0 0 0 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 0 0-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 0 1-4.49-4.482 4.488 4.488 0 0 1 4.49-4.482 4.488 4.488 0 0 1 4.489 4.482 4.484 4.484 0 0 1-4.49 4.482m0-10.85a6.363 6.363 0 1 0 0 12.729 6.37 6.37 0 0 0 6.372-6.368 6.358 6.358 0 0 0-6.371-6.36' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E");background-repeat:no-repeat;background-position:50%;background-size:100%;overflow:hidden;text-indent:-9000px;padding:0!important;width:100%;height:100%;display:block} /* These styles enhance the home page carousel, located here: themes/gohugoioTheme/layouts/partials/home-page-sections/showcase.html */ .overflow-x-scroll{ -webkit-overflow-scrolling: touch; } .row { -webkit-transition: 450ms -webkit-transform; transition: 450ms -webkit-transform; transition: 450ms transform; transition: 450ms transform, 450ms -webkit-transform; font-size: 0; } .tile { -webkit-transition: 450ms all; transition: 450ms all; } .details { background: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, .9)), to(rgba(0, 0, 0, 0))); background: linear-gradient(to top, rgba(0, 0, 0, .9) 0%, rgba(0, 0, 0, 0) 100%); -webkit-transition: 450ms opacity; transition: 450ms opacity; } .tile:hover .details { opacity: 1; } .row:hover .tile { opacity: 0.3; } .row:hover .tile:hover { opacity: 1; } .chroma .lntable pre { padding: 0; margin: 0; border: 0; } .chroma .lntable pre code { padding: 0; margin: 0; } pre, .pre { overflow-x: auto; overflow-y: hidden; overflow: scroll; } code { padding: 0.2em; margin: 0; font-size: 85%; background-color: rgba(27, 31, 35, .05); border-radius: 3px; } pre code { display: block; padding: 1.5em 1.5em; font-size: .875rem; line-height: 2; overflow-x: auto; } pre { background-color: #fff; color: #333; white-space: pre; -webkit-hyphens: none; -ms-hyphens: none; hyphens: none; position: relative; border-width: 1px; border-color: #ccc; border-style: solid; } /* The Pygments highlighter comes with its own styles. */ .highlight pre { background-color: inherit; color: inherit; padding: 0.5em; font-size: .875rem; } /*We are adding the copy button content here so we can change it with javascript. See the "Clipboard scripts"*/ .copy:after { content: "Copy" } .copied:after { content: "Copied" } @media screen and (min-width: 60em) { .full-width, pre.expand:hover { /*width: 100vw; position: relative; left: 50%; right: 50%; margin-left: -50vw; margin-right: -50vw;*/ /*width: 60vw;*/ /*position: relative; left: 50%; right: 50%;*/ /*margin-left: -30vw;*/ margin-right: -30vw; max-width: 100vw; } } .code-block .line-numbers-rows { background: #2f3a46; border: none; bottom: -50px; color: #98a4b3; left: -178px; padding: 50px 0; top: -50px; width: 138px } .code-block .line-numbers-rows>span:before { color: inherit; padding-right: 30px } .tab-button{ margin-bottom:1px; position: relative; z-index: 1; color:#333; border-color:#ccc; outline: none; background-color:white; } .tab-pane code{ background:#f1f2f2; border-radius:0; } .tab-pane .chroma{ background:none; padding:0; } .tab-button.active{ border-bottom-color:#f1f2f2; background-color: #f1f2f2; } .tab-content .tab-pane{ display: none; } .tab-content .tab-pane.active{ display: block; } /* Treatment of copy buttons inside a tab module */ .tab-content .copy, .tab-content .copied{ display: none; } .tab-content .tab-pane.active + .copy, .tab-content .tab-pane.active + .copied{ display: block; } .primary-color {color: #0594CB} .bg-primary-color {background-color: #0594CB} .hover-bg-primary-color:hover {background-color: #0594CB} .primary-color-dark {color: #0A1922} .bg-primary-color-dark {background-color: #0A1922} .hover-bg-primary-color-dark:hover {background-color: #0A1922} .primary-color-light {color: #f9f9f9} .bg-primary-color-light {background-color: #f9f9f9} .hover-bg-primary-color-light:hover {background-color: #f9f9f9} .accent-color {color: #EBB951} .bg-accent-color {background-color: #EBB951} .hover-bg-accent-color:hover {background-color: #EBB951} .accent-color-light {color: #FF4088} .hover-accent-color-light:hover {color: #FF4088} .bg-accent-color-light {background-color: #FF4088} .hover-bg-accent-color-light:hover {background-color: #FF4088} .accent-color-dark {color: #33ba91} .bg-accent-color-dark {background-color: #33ba91} .hover-bg-accent-color-dark:hover {background-color: #33ba91} .text-color-primary {color: #373737} .text-on-primary-color {color: #fff} .text-color-secondary {color: #ccc} .text-color-disabled {color: #F7f7f7} .divider-color {color: #f6f6f6} .warn-color {color: red} .nested-links a { color: #0594CB; text-decoration: none; } .column-count-2 {-webkit-column-count: 1;column-count: 1} .column-gap-1 {-webkit-column-gap: 0;column-gap: 0} .break-inside-avoid {-webkit-column-break-inside: auto;break-inside: auto} @media screen and (min-width: 60em) { .column-count-3-l {-webkit-column-count: 3;column-count: 3} .column-count-2-l {-webkit-column-count: 2;column-count: 2} .column-gap-1-l {-webkit-column-gap: 1;column-gap: 1} .break-inside-avoid-l {-webkit-column-break-inside: avoid;break-inside: avoid} } .prose ul, .prose ol { margin-bottom: 2em; } .prose ul li, .prose ol li { margin-bottom: .5em; } .prose li:hover { background-color: #eee } .prose ::selection { background: #0594CB; /* WebKit/Blink Browsers */ color: white; } body { line-height: 1.45; } p {margin-bottom: 1.3em;} h1, h2, h3, h4 { margin: 1.414em 0 0.5em; line-height: 1.2; } h1 { margin-top: 0; font-size: 2.441em; } h2 {font-size: 1.953em;} h3 {font-size: 1.563em;} h4 {font-size: 1.25em;} small, .font_small {font-size: 0.8em;} .prose table { width: 100%; margin-bottom: 3em; border-collapse: collapse; border-spacing: 0; font-size: 1em; border: 1px solid #eee } .prose table th { background-color: #0594CB; border-bottom: 1px solid #0594CB; color: white; font-weight: 400; text-align: left; padding: .375em .5em; } .prose table td, .prose table tc { padding: .75em .5em; text-align: left; border-right: 1px solid #eee; } .prose table tr:nth-child(even) { background-color: #eee; } dl dt { font-weight: bold; font-size: 1.125rem; } dd { margin: .5em 0 2em 0; padding: 0; } .f2-fluid { font-size: 2.25rem; } @media screen and (min-width: 60em) { .f2-fluid { font-size: 1.25rem; font-size: calc(0.70833rem + 0.83333vw); } } /* From http://cssfontstack.com */ code, .code, pre code, .highlight pre { font-family: 'inconsolata',Menlo,Monaco,'Courier New',monospace; } .sans-serif { font-family: 'Muli', avenir, 'helvetica neue', helvetica, ubuntu, roboto, noto, 'segoe ui', arial, sans-serif; } .serif { font-family: Palatino,"Palatino Linotype","Palatino LT STD","Book Antiqua",Georgia,serif; } /* Monospaced Typefaces (for code) */ .courier { font-family: 'Courier Next', courier, monospace; } /* Sans-Serif Typefaces */ .helvetica { font-family: 'helvetica neue', helvetica, sans-serif; } .avenir { font-family: 'avenir next', avenir, sans-serif; } /* Serif Typefaces */ .athelas { font-family: athelas, georgia, serif; } .georgia { font-family: georgia, serif; } .times { font-family: times, serif; } .bodoni { font-family: "Bodoni MT", serif; } .calisto { font-family: "Calisto MT", serif; } .garamond { font-family: garamond, serif; } .baskerville { font-family: baskerville, serif; } /* pagination.html: https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/template_embedded.go#L117 */ .pagination { margin: 3rem 0; } .pagination li { display: inline-block; margin-right: .375rem; font-size: .875rem; margin-bottom: 2.5em; } .pagination li a { padding: .5rem .625rem; background-color: white; color: #333; border: 1px solid #ddd; border-radius: 3px; text-decoration: none; } .pagination li.disabled { display: none; } .pagination li.active a:link, .pagination li.active a:active, .pagination li.active a:visited { background-color: #ddd; } /* Hides non-meaningful TOC items*/ #TableOfContents ul li ul li ul li{ display: none; } #TableOfContents ul li { color: black; display: block; margin-bottom: .375em; line-height: 1.375; } #TableOfContents ul li a{ width: 100%; padding: .25em .375em; margin-left: -.375em; } #TableOfContents ul li a:hover { background-color: #999; color: white; } .no-js .needs-js { opacity: 0 } .js .needs-js { opacity: 1; -webkit-transition: opacity .15s ease-in; transition: opacity .15s ease-in; } .facebook, .twitter, .instagram, .youtube { fill: #BABABA; } .facebook:hover { fill: #3b5998; } .twitter { fill: #55acee; } .twitter:hover { fill: #BABABA; } .instagram:hover { fill: #e95950; } .youtube:hover { fill: #bb0000; } @media (min-width: 75em) { [data-scrolldir="down"] .sticky { position: fixed; top:100px; right:0; } [data-scrolldir="up"] .sticky { position: fixed; top:100px; right:0; } } .fill-current { fill: currentColor; } /* Background */ .chroma { background-color: #ffffff } /* Error */ .chroma .err { color: #a61717; background-color: #e3d2d2 } /* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } /* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; } /* LineHighlight */ .chroma .hl { display: block; width: 100%;background-color: #ffffcc } /* LineNumbersTable */ .chroma .lnt { margin-right: 0.4em; padding: 0 0.4em 0 0.4em; } /* LineNumbers */ .chroma .ln { margin-right: 0.4em; padding: 0 0.4em 0 0.4em; } /* Keyword */ .chroma .k { font-weight: bold } /* KeywordConstant */ .chroma .kc { font-weight: bold } /* KeywordDeclaration */ .chroma .kd { font-weight: bold } /* KeywordNamespace */ .chroma .kn { font-weight: bold } /* KeywordPseudo */ .chroma .kp { font-weight: bold } /* KeywordReserved */ .chroma .kr { font-weight: bold } /* KeywordType */ .chroma .kt { color: #445588; font-weight: bold } /* NameAttribute */ .chroma .na { color: #008080 } /* NameBuiltin */ .chroma .nb { color: #999999 } /* NameClass */ .chroma .nc { color: #445588; font-weight: bold } /* NameConstant */ .chroma .no { color: #008080 } /* NameEntity */ .chroma .ni { color: #800080 } /* NameException */ .chroma .ne { color: #990000; font-weight: bold } /* NameFunction */ .chroma .nf { color: #990000; font-weight: bold } /* NameNamespace */ .chroma .nn { color: #555555 } /* NameTag */ .chroma .nt { color: #000080 } /* NameVariable */ .chroma .nv { color: #008080 } /* LiteralString */ .chroma .s { color: #bb8844 } /* LiteralStringAffix */ .chroma .sa { color: #bb8844 } /* LiteralStringBacktick */ .chroma .sb { color: #bb8844 } /* LiteralStringChar */ .chroma .sc { color: #bb8844 } /* LiteralStringDelimiter */ .chroma .dl { color: #bb8844 } /* LiteralStringDoc */ .chroma .sd { color: #bb8844 } /* LiteralStringDouble */ .chroma .s2 { color: #bb8844 } /* LiteralStringEscape */ .chroma .se { color: #bb8844 } /* LiteralStringHeredoc */ .chroma .sh { color: #bb8844 } /* LiteralStringInterpol */ .chroma .si { color: #bb8844 } /* LiteralStringOther */ .chroma .sx { color: #bb8844 } /* LiteralStringRegex */ .chroma .sr { color: #808000 } /* LiteralStringSingle */ .chroma .s1 { color: #bb8844 } /* LiteralStringSymbol */ .chroma .ss { color: #bb8844 } /* LiteralNumber */ .chroma .m { color: #009999 } /* LiteralNumberBin */ .chroma .mb { color: #009999 } /* LiteralNumberFloat */ .chroma .mf { color: #009999 } /* LiteralNumberHex */ .chroma .mh { color: #009999 } /* LiteralNumberInteger */ .chroma .mi { color: #009999 } /* LiteralNumberIntegerLong */ .chroma .il { color: #009999 } /* LiteralNumberOct */ .chroma .mo { color: #009999 } /* Operator */ .chroma .o { font-weight: bold } /* OperatorWord */ .chroma .ow { font-weight: bold } /* Comment */ .chroma .c { color: #999988; font-style: italic } /* CommentHashbang */ .chroma .ch { color: #999988; font-style: italic } /* CommentMultiline */ .chroma .cm { color: #999988; font-style: italic } /* CommentSingle */ .chroma .c1 { color: #999988; font-style: italic } /* CommentSpecial */ .chroma .cs { color: #999999; font-weight: bold; font-style: italic } /* CommentPreproc */ .chroma .cp { color: #999999; font-weight: bold } /* CommentPreprocFile */ .chroma .cpf { color: #999999; font-weight: bold } /* GenericDeleted */ .chroma .gd { color: #000000; background-color: #ffdddd } /* GenericEmph */ .chroma .ge { font-style: italic } /* GenericError */ .chroma .gr { color: #aa0000 } /* GenericHeading */ .chroma .gh { color: #999999 } /* GenericInserted */ .chroma .gi { color: #000000; background-color: #ddffdd } /* GenericOutput */ .chroma .go { color: #888888 } /* GenericPrompt */ .chroma .gp { color: #555555 } /* GenericStrong */ .chroma .gs { font-weight: bold } /* GenericSubheading */ .chroma .gu { color: #aaaaaa } /* GenericTraceback */ .chroma .gt { color: #aa0000 } /* TextWhitespace */ .chroma .w { color: #bbbbbb } .nested-blockquote blockquote { border-left: 4px solid #0594CB; padding-left: 1em; /*margin: 0;*/ } .mw-90 { max-width:90%; } /* purgecss end ignore */ hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/output/js/000077500000000000000000000000001420147000300270615ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/assets/output/js/app.js000066400000000000000000004724141420147000300302130ustar00rootroot00000000000000!function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([function(e,t,n){!function(t,n){var r=function(e,t){"use strict";if(!t.getElementsByClassName)return;var n,r,i=t.documentElement,s=e.Date,o=e.HTMLPictureElement,a=e.addEventListener,c=e.setTimeout,u=e.requestAnimationFrame||c,l=e.requestIdleCallback,h=/^picture$/i,d=["load","error","lazyincluded","_lazyloaded"],f={},p=Array.prototype.forEach,g=function(e,t){return f[t]||(f[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),f[t].test(e.getAttribute("class")||"")&&f[t]},m=function(e,t){g(e,t)||e.setAttribute("class",(e.getAttribute("class")||"").trim()+" "+t)},v=function(e,t){var n;(n=g(e,t))&&e.setAttribute("class",(e.getAttribute("class")||"").replace(n," "))},y=function(e,t,n){var r=n?"addEventListener":"removeEventListener";n&&y(e,t),d.forEach((function(n){e[r](n,t)}))},b=function(e,r,i,s,o){var a=t.createEvent("Event");return i||(i={}),i.instance=n,a.initEvent(r,!s,!o),a.detail=i,e.dispatchEvent(a),a},w=function(t,n){var i;!o&&(i=e.picturefill||r.pf)?(n&&n.src&&!t.getAttribute("srcset")&&t.setAttribute("srcset",n.src),i({reevaluate:!0,elements:[t]})):n&&n.src&&(t.src=n.src)},_=function(e,t){return(getComputedStyle(e,null)||{})[t]},E=function(e,t,n){for(n=n||e.offsetWidth;n0)&&"visible"!=_(s,"overflow")&&(r=s.getBoundingClientRect(),o=G>r.left&&Wr.top-1&&J500&&i.clientWidth>500?500:370),X=r.expand,Z=X*r.expFactor),re2&&z>2&&!t.hidden?(re=Z,se=0):re=z>1&&se>1&&ie<6?X:0;for(;s=l&&(J=o.top)<=V&&(G=o.right)>=l*Y&&(W=o.left)<=K&&(Q||G||W||J)&&(r.loadHidden||"hidden"!=_(f[s],"visibility"))&&(q&&ie<3&&!h&&(z<3||se<4)||ae(f[s],u))){if(ge(f[s]),c=!0,ie>9)break}else!c&&q&&!a&&ie<4&&se<4&&z>2&&(B[0]||r.preloadAfterLoad)&&(B[0]||!h&&(Q||G||W||J||"auto"!=f[s].getAttribute(r.sizesAttr)))&&(a=B[0]||f[s]);else ge(f[s]);a&&!c&&ge(a)}},ue=function(e){var t,n=0,i=r.throttleDelay,o=r.ricTimeout,a=function(){t=!1,n=s.now(),e()},u=l&&o>49?function(){l(a,{timeout:o}),o!==r.ricTimeout&&(o=r.ricTimeout)}:S((function(){c(a)}),!0);return function(e){var r;(e=!0===e)&&(o=33),t||(t=!0,(r=i-(s.now()-n))<0&&(r=0),e||r<9?u():c(u,r))}}(ce),le=function(e){m(e.target,r.loadedClass),v(e.target,r.loadingClass),y(e.target,de),b(e.target,"lazyloaded")},he=S(le),de=function(e){he({target:e.target})},fe=function(e){var t,n=e.getAttribute(r.srcsetAttr);(t=r.customMedia[e.getAttribute("data-media")||e.getAttribute("media")])&&e.setAttribute("media",t),n&&e.setAttribute("srcset",n)},pe=S((function(e,t,n,i,s){var o,a,u,l,d,f;(d=b(e,"lazybeforeunveil",t)).defaultPrevented||(i&&(n?m(e,r.autosizesClass):e.setAttribute("sizes",i)),a=e.getAttribute(r.srcsetAttr),o=e.getAttribute(r.srcAttr),s&&(l=(u=e.parentNode)&&h.test(u.nodeName||"")),f=t.firesLoad||"src"in e&&(a||o||l),d={target:e},f&&(y(e,oe,!0),clearTimeout(F),F=c(oe,2500),m(e,r.loadingClass),y(e,de,!0)),l&&p.call(u.getElementsByTagName("source"),fe),a?e.setAttribute("srcset",a):o&&!l&&(te.test(e.nodeName)?function(e,t){try{e.contentWindow.location.replace(t)}catch(n){e.src=t}}(e,o):e.src=o),s&&(a||l)&&w(e,{src:o})),e._lazyRace&&delete e._lazyRace,v(e,r.lazyClass),x((function(){(!f||e.complete&&e.naturalWidth>1)&&(f?oe(d):ie--,le(d))}),!0)})),ge=function(e){var t,n=ee.test(e.nodeName),i=n&&(e.getAttribute(r.sizesAttr)||e.getAttribute("sizes")),s="auto"==i;(!s&&q||!n||!e.getAttribute("src")&&!e.srcset||e.complete||g(e,r.errorClass)||!g(e,r.lazyClass))&&(t=b(e,"lazyunveilread").detail,s&&I.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,ie++,pe(e,t,s,i,n))},me=function(){if(!q)if(s.now()-U<999)c(me,999);else{var e=C((function(){r.loadMode=3,ue()}));q=!0,r.loadMode=3,ue(),a("scroll",(function(){3==r.loadMode&&(r.loadMode=2),e()}),!0)}},{_:function(){U=s.now(),n.elements=t.getElementsByClassName(r.lazyClass),B=t.getElementsByClassName(r.lazyClass+" "+r.preloadClass),Y=r.hFac,a("scroll",ue,!0),a("resize",ue,!0),e.MutationObserver?new MutationObserver(ue).observe(i,{childList:!0,subtree:!0,attributes:!0}):(i.addEventListener("DOMNodeInserted",ue,!0),i.addEventListener("DOMAttrModified",ue,!0),setInterval(ue,999)),a("hashchange",ue,!0),["focus","mouseover","click","load","transitionend","animationend","webkitAnimationEnd"].forEach((function(e){t.addEventListener(e,ue,!0)})),/d$|^c/.test(t.readyState)?me():(a("load",me),t.addEventListener("DOMContentLoaded",ue),c(me,2e4)),n.elements.length?(ce(),x._lsFlush()):ue()},checkElems:ue,unveil:ge}),I=(P=S((function(e,t,n,r){var i,s,o;if(e._lazysizesWidth=r,r+="px",e.setAttribute("sizes",r),h.test(t.nodeName||""))for(s=0,o=(i=t.getElementsByTagName("source")).length;s0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText,this.container="object"===r(e.container)?e.container:document.body}},{key:"listenClick",value:function(e){var t=this;this.listener=(0,a.default)(e,"click",(function(e){return t.onClick(e)}))}},{key:"onClick",value:function(e){var t=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new s.default({action:this.action(t),target:this.target(t),text:this.text(t),container:this.container,trigger:t,emitter:this})}},{key:"defaultAction",value:function(e){return l("action",e)}},{key:"defaultTarget",value:function(e){var t=l("target",e);if(t)return document.querySelector(t)}},{key:"defaultText",value:function(e){return l("text",e)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],t="string"==typeof e?[e]:e,n=!!document.queryCommandSupported;return t.forEach((function(e){n=n&&!!document.queryCommandSupported(e)})),n}}]),t}(o.default);function l(e,t){var n="data-clipboard-"+e;if(t.hasAttribute(n))return t.getAttribute(n)}e.exports=u},function(e,t,n){"use strict";var r,i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},s=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action=e.action,this.container=e.container,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var e=this,t="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[t?"right":"left"]="-9999px";var n=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=n+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=(0,a.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=(0,a.default)(this.target),this.copyText()}},{key:"copyText",value:function(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function(e){this.emitter.emit(e?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(e){if(void 0!==e){if(!e||"object"!==(void 0===e?"undefined":i(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function(){return this._target}}]),e}();e.exports=c},function(e,t){e.exports=function(e){var t;if("SELECT"===e.nodeName)e.focus(),t=e.value;else if("INPUT"===e.nodeName||"TEXTAREA"===e.nodeName){var n=e.hasAttribute("readonly");n||e.setAttribute("readonly",""),e.select(),e.setSelectionRange(0,e.value.length),n||e.removeAttribute("readonly"),t=e.value}else{e.hasAttribute("contenteditable")&&e.focus();var r=window.getSelection(),i=document.createRange();i.selectNodeContents(e),r.removeAllRanges(),r.addRange(i),t=r.toString()}return t}},function(e,t){function n(){}n.prototype={on:function(e,t,n){var r=this.e||(this.e={});return(r[e]||(r[e]=[])).push({fn:t,ctx:n}),this},once:function(e,t,n){var r=this;function i(){r.off(e,i),t.apply(n,arguments)}return i._=t,this.on(e,i,n)},emit:function(e){for(var t=[].slice.call(arguments,1),n=((this.e||(this.e={}))[e]||[]).slice(),r=0,i=n.length;r0&&n.parentNode.classList.add("expand")}}},function(e,t,n){n(8)({apiKey:"167e7998590aebda7f9fedcf86bc4a55",indexName:"hugodocs",inputSelector:"#search-input",debug:!0})},function(e,t,n){ /*! docsearch 2.6.1 | © Algolia | github.com/algolia/docsearch */ var r;"undefined"!=typeof self&&self,r=function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=22)}([function(e,t,n){"use strict";var r,i=n(1);function s(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}e.exports={isArray:null,isFunction:null,isObject:null,bind:null,each:null,map:null,mixin:null,isMsie:function(e){if(void 0===e&&(e=navigator.userAgent),/(msie|trident)/i.test(e)){var t=e.match(/(msie |rv:)(\d+(.\d+)?)/i);if(t)return t[2]}return!1},escapeRegExChars:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isNumber:function(e){return"number"==typeof e},toStr:function(e){return null==e?"":e+""},cloneDeep:function(e){var t=this.mixin({},e),n=this;return this.each(t,(function(e,r){e&&(n.isArray(e)?t[r]=[].concat(e):n.isObject(e)&&(t[r]=n.cloneDeep(e)))})),t},error:function(e){throw new Error(e)},every:function(e,t){var n=!0;return e?(this.each(e,(function(r,i){if(!(n=t.call(null,r,i,e)))return!1})),!!n):n},any:function(e,t){var n=!1;return e?(this.each(e,(function(r,i){if(t.call(null,r,i,e))return n=!0,!1})),n):n},getUniqueId:(r=0,function(){return r++}),templatify:function(e){if(this.isFunction(e))return e;var t=i.element(e);return"SCRIPT"===t.prop("tagName")?function(){return t.text()}:function(){return String(e)}},defer:function(e){setTimeout(e,0)},noop:function(){},formatPrefix:function(e,t){return t?"":e+"-"},className:function(e,t,n){return(n?"":".")+e+t},escapeHighlightedString:function(e,t,n){t=t||"";var r=document.createElement("div");r.appendChild(document.createTextNode(t)),n=n||"";var i=document.createElement("div");i.appendChild(document.createTextNode(n));var o=document.createElement("div");return o.appendChild(document.createTextNode(e)),o.innerHTML.replace(RegExp(s(r.innerHTML),"g"),t).replace(RegExp(s(i.innerHTML),"g"),n)}}},function(e,t,n){"use strict";e.exports={element:null}},function(e,t){var n=Object.prototype.hasOwnProperty,r=Object.prototype.toString;e.exports=function(e,t,i){if("[object Function]"!==r.call(t))throw new TypeError("iterator must be a function");var s=e.length;if(s===+s)for(var o=0;o was loaded but did not call our provided callback"),JSONPScriptError:s("JSONPScriptError"," {{ end }} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/head-additions.html000066400000000000000000000000161420147000300326620ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/hero.html000066400000000000000000000012521420147000300307450ustar00rootroot00000000000000
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/home-page-sections/000077500000000000000000000000001420147000300326115ustar00rootroot00000000000000features-icons.html000066400000000000000000000026051420147000300363520ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/home-page-sections
    {{ if .Params.features }}
    {{ $features := .Params.features }} {{ range $i, $e := $features }} {{ $features_count := $e | len }}
    {{ with .image_path }} icon depicting {{ $e.heading }} {{ end }}

    {{ .heading }}

    {{.tagline}}

    {{ .copy }}
    {{ end }}
    {{ end }}
    features-single.html000066400000000000000000000021061420147000300365140ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/home-page-sections{{ if .Params.sections }} {{ range .Params.sections }} {{ $.Scratch.Add "i" 1 }}{{ $i := $.Scratch.Get "i" }}
    {{ end }} {{ end }} installation.html000066400000000000000000000033771420147000300361330ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/home-page-sections

    Install in seconds, build in milliseconds.

    Hugo works on macOS, Windows, Linux, FreeBSD, and others.

    Host on any server or your favorite CDN.

    Hugo Gopher

    macOS

    $ brew install hugo

    Windows

    $ choco install hugo -confirm

    Linux

    $ snap install hugo
    open-source-involvement.html000066400000000000000000000033331420147000300402250ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/home-page-sections
    Github Logo
    showcase.html000066400000000000000000000034241420147000300352370ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/home-page-sections

    Showcase

    {{/* NOTE: transitions for this section are in themes/gohugoioTheme/src/css/_carousel.css */}}
    {{ $showcasePages := where .Site.RegularPages "Section" "showcase" }} {{ if $showcasePages }} {{ template "home_showcase_item" (index $showcasePages 0) }} {{ range $p := first 10 ($showcasePages | after 1 | shuffle) }} {{template "home_showcase_item" $p }} {{end}} {{end}}
    {{/* END */}}
    {{/* using Flex to make the button show up on the right side */}} See All
    {{ define "home_showcase_item" }} {{ $img := (.Resources.ByType "image").GetMatch "*featured*" }} {{ with $img }} {{ $big := .Fill "1024x512 top" }} {{ $small := $big.Resize "512x" }} {{with $.Title}}
    {{.}} →
    {{end}}
    {{ end }} {{ end }}sponsors.html000066400000000000000000000035031420147000300353070ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/home-page-sections{{$classes_box := "ba b--dark-gray bg-light-gray br3 flex flex-column flex-wrap items-center justify-center ph3 pv4 mb4 w-100 w-30-l "}} {{$gtag := .gtag | default "unknown" }} {{ with .cx.Site.Data.sponsors }}
     

    Hugo Sponsors

    {{ range .banners }} {{ $banner := . }} {{if .logo}}
    {{with .link -}} {{ $url := printf "%s?%s" . (querify "utm_source" "homepage" "utm_medium" "banner" "utm_campaign" "hugosponsor") | safeURL }} {{ if eq (getenv "HUGO_ENV") "production" | or (eq $.cx.Site.Params.env "production") }} {{ $gtagID := printf "Sponsor %s %s" $banner.name $gtag | title }} {{ else }} {{ end }} {{- end}} Logo for {{ .name }} {{with .link}}{{end}} {{with .copy}}

    {{- . -}}

    {{end}}
    {{else}}

    Your Logo Here

    {{end}} {{end}}
    {{end}} tweets.html000066400000000000000000000016131420147000300347340ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/home-page-sections
    {{ $interior_classes := $.Site.Params.flex_box_interior_classes }}

    See what others are saying about Hugo…

    {{ range first 4 (sort $.Site.Data.homepagetweets.tweet "date" "desc" ) }} {{ end }}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/icon-link.html000066400000000000000000000006441420147000300316770ustar00rootroot00000000000000 nav-links-docs-mobile.html000066400000000000000000000007771420147000300340410ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials{{ $currentPage := . }} {{ $menu := .Site.Menus.docs.ByWeight }}
      {{ range $menu }}{{ $post := printf "%s" .Post }}
    • {{ .Name }}
    • {{end}}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/nav-links-docs.html000066400000000000000000000022411420147000300326370ustar00rootroot00000000000000{{ $currentPage := . }} nav-links-global-mobile.html000066400000000000000000000006561420147000300343450ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials{{ $currentPage := . }} {{ $menu := .Site.Menus.global }} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/nav-links.html000066400000000000000000000030151420147000300317110ustar00rootroot00000000000000{{ $currentPage := . }} {{ $.Scratch.Add "listlinkClasses" "f6 link primary-color-dark hover-white db brand-font ma0 w-100 pv3 ph4" }} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/nav-mobile.html000066400000000000000000000011541420147000300320420ustar00rootroot00000000000000
    {{ partial "nav-links-docs-mobile.html" . }}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/nav-top.html000066400000000000000000000010701420147000300313720ustar00rootroot00000000000000{{ $currentPage := . }}
    {{ partial "nav-links" .}}
    {{ partial "nav-button-open" .}}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/opengraph/000077500000000000000000000000001420147000300311055ustar00rootroot00000000000000get-featured-image.html000066400000000000000000000014561420147000300353560ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/opengraph{{ $images := $.Resources.ByType "image" }} {{ $featured := $images.GetMatch "*feature*" }} {{ if not $featured }}{{ $featured = $images.GetMatch "{*cover*,*thumbnail*}" }}{{ end }} {{ if not $featured }} {{ $featured = resources.Get "/opengraph/gohugoio-card-base-1.png" }} {{ $size := 80 }} {{ $title := $.LinkTitle }} {{ if gt (len $title) 20 }} {{ $size = 70 }} {{ end }} {{ $text := $title }} {{ $textOptions := dict "color" "#FFF" "size" $size "lineSpacing" 10 "x" 65 "y" 80 "font" (resources.Get "/opengraph/mulish-black.ttf") }} {{ $featured = $featured | images.Filter (images.Text $text $textOptions) }} {{ end }} {{ return $featured }}hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/opengraph/opengraph.html000066400000000000000000000042051420147000300337570ustar00rootroot00000000000000 {{- with $.Params.images -}} {{- range first 6 . }}{{ end -}} {{- else -}} {{- $featured := partial "opengraph/get-featured-image.html" . }} {{- with $featured -}} {{- else -}} {{- with $.Site.Params.images }}{{ end -}} {{- end -}} {{- end -}} {{- if .IsPage }} {{- $iso8601 := "2006-01-02T15:04:05-07:00" -}} {{ with .PublishDate }}{{ end }} {{ with .Lastmod }}{{ end }} {{- end -}} {{- with .Params.audio }}{{ end }} {{- with .Params.locale }}{{ end }} {{- with .Site.Params.title }}{{ end }} {{- with .Params.videos }}{{- range . }} {{ end }}{{ end }} {{- /* If it is part of a series, link to related articles */}} {{- $permalink := .Permalink }} {{- $siteSeries := .Site.Taxonomies.series }} {{ with .Params.series }}{{- range $name := . }} {{- $series := index $siteSeries ($name | urlize) }} {{- range $page := first 6 $series.Pages }} {{- if ne $page.Permalink $permalink }}{{ end }} {{- end }} {{ end }}{{ end }} {{- /* Facebook Page Admin ID for Domain Insights */}} {{- with .Site.Social.facebook_admin }}{{ end }}twitter_cards.html000066400000000000000000000017151420147000300345760ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/opengraph{{- with $.Params.images -}} {{ else -}} {{- $featured := partial "opengraph/get-featured-image.html" . }} {{- with $featured -}} {{- else -}} {{- with $.Site.Params.images -}} {{ else -}} {{- end -}} {{- end -}} {{- end }} {{ with .Site.Social.twitter -}} {{ end -}}hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/page-edit.html000066400000000000000000000002721420147000300316500ustar00rootroot00000000000000Improve this page hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/page-header.html000066400000000000000000000014471420147000300321600ustar00rootroot00000000000000{{ $currentPage := . }} {{ $currentURL := .RelPermalink }}
    • News:
    • {{ range $name, $taxonomy := .Site.Taxonomies.categories }} {{ $link := $name | printf "%s%s" "/categories/" | printf "%s/" }}
    • {{ $name | humanize }}
    • {{ end }}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/pagelayout.html000066400000000000000000000021471420147000300321660ustar00rootroot00000000000000{{ $section_to_display := .section_to_display }}
    {{ partial "nav-links-docs.html" .context }}
    {{ $interior_classes := .context.Site.Params.flex_box_interior_classes }}
    {{ range $section_to_display }} {{ partial "boxes-section-summaries" (dict "context" . "classes" $interior_classes "fullcontent" true) }} {{ end }}
    previous-next-links-in-section-with-title.html000066400000000000000000000013261420147000300400370ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials{{ if or .PrevInSection .NextInSection }} {{/* this div holds these a tags as a unit for flex-box display */}} {{ end }} previous-next-links-in-section.html000066400000000000000000000012351420147000300357460ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials{{ if or .PrevInSection .NextInSection }} {{/* this div holds these a tags as a unit for flex-box display */}} {{ end }} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/previous-next-links.html000066400000000000000000000015251420147000300337610ustar00rootroot00000000000000{{if .Prev }} {{ partial "svg/ic_chevron_left_black_24px.svg" (dict "size" "30px") }} {{ .Prev.Title }} {{end}} {{if .Next }} {{ .Next.Title }} {{ partial "svg/ic_chevron_right_black_24px.svg" (dict "size" "30px") }} {{end}} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/related.html000066400000000000000000000003061420147000300314270ustar00rootroot00000000000000{{ $related := .Site.RegularPages.Related . | first 5 }} {{ with $related }}

    See Also

    {{ end }}hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/site-footer.html000066400000000000000000000045241420147000300322550ustar00rootroot00000000000000
    Hugo Logo
    {{ with getenv "REPOSITORY_URL" -}}

    Netlify badge

    {{- end }}
      {{ partial "home-page-sections/sponsors.html" (dict "cx" . "gtag" "footer" "classes_section" "pb3 w-100" "classes_copy" "f7 w-90-ns") }}
     

    The Hugo logos are copyright © Steve Francia 2013–{{ now.Year }}.

    The Hugo Gopher is based on an original work by Renée French.

    {{- partial "nav-mobile.html" . -}}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/site-manifest.html000066400000000000000000000005771420147000300325710ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/site-nav.html000066400000000000000000000024701420147000300315410ustar00rootroot00000000000000{{ $currentPage := . }} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/site-scripts.html000066400000000000000000000012461420147000300324440ustar00rootroot00000000000000 {{ $scripts := resources.Get "output/js/app.js" }} {{ $isDev := eq hugo.Environment "development" }} {{ if not $isDev }} {{ $scripts = $scripts | fingerprint }} {{ end }} {{ with $scripts }} {{ if $isDev }} {{ else }} {{ end }} {{ $.Scratch.Set "scripts" . }} {{end}} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/site-search.html000066400000000000000000000007241420147000300322220ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/social-follow.html000066400000000000000000000010311420147000300325550ustar00rootroot00000000000000 {{ with .Site.Social.twitter }} {{ end }} Star hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/summary.html000066400000000000000000000006361420147000300315120ustar00rootroot00000000000000
    {{ humanize .Section }}

    {{ .Title }}

    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/000077500000000000000000000000001420147000300277215ustar00rootroot00000000000000Twitter_Logo_Blue.svg000066400000000000000000000014271420147000300337600ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svgTwitter_Logo_Blue hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/apple.svg000066400000000000000000000010661420147000300315460ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/clipboard.svg000066400000000000000000000010071420147000300323770ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/clippy.svg000066400000000000000000000010071420147000300317400ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/cloud.svg000066400000000000000000000036771420147000300315650ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/content.svg000066400000000000000000000050401420147000300321130ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/design.svg000066400000000000000000000013031420147000300317100ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/exclamation.svg000066400000000000000000000000001420147000300327340ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/facebook.svg000066400000000000000000000007651420147000300322230ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/focus.svg000066400000000000000000000026231420147000300315640ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/freebsd.svg000066400000000000000000000015521420147000300320570ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/functions.svg000066400000000000000000000046061420147000300324600ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/github-corner.svg000066400000000000000000000030011420147000300332040ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/github-squared.svg000066400000000000000000000036241420147000300333730ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/gitter.svg000066400000000000000000000106411420147000300317420ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/gme.svg000066400000000000000000005270721420147000300312270ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/godoc-icon.html000066400000000000000000000076531420147000300326430ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/gopher-2.svg000066400000000000000000000042251420147000300320700ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/gopher-front.svg000066400000000000000000000045751420147000300330670ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/gopher-homepage.svg000066400000000000000000000157711420147000300335240ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/gopher-side_path.svg000066400000000000000000000071261420147000300336720ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/gopher-small.svg000066400000000000000000000127171420147000300330440ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/gopher.svg000066400000000000000000000127241420147000300317340ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/hugo-h-only.svg000066400000000000000000002015721420147000300326170ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/hugo.svg000066400000000000000000000021521420147000300314040ustar00rootroot00000000000000 ic_arrow_drop_down.svg000066400000000000000000000002711420147000300342430ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/ic_arrow_drop_up.svg000066400000000000000000000002711420147000300337770ustar00rootroot00000000000000 ic_chevron_left_black_24px.svg000066400000000000000000000003521420147000300355250ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg ic_chevron_right_black_24px.svg000066400000000000000000000003531420147000300357110ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/idea.svg000066400000000000000000000374061420147000300313560ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/instagram.svg000066400000000000000000000033301420147000300324260ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/javascript.svg000066400000000000000000000044561420147000300326210ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/json.svg000066400000000000000000000074651420147000300314270ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/link-ext.svg000066400000000000000000000016161420147000300322010ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/link-permalink.svg000066400000000000000000000006211420147000300333560ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/md.svg000066400000000000000000000004701420147000300310430ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/mdsolid.svg000066400000000000000000000014771420147000300321060ustar00rootroot00000000000000 Svg Vector Icons : http://www.onlinewebfonts.com/icon hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/newlogo.svg000066400000000000000000000415141420147000300321210ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/sass.svg000066400000000000000000000054261420147000300314220ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/search.svg000066400000000000000000000022011420147000300317020ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/twitter.svg000066400000000000000000000026221420147000300321460ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/website.svg000066400000000000000000000120241420147000300321030ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/windows.svg000066400000000000000000000003121420147000300321300ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/svg/yaml.svg000066400000000000000000000022741420147000300314110ustar00rootroot00000000000000iconhugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/tags.html000066400000000000000000000020001420147000300307360ustar00rootroot00000000000000{{ $currentPageUrl := .RelPermalink }} {{ if and .Params.tags .Site.Taxonomies.tags }} {{ $name := index .Params.tags 0 }} {{ $name := $name | urlize }} {{ $tags := index .Site.Taxonomies.tags $name }}
    {{end}} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/partials/toc.html000066400000000000000000000010641420147000300305760ustar00rootroot00000000000000 hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/robots.txt000066400000000000000000000003161420147000300273540ustar00rootroot00000000000000User-agent: * # robotstxt.org - if ENV production variable is false robots will be disallowed. {{ if eq (getenv "HUGO_ENV") "production" }} Disallow: admin/ Disallow: {{ else }} Disallow: / {{ end }} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/000077500000000000000000000000001420147000300274605ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/articlelist.html000066400000000000000000000006471420147000300326740ustar00rootroot00000000000000 {{ range $ind, $art := $.Site.Data.articles.article }} {{ end }}
    Title Author Date
    {{$art.title | markdownify }} {{ $art.author | markdownify }} {{ $art.date }}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/code-toggle.html000066400000000000000000000022571420147000300325450ustar00rootroot00000000000000{{ $langs := (slice "yaml" "toml" "json") }}
    {{- with .Get "file" -}}
    {{ . }}.
    {{- end -}} {{ range $langs }}   {{ end }}
    {{ range $langs }}
    {{ highlight ($.Inner | transform.Remarshal . | safeHTML) . ""}}
    {{ if ne ($.Get "copy") "false" }} {{/* Functionality located within filesaver.js The copy here is located in the css with .copy class so it can be replaced with JS on success */}} {{end}} {{ end }}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/code.html000066400000000000000000000013451420147000300312630ustar00rootroot00000000000000
    {{- with .Get "file" -}}
    {{.}}
    {{- end -}} {{ if ne (.Get "copy") "false" }} {{/* Functionality located within filesaver.js The copy here is located in the css with .copy class so it can be replaced with JS on success */}} {{end}}
    {{- .Inner -}}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/datatable.html000066400000000000000000000006461420147000300322750ustar00rootroot00000000000000 {{ range $ind, $art := $.Site.Data.articles.article }} {{ end }}
    Title Author Date
    {{$art.title | markdownify }} {{ $art.author | markdownify }} {{ $art.date }}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/directoryindex.html000066400000000000000000000005141420147000300334020ustar00rootroot00000000000000{{- $pathURL := .Get "pathURL" -}} {{- $path := .Get "path" -}} {{- $files := readDir $path -}} {{- range $files }} {{- end }}
    Size in bytes Name
    {{ .Size }} {{ .Name }}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/docfile.html000066400000000000000000000011701420147000300317520ustar00rootroot00000000000000{{ $file := .Get 0}} {{ $filepath := $file }} {{ $syntax := index (split $file ".") 1 }} {{ $syntaxoverride := eq (len .Params) 2 }}
    {{$filepath}}
    {{- readFile $file -}}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/exfile.html000066400000000000000000000016331420147000300316250ustar00rootroot00000000000000{{ $file := .Get 0}} {{ $filepath := replace $file "static/" ""}} {{ $syntax := index (split $file ".") 1 }} {{ $syntaxoverride := eq (len .Params) 2 }}
    {{$filepath}}
    {{- readFile $file -}}
    Source
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/exfm.html000066400000000000000000000016451420147000300313130ustar00rootroot00000000000000 {{ $file := .Get 0}} {{ $filepath := replace $file "static/" ""}} {{ $syntax := index (split $file ".") 1 }} {{ $syntaxoverride := eq (len .Params) 2 }}
    {{$filepath}}
    {{- readFile $file -}}
    Source
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/gh.html000066400000000000000000000005141420147000300307440ustar00rootroot00000000000000{{ range .Params }} {{ if eq (substr . 0 1) "@" }} {{ . }} {{ else if eq (substr . 0 2) "0x" }} {{ substr . 2 6 }} {{ else }} #{{ . }} {{ end }} {{ end }}hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/ghrepo.html000066400000000000000000000001101420147000300316220ustar00rootroot00000000000000GitHub repositoryhugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/nohighlight.html000066400000000000000000000000711420147000300326500ustar00rootroot00000000000000
    {{ .Inner }}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/note.html000066400000000000000000000006021420147000300313110ustar00rootroot00000000000000{{ $_hugo_config := `{ "version": 1 }` }} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/output.html000066400000000000000000000004761420147000300317150ustar00rootroot00000000000000{{$file := .Get "file"}} {{$icon := index (split $file ".") 1 }}
    {{$file}}
    {{- .Inner -}}
    hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/readfile.html000066400000000000000000000002431420147000300321200ustar00rootroot00000000000000{{$file := .Get "file"}} {{- if eq (.Get "markdown") "true" -}} {{- $file | readFile | markdownify -}} {{- else -}} {{ $file | readFile | safeHTML }} {{- end -}}hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/tip.html000066400000000000000000000005501420147000300311420ustar00rootroot00000000000000{{ $_hugo_config := `{ "version": 1 }` }} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/warning.html000066400000000000000000000005771420147000300320240ustar00rootroot00000000000000{{ $_hugo_config := `{ "version": 1 }` }} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/shortcodes/yt.html000066400000000000000000000010641420147000300310030ustar00rootroot00000000000000
    {{if (.Get "thumbnail")}}
    {{else}}
    {{end}}
    {{ if (.Get "description") }}
    {{ .Get "description" | markdownify }}
    {{ end }}hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/showcase/000077500000000000000000000000001420147000300271175ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/showcase/list.html000066400000000000000000000043231420147000300307620ustar00rootroot00000000000000{{ define "main" }}

    {{ .Title }}

    {{ .Content }}
    {{ range (.Paginate (.Pages | shuffle ) 20).Pages }} {{template "showcase_items" .}} {{ end }}
    The Showcase articles are copyrighted by their respective content authors. Any open source license will be attached.
    {{ end }} {{define "showcase_items"}}
    {{ $img := (.Resources.ByType "image").GetMatch "*featured*" }} {{ with $img }} {{ $big := .Fill "1024x512 top" }} {{ $small := $big.Resize "512x" }} {{end}}
    {{/* the margin aligns to the bottom */}}

    {{- .Title -}}

    {{end}} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/layouts/showcase/single.html000066400000000000000000000064451420147000300312770ustar00rootroot00000000000000{{ define "title" }} Showcase: {{ .Title }} {{ end }} {{ define "main" }}
    {{template "sc-details" .}}
    {{template "sc-main-column" .}}
    {{/* bottom row */}} Last Update: {{ .Lastmod.Format "January 2, 2006" }}
    {{ partial "page-edit.html" . }}
    The Showcase articles are copyright the content authors. Any open source license will be attached.
    {{ end }} {{define "sc-main-column"}} {{ $img := (.Resources.ByType "image").GetMatch "*featured*" }} {{ with $img }} {{ $big := .Fill "1024x512 top" }} {{ $small := $big.Resize "512x" }} {{ $img.Title }} {{ end }} {{end}} {{define "sc-details"}} {{end}} {{define "sc-navigation"}} {{$section := where .Site.RegularPages "Section" .Section}} {{$number_of_entries := $section | len}} {{end}} hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/package.json000066400000000000000000000022511420147000300260710ustar00rootroot00000000000000{ "name": "gohugo-default-styles", "version": "1.1.0", "description": "Default Theme for Hugo Sites", "main": "index.js", "homepage": "https://gohugo.io/", "bugs": { "url": "https://github.com/gohugoio/gohugoioTheme/issues" }, "repository": { "type": "git", "url": "git+https://github.com/gohugoio/gohugoioTheme.git" }, "author": "budparr", "license": "MIT", "scripts": { "build": "NODE_ENV=production webpack", "build-dev": "NODE_ENV=development webpack --progress --watch", "start": "npm run build-dev" }, "devDependencies": { "clean-webpack-plugin": "^1.0.0", "clipboard": "^2.0.4", "css-loader": "^4.3.0", "docsearch.js": "^2.6.1", "file-loader": "^2.0.0", "glob-all": "^3.1.0", "highlight.js": "^9.13.1", "lazysizes": "^5.2.1", "mini-css-extract-plugin": "^0.4.4", "postcss": "^7.0.36", "postcss-cssnext": "^3.1.0", "postcss-import": "^12.0.1", "postcss-loader": "^3.0.0", "purgecss-webpack-plugin": "^1.3.1", "scrolldir": "^1.4.0", "tachyons": "^4.7.0", "typeface-muli": "0.0.54", "webpack": "^4.44.1", "webpack-command": "^0.4.2" }, "dependencies": {} } hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/static/000077500000000000000000000000001420147000300250725ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/static/android-chrome-144x144.png000066400000000000000000000166741420147000300314400ustar00rootroot00000000000000PNG  IHDRFgAMA a cHRMz&u0`:pQ<bKGDtIME]]IDATxYpyHWM[^3=3In%g*˭8=x_Sc[y/qblj]S+\ۙxZJWHq  ($@wXjO?lٲW"{=l<b'>## Pp75` 7G#v`:mF-DGaXtH47i=@m`C{Ɇ.q)(OS'h@ftЀ#ҡh c8:8N.gQ צV< 5}PmR\ϟ>5W)2 G$C 6'Ý=ZQNh,dHcQCN vS kt s ?8z8DVO#F4њ?:ush+OF ^$Sd.R"K.ޫڧ_̕frHk:Hh9, "~z#o-F^wR. />]x[H m5cpA:stpt>u8"GJ3_w_ԖԱA:iz{%v5rIT>_MtjKa;7/~(~pU){?wm# P/mD?};saCEYXC(܂H,`d=8E2r5 ԫUXr,~GJ}|QyBiȮka9][Ț/2sʊ Ӊ£pt :2%Ӑ$ɪi?;a7gz&"Cb z:86tLsW(Nc`YP<>>+Gb xlZ5*nWK? 3yj @͂pm^|Qmkմ!:C òփhB6T;^\qiE,6 יǩs?_f CAyc#E#p8]@$dSidIk5P8-?x8]ޓY9ZWwm2z-?Dސ;Lf$U@(Fxl 4GK%ZL|t,[Vrw.W==Aw* $gk]k7=^טw@ˊi90 @HAPMCXB*@1,lkgoݼV#Z1u]6ҕJ[3<.;h$`DW@UU2YqT-,PּO|઼КRk佶YL>f&>i$N!֕F1<,?WpE$YYMA׭+pM:(뭙ҿ,OkpHϣ"t*? :|+)7\"3C90"c1^O ]MTmE5(E*+Q_])8JhoR4&<ƍEʪ<7* U>;,? z+?W5"|x|2R =(}z{e@{Qy=Gw_*q$d~ZNB{凡08;ഋ(\z DJylާ?>$?&,NG=A趀ggdBYϝ2s2{;QP8].F"嶰_Ez$4$ѲMrh/3!o~?Mh1D;ygWNn޾]+˱B  @mvu WT;,YD6"Rxlb,ҜUrweD֗WJ?+F;vڝ 궧y0>qx+D~Xo7|?6}.wSv 9$"B@o qH o# <~{<(rH(Fhc^ZG߼}_tHRx* PUr^ UFc^Fw0*r dm#( T/ofZi[z\>+PJ~OAAX0N Jw;.JxL<  XJ0V??"fmm:5;C҉!mÆaaY?ֲH}O]s"ĻJb=ﷆP7)l7aHϫ.ލB#Q86 E)XA(w(l2jba5"ve^]ר`zZ!,p$x n12N#H$MA-jt~C6D!J)҃y&@tl 㓇LkǃɩS$߬t%T{ѷ-miYl׾ހщ1A6щ1xuc#OW  `3ݽ"ulY+JhveuE X\5^XwiU=JQ a@mj/8=›l -SeJ6@LȖ)2% [dd˔ll -SeJG gL@I'Z ky::,i +.9`'@.^hy [Ȗ)2% [dd˔ll -SeJ6@LȖ)RFLyZb0jM@eRqpoi8.g{}FT Xl:]Sq*YH5&}&D2% [dd˔ll -SeJ6@LȖ)2% [dd˔ll -SeJ6@LȖ)2Dkn?Qo8@B?["TuH42kд>NcEy{H@O5m V ^C>ÿ{S=C) V^F5#a,kgETUE.Akh>t 5^D =G!Et{ !6HfE(( H(f󠚆^i-{;(\ JdQ.F~Ej*2$4YnR~_t"5ZEe>J@ R+q9cE#p86H݊Ȓl*LbZ T-VZY;wJmţ-AVʋȯ!:?vjb.Jb Ҿih+BQh0;KҚPfOdw%~ @rZp<>sobΏZ7}NXB:@a- UUMEơ ^كd4e{8]s{-TIPhl*rP4\{3D@U~!@MJ`!R(0ZzA:2IdS)Hd~iţ.߹PNfѸ(It(6T̊wAv+cΫN̔-Hs "Q#`MaP 7Z3.B2r5U+ ! Ζcu\}=o-߄4??9~ψqc0e??;QQȫ:Lfe |rv0m?m7˸(Z"!(E1ʋWȬ&!KU 1UJ7* tG K9BMw'sg:/.* PˣZ*c((+B+ SOIw%k)ȣPHR  = 5Y -I'Kz- U&d6j| FtlH2$h 8 ZlbKulT~ۗ1X7zRE7ש%2q\,/0 \n7P~XyLZ ;Sѣ Ҽ( F7? ؀@FM@:DOLH @)h y|="`$IVs:tAe!B@)P*+ HCPr2,/ݼ\/JA<6S< %[)CR1CѠ:P{2#U^_,}&\+Qa-J`$H,m55j*҉r :S*G_<8/ޮ{h4~$]E=uB-℘WoF_傜¸M]&HR|p`}GB K҉U_D1̭"@rӓ_׻8#/(NdMQ8ңN;<뾧8~㏍z}ӧ\sspp< cf%]g9ͶRPB!0O"MSX!OR2_~>h|`P7c=NOc}HƵ!A $VOO9qht蠠`YPѱ<~޴xln`j(CLP~hv[Sq#8Fs^+՗")\刔Q/&j(PW!0Cиqj\,v5VwKQ(N.A2*`*2^ɢjte,OziMHUZFĥEEx m#ֲj 2UjUKҊ|7 Q NWfvHk,6Қ71uhevSP0𯷍0 cHQ .rH,9AL姷ϕ?_>%/Qѥ}vXe2@{'c c譇΋OEnh!˱nEǜ?jjtGc+XqP}oiyz@VE#`8[+}tvI>Tbf"((8`8plQMCZC&\f`}JTGw^|zaɴs؍?ңt:4]Zsr}3C~P\nx>܍JXR(A떀À/&\ l?-Zԋ:iJE<Шo"Xu!= .젵pavcKVjO{ ogf r&Oh QAt3Ӛwuo _X\9FA hɫ&y|vG2 Ni9۟>e$Ư]?dUYmĻ.ȏ`>GUz܇ڦ,NGCTxM]y{/9.$@ᨘ(oϔn9vpӕc4)?X}R&" C O= $,(tCB@Yw|ɴIX!߳ڷ,bLki&y,W_zTa+"ZhkOT\<_ :^U;龎:~@d, 7g&/-z=w_pHy_vIGԡ9Hk} .hs}voDG%tEXtdate:create2017-02-21T08:06:30+01:00pn%tEXtdate:modify2017-02-21T08:06:30+01:0038WzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/static/android-chrome-192x192.png000066400000000000000000000240301420147000300314270ustar00rootroot00000000000000PNG  IHDRRlgAMA a cHRMz&u0`:pQ<bKGDtIME]&IDATxwם翷ADQ,JԾyi;I'$ӝg潏Ϝ3O/:O4/st$vH.JBR\@RC"RR HOB۲{{0 ` d/0;E?n?}] %0X_fhK0t&o=<h;?3=&.LlFfb(gB&ioiM+o @w˿{$ȏ8PP.0] Mv |A/A{wYE;A(l0& Z>>es]aA.Zd<ߜj}_NƝ?rKEP)*er{9R|B0fVtC9vPWTӼM޿{v"6`FZ6a{mlDc+O۾)PP% & ~yDK*2t!`A0 |zc;vww?FD-ljag򿉝>0ah yß YWQ^ӝꍹ{/g4 l+ͳy1 L&(p5IqRz~T~op$H3كkW]0"C洈Py9ݱO#/a('~!shO%B˿99 X}/=Fc`,`_O'?rӔRQ'!J٦>\{xF0>( anX{lkn;BI^Ʃ-W{ uW7BTvj=+O7gn&+@QlP3_`5γgo_* uT&޿srOtAj! J{7sGgw1ځx^<8ZPO~喰-2 Z/8|Z]g f_W IH+㘭bs:Ĵ4_q3ǁ:9hP̺O'>ly0[ERZ/PYsϟt7~\@6e>! qkͩu=Uiecnw(&RB& I7aݯ~P):[K|r)j؞^pu~?ˎ7ynkRP0Bp8S MKH#JAKElM3 WߗJ?s|G  @ E#rW>|臑;B&)(G o(CMӐd#͂jr!,Մ_3ɟϋOEVq GϷGaIێ7 t.FG ΁!eDʥ2@Bm*Wmj҇Xl`^?84@[J |Q+*U';aG0FhtvG-~r==*U$cH'U% e'|%}0Vɗ  YR[Ł@+L=wK C?)ٿNT [֤y cp{= J)J"kQRiڋRG̿#s"#-:𶊾@kO&sG5 F Z~K!^;6- `_O?PΑL?}tpn1CaB( kQEDŕʿZQ}7Z_*UIe 7fzU=Ϸ]Vvl{~#VǑ!U=irʍHმWJ!*ElE9w~yv%/&Q8ݮ56JH#JC*8+& ݻ$ݬyH̾U\TUu_:ywz`_x^qxۥ^yP堩Z/ڦPm}Wϟ<_A*z&VOY /[M/P?}:((!p]"n;Я&#J!]GT[M!lo^*:1I,@mM߸ډ-OExRjvD Á`$6 aVZ#O@V{6%H%œbcqGmSK.5ךN ?tK9jBo v!4:p] F8YI$\_GTַkZ=#N)ٕ{aw9`VivMv/HwHn[u@*ѨmM݆pB*UŐI$Pjp )f'*u l:V 8gof=?/ Z~ʚ;y~b>:L$-nX=^嶊nQ[?#T;wl27E{׋(| a(|:* EۦrJMԖC}:UBxn/2;Aw;Z廾ŷ}xRXnS&.'B##m Ro֤2r@owb/mA[w$zqumI Cfy~'Jz DJlC.V>=yozCpm8m41mJMv_:=px X<?c#P5tE|iUڝ.muQ?v"jv;(wyܺ}axMR+3~7n +oooL{Q.vQPwB u%Op$jVj(al: tԧ1os)%hHxoY.F~__fMv6} ndHH␤*)ڶ&{GsoV"h)jg6fc8'X Fhl.O[<NN k:WvG !LAQ;NQp럖T5#py<T&7Goz!@Ec7!ip JkGD,(np$.'`tByG ő![`!L| 0~t D][y~aǎnET!Dx}`[}V`N6,nB<^"c 7OYcp0N u VAQpqhMK@@C-οUt <6`$ fR،h &vՅ__F|cm&vyV_ AN)7@0 !z ul^mX dh ca` 4L 100&@h ca` 4L 100&@h ca` 4L 100>@1;wh J|MF!RhWIjRm/cjR 5I_$ ln9$ dx@4b1T+ Z AӴq%C@P.Y3@e/\,uk(xtt2 #GtGCSB@TJ%ĖWI=1:T HǓ(`(ag"8*!H ToЉ.-Rsy&!PUt(ʅ4vocn3ۤ]?Rr_ PQ) <6 BiJ<(,TEKc#~w9rBIVsh$RX|4稖"V(K\s,>G&h]h\PB=$wm33>\ӹuc%n}* Bcal/Zl2dtr’B8-WsbZNPTV>Jy_jv;, @Jg ȥR7`~R,(fPgx>LЬ7>'ŏfjc< -`#Tr^vj㏀@UTbqr9#a tԯp%($ $3}_. AZ"!OV]6MCZ}˥S;PV$j Ry3K(Ԫb˫gA(A@?u> T=jJgA4f"+$HP)@iۚ;~,QKm}~%/YPslhyRoxp4 cxtuY*4Kqwhv2Z\?t(NzԐhB.ZlN#<8ZqjمgKFq((C zQCW!_qƁfƠ[(~$>tD>pZQ"ΠT,"0<(\/AvƻT4{_b :ܓtGQY WNWt|@zy0ꀖi)=q^z7hH)YYt7ml2z |<_Gn9prW R>?ѿhq6f'X"0$";Q~>Q[YKKDwXtS-!"D !(E1k Ӛ>ɡTo~r_J7c3BЃݟVGT蹿QЋc;g^,{!kɧ̵GW#)%N۫ȍPP6!FGpv]WKe$c$k5 \)\?l23<ڗu7X;14Y$}7'r>DSKե(g Bۥfbacpy\ư\: Ԕ_^jo_^+)5N#Y}lA#3^C D賁1#:5f7ы=׎-/JBXm3x|^۵aSNeFQA<8JbqRulzaF?hY/a3W|;J{^W4 uo oRsxIQLHjs*lVB_$I(dUl"D]M2b ' 6l|˹?_.oG M=?~}]a60@ਿOI nFolq,~z-l`6lNPx1L\~vly QxڍFTUC!Erm\o 7gG eoiyA1ձ$7OEEv4O< ɳ]L]x.k"] Fhl.GwGE$1d)(ba RcpMHw]#i,p- k&S}`8-ReS>yK/T).f2Z>xA} `k6xR=5gr犷,)8@8ǫfm[@nS .%hxifqy4{+^PBh\?0f !h.sH~^#^E "4:Y۴,HǐKd1SkGg7Y*7~_@365ZZ`}Ҽ`bbvm*.gtRlzaS& P*gώKbfA냂:;xfP^ըj}}v!46PM|rMO_R*t#_ޟ-V|{kk}6lF%- Ņه+/-.;|*xivmGM6OY-߇ y~šNoΝ~(dt4V؃œXPU󆟓/_O5EZ  a8._@U5TKed)di=/6ZZH>O l,p{j_s8`tV+cǙ󏽯,UlDM_I( d3x逺td9e^yTg_4E1,ښ~~ɁA-m`L^28om^ꝯf_ ښ}m_&^@Wl i2M,/{~u2<)pT!p PDTÕN>[=>}Ey~ɡ.mfy[斴‰g}hҶi7!(Gx@Zzz\q|g<߼v=γ:t>0ҢڦnJǓΫg%m U7M<,ܼr8!YۚF7pҝa`ǴU:u(oEd;-,U}uEv,};ٮCb6ofǶ(M^2OsN9n[NߕU[H/֕! ez&#w!̴i03Dg8/.shzpDҍ57Ic{<>nmS7/3Nx/ܐfi8ZviGśf+7;)B0c 7^!.y_=sjv́fCie:wL]ݫ}aٚvXl9ґrKV*v5xG}=[9:WJLmy~fƵwc`g3-ڦ+G||~B/)c4+n: &mfg>z>/x+BӮyp(8t֙(Vs)k&&y]l&5?\8~mO_h 濚Tk0`,Y,Ϸ&.b0Pl߫eXw"='[%tEXtdate:create2017-02-21T08:06:30+01:00pn%tEXtdate:modify2017-02-21T08:06:30+01:0038WzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/static/android-chrome-256x256.png000066400000000000000000000353601420147000300314410ustar00rootroot00000000000000PNG  IHDR\rfgAMA a cHRMz&u0`:pQ<bKGDtIME]9IDATxYwcǕ8#rdLKJ dU\.U]]^ G}ݫv.]nٖ풥T*I )> D$H?#)y8;v@0{I߀`|L&7y? l.c 1Bp00la.Bo /f `0 i"}_ A3l^C273|UA8=Nߟm"0"gxH[z9y7|Ik$ s(M)k'C҆k66Ġ_D5^\8ʑIݰ< 7־H8C<0N`srIo\GO`7;+ݩ%Q {bY0e(CTwKwOK X)l57XG?X9c?bA@ !cw֗j[|_[ Hw-awGAO%[?T(ʊ܆+^ 5x!au WZ;wY7ɦ˲C6؞?`@-b}!~rgA/6x!݈+}'?WߜnI cO 2ڊh=FZ^!.@0A61|`OhS1#C2| @jo|©L;}Gs F#2Crr-|ǿz'Q( !A>uK<VR]hBBA@ yh'r\]0fvk 5tXXd4нbPpjϿiWB Ҋ'1]}ވ._վ uƜ oQpJzM3in70>ҁ / Vc1u6~n=Ҋ!cC $6YoM}~ /?[4r?`ɧ_ :&l- Owz\|y <2ݍݶ/7\>=ͤUφpPk-`e]mcp!_vS޵޸w'ѯ~/ơKC(bp93rAK)ky&ʙDr+Ϟ~zD㾝R+x9ېDlzF.t_F_~ ٱ< KZ-;*X0${IuG[z׾ho1 :c`zz>@8D.!P91~W/0mT %Q9Smh2{v)󓵷(2LĶ&̬LE4Y.ſCM>/H̥K%|=1B)Ga= 7 Axx3V/fu j[.0s] s%L|m:e$< 2iC!H3sogta j Lbm{"HtJKgWϗǗ*DZx/vKJ6}f.c /$9 Mz>pycQPYpBgYlR *8*IRKk%rӑ/;iů ]fv;=^ }[qq|XاC,1~:B`&J˲@SuZyyJ:Vrq<󩍒=:\gه奧cA!B(R Fà!1U2Upl3*HRZ_ ?X9owN4o6$]}LO1{[4BWBKs+-۞~>?(|s/)2&aH)vh5`tY\ g\_ uO;J#b/XmSnXbaS]6`{bl>MK&KCONABq=R>L4ȼ7k?*Ly79knpF[ʻwv}(p{p,|pA)hV(gQ-`&ܷ2G@!QY*{'Okӌ&=4WwsɌT]␸>|ɲ`$x:p<I? pl&PT`6^lM [/Ư/"f4 M݁n>z^^]ҍؿ?O.<<` Ra>|H? R _0`8 UU02 +kY5JkNI^WUUܻ<0݊'s=z^뱲WC9DWC,@4?p0oEgYoˣT(jyjY@iW4F)j<{9hu͌]}\!pKyGbڞwQDTp-ӝvR8fb.rF1Ƞp(Ud韯f\PKx@f4߆!z3>ف WK[[_|Em=JǢSF#PT[Q-LrlRsz{Iߕܗώ,? {{!}΂CYIA[MM8u_8yQvt n1|1Gkiε?<^C}uzu @eӤ'^gߝk wA1$A۟(gJuTeX 3f2G/']qr-iFw_r۹Z˷פ>ш%nˆS$S{nqPD1CVcyX.@Ͽ?_ Uӌ!#Mfͺl:s*߈UoDM{ Jt]^,0msry4u0A‘HFd ؇l}*gĚڻ! 3O;~( EP^{&j2j sAP&[v8` !f}-~f鷑vݫww`OZ{g~=/^VXUG;>/vBRsbPwp^OI '8ӧeHS6"* QS45dbh|$!#/!O8#0UxYeAHwo'lv@jv5@u$iRv\{# Q:Sp'?xC][p=NڝYQRF(Pfa/;స[ȵb{g}w{jѮ0nїG[ٹNCR$X:wsGCusonj EPsNsGc$ҐTogyvtlT'M-%*iȤ2`R(4}lE"H̥FE޾`t& _0C'#ERcB9 (mSa ]{A^@O?W((ӕeBaR 1BP.Q\uVvL\[ ^^KU ( lkēIDSIh>0|Č$YBb.`8r.b>f/e[ ׌H_:sH=ޝuh4@0B0|x!}ʹ<ʅV/\?U ^c<;mDb1$ݮgX̽_6 /C4+nÁ,'}'!ecHSV)+CI'R# J0zDP a3` 0BF@0f! #@ a3` 0BF@0f! #@ a3`=Ntr22.Zl6v-uRhw#!^X?{;zNϧLB%LFi \jB5*0οt`$ tZ i3` 0BF@0f! #@ a3` 0BF@0f! #@ a3` 0BF@0f! #@ a3` 0BF@0f! #@ aF8瓾`(Yma!`09 mONfjL[-!Bڭ,˜ iWg`0^4ILUTBm,!QMTK%0`:<թFzvR@sh듾16y8C!C1S_`ͣ?ΩNCٞ 062Osx:IK /c(fsXߜ:;۫w!0Z-=yVx:(J)DPP *ʅ,z6 `PXZjDTZ" FR.R!9ͶF%}74zFZx:h2YQIJ@0::mY( (fshj`7:Wlj$(=M^ctk ZMw&N#JbY #WB6Z۴` jKmwctQWtY!#1?(й; v@gYYGTi?wl۶0&ؑ?,8s RQP t! zCsnvP 0yCn=mlRZ0 gݔQc9V`x' 08bm}r{9̿N PTl4ŐZw  !`Y"ATc 벹jvШVϬZ,ɭ_=>BckS^HvFU U$չY@+~ye۷/+G%:(W'SЃH"@ׁ[^Ep jZ<6r':{'09팥<,Mߝn#v1j=|ǧk\uml@n8w?}'J(4: 0H5Xuȓ|Ʉ Z62)z;Kö\CrB/ (rh5KA{ؾqBz*=u lxNt=K!8~G ]:clvf rN6i$,IwOBNظ;?ZB6z 8+=PJYSw*OҭW֮G\co%@`WO˗[ou=!~gjyY)Lט0>5nѨTNB!k*0頓c;j2ϟ#A<7~HX33g=r^/b&UBHkpgyЋ{{zwLK,Uf=o6/>>D=8+63wUh6 bb$|(;22V֩+h;:5|7XOl3R^ƌ7tp/`+st^_tVSLM0 AwYZہ*5uCP-ֱ칛cYu _!+DՏ^vi ^{g5W^2h;uEF՟y%OsƂd~?=9y~i*RhS(FVH! o`P ۲P)QPv'PՕ'[+[O%U5fk5A9{&u_{glW.*QesL-4B23Ao}c16&$I ل `V.#)uMp;dg}B W.6JϩLxu3ߞf` qg ,TɨYy=iVYm:p&$t:h7W BV5QlN(ڍVڋf#|DeOO+zBaTyofk^vFbKͼ[=Ww)ZƝ]^_>ܷ-? ^66nqfF4B<8tLMYϡjvzO>w@z.]9Vqdv9׹LzgVmwmwG٨uzow{IpG4P<]~>ιO5I(!gnk[ LlmAWL \tˎ)˂AcnjzMAay{z9ji*B}off^Q&"Z/f/ycuKr6WMIő\G eǻpѨՑ_͠R*±L) 3_>W䘹 J6~6=BП+ ^o`3!R\u'ooD_ 5g&,MՐO#>x'tv, , l큀P8STsM;,}ioݔ~4.cIo *Y 8vt..̍dyy%ɇlFVCR!תp龛+`u18ZJJ{`K$P 3aTM*^5׽ ˬ6Sp!{jeteUv7$H᠓4FF9dE(np 6֞ H,jok?=8m~]ߓf˂m;|yUi_[ ziY 2B0‰vsnPB1CZuȬ@B[g{VYϨ${L iŀO xgY@@8Eb~Hx:u4*U2먖˰,0| Y꣇'Gǭ0:R:+&l. ^2>G4h6wWPU'{leM3Y m3mPDTdޫYR?oߪLs' C, =A˂Aل/ydtQM-ŅGCm9lA$ ߏb7@)lD1Ga=V ,>mYիG72gp37s\ݮ<[U ozV貋]KmNe7n^_Nf~n9kNL?CY vVL8|j#~;KJChpȲh"<O;ۮ7[ˠ\xcxBD{k=|i8Vʜ9}wPGީqդo` $a(e;~;q=Rv >$ӈSP5me2]@i=zv #j= 7nk]rmgA ßuc6Ō)eG8ƍәIMfԥ( CH.#A AFμ# 0CW/6h4pK=p;8xf9oމ^C{eY);Htˎ=t3^2452Eϔ麷H]/^yxx@e/o70JƔV/:wWBc5%%PPv p0phx-;~Y%h7(es(f0̶ GU YK6nҐZĶǴR{_$#&kGe-'tuN7VPp*e]_"~~+]vVmTٶՆN ys%-It&{ȩK@UU1c1$Eqp]}DznP-P-`'~[eRy~x3m ж^oATI?l9>^{>sv~1Ǒ(|E{ћqXeMѐ@@%^5ndrdz3ߊ6˂ۖo[5Ň 39i]\y^(S^ CK;9Wlw wGɤlj`jC@xtĊvZϐ&!pOmiNB%v0lWsb?$3,0xmiU;H=yabQ?BlxX3 Z:ѸmaQ2eiŃN3ұQ_0# Krr!98W8~_D3_zBuY@@ IԮExקVOKw[>^!;MW6؂]n?r}UėnH{qb%ESvwe S|x2 "ȰL?B`i/x0/܈^:Ob~&{^ BO>P< WHncO{VUZ+0Cr;7%bSsӎ=Mr[fz|gk'Ch0"}w Fcf^pIx_)ɡ); ĬfܼܸBn:ۀ` ϸFa; QHa%>[iǃ Tr*AH*|5Zp l~!<=_ٶ{D^t^=kӠnݖ٤ӥ?gdY.o3x:"xW܃铏EaڤҊeP8 1Vgo^;YO{#w!#f/}_ .=*s:͈@mgwi:_ӟ'!ӊSkMJ| E3SE:fP_jPP ׮\|{ٸnIßۿŷY&pfno'|dz!GݖL4[+Nnm?&*Bf}ZqǗKG* #ԁW@`$ϞkBAX{, 쭶 VBl['F>i2I#RZw@#2/ܧgZcG^7w7] 3Cvܿ[!:%-#,/_x>Ih nzxڼYǪ[o}o_oCFcVi/Ds {B]~pwَ8!,OG-~V:JBkY;.QqL1w/0I88)DPr-KE=j̝"[^%I;Hߝbxu+$ݯ{=6mս3|}w !F\v{u\V 6 @2~!迺?#cCL r{ _lM!B<KKޓ>_[: q6H+3$e@'os?v-4}~@`'5?2 :Do7? q+W_"` `{!5zsițu1aӈ)f~A^#plnb?!Š%tEXtdate:create2017-02-21T08:06:30+01:00pn%tEXtdate:modify2017-02-21T08:06:30+01:0038WzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/static/android-chrome-36x36.png000066400000000000000000000030701420147000300312620ustar00rootroot00000000000000PNG  IHDR$$hgAMA a cHRMz&u0`:pQ<4PLTEfffffffff+q x{Gkwz{ffffffuz{z"s y{{5o wz{~Mjvz{)qy{fffz{fff z{fff#y#yfff#w{Dlx{ffffffm_g+r y{ffffffySj tzffffffDmvzDlffffffhdf5px{ffffffo\h(r y{(rfffffffffLkvzufffffffffzz| { $95>=}-:<{)ZyvOVxR("8;:~,;w49}BE~DG9~-%:+aS\X~//7 ':|AWtRNSj D,vW=R cgh`-+h $;(HH,Z!3oo %@0PbKGDjtIME];IDAT8c`fV66VfF|-<> &:3:<4}1B|KMXBJw2!H% $s|?T3&{B`Z& i{懍WwfU̍ a~\T۾nģ%bD _lXLj@7mHfA6H.jm>_;] mhuI=~/ UUߗ"0B OFpV&K;Ӡv^J()%rŕU'\FRP? nG3V& `ȳ%£8½)@0<+y2irmT> N.K; UGx֞)q4s?AJ:H,P$B.aine:^uЁF%Tl5߷$&yJh$&<ߙk}mz7ȁe{t0=9\'{?X߀D(Es䬕(B A V{zhP^qJJen7 @2>Ƙw0ȧ'^e6c48@at=@=48jM3;CHv=ep2uw{\%TddKP6dCH7I 8!LC{zhPmU94% ŷ<<P|) A\Xdm9P­;H)LaؖE!B]~I˶ Ys +% ǻ% KdWHbH˲- 2{u3Ry2kzm,bDX2%RoK>H:,z+KFrkߺ)%_@F:e4]ˁ_}yid)%G4 n/ΠnB3W = +,E.i f)l]=Qtʜ.U@- iqLC/ʾ_Q1M a;{B&IP 3@TBJ隫X 76ߘY׀|7a?(_ҁ0i'.JN:s[CۓݺVJ;50BGӵo-%OE`(uu~8"@TH~eע9 u36 :@m!?z]F%Z#Zld̏fO_p󂭒@޹.oMVFSǮ.GDuk ۗd$:_}0iXOS\_;x}vN+pFLgVUiFD$zbwu%K( E"'R ht#mrDfnrq㚍^uyڛ&;AJV}w=5cWЮE~VV#۰rzݙ`@'qӥU?TkާN\ 4M)K=jxDW7h-e.n\7f+r׮=|3-Wlg9jOqMO}?6TQҽ0 9% "4J5Εn]Lz@2ۉ:˪xqĺ^l۟>g1l6LggNxF.jN9ٶmߊwS"?xK)|^3kٔӱ]35Y]ߛv1`gJ8>;]Ի?a {' ^)[(D̫Wv{)L'~ޭpC)TVNMߏjʄ?I] s75}qՐ}gV*XnX`5,c@"Ă):e+sӵ3 ZLg^}î\O~;!?OI܈9;3Y?@Muv|ɺm NT5pQ{>oy^m 0U3;P(gDi㌘]y˞#g%tEXtdate:create2017-02-21T08:06:30+01:00pn%tEXtdate:modify2017-02-21T08:06:30+01:0038WzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/static/android-chrome-96x96.png000066400000000000000000000112131420147000300312740ustar00rootroot00000000000000PNG  IHDR``w8gAMA a cHRMz&u0`:pQ<bKGDtIME],IDATx]koWz~p83)Ȳ_e;786n l|跢c 4@"@AM4ms٤ĖDJH:3pp$eDQ"`9y3 裏>H'`o5WR3 更s'*Lelj0I0'g 30pTjQI"z:g` !=}o\ E㛻_yRD($º2z"|kp';_^ ?$R5Zh4޽t@~>.@&:V =A@[r@% Lh륑5g/cFa ">E.av%މKo_7m燎@n 4Nu=3&TTp=``0Z BX^J"Aƅ#[gTcRGhP>(±=w=yRPN'a  nE%E$(eA!xԯ4汚4lAYc(HW]~L;-!gY ‘Hn[|Pģ1u6:G~?.߾q@mkmЪ|2.^I8"$m\>XxB>/F# 0Lo}rQ3YPjoDCuP->1؂Ɔ h<*g]O=2'\Twd A c 4h?u(kKHDʲS"g>{FkeiSaC4+@Co^x텝C ) |"DlxZ@YqD12:Tְu:rSo8vN]qup{HV, o`<B.U$PJQ!Z@KMߙ9XI>LYؐ,Bp8 Y) \`3 hܡ}H.ıh$4, (_F} (.'G\I涒00D(2%,y#; ưޢ(.EQrX}.QJyЦ[LǍ];2:.ܳ bC~ 0۔FuڄrcǞ s3 PN `Ǟ JW(c dU v}3n. `MV̪_"^V^'o"1SC@ؽ]fT־Y"6o촱vjS7}9 2t}>]F.ðݞ|k6SG^bon`s@'e 2t}ކRm:̗zMK=4yq,'`S +>]F.O@'e 2t}nnfs;HmGlҢIQToǏ4AQQI[|^,^M~Cdݾ JejAn [8I& FpG| :Dr1J ~ui\TѻI&t SXE!娢圦iծ) шju]Ks~EӌN&3( n#mJ&#jS(E<E&)|RK9떿\Si%A:̟ګ秕Orh[yn`9D>E }.6؜AC ƴ#O+†M \rID͞U w}? % sȤF \˗mY}iH!_B"f C=3YΎγT3g˟:\$,WvgYfo܊9/"p| Ej%!4_񗞏mƑ7O_;- Hb_@M!/Tᶈ𦙑#3;/̰] KarFq\}uPY2bwvxqJ߬߈U>_ 6Cm"̫c12ힺ$=?|`ĕ8 TDIg-ȲiHnǀҟg˧ccXۮuqJ*"|L{o8&\3:)Pge BKH.vcEU݈ b19Ptiޭe[Wyc`"BIe;n?i*@ud)cg&N(TT% %7v00_bFHs2a;3eqz5U>]$ހC.LyZ5ttj+]TJ;S Nk^֨&s8*ea^? [@*ؐjفB3vn4uZڊ& {aue5^w=b 8@ jF?VdH.7j;+f-^HaoKhS+Kk'Kɉ;sC"3?0J C߈wn?4:_-7G:$XX'5apydFzvGHl(N|)~rqJhiH:&[V'¿cUc-[MZA稼8t@~ބvQ_緽v2uM7+ϲ{/y(rګ~Wy~Dfo} Sr[_ch-f~TϓaFψOOuɌӂdDoR?4|rQ]ݕHl5Vp?2#=7tٱ5å/L.Dw^7]>$"`햼 k $wTj"XpyeʬyKnzvOIբ&?8e]ps[xER1E}nvǔϊbK=A`a?aJ<`3=Ƽ=C:DpXII;* Uջ #BjpX}cQ56U&.,T `5xHoJcL,o%tEXtdate:create2017-02-21T08:06:30+01:00pn%tEXtdate:modify2017-02-21T08:06:30+01:0038WzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/static/apple-touch-icon.png000066400000000000000000000141361420147000300307540ustar00rootroot00000000000000PNG  IHDRegAMA a cHRMz&u0`:pQ<bKGDtIME7 IDATxٓ}cf0\K\xKRv,(ǎ*ʖd;D< )W^ R$ZۡeGdr;M9x-IAܹ0`ptNQA<0gE70@ j /D+D+D+D+D+D+D+D+D+D+D+̠0x얥N^,4$wFӷѾ}B~*nQʡ[תv-C#tK•V~t L;'EQܺTC)a QaT낼ǰ03gJ _ZA,,9U;qMRZVJOo mYD-Bdȁqx)cMEG614)(DRg9۴\fnCZع9@,41Ԍ\T%Gku/,*|a|e[9imYX^oƯPƉ)>S.t)sej([?1 ؠeM~v~lcy1whNwo߷ t1m%e/.V[!_++c w/Xz9_:g:Xv ;=Vz|[.DF[~t湢0DMC}>a9zS3b-/€)D,Cєc;i9h >DܳU*6ꄑ1mekYi"шEQ^KUEmۋ"_]9%n[:rȈɁ1/i+U/( !?TضS-zOs Y*F!c3RYfhOT7NcwHrR:K&Xnz2[r(gM]ASSoIVèbc^5<؈$%2![] h6b6Weeze gÿ`p,[=yx9?d)0EQB,ȄD!s;BZ-feq<ժC_CܹEܴbj9eӭe* Bt$fZ|V!۲*rq6{+D[>Y eC)W5N-r) x*;FjF)_( f-woIEwm޿} S=|I{T%8 aH,rhWЙ ƻ0BIG8òFLSKr674E"m^\aعaV+;UǴ<#>/JJ 117\\(YbwmRǴo].=Ӵ%'2pkAc٬Z*{Y!ݷ"{pײA;\yazmcFS!!MFmTz" RQxx}UR ȡKoמ;{Ç1 JT4`{]^LT E95 xYޅ}p=ajFgt%&R&qAwkr6]ݹ{J{ }q )wشk'^}oGn~)4M H"3 1b6[-W"8[["C\.:  Mf)W( u;Zٳ5v4M,VEpfKd2U 12(ư:ߞ?=fX8WI3ڹ{QVJe &o?Eѝȯ}U:BPe'< )ÛE˳!⃻՛7cCHc/ W+eKv &)-3<C4ς=)Hq^,gsMM︔znR^vAMg;[`K&L*qce!rh:kYH1,b3jI/os+&}!$ O`^ѿhzx 4M>Or @} afcwApApApApApApApApApApApApApApApel1XNOD:0rP&.@ߘ.*ViI}WWWWWWWWWWW4mhy̠ `x2/Ʒ0 0*w90Yr0h@!`.tH )H 99999999999999999999sӃE qsM]wȇ=`VUTCq鵊ڟ_߷f:C)fF9n߲Gbڬmďymۅ|?f@C:7DB@? BFVVJ%lw%,6.uO%?Af˗Ŗa @}3#<[ #w媪(R: ?>Bi*rIzc<ijE]tq|V_mhjȄ#"EQDgMg84_3C~ duNo2aeQE$)Is!ezQ*lVZNUQj%*yx=tx)6m9x̕a,е B-\x9MU PW%< #EQ'Zyg7e%1b4C|-Z8s`z4c M0Vٖ])YV祿{b#ܥ1\T.k?:*5`M Hb"/w1*|\r Nf1@+s}P'E05ZVcw>Z&3^vMJi4u1`F ) P`ۙ~4+0k>]dG@chj+Ţ2iLgi|v+蠯+]mZwG=%'rR:K&Y-w2[fPsyCk?E Sm $lfƅBtg|?q)B!AHd2B,Bh+mղR*vK#vlW&QȞ6+#/ZiZF8woZq6ʶvn m_B=I{(GaT^H󍫶iz,D|~_,)?DM9/ -屼Y6pm⽷3[VhӼVQ)0mS% B2g?wG4͊\9^ w&boZXy#`ǩϫOδru;W(DFF4wGqR)fx+/|:͡)9ØӏM6aV޸T{Lϋfq&*4 QNkb6%۲<#,b2{k崟_?,G+?=_\?z6-/€@<~~ dF9W( ޷l,m[9j6+MsF)txeB.D"Y./(d4w6z}a(`۩>7YSܥ(ꏹ>.wq<.SY)ZM=E\>sVr) aXB2z ސrdSpD>s˄=[_t)= GCW^>W}vZ;5k[^rwA.Jœ FT({,/f7OMEXB=i|7⽷ȤPqMUtI]y^G";6ž7! fh8NlNεr:wG|p5'5q-/n&G۰]P~yr9x>kK+i87eѦU*W׎g vyJGwm}u5 aAF@.<|PutX6Q|`Mlf~4D+ """""""""""- ۝?v%tEXtdate:create2017-02-21T08:06:29+01:00)\%tEXtdate:modify2017-02-21T08:06:29+01:00XXuWzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/static/browserconfig.xml000066400000000000000000000005171420147000300304700ustar00rootroot00000000000000 #2d89ef hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/static/dist/000077500000000000000000000000001420147000300260355ustar00rootroot00000000000000hugo-0.92.2/docs/_vendor/github.com/gohugoio/gohugoioTheme/static/dist/app.bundle.js000066400000000000000000004125641420147000300304370ustar00rootroot00000000000000!function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var n={};e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=11)}([function(t,e,n){"use strict";var r=function(t){var e=document.createElement("a");return e.className="header-link",e.href="#"+t,e.innerHTML=' ',e},i=function(t,e){for(var n=e.getElementsByTagName("h"+t),i=0;i0&&p.parentNode.classList.add("expand")}}catch(t){a=!0,u=t}finally{try{!s&&l.return&&l.return()}finally{if(a)throw u}}}},function(t,e,n){"use strict";n(13)({apiKey:"167e7998590aebda7f9fedcf86bc4a55",indexName:"hugodocs",inputSelector:"#search-input",debug:!0})},function(t,e,n){"use strict";n(14),n(15)},function(t,e,n){"use strict";function r(){for(var t=this.dataset.target.split(" "),e=document.querySelector(".mobilemenu:not(.dn)"),n=document.querySelector(".desktopmenu:not(.dn)"),r=document.querySelector(".desktopmenu:not(.dn)"),i=0;i=0?function(){var t=window.pageYOffset;(t>=i-s||window.innerHeight+t>=document.body.offsetHeight)&&clearInterval(u)}:function(){window.pageYOffset<=(i||0)&&clearInterval(u)};var u=setInterval(a,16)},e=document.querySelectorAll("#TableOfContents ul li a");[].forEach.call(e,function(e){e.addEventListener("click",function(n){n.preventDefault();var r=e.getAttribute("href"),i=document.querySelector(r),o=e.getAttribute("data-speed");i&&t(i,o||500)},!1)})}}()},function(t,e,n){"use strict";function r(t){if(t.target){t.preventDefault();var e=t.currentTarget,n=e.getAttribute("data-toggle-tab")}else var n=t;window.localStorage&&window.localStorage.setItem("configLangPref",n);for(var r=document.querySelectorAll("[data-toggle-tab='"+n+"']"),i=document.querySelectorAll("[data-pane='"+n+"']"),a=0;a0&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.container=t.container,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var t=this,e="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[e?"right":"left"]="-9999px";var n=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=n+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=(0,r.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=(0,r.default)(this.target),this.copyText()}},{key:"copyText",value:function(){var t=void 0;try{t=document.execCommand(this.action)}catch(e){t=!1}this.handleResult(t)}},{key:"handleResult",value:function(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(t){if(void 0!==t){if(!t||"object"!==(void 0===t?"undefined":i(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function(){return this._target}}]),t}();t.exports=s})},{select:5}],8:[function(e,n,r){!function(i,o){if("function"==typeof t&&t.amd)t(["module","./clipboard-action","tiny-emitter","good-listener"],o);else if(void 0!==r)o(n,e("./clipboard-action"),e("tiny-emitter"),e("good-listener"));else{var s={exports:{}};o(s,i.clipboardAction,i.tinyEmitter,i.goodListener),i.clipboard=s.exports}}(this,function(t,e,n,r){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function s(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function a(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}var c=i(e),l=i(n),h=i(r),f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},p=function(){function t(t,e){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText,this.container="object"===f(t.container)?t.container:document.body}},{key:"listenClick",value:function(t){var e=this;this.listener=(0,h.default)(t,"click",function(t){return e.onClick(t)})}},{key:"onClick",value:function(t){var e=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new c.default({action:this.action(e),target:this.target(e),text:this.text(e),container:this.container,trigger:e,emitter:this})}},{key:"defaultAction",value:function(t){return u("action",t)}},{key:"defaultTarget",value:function(t){var e=u("target",t);if(e)return document.querySelector(e)}},{key:"defaultText",value:function(t){return u("text",t)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],e="string"==typeof t?[t]:t,n=!!document.queryCommandSupported;return e.forEach(function(t){n=n&&!!document.queryCommandSupported(t)}),n}}]),e}(l.default);t.exports=d})},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)})},function(t,e,n){/*! docsearch 2.4.1 | © Algolia | github.com/algolia/docsearch */ !function(e,n){t.exports=n()}(0,function(){return function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var n={};return e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=46)}([function(t,e,n){"use strict";function r(t){return t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}var i=n(1);t.exports={isArray:null,isFunction:null,isObject:null,bind:null,each:null,map:null,mixin:null,isMsie:function(){return!!/(msie|trident)/i.test(navigator.userAgent)&&navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2]},escapeRegExChars:function(t){return t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isNumber:function(t){return"number"==typeof t},toStr:function(t){return void 0===t||null===t?"":t+""},cloneDeep:function(t){var e=this.mixin({},t),n=this;return this.each(e,function(t,r){t&&(n.isArray(t)?e[r]=[].concat(t):n.isObject(t)&&(e[r]=n.cloneDeep(t)))}),e},error:function(t){throw new Error(t)},every:function(t,e){var n=!0;return t?(this.each(t,function(r,i){if(!(n=e.call(null,r,i,t)))return!1}),!!n):n},any:function(t,e){var n=!1;return t?(this.each(t,function(r,i){if(e.call(null,r,i,t))return n=!0,!1}),n):n},getUniqueId:function(){var t=0;return function(){return t++}}(),templatify:function(t){if(this.isFunction(t))return t;var e=i.element(t);return"SCRIPT"===e.prop("tagName")?function(){return e.text()}:function(){return String(t)}},defer:function(t){setTimeout(t,0)},noop:function(){},formatPrefix:function(t,e){return e?"":t+"-"},className:function(t,e,n){return(n?"":".")+t+e},escapeHighlightedString:function(t,e,n){e=e||"";var i=document.createElement("div");i.appendChild(document.createTextNode(e)),n=n||"";var o=document.createElement("div");o.appendChild(document.createTextNode(n));var s=document.createElement("div");return s.appendChild(document.createTextNode(t)),s.innerHTML.replace(RegExp(r(i.innerHTML),"g"),e).replace(RegExp(r(o.innerHTML),"g"),n)}}},function(t,e,n){"use strict";t.exports={element:null}},function(t,e){var n=Object.prototype.hasOwnProperty,r=Object.prototype.toString;t.exports=function(t,e,i){if("[object Function]"!==r.call(e))throw new TypeError("iterator must be a function");var o=t.length;if(o===+o)for(var s=0;s was loaded but did not call our provided callback"),JSONPScriptError:i("JSONPScriptError"," {{ end }} {{ with .Resources.GetMatch "style.css" }} {{ end }} {{ with .Resources.GetMatch "img.png" }} {{ end }} ``` MediaType : The MIME type of the resource, such as `image/jpeg`. MediaType.MainType : The main type of the resource's MIME type. For example, a file of MIME type `application/pdf` has for MainType `application`. MediaType.SubType : The subtype of the resource's MIME type. For example, a file of MIME type `application/pdf` has for SubType `pdf`. Note that this is not the same as the file extension - PowerPoint files have a subtype of `vnd.mspowerpoint`. MediaType.Suffixes : A slice of possible suffixes for the resource's MIME type. ## Methods ByType : Returns the page resources of the given type. ```go {{ .Resources.ByType "image" }} ``` Match : Returns all the page resources (as a slice) whose `Name` matches the given Glob pattern ([examples](https://github.com/gobwas/glob/blob/master/readme.md)). The matching is case-insensitive. ```go {{ .Resources.Match "images/*" }} ``` GetMatch : Same as `Match` but will return the first match. ### Pattern Matching ```go // Using Match/GetMatch to find this images/sunset.jpg ? .Resources.Match "images/sun*" ✅ .Resources.Match "**/sunset.jpg" ✅ .Resources.Match "images/*.jpg" ✅ .Resources.Match "**.jpg" ✅ .Resources.Match "*" 🚫 .Resources.Match "sunset.jpg" 🚫 .Resources.Match "*sunset.jpg" 🚫 ``` ## Page Resources Metadata The page resources' metadata is managed from the corresponding page's front matter with an array/table parameter named `resources`. You can batch assign values using [wildcards](https://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm). {{% note %}} Resources of type `page` get `Title` etc. from their own front matter. {{% /note %}} name : Sets the value returned in `Name`. {{% warning %}} The methods `Match` and `GetMatch` use `Name` to match the resources. {{%/ warning %}} title : Sets the value returned in `Title` params : A map of custom key/values. ### Resources metadata example {{< code-toggle copy="false">}} title: Application date : 2018-01-25 resources : - src : "images/sunset.jpg" name : "header" - src : "documents/photo_specs.pdf" title : "Photo Specifications" params: icon : "photo" - src : "documents/guide.pdf" title : "Instruction Guide" - src : "documents/checklist.pdf" title : "Document Checklist" - src : "documents/payment.docx" title : "Proof of Payment" - src : "**.pdf" name : "pdf-file-:counter" params : icon : "pdf" - src : "**.docx" params : icon : "word" {{}} From the example above: - `sunset.jpg` will receive a new `Name` and can now be found with `.GetMatch "header"`. - `documents/photo_specs.pdf` will get the `photo` icon. - `documents/checklist.pdf`, `documents/guide.pdf` and `documents/payment.docx` will get `Title` as set by `title`. - Every `PDF` in the bundle except `documents/photo_specs.pdf` will get the `pdf` icon. - All `PDF` files will get a new `Name`. The `name` parameter contains a special placeholder [`:counter`](#the-counter-placeholder-in-name-and-title), so the `Name` will be `pdf-file-1`, `pdf-file-2`, `pdf-file-3`. - Every docx in the bundle will receive the `word` icon. {{% warning %}} The __order matters__ --- Only the **first set** values of the `title`, `name` and `params`-**keys** will be used. Consecutive parameters will be set only for the ones not already set. In the above example, `.Params.icon` is first set to `"photo"` in `src = "documents/photo_specs.pdf"`. So that would not get overridden to `"pdf"` by the later set `src = "**.pdf"` rule. {{%/ warning %}} ### The `:counter` placeholder in `name` and `title` The `:counter` is a special placeholder recognized in `name` and `title` parameters `resources`. The counter starts at 1 the first time they are used in either `name` or `title`. For example, if a bundle has the resources `photo_specs.pdf`, `other_specs.pdf`, `guide.pdf` and `checklist.pdf`, and the front matter has specified the `resources` as: {{< code-toggle copy="false">}} [[resources]] src = "*specs.pdf" title = "Specification #:counter" [[resources]] src = "**.pdf" name = "pdf-file-:counter" {{}} the `Name` and `Title` will be assigned to the resource files as follows: | Resource file | `Name` | `Title` | |-------------------|-------------------|-----------------------| | checklist.pdf | `"pdf-file-1.pdf` | `"checklist.pdf"` | | guide.pdf | `"pdf-file-2.pdf` | `"guide.pdf"` | | other\_specs.pdf | `"pdf-file-3.pdf` | `"Specification #1"` | | photo\_specs.pdf | `"pdf-file-4.pdf` | `"Specification #2"` | hugo-0.92.2/docs/content/en/content-management/related.md000066400000000000000000000133341420147000300232730ustar00rootroot00000000000000--- title: Related Content description: List related content in "See Also" sections. date: 2017-09-05 categories: [content management] keywords: [content] menu: docs: parent: "content-management" weight: 40 weight: 30 draft: false aliases: [/content/related/,/related/] toc: true --- Hugo uses a set of factors to identify a page's related content based on Front Matter parameters. This can be tuned to the desired set of indices and parameters or left to Hugo's default [Related Content configuration](#configure-related-content). ## List Related Content To list up to 5 related pages (which share the same _date_ or _keyword_ parameters) is as simple as including something similar to this partial in your single page template: {{< code file="layouts/partials/related.html" >}} {{ $related := .Site.RegularPages.Related . | first 5 }} {{ with $related }}

    See Also

    {{ end }} {{< /code >}} ### Methods Here is the list of "Related" methods available on a page collection such `.RegularPages`. #### .Related PAGE Returns a collection of pages related the given one. ``` {{ $related := .Site.RegularPages.Related . }} ``` #### .RelatedIndices PAGE INDICE1 [INDICE2 ...] Returns a collection of pages related to a given one restricted to a list of indices. ``` {{ $related := .Site.RegularPages.RelatedIndices . "tags" "date" }} ``` #### .RelatedTo KEYVALS [KEYVALS2 ...] Returns a collection of pages related together by a set of indices and their match. In order to build those set and pass them as argument, one must use the `keyVals` function where the first argument would be the `indice` and the consecutive ones its potential `matches`. ``` {{ $related := .Site.RegularPages.RelatedTo ( keyVals "tags" "hugo" "rocks") ( keyVals "date" .Date ) }} ``` {{% note %}} Read [this blog article](https://regisphilibert.com/blog/2018/04/hugo-optmized-relashionships-with-related-content/) for a great explanation of more advanced usage of this feature. {{% /note %}} ## Configure Related Content Hugo provides a sensible default configuration of Related Content, but you can fine-tune this in your configuration, on the global or language level if needed. ### Default configuration Without any `related` configuration set on the project, Hugo's Related Content methods will use the following. {{< code-toggle file="config" >}} related: threshold: 80 includeNewer: false toLower: false indices: - name: keywords weight: 100 - name: date weight: 10 {{< /code-toggle >}} Note that if you have configured `tags` as a taxonomy, `tags` will also be added to the default configuration above with the weight of `80`. Custom configuration should be set using the same syntax. {{% note %}} If you add a `related` config section, you need to add a complete configuration. It is not possible to just set, say, `includeNewer` and use the rest from the Hugo defaults. {{% /note %}} ### Top Level Config Options threshold : A value between 0-100. Lower value will give more, but maybe not so relevant, matches. includeNewer : Set to true to include **pages newer than the current page** in the related content listing. This will mean that the output for older posts may change as new related content gets added. toLower : Set to true to lower case keywords in both the indexes and the queries. This may give more accurate results at a slight performance penalty. Note that this can also be set per index. ### Config Options per Index name : The index name. This value maps directly to a page param. Hugo supports string values (`author` in the example) and lists (`tags`, `keywords` etc.) and time and date objects. weight : An integer weight that indicates _how important_ this parameter is relative to the other parameters. It can be 0, which has the effect of turning this index off, or even negative. Test with different values to see what fits your content best. pattern : This is currently only relevant for dates. When listing related content, we may want to list content that is also close in time. Setting "2006" (default value for date indexes) as the pattern for a date index will add weight to pages published in the same year. For busier blogs, "200601" (year and month) may be a better default. toLower : See above. ## Performance Considerations **Fast is Hugo's middle name** and we would not have released this feature had it not been blistering fast. This feature has been in the back log and requested by many for a long time. The development got this recent kick start from this Twitter thread: {{< tweet user="scott_lowe" id="898398437527363585" >}} Scott S. Lowe removed the "Related Content" section built using the `intersect` template function on tags, and the build time dropped from 30 seconds to less than 2 seconds on his 1700 content page sized blog. He should now be able to add an improved version of that "Related Content" section without giving up the fast live-reloads. But it's worth noting that: * If you don't use any of the `Related` methods, you will not use the Relate Content feature, and performance will be the same as before. * Calling `.RegularPages.Related` etc. will create one inverted index, also sometimes named posting list, that will be reused for any lookups in that same page collection. Doing that in addition to, as an example, calling `.Pages.Related` will work as expected, but will create one additional inverted index. This should still be very fast, but worth having in mind, especially for bigger sites. {{% note %}} We currently do not index **Page content**. We thought we would release something that will make most people happy before we start solving [Sherlock's last case](https://github.com/joearms/sherlock). {{% /note %}} hugo-0.92.2/docs/content/en/content-management/sections.md000066400000000000000000000076221420147000300235050ustar00rootroot00000000000000--- title: Content Sections linktitle: Sections description: "Hugo generates a **section tree** that matches your content." date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [content management] keywords: [lists,sections,content types,organization] menu: docs: parent: "content-management" weight: 50 weight: 50 #rem draft: false aliases: [/content/sections/] toc: true --- A **Section** is a collection of pages that gets defined based on the organization structure under the `content/` directory. By default, all the **first-level** directories under `content/` form their own sections (**root sections**) provided they constitute [Branch Bundles][branch bundles]. Directories which are just [Leaf Bundles][leaf bundles] do *not* form their own sections, despite being first-level directories. If a user needs to define a section `foo` at a deeper level, they need to create a directory named `foo` with an `_index.md` file (see [Branch Bundles][branch bundles] for more information). {{% note %}} A **section** cannot be defined or overridden by a front matter parameter -- it is strictly derived from the content organization structure. {{% /note %}} ## Nested Sections The sections can be nested as deeply as you need. ```bash content └── blog <-- Section, because first-level dir under content/ ├── funny-cats │   ├── mypost.md │   └── kittens <-- Section, because contains _index.md │   └── _index.md └── tech <-- Section, because contains _index.md └── _index.md ``` **The important part to understand is, that to make the section tree fully navigational, at least the lower-most section needs a content file. (e.g. `_index.md`).** {{% note %}} When we talk about a **section** in correlation with template selection, it is currently always the *root section* only (`/blog/funny-cats/mypost/ => blog`). If you need a specific template for a sub-section, you need to adjust either the `type` or `layout` in front matter. {{% /note %}} ## Example: Breadcrumb Navigation With the available [section variables and methods](#section-page-variables-and-methods) you can build powerful navigation. One common example would be a partial to show Breadcrumb navigation: {{< code file="layouts/partials/breadcrumb.html" download="breadcrumb.html" >}} {{ define "breadcrumbnav" }} {{ if .p1.Parent }} {{ template "breadcrumbnav" (dict "p1" .p1.Parent "p2" .p2 ) }} {{ else if not .p1.IsHome }} {{ template "breadcrumbnav" (dict "p1" .p1.Site.Home "p2" .p2 ) }} {{ end }} {{ .p1.Title }} {{ end }} {{< /code >}} ## Section Page Variables and Methods Also see [Page Variables](/variables/page/). {{< readfile file="/content/en/readfiles/sectionvars.md" markdown="true" >}} ## Content Section Lists Hugo will automatically create pages for each *root section* that list all of the content in that section. See the documentation on [section templates][] for details on customizing the way these pages are rendered. ## Content *Section* vs Content *Type* By default, everything created within a section will use the [content `type`][content type] that matches the *root section* name. For example, Hugo will assume that `posts/post-1.md` has a `posts` content `type`. If you are using an [archetype][] for your `posts` section, Hugo will generate front matter according to what it finds in `archetypes/posts.md`. [archetype]: /content-management/archetypes/ [content type]: /content-management/types/ [directory structure]: /getting-started/directory-structure/ [section templates]: /templates/section-templates/ [leaf bundles]: /content-management/page-bundles/#leaf-bundles [branch bundles]: /content-management/page-bundles/#branch-bundles hugo-0.92.2/docs/content/en/content-management/shortcodes.md000066400000000000000000000372521420147000300240350ustar00rootroot00000000000000--- title: Shortcodes linktitle: description: Shortcodes are simple snippets inside your content files calling built-in or custom templates. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2019-11-07 menu: docs: parent: "content-management" weight: 35 weight: 35 #rem categories: [content management] keywords: [markdown,content,shortcodes] draft: false aliases: [/extras/shortcodes/] testparam: "Hugo Rocks!" toc: true --- ## What a Shortcode is Hugo loves Markdown because of its simple content format, but there are times when Markdown falls short. Often, content authors are forced to add raw HTML (e.g., video ` {{< /code >}} {{< code file="youtube-embed.html" copy="false" >}}
    {{< /code >}} ### Single Named Example: `image` Let's say you want to create your own `img` shortcode rather than use Hugo's built-in [`figure` shortcode][figure]. Your goal is to be able to call the shortcode as follows in your content files: {{< code file="content-image.md" >}} {{}} {{< /code >}} You have created the shortcode at `/layouts/shortcodes/img.html`, which loads the following shortcode template: {{< code file="/layouts/shortcodes/img.html" >}}
    {{ with .Get "link" }}{{ end }} {{ if .Get "link" }}{{ end }} {{ if or (or (.Get "title") (.Get "caption")) (.Get "attr") }}
    {{ if isset .Params "title" }}

    {{ .Get "title" }}

    {{ end }} {{ if or (.Get "caption") (.Get "attr") }}

    {{ .Get "caption" }} {{ with .Get "attrlink" }} {{ end }} {{ .Get "attr" }} {{ if .Get "attrlink" }} {{ end }}

    {{ end }}
    {{ end }}
    {{< /code >}} Would be rendered as: {{< code file="img-output.html" copy="false" >}}

    Steve Francia

    {{< /code >}} ### Single Flexible Example: `vimeo` ``` {{}} {{}} ``` Would load the template found at `/layouts/shortcodes/vimeo.html`: {{< code file="/layouts/shortcodes/vimeo.html" >}} {{ if .IsNamedParams }}
    {{ else }}
    {{ end }} {{< /code >}} Would be rendered as: {{< code file="vimeo-iframes.html" copy="false" >}}
    {{< /code >}} ### Paired Example: `highlight` The following is taken from `highlight`, which is a [built-in shortcode][] that ships with Hugo. {{< code file="highlight-example.md" >}} {{}} This HTML {{}} {{< /code >}} The template for the `highlight` shortcode uses the following code, which is already included in Hugo: ``` {{ .Get 0 | highlight .Inner }} ``` The rendered output of the HTML example code block will be as follows: {{< code file="syntax-highlighted.html" copy="false" >}}
    <html>
        <body> This HTML </body>
    </html>
    
    {{< /code >}} ### Nested Shortcode: Image Gallery Hugo's [`.Parent` shortcode variable][parent] returns a boolean value depending on whether the shortcode in question is called within the context of a *parent* shortcode. This provides an inheritance model for common shortcode parameters. The following example is contrived but demonstrates the concept. Assume you have a `gallery` shortcode that expects one named `class` parameter: {{< code file="layouts/shortcodes/gallery.html" >}}
    {{ .Inner }}
    {{< /code >}} You also have an `img` shortcode with a single named `src` parameter that you want to call inside of `gallery` and other shortcodes, so that the parent defines the context of each `img`: {{< code file="layouts/shortcodes/img.html" >}} {{- $src := .Get "src" -}} {{- with .Parent -}} {{- else -}} {{- end -}} {{< /code >}} You can then call your shortcode in your content as follows: ``` {{}} {{}} {{}} {{}} {{}} ``` This will output the following HTML. Note how the first two `img` shortcodes inherit the `class` value of `content-gallery` set with the call to the parent `gallery`, whereas the third `img` only uses `src`: ``` ``` ## Error Handling in Shortcodes Use the [errorf](/functions/errorf) template func and [.Position](/variables/shortcodes/) variable to get useful error messages in shortcodes: ```bash {{ with .Get "name" }} {{ else }} {{ errorf "missing value for param 'name': %s" .Position }} {{ end }} ``` When the above fails, you will see an `ERROR` log similar to the below: ```bash ERROR 2018/11/07 10:05:55 missing value for param name: "/Users/bep/dev/go/gohugoio/hugo/docs/content/en/variables/shortcodes.md:32:1" ``` ## More Shortcode Examples More shortcode examples can be found in the [shortcodes directory for spf13.com][spfscs] and the [shortcodes directory for the Hugo docs][docsshortcodes]. ## Inline Shortcodes {{< new-in "0.52" >}} Since Hugo 0.52, you can implement your shortcodes inline -- e.g. where you use them in the content file. This can be useful for scripting that you only need in one place. This feature is disabled by default, but can be enabled in your site config: {{< code-toggle file="config">}} enableInlineShortcodes = true {{< /code-toggle >}} It is disabled by default for security reasons. The security model used by Hugo's template handling assumes that template authors are trusted, but that the content files are not, so the templates are injection-safe from malformed input data. But in most situations you have full control over the content, too, and then `enableInlineShortcodes = true` would be considered safe. But it's something to be aware of: It allows ad-hoc [Go Text templates](https://golang.org/pkg/text/template/) to be executed from the content files. And once enabled, you can do this in your content files: ```go-text-template {{}}{{ now }}{{}} ``` The above will print the current date and time. Note that an inline shortcode's inner content is parsed and executed as a Go text template with the same context as a regular shortcode template. This means that the current page can be accessed via `.Page.Title` etc. This also means that there are no concept of "nested inline shortcodes". The same inline shortcode can be reused later in the same content file, with different params if needed, using the self-closing syntax: ```go-text-template {{}} ``` [basic content files]: /content-management/formats/ "See how Hugo leverages markdown--and other supported formats--to create content for your website." [built-in shortcode]: /content-management/shortcodes/ [config]: /getting-started/configuration/ "Learn more about Hugo's built-in configuration variables as well as how to us your site's configuration file to include global key-values that can be used throughout your rendered website." [Content Management: Shortcodes]: /content-management/shortcodes/#using-hugo-s-built-in-shortcodes "Check this section if you are not familiar with the definition of what a shortcode is or if you are unfamiliar with how to use Hugo's built-in shortcodes in your content files." [source organization]: /getting-started/directory-structure/#directory-structure-explained "Learn how Hugo scaffolds new sites and what it expects to find in each of your directories." [docsshortcodes]: https://github.com/gohugoio/hugo/tree/master/docs/layouts/shortcodes "See the shortcode source directory for the documentation site you're currently reading." [figure]: /content-management/shortcodes/#figure [hugosc]: /content-management/shortcodes/#using-hugo-s-built-in-shortcodes [lookup order]: /templates/lookup-order/ "See the order in which Hugo traverses your template files to decide where and how to render your content at build time" [pagevars]: /variables/page/ "See which variables you can leverage in your templating for page vs list templates." [parent]: /variables/shortcodes/ [shortcodesvars]: /variables/shortcodes/ "Certain variables are specific to shortcodes, although most .Page variables can be accessed within your shortcode template." [spfscs]: https://github.com/spf13/spf13.com/tree/master/layouts/shortcodes "See more examples of shortcodes by visiting the shortcode directory of the source for spf13.com, the blog of Hugo's creator, Steve Francia." [templates]: /templates/ "The templates section of the Hugo docs." [vimeoexample]: #single-flexible-example-vimeo [youtubeshortcode]: /content-management/shortcodes/#youtube "See how to use Hugo's built-in YouTube shortcode." hugo-0.92.2/docs/content/en/templates/single-page-templates.md000066400000000000000000000057011420147000300242530ustar00rootroot00000000000000--- title: Single Page Templates linktitle: description: The primary view of content in Hugo is the single view. Hugo will render every Markdown file provided with a corresponding single template. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-04-06 categories: [templates] keywords: [page,templates] menu: docs: parent: "templates" weight: 60 weight: 60 sections_weight: 60 draft: false aliases: [/layout/content/] toc: true --- ## Single Page Template Lookup Order See [Template Lookup](/templates/lookup-order/). ## Example Single Page Templates Content pages are of the type `page` and will therefore have all the [page variables][pagevars] and [site variables][] available to use in their templates. ### `posts/single.html` This single page template makes use of Hugo [base templates][], the [`.Format` function][] for dates, the [`.WordCount` page variable][pagevars], and ranges through the single content's specific [taxonomies][pagetaxonomy]. [`with`][] is also used to check whether the taxonomies are set in the front matter. {{< code file="layouts/posts/single.html" download="single.html" >}} {{ define "main" }}

    {{ .Title }}

    {{ .Content }}
    {{ end }} {{< /code >}} To easily generate new instances of a content type (e.g., new `.md` files in a section like `project/`) with preconfigured front matter, use [content archetypes][archetypes]. [archetypes]: /content-management/archetypes/ [base templates]: /templates/base/ [config]: /getting-started/configuration/ [content type]: /content-management/types/ [directory structure]: /getting-started/directory-structure/ [dry]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself [`.Format` function]: /functions/format/ [front matter]: /content-management/front-matter/ [pagetaxonomy]: /templates/taxonomy-templates/#displaying-a-single-piece-of-content-s-taxonomies [pagevars]: /variables/page/ [partials]: /templates/partials/ [section]: /content-management/sections/ [site variables]: /variables/site/ [spf13]: https://spf13.com/ [`with`]: /functions/with/ hugo-0.92.2/docs/content/en/templates/sitemap-template.md000066400000000000000000000066201420147000300233400ustar00rootroot00000000000000--- title: Sitemap Template # linktitle: Sitemap description: Hugo ships with a built-in template file observing the v0.9 of the Sitemap Protocol, but you can override this template if needed. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [templates] keywords: [sitemap, xml, templates] menu: docs: parent: "templates" weight: 160 weight: 160 sections_weight: 160 draft: false aliases: [/layout/sitemap/,/templates/sitemap/] toc: false --- A single Sitemap template is used to generate the `sitemap.xml` file. Hugo automatically comes with this template file. *No work is needed on the users' part unless they want to customize `sitemap.xml`.* A sitemap is a `Page` and therefore has all the [page variables][pagevars] available to use in this template along with Sitemap-specific ones: `.Sitemap.ChangeFreq` : The page change frequency `.Sitemap.Priority` : The priority of the page `.Sitemap.Filename` : The sitemap filename If provided, Hugo will use `/layouts/sitemap.xml` instead of the internal `sitemap.xml` template that ships with Hugo. ## Sitemap Templates Hugo has built-on Sitemap templates, but you can provide your own if needed, in either `layouts/sitemap.xml` or `layouts/_default/sitemap.xml`. For multilingual sites, we also create a Sitemap index. You can provide a custom layout for that in either `layouts/sitemapindex.xml` or `layouts/_default/sitemapindex.xml`. ## Hugo’s sitemap.xml This template respects the version 0.9 of the [Sitemap Protocol](https://www.sitemaps.org/protocol.html). ```xml {{ printf "" | safeHTML }} {{ range .Data.Pages }} {{ .Permalink }}{{ if not .Lastmod.IsZero }} {{ safeHTML ( .Lastmod.Format "2006-01-02T15:04:05-07:00" ) }}{{ end }}{{ with .Sitemap.ChangeFreq }} {{ . }}{{ end }}{{ if ge .Sitemap.Priority 0.0 }} {{ .Sitemap.Priority }}{{ end }}{{ if .IsTranslated }}{{ range .Translations }} {{ end }} {{ end }} {{ end }} ``` ## Hugo's sitemapindex.xml This is used to create a Sitemap index in multilingual mode: ```xml {{ printf "" | safeHTML }} {{ range . }} {{ .SitemapAbsURL }} {{ if not .LastChange.IsZero }} {{ .LastChange.Format "2006-01-02T15:04:05-07:00" | safeHTML }} {{ end }} {{ end }} ``` ## Configure `sitemap.xml` Defaults for ``, `` and `filename` values can be set in the site's config file, e.g.: {{< code-toggle file="config" >}} [sitemap] changefreq = "monthly" priority = 0.5 filename = "sitemap.xml" {{}} The same fields can be specified in an individual content file's front matter in order to override the value assigned to that piece of content at render time. [pagevars]: /variables/page/ hugo-0.92.2/docs/content/en/templates/taxonomy-templates.md000066400000000000000000000304071420147000300237370ustar00rootroot00000000000000--- title: Taxonomy Templates # linktitle: description: Taxonomy templating includes taxonomy list pages, taxonomy terms pages, and using taxonomies in your single page templates. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [templates] keywords: [taxonomies,metadata,front matter,terms,templates] menu: docs: parent: "templates" weight: 50 weight: 50 sections_weight: 50 draft: false aliases: [/taxonomies/displaying/,/templates/terms/,/indexes/displaying/,/taxonomies/templates/,/indexes/ordering/, /templates/taxonomies/, /templates/taxonomy/] toc: true --- Hugo includes support for user-defined groupings of content called **taxonomies**. Taxonomies are classifications that demonstrate logical relationships between content. See [Taxonomies under Content Management](/content-management/taxonomies) if you are unfamiliar with how Hugo leverages this powerful feature. Hugo provides multiple ways to use taxonomies throughout your project templates: * Order the way content associated with a taxonomy term is displayed in a [taxonomy list template](#taxonomy-list-template) * Order the way the terms for a taxonomy are displayed in a [taxonomy terms template](#taxonomy-terms-template) * List a single content's taxonomy terms within a [single page template][] ## Taxonomy List Templates Taxonomy list page templates are lists and therefore have all the variables and methods available to [list pages][lists]. ### Taxonomy List Template Lookup Order See [Template Lookup](/templates/lookup-order/). ## Taxonomy Terms Template ### Taxonomy Terms Templates Lookup Order See [Template Lookup](/templates/lookup-order/). ### Taxonomy Methods A Taxonomy is a `map[string]WeightedPages`. .Get(term) : Returns the WeightedPages for a term. .Count(term) : The number of pieces of content assigned to this term. .Alphabetical : Returns an OrderedTaxonomy (slice) ordered by Term. .ByCount : Returns an OrderedTaxonomy (slice) ordered by number of entries. .Reverse : Returns an OrderedTaxonomy (slice) in reverse order. Must be used with an OrderedTaxonomy. ### OrderedTaxonomy Since Maps are unordered, an OrderedTaxonomy is a special structure that has a defined order. ```go []struct { Name string WeightedPages WeightedPages } ``` Each element of the slice has: .Term : The Term used. .WeightedPages : A slice of Weighted Pages. .Count : The number of pieces of content assigned to this term. .Pages : All Pages assigned to this term. All [list methods][renderlists] are available to this. ## WeightedPages WeightedPages is simply a slice of WeightedPage. ```go type WeightedPages []WeightedPage ``` .Count(term) : The number of pieces of content assigned to this term. .Pages : Returns a slice of pages, which then can be ordered using any of the [list methods][renderlists]. ## Displaying custom metadata in Taxonomy Terms Templates If you need to display custom metadata for each taxonomy term, you will need to create a page for that term at `/content///_index.md` and add your metadata in its front matter, [as explained in the taxonomies documentation](/content-management/taxonomies/#add-custom-meta-data-to-a-taxonomy-term). Based on the Actors taxonomy example shown there, within your taxonomy terms template, you may access your custom fields by iterating through the variable `.Pages` as such: ```go-html-template
      {{ range .Pages }}
    • {{ .Title }} {{ .Params.wikipedia }}
    • {{ end }}
    ``` ## Order Taxonomies Taxonomies can be ordered by either alphabetical key or by the number of content pieces assigned to that key. ### Order Alphabetically Example ```go-html-template ``` ## Order Content within Taxonomies Hugo uses both `date` and `weight` to order content within taxonomies. Each piece of content in Hugo can optionally be assigned a date. It can also be assigned a weight for each taxonomy it is assigned to. When iterating over content within taxonomies, the default sort is the same as that used for section and list pages: first by weight, then by date. This means that if the weights for two pieces of content are the same, then the more recent content will be displayed first. The default weight for any piece of content is 0. Zero means "does not have a weight", not "has a weight of numerical value zero". Weights of zero are thus treated specially: if two pages have unequal weights, and one of them is zero, then the zero-weighted page will always appear after the other one, regardless of the other's weight. Zero weights should thus be used with care: for example, if both positive and negative weights are used to extend a sequence in both directions, a zero-weighted page will appear not in the middle of the list, but at the end. ### Assign Weight Content can be assigned weight for each taxonomy that it's assigned to. ``` +++ tags = [ "a", "b", "c" ] tags_weight = 22 categories = ["d"] title = "foo" categories_weight = 44 +++ Front Matter with weighted tags and categories ``` The convention is `taxonomyname_weight`. In the above example, this piece of content has a weight of 22 which applies to the sorting when rendering the pages assigned to the "a", "b" and "c" values of the 'tag' taxonomy. It has also been assigned the weight of 44 when rendering the 'd' category. With this the same piece of content can appear in different positions in different taxonomies. Currently taxonomies only support the default ordering of content which is weight -> date. There are two different templates that the use of taxonomies will require you to provide. Both templates are covered in detail in the templates section. A [list template](/templates/list/) is any template that will be used to render multiple pieces of content in a single html page. This template will be used to generate all the automatically created taxonomy pages. A [taxonomy terms template](/templates/terms/) is a template used to generate the list of terms for a given template. There are four common ways you can display the data in your taxonomies in addition to the automatic taxonomy pages created by hugo using the [list templates](/templates/list/): 1. For a given piece of content, you can list the terms attached 2. For a given piece of content, you can list other content with the same term 3. You can list all terms for a taxonomy 4. You can list all taxonomies (with their terms) ## Display a Single Piece of Content's Taxonomies Within your content templates, you may wish to display the taxonomies that piece of content is assigned to. Because we are leveraging the front matter system to define taxonomies for content, the taxonomies assigned to each content piece are located in the usual place (i.e., `.Params.`). ### Example: List Tags in a Single Page Template ```go-html-template ``` If you want to list taxonomies inline, you will have to take care of optional plural endings in the title (if multiple taxonomies), as well as commas. Let's say we have a taxonomy "directors" such as `directors: [ "Joel Coen", "Ethan Coen" ]` in the TOML-format front matter. To list such taxonomies, use the following: ### Example: Comma-delimit Tags in a Single Page Template ```go-html-template {{ $taxo := "directors" }} {{ with .Param $taxo }} Director{{ if gt (len .) 1 }}s{{ end }}: {{ range $index, $director := . }} {{- if gt $index 0 }}, {{ end -}} {{ with $.Site.GetPage (printf "/%s/%s" $taxo $director) -}} {{ $director }} {{- end -}} {{- end -}} {{ end }} ``` Alternatively, you may use the [delimit template function][delimit] as a shortcut if the taxonomies should just be listed with a separator. See {{< gh 2143 >}} on GitHub for discussion. ## List Content with the Same Taxonomy Term If you are using a taxonomy for something like a series of posts, you can list individual pages associated with the same taxonomy. This is also a quick and dirty method for showing related content: ### Example: Showing Content in Same Series ```go-html-template ``` ## List All content in a Given taxonomy This would be very useful in a sidebar as “featured content”. You could even have different sections of “featured content” by assigning different terms to the content. ### Example: Grouping "Featured" Content ```go-html-template ``` ## Render a Site's Taxonomies If you wish to display the list of all keys for your site's taxonomy, you can retrieve them from the [`.Site` variable][sitevars] available on every page. This may take the form of a tag cloud, a menu, or simply a list. The following example displays all terms in a site's tags taxonomy: ### Example: List All Site Tags {#example-list-all-site-tags} ```go-html-template ``` ### Example: List All Taxonomies, Terms, and Assigned Content This example will list all taxonomies and their terms, as well as all the content assigned to each of the terms. {{< code file="layouts/partials/all-taxonomies.html" download="all-taxonomies.html" download="all-taxonomies.html" >}}
      {{ range $taxonomy_term, $taxonomy := .Site.Taxonomies }} {{ with $.Site.GetPage (printf "/%s" $taxonomy_term) }}
    • {{ $taxonomy_term }}
        {{ range $key, $value := $taxonomy }}
      • {{ $key }}
      • {{ end }}
    • {{ end }} {{ end }}
    {{< /code >}} ## `.Site.GetPage` for Taxonomies Because taxonomies are lists, the [`.GetPage` function][getpage] can be used to get all the pages associated with a particular taxonomy term using a terse syntax. The following ranges over the full list of tags on your site and links to each of the individual taxonomy pages for each term without having to use the more fragile URL construction of the ["List All Site Tags" example above]({{< relref "#example-list-all-site-tags" >}}): {{< code file="links-to-all-tags.html" >}} {{ $taxo := "tags" }}
      {{ with ($.Site.GetPage (printf "/%s" $taxo)) }} {{ range .Pages }}
    • {{ .Title}}
    • {{ end }} {{ end }}
    {{< /code >}} [delimit]: /functions/delimit/ [getpage]: /functions/getpage/ [lists]: /templates/lists/ [renderlists]: /templates/lists/ [single page template]: /templates/single-page-templates/ [sitevars]: /variables/site/ hugo-0.92.2/docs/content/en/templates/template-debugging.md000066400000000000000000000040601420147000300236250ustar00rootroot00000000000000--- title: Template Debugging # linktitle: Template Debugging description: You can use Go templates' `printf` function to debug your Hugo templates. These snippets provide a quick and easy visualization of the variables available to you in different contexts. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [templates] keywords: [debugging,troubleshooting] menu: docs: parent: "templates" weight: 180 weight: 180 sections_weight: 180 draft: false aliases: [] toc: false --- Here are some snippets you can add to your template to answer some common questions. These snippets use the `printf` function available in all Go templates. This function is an alias to the Go function, [fmt.Printf](https://golang.org/pkg/fmt/). ## What Variables are Available in this Context? You can use the template syntax, `$.`, to get the top-level template context from anywhere in your template. This will print out all the values under, `.Site`. ``` {{ printf "%#v" $.Site }} ``` This will print out the value of `.Permalink`: ``` {{ printf "%#v" .Permalink }} ``` This will print out a list of all the variables scoped to the current context (`.`, aka ["the dot"][tempintro]). ``` {{ printf "%#v" . }} ``` When developing a [homepage][], what does one of the pages you're looping through look like? ``` {{ range .Pages }} {{/* The context, ".", is now each one of the pages as it goes through the loop */}} {{ printf "%#v" . }} {{ end }} ``` ## Why Am I Showing No Defined Variables? Check that you are passing variables in the `partial` function: ``` {{ partial "header" }} ``` This example will render the header partial, but the header partial will not have access to any contextual variables. You need to pass variables explicitly. For example, note the addition of ["the dot"][tempintro]. ``` {{ partial "header" . }} ``` The dot (`.`) is considered fundamental to understanding Hugo templating. For more information, see [Introduction to Hugo Templating][tempintro]. [homepage]: /templates/homepage/ [tempintro]: /templates/introduction/ hugo-0.92.2/docs/content/en/templates/views.md000066400000000000000000000105341420147000300212210ustar00rootroot00000000000000--- title: Content View Templates # linktitle: Content Views description: Hugo can render alternative views of your content, which is especially useful in list and summary views. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [templates] keywords: [views] menu: docs: parent: "templates" weight: 70 weight: 70 sections_weight: 70 draft: false aliases: [] toc: true --- These alternative **content views** are especially useful in [list templates][lists]. The following are common use cases for content views: * You want content of every type to be shown on the homepage but only with limited [summary views][summaries]. * You only want a bulleted list of your content on a [taxonomy list page][taxonomylists]. Views make this very straightforward by delegating the rendering of each different type of content to the content itself. ## Create a Content View To create a new view, create a template in each of your different content type directories with the view name. The following example contains an "li" view and a "summary" view for the `posts` and `project` content types. As you can see, these sit next to the [single content view][single] template, `single.html`. You can even provide a specific view for a given type and continue to use the `_default/single.html` for the primary view. ``` ▾ layouts/ ▾ posts/ li.html single.html summary.html ▾ project/ li.html single.html summary.html ``` Hugo also has support for a default content template to be used in the event that a specific content view template has not been provided for that type. Content views can also be defined in the `_default` directory and will work the same as list and single templates who eventually trickle down to the `_default` directory as a matter of the lookup order. ``` ▾ layouts/ ▾ _default/ li.html single.html summary.html ``` ## Which Template Will be Rendered? The following is the [lookup order][lookup] for content views: 1. `/layouts//.html` 2. `/layouts/_default/.html` 3. `/themes//layouts//.html` 4. `/themes//layouts/_default/.html` ## Example: Content View Inside a List The following example demonstrates how to use content views inside of your [list templates][lists]. ### `list.html` In this example, `.Render` is passed into the template to call the [render function][render]. `.Render` is a special function that instructs content to render itself with the view template provided as the first argument. In this case, the template is going to render the `summary.html` view that follows: {{< code file="layouts/_default/list.html" download="list.html" >}}

    {{ .Title }}

    {{ range .Pages }} {{ .Render "summary"}} {{ end }}
    {{< /code >}} ### `summary.html` Hugo will pass the entire page object to the following `summary.html` view template. (See [Page Variables][pagevars] for a complete list.) {{< code file="layouts/_default/summary.html" download="summary.html" >}} {{< /code >}} ### `li.html` Continuing on the previous example, we can change our render function to use a smaller `li.html` view by changing the argument in the call to the `.Render` function (i.e., `{{ .Render "li" }}`). {{< code file="layouts/_default/li.html" download="li.html" >}}
  1. {{ .Title }}
    {{ .Date.Format "Mon, Jan 2, 2006" }}
  2. {{< /code >}} [lists]: /templates/lists/ [lookup]: /templates/lookup-order/ [pagevars]: /variables/page/ [render]: /functions/render/ [single]: /templates/single-page-templates/ [spf]: https://spf13.com [spfsourceli]: https://github.com/spf13/spf13.com/blob/master/layouts/_default/li.html [spfsourcesection]: https://github.com/spf13/spf13.com/blob/master/layouts/_default/section.html [spfsourcesummary]: https://github.com/spf13/spf13.com/blob/master/layouts/_default/summary.html [summaries]: /content-management/summaries/ [taxonomylists]: /templates/taxonomy-templates/ hugo-0.92.2/docs/content/en/tools/000077500000000000000000000000001420147000300167015ustar00rootroot00000000000000hugo-0.92.2/docs/content/en/tools/_index.md000066400000000000000000000016371420147000300205000ustar00rootroot00000000000000--- title: Developer Tools linktitle: Developer Tools Overview description: In addition to Hugo's powerful CLI, there is a large number of community-developed tool chains for Hugo developers. date: 2016-12-05 publishdate: 2016-12-05 lastmod: 2017-02-26 categories: [developer tools] keywords: [] menu: docs: parent: "tools" weight: 01 weight: 01 sections_weight: 01 draft: false --- One of Hugo's greatest strengths is its passionate---and always evolving---developer community. With the exception of the `highlight` shortcode mentioned in [Syntax Highlighting][syntax], the tools and other projects featured in this section are offerings from both commercial services and open-source projects, many of which are developed by Hugo developers just like you. [See the popularity of Hugo compared with other static site generators.][staticgen] [staticgen]: https://staticgen.com [syntax]: /tools/syntax-highlighting/ hugo-0.92.2/docs/content/en/tools/editors.md000066400000000000000000000065211420147000300207000ustar00rootroot00000000000000--- title: Editor Plug-ins for Hugo linktitle: Editor Plug-ins description: The Hugo community uses a wide range of preferred tools and has developed plug-ins for some of the most popular text editors to help automate parts of your workflow. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [developer tools] keywords: [editor, plug-ins] menu: docs: parent: "tools" weight: 50 weight: 50 sections_weight: 50 draft: false aliases: [] toc: false --- The Hugo community uses a wide range of preferred tools and has developed plug-ins for some of the most popular text editors to help automate parts of your workflow. ## Sublime Text * [Hugofy](https://github.com/akmittal/Hugofy). Hugofy is a plugin for Sublime Text 3 to make life easier to use Hugo static site generator. * [Hugo Snippets](https://packagecontrol.io/packages/Hugo%20Snippets). Hugo Snippets is a useful plugin for adding automatic snippets to Sublime Text 3. ## Visual Studio Code * [Hugofy](https://marketplace.visualstudio.com/items?itemName=akmittal.hugofy). Hugofy is a plugin for Visual Studio Code to "make life easier" when developing with Hugo. The source code can be found [here](https://github.com/akmittal/hugofy-vscode). * [Hugo Helper](https://marketplace.visualstudio.com/items?itemName=rusnasonov.vscode-hugo). Hugo Helper is a plugin for Visual Studio Code that has some useful commands for Hugo. The source code can be found [here](https://github.com/rusnasonov/vscode-hugo). * [Hugo Language and Syntax Support](https://marketplace.visualstudio.com/items?itemName=budparr.language-hugo-vscode). Hugo Language and Syntax Support is a Visual Studio Code plugin for Hugo syntax highlighting and snippets. The source code can be found [here](https://github.com/budparr/language-hugo-vscode). * [Hugo Themer](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-hugo-themer). Hugo Themer is an extension to help you while developing themes. It allows you to easily navigate through your theme files. * [Front Matter](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter). Once you go for a static site, you need to think about how you are going to manage your articles. Front matter is a tool that helps you maintaining the metadata/front matter of your articles like: creation date, modified date, slug, tile, SEO check, and many more... ## Emacs * [emacs-easy-hugo](https://github.com/masasam/emacs-easy-hugo). Emacs major mode for managing hugo blogs. Note that Hugo also supports [Org-mode][formats]. * [ox-hugo.el](https://ox-hugo.scripter.co). Native Org-mode exporter that exports to Blackfriday Markdown with Hugo front-matter. `ox-hugo` supports two common Org blogging flows --- exporting multiple Org sub-trees in a single file to multiple Hugo posts, and exporting a single Org file to a single Hugo post. It also leverages the Org tag and property inheritance features. See [*Why ox-hugo?*](https://ox-hugo.scripter.co/doc/why-ox-hugo/) for more. ## Vim * [Vim Hugo Helper](https://github.com/robertbasic/vim-hugo-helper). A small Vim plugin to help me with writing posts with Hugo. ## Atom * [Hugofy](https://atom.io/packages/hugofy). A Hugo Static Website Generator package for Atom. * [language-hugo](https://atom.io/packages/language-hugo). Adds syntax highlighting to Hugo files. [formats]: /content-management/formats/ hugo-0.92.2/docs/content/en/tools/frontends.md000066400000000000000000000040711420147000300212270ustar00rootroot00000000000000--- title: Frontend Interfaces with Hugo linktitle: Frontends description: Do you prefer a graphical user interface over a text editor? Give these frontends a try. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [developer tools] keywords: [frontend,gui] menu: docs: parent: "tools" weight: 40 weight: 40 sections_weight: 40 draft: false aliases: [] toc: false --- * [enwrite](https://github.com/zzamboni/enwrite). Enwrite enables evernote-powered, statically generated blogs and websites. Now posting to your blog or updating your website is as easy as writing a new note in Evernote! * [Lipi](https://github.com/SohanChy/Lipi). Lipi is a native GUI frontend written in Java to manage your Hugo websites. * [Netlify CMS](https://netlifycms.org). Netlify CMS is an open source, serverless solution for managing Git based content in static sites, and it works on any platform that can host static sites. A [Hugo/Netlify CMS starter](https://github.com/netlify-templates/one-click-hugo-cms) is available to get new projects running quickly. * [Hokus CMS](https://github.com/julianoappelklein/hokus). Hokus CMS is an open source, multi-platform, easy to use, desktop application for Hugo. Build from simple to complex user interfaces for Hugo websites by choosing from a dozen ready-to-use components — all for free, with no vendor lock-in. ## Commercial Services * [DATOCMS](https://www.datocms.com) DatoCMS is a fully customizable administrative area for your static websites. Use your favorite website generator, let your clients publish new content independently, and the host the site anywhere you like. * [Forestry.io](https://forestry.io/). Forestry is a git-backed CMS for Hugo, Gatsby, Jekyll and VuePress websites with support for GitHub, GitLab, Bitbucket and Azure Devops. Forestry provides a nice user interface to edit and model content for non technical editors. It supports S3, Cloudinary and Netlify Large Media integrations for storing media. Every time an update is made via the CMS, Forestry will commit changes back to your repo and vice-versa. hugo-0.92.2/docs/content/en/tools/migrations.md000066400000000000000000000135201420147000300214000ustar00rootroot00000000000000--- title: Migrate to Hugo linktitle: Migrations description: A list of community-developed tools for migrating from your existing static site generator or content management system to Hugo. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 keywords: [migrations,jekyll,wordpress,drupal,ghost,contentful] menu: docs: parent: "tools" weight: 10 weight: 10 sections_weight: 10 draft: false aliases: [/developer-tools/migrations/,/developer-tools/migrated/] toc: true --- This section highlights some projects around Hugo that are independently developed. These tools try to extend the functionality of our static site generator or help you to get started. {{% note %}} Do you know or maintain a similar project around Hugo? Feel free to open a [pull request](https://github.com/gohugoio/hugoDocs/pulls) on GitHub if you think it should be added. {{% /note %}} Take a look at this list of migration tools if you currently use other blogging tools like Jekyll or WordPress but intend to switch to Hugo instead. They'll take care to export your content into Hugo-friendly formats. ## Jekyll Alternatively, you can use the new [Jekyll import command](/commands/hugo_import_jekyll/). - [JekyllToHugo](https://github.com/SenjinDarashiva/JekyllToHugo) - A Small script for converting Jekyll blog posts to a Hugo site. - [ConvertToHugo](https://github.com/coderzh/ConvertToHugo) - Convert your blog from Jekyll to Hugo. ## Ghost - [ghostToHugo](https://github.com/jbarone/ghostToHugo) - Convert Ghost blog posts and export them to Hugo. ## Octopress - [octohug](https://github.com/codebrane/octohug) - Octopress to Hugo migrator. ## DokuWiki - [dokuwiki-to-hugo](https://github.com/wgroeneveld/dokuwiki-to-hugo) - Migrates your DokuWiki source pages from [DokuWiki syntax](https://www.dokuwiki.org/wiki:syntax) to Hugo Markdown syntax. Includes extra's like the TODO plugin. Written with extensibility in mind using python 3. Also generates a TOML header for each page. Designed to copypaste the wiki directory into your /content directory. ## WordPress - [wordpress-to-hugo-exporter](https://github.com/SchumacherFM/wordpress-to-hugo-exporter) - A one-click WordPress plugin that converts all posts, pages, taxonomies, metadata, and settings to Markdown and YAML which can be dropped into Hugo. (Note: If you have trouble using this plugin, you can [export your site for Jekyll](https://wordpress.org/plugins/jekyll-exporter/) and use Hugo's built in Jekyll converter listed above.) - [exitwp-for-hugo](https://github.com/wooni005/exitwp-for-hugo) - A python script which works with the xml export from WordPress and converts WordPress pages and posts to Markdown and YAML for hugo. - [blog2md](https://github.com/palaniraja/blog2md) - Works with [exported xml](https://en.support.wordpress.com/export/) file of your free YOUR-TLD.wordpress.com website. It also saves approved comments to `YOUR-POST-NAME-comments.md` file along with posts. - [wordhugopress](https://github.com/nantipov/wordhugopress) - A small utility written in Java, exports the entire WordPress site from the database and resource (e.g. images) files stored locally or remotely. Therefore, migration from the backup files is possible. Supports merging of the multiple WordPress sites into a single Hugo one. ## Medium - [medium2md](https://github.com/gautamdhameja/medium-2-md) - A simple Medium to Hugo exporter able to import stories in one command, including Front Matter. - [medium-to-hugo](https://github.com/bgadrian/medium-to-hugo) - CLI tool written in Go to export medium posts into a Hugo compatible Markdown format. Tags and images are included. All images will be downloaded locally and linked appropriately. ## Tumblr - [tumblr-importr](https://github.com/carlmjohnson/tumblr-importr) - An importer that uses the Tumblr API to create a Hugo static site. - [tumblr2hugomarkdown](https://github.com/Wysie/tumblr2hugomarkdown) - Export all your Tumblr content to Hugo Markdown files with preserved original formatting. - [Tumblr to Hugo](https://github.com/jipiboily/tumblr-to-hugo) - A migration tool that converts each of your Tumblr posts to a content file with a proper title and path. Furthermore, "Tumblr to Hugo" creates a CSV file with the original URL and the new path on Hugo, to help you setup the redirections. ## Drupal - [drupal2hugo](https://github.com/danapsimer/drupal2hugo) - Convert a Drupal site to Hugo. ## Joomla - [hugojoomla](https://github.com/davetcc/hugojoomla) - This utility written in Java takes a Joomla database and converts all the content into Markdown files. It changes any URLs that are in Joomla's internal format and converts them to a suitable form. ## Blogger - [blogimport](https://github.com/natefinch/blogimport) - A tool to import from Blogger posts to Hugo. - [blogger-to-hugo](https://pypi.org/project/blogger-to-hugo/) - Another tool to import Blogger posts to Hugo. It also downloads embedded images so they will be stored locally. - [blog2md](https://github.com/palaniraja/blog2md) - Works with [exported xml](https://support.google.com/blogger/answer/41387?hl=en) file of your YOUR-TLD.blogspot.com website. It also saves comments to `YOUR-POST-NAME-comments.md` file along with posts. - [BloggerToHugo](https://github.com/huanlin/blogger-to-hugo) - Yet another tool to import Blogger posts to Hugo. For Windows platform only, and .NET Framework 4.5 is required. See README.md before using this tool. ## Contentful - [contentful2hugo](https://github.com/ArnoNuyts/contentful2hugo) - A tool to create content-files for Hugo from content on [Contentful](https://www.contentful.com/). ## BlogML - [BlogML2Hugo](https://github.com/jijiechen/BlogML2Hugo) - A tool that helps you convert BlogML xml file to Hugo markdown files. Users need to take care of links to attachments and images by themselves. This helps the blogs that export BlogML files (e.g. BlogEngine.NET) transform to hugo sites easily. hugo-0.92.2/docs/content/en/tools/other.md000066400000000000000000000031251420147000300203450ustar00rootroot00000000000000--- title: Other Hugo Community Projects linktitle: Other Projects description: Some interesting projects developed by the Hugo community that don't quite fit into our other developer tool categories. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [developer tools] keywords: [frontend,gui] menu: docs: parent: "tools" weight: 70 weight: 70 sections_weight: 70 draft: false aliases: [] toc: false --- And for all the other small things around Hugo: * [hugo-gallery](https://github.com/icecreammatt/hugo-gallery) lets you create an image gallery for Hugo sites. * [flickr-hugo-embed](https://github.com/nikhilm/flickr-hugo-embed) prints shortcodes to embed a set of images from an album on Flickr into Hugo. * [hugo-openapispec-shortcode](https://github.com/tenfourty/hugo-openapispec-shortcode) A shortcode that allows you to include [Open API Spec](https://openapis.org) (formerly known as Swagger Spec) in a page. * [HugoPhotoSwipe](https://github.com/GjjvdBurg/HugoPhotoSwipe) makes it easy to create image galleries using PhotoSwipe. * [Hugo SFTP Upload](https://github.com/thomasmey/HugoSftpUpload) Syncs the local build of your Hugo website with your remote webserver via SFTP. * [Emacs Easy Hugo](https://github.com/masasam/emacs-easy-hugo) Emacs package for writing blog posts in markdown or org-mode and building your site with Hugo. * [JAMStack Themes](https://jamstackthemes.dev/ssg/hugo/). JAMStack themes is a collection of site themes filterable by static site generator and supported CMS to help build CMS-connected sites using Hugo (linking to Hugo-specific themes). hugo-0.92.2/docs/content/en/tools/search.md000066400000000000000000000065731420147000300205030ustar00rootroot00000000000000--- title: Search for your Hugo Website linktitle: Search description: See some of the open-source and commercial search options for your newly created Hugo website. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-26 categories: [developer tools] keywords: [search,tools] menu: docs: parent: "tools" weight: 60 weight: 60 sections_weight: 60 draft: false aliases: [] toc: true --- A static website with a dynamic search function? Yes, Hugo provides an alternative to embeddable scripts from Google or other search engines for static websites. Hugo allows you to provide your visitors with a custom search function by indexing your content files directly. * [GitHub Gist for Hugo Workflow](https://gist.github.com/sebz/efddfc8fdcb6b480f567). This gist contains a simple workflow to create a search index for your static website. It uses a simple Grunt script to index all your content files and [lunr.js](https://lunrjs.com/) to serve the search results. * [hugo-elasticsearch](https://www.npmjs.com/package/hugo-elasticsearch). Generate [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) indexes for Hugo static sites by parsing front matter. Hugo-Elasticsearch will generate a newline delimited JSON (NDJSON) file that can be bulk uploaded into Elasticsearch using any one of the available [clients](https://www.elastic.co/guide/en/elasticsearch/client/index.html). * [hugo-lunr](https://www.npmjs.com/package/hugo-lunr). A simple way to add site search to your static Hugo site using [lunr.js](https://lunrjs.com/). Hugo-lunr will create an index file of any html and markdown documents in your Hugo project. * [hugo-lunr-zh](https://www.npmjs.com/package/hugo-lunr-zh). A bit like Hugo-lunr, but Hugo-lunr-zh can help you separate the Chinese keywords. * [Github Gist for Fuse.js integration](https://gist.github.com/eddiewebb/735feb48f50f0ddd65ae5606a1cb41ae). This gist demonstrates how to leverage Hugo's existing build time processing to generate a searchable JSON index used by [Fuse.js](https://fusejs.io/) on the client side. Although this gist uses Fuse.js for fuzzy matching, any client side search tool capable of reading JSON indexes will work. Does not require npm, grunt or other build-time tools except Hugo! * [hugo-search-index](https://www.npmjs.com/package/hugo-search-index). A library containing Gulp tasks and a prebuilt browser script that implements search. Gulp generates a search index from project markdown files. * [hugofastsearch](https://gist.github.com/cmod/5410eae147e4318164258742dd053993). A usability and speed update to "GitHub Gist for Fuse.js integration" — global, keyboard-optimized search. ## Commercial Search Services * [Algolia](https://www.algolia.com/)'s Search API makes it easy to deliver a great search experience in your apps and websites. Algolia Search provides hosted full-text, numerical, faceted, and geolocalized search. * [Bonsai](https://www.bonsai.io) is a fully-managed hosted Elasticsearch service that is fast, reliable, and simple to set up. Easily ingest your docs from Hugo into Elasticsearch following [this guide from the docs](https://docs.bonsai.io/docs/hugo). * [ExpertRec](https://www.expertrec.com/) is a hosted search-as-a-service solution that is fast and scalable. Set-up and integration is extremely easy and takes only a few minutes. The search settings can be modified without coding using a dashboard. hugo-0.92.2/docs/content/en/tools/starter-kits.md000066400000000000000000000056701420147000300216670ustar00rootroot00000000000000--- title: Starter Kits linktitle: Starter Kits description: A list of community-developed projects designed to help you get up and running with Hugo. date: 2017-02-22 publishdate: 2017-02-01 lastmod: 2018-08-11 keywords: [starters,assets,pipeline] menu: docs: parent: "tools" weight: 30 weight: 30 sections_weight: 30 draft: false aliases: [/developer-tools/migrations/,/developer-tools/migrated/] toc: false --- Know of a Hugo-related starter kit that isn't mentioned here? [Please add it to the list.][addkit] {{% note "Starter Kits are Not Maintained by the Hugo Team"%}} The following starter kits are developed by active members of the Hugo community. If you find yourself having issues with any of the projects, it's best to file an issue directly with the project's maintainer(s). {{% /note %}} * [Hugo Wrapper][hugow]. Hugo Wrapper is a POSIX-style shell script which acts as a wrapper to download and run Hugo binary for your platform. It can be executed in variety of [Operating Systems][hugow-test] and [Command Shells][hugow-test]. * [Victor Hugo][]. Victor Hugo is a Hugo boilerplate for creating truly epic websites using Webpack as an asset pipeline. Victor Hugo uses post-css and Babel for CSS and JavaScript, respectively, and is actively maintained. * [GOHUGO AMP][]. GoHugo AMP is a starter theme that aims to make it easy to adopt [Google's AMP Project][amp]. The starter kit comes with 40+ shortcodes and partials plus automatic structured data. The project also includes a [separate site with extensive documentation][gohugodocs]. * [Blaupause][]. Blaupause is a developer-friendly Hugo starter kit based on Gulp tasks. It comes ES6-ready with several helpers for SVG and fonts and basic structure for HTML, SCSS, and JavaScript. * [hugulp][]. hugulp is a tool to optimize the assets of a Hugo website. The main idea is to recreate the famous Ruby on Rails Asset Pipeline, which minifies, concatenates and fingerprints the assets used in your website. * [Atlas][]. Atlas is a Hugo boilerplate designed to speed up development with support for Netlify, Hugo Pipes, SCSS & more. It's actively maintained and contributions are always welcome. * [Hyas][]. Hyas is a Hugo starter helping you build modern websites that are secure, fast, and SEO-ready — by default. It is Netlify-ready (functions, redirects, headers) and comes with [documentation](https://gethyas.com/) to easily make it your own. [addkit]: https://github.com/gohugoio/hugo/edit/master/docs/content/en/tools/starter-kits.md [amp]: https://amp.dev [Blaupause]: https://github.com/fspoettel/blaupause [GOHUGO AMP]: https://github.com/wildhaber/gohugo-amp [gohugodocs]: https://gohugo-amp.gohugohq.com/ [hugow]: https://github.com/khos2ow/hugo-wrapper [hugow-test]: https://github.com/khos2ow/hugo-wrapper#tested-on [hugulp]: https://github.com/jbrodriguez/hugulp [Victor Hugo]: https://github.com/netlify/victor-hugo [Atlas]: https://github.com/indigotree/atlas [Hyas]: https://github.com/h-enk/hyas hugo-0.92.2/docs/content/en/troubleshooting/000077500000000000000000000000001420147000300207705ustar00rootroot00000000000000hugo-0.92.2/docs/content/en/troubleshooting/_index.md000066400000000000000000000010541420147000300225600ustar00rootroot00000000000000--- title: Troubleshoot linktitle: Troubleshoot description: Frequently asked questions and known issues pulled from the Hugo Discuss forum. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 menu: docs: parent: "troubleshooting" weight: 1 weight: 1 draft: false hidesectioncontents: false slug: aliases: [/troubleshooting/faqs/,/faqs/] toc: false notesforauthors: --- The Troubleshooting section includes known issues, recent workarounds, and FAQs pulled from the [Hugo Discussion Forum][forum]. [forum]: https://discourse.gohugo.io hugo-0.92.2/docs/content/en/troubleshooting/build-performance.md000066400000000000000000000074041420147000300247150ustar00rootroot00000000000000--- title: Build Performance linktitle: Build Performance description: An overview of features used for diagnosing and improving performance issues in site builds. date: 2017-03-12 publishdate: 2017-03-12 lastmod: 2017-03-12 keywords: [performance, build] categories: [troubleshooting] menu: docs: parent: "troubleshooting" weight: 3 slug: aliases: [] toc: true --- {{% note %}} The example site used below is from https://github.com/gohugoio/hugo/tree/master/examples/blog {{% /note %}} ## Template Metrics Hugo is a very fast static site generator, but it is possible to write inefficient templates. Hugo's *template metrics* feature is extremely helpful in pinpointing which templates are executed most often and how long those executions take **in terms of CPU time**. | Metric Name | Description | |---------------------|-------------| | cumulative duration | The cumulative time spent executing a given template. | | average duration | The average time spent executing a given template. | | maximum duration | The maximum time a single execution took for a given template. | | count | The number of times a template was executed. | | template | The template name. | ``` ▶ hugo --templateMetrics Started building sites ... Built site for language en: 0 draft content 0 future content 0 expired content 2 regular pages created 22 other pages created 0 non-page files copied 0 paginator pages created 4 tags created 3 categories created total in 18 ms Template Metrics: cumulative average maximum duration duration duration count template ---------- -------- -------- ----- -------- 6.419663ms 583.605µs 994.374µs 11 _internal/_default/rss.xml 4.718511ms 1.572837ms 3.880742ms 3 indexes/category.html 4.642666ms 2.321333ms 3.282842ms 2 posts/single.html 4.364445ms 396.767µs 2.451372ms 11 partials/header.html 2.346069ms 586.517µs 903.343µs 4 indexes/tag.html 2.330919ms 211.901µs 2.281342ms 11 partials/header.includes.html 1.238976ms 103.248µs 446.084µs 12 posts/li.html 972.16µs 972.16µs 972.16µs 1 _internal/_default/sitemap.xml 953.597µs 953.597µs 953.597µs 1 index.html 822.263µs 822.263µs 822.263µs 1 indexes/post.html 567.498µs 51.59µs 112.205µs 11 partials/navbar.html 348.22µs 31.656µs 88.249µs 11 partials/meta.html 346.782µs 173.391µs 276.176µs 2 posts/summary.html 235.184µs 21.38µs 124.383µs 11 partials/footer.copyright.html 132.003µs 12µs 117.999µs 11 partials/menu.html 72.547µs 6.595µs 63.764µs 11 partials/footer.html ``` {{% note %}} **A Note About Parallelism** Hugo builds pages in parallel where multiple pages are generated simultaneously. Because of this parallelism, the sum of "cumulative duration" values is usually greater than the actual time it takes to build a site. {{% /note %}} ## Cached Partials Some `partial` templates such as sidebars or menus are executed many times during a site build. Depending on the content within the `partial` template and the desired output, the template may benefit from caching to reduce the number of executions. The [`partialCached`][partialCached] template function provides caching capabilities for `partial` templates. {{% tip %}} Note that you can create cached variants of each `partial` by passing additional parameters to `partialCached` beyond the initial context. See the `partialCached` documentation for more details. {{% /tip %}} [partialCached]:{{< ref "/functions/partialCached.md" >}} hugo-0.92.2/docs/content/en/troubleshooting/faq.md000066400000000000000000000055341420147000300220700ustar00rootroot00000000000000--- title: Frequently Asked Questions linktitle: FAQ description: Solutions to some common Hugo problems. date: 2018-02-10 categories: [troubleshooting] menu: docs: parent: "troubleshooting" keywords: [faqs] weight: 2 toc: true aliases: [/faq/] --- {{% note %}} **Note:** The answers/solutions presented below are short, and may not be enough to solve your problem. Visit [Hugo Discourse](https://discourse.gohugo.io/) and use the search. It that does not help, start a new topic and ask your questions. {{% /note %}} ## I can't see my content! Is your markdown file [in draft mode](https://gohugo.io/content-management/front-matter/#front-matter-variables)? When testing, run `hugo server` with the `-D` or `--buildDrafts` [switch](https://gohugo.io/getting-started/usage/#draft-future-and-expired-content). ## Can I set configuration variables via OS environment? Yes you can! See [Configure with Environment Variables](/getting-started/configuration/#configure-with-environment-variables). ## How do I schedule posts? 1. Set `publishDate` in the page [Front Matter](/content-management/front-matter/) to a datetime in the future. If you want the creation and publication datetime to be the same, it's also sufficient to only set `date`[^date-hierarchy]. 2. Build and publish at intervals. How to automate the "publish at intervals" part depends on your situation: * If you deploy from your own PC/server, you can automate with [Cron](https://en.wikipedia.org/wiki/Cron) or similar. * If your site is hosted on a service similar to [Netlify](https://www.netlify.com/) you can use a service such as [ifttt](https://ifttt.com/date_and_time) to schedule the updates. Also see this Twitter thread: {{< tweet user="ChrisShort" id="962380712027590657" >}} [^date-hierarchy]: See [Configure Dates](https://gohugo.io/getting-started/configuration/#configure-dates) for the order in which the different date variables are complemented by each other when not explicitly set. ## Can I use the latest Hugo version on Netlify? Yes you can! Read [this](/hosting-and-deployment/hosting-on-netlify/#configure-hugo-version-in-netlify). ## I get "TOCSS ... this feature is not available in your current Hugo version" If you process `SCSS` or `SASS` to `CSS` in your Hugo project, you need the Hugo `extended` version, or else you may see this error message: ```bash error: failed to transform resource: TOCSS: failed to transform "scss/main.scss" (text/x-scss): this feature is not available in your current Hugo version ``` We release two set of binaries for technical reasons. The extended version is not what you get by default for some installation methods. On the [release page](https://github.com/gohugoio/hugo/releases), look for archives with `extended` in the name. To build `hugo-extended`, use `go install --tags extended` To confirm, run `hugo version` and look for the word `extended`. hugo-0.92.2/docs/content/en/variables/000077500000000000000000000000001420147000300175115ustar00rootroot00000000000000hugo-0.92.2/docs/content/en/variables/_index.md000066400000000000000000000013231420147000300213000ustar00rootroot00000000000000--- title: Variables and Params linktitle: Variables Overview description: Page-, file-, taxonomy-, and site-level variables and parameters available in templates. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [variables and params] keywords: [variables,params,values,globals] draft: false menu: docs: parent: "variables" weight: 1 weight: 01 #rem sections_weight: 01 aliases: [/templates/variables/] toc: false --- Hugo's templates are context aware and make a large number of values available to you as you're creating views for your website. [Go templates]: /templates/introduction/ "Understand context in Go templates by learning the language's fundamental templating functions." hugo-0.92.2/docs/content/en/variables/files.md000066400000000000000000000032241420147000300211360ustar00rootroot00000000000000--- title: File Variables linktitle: description: "You can access filesystem-related data for a content file in the `.File` variable." date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [variables and params] keywords: [files] draft: false menu: docs: parent: "variables" weight: 40 weight: 40 sections_weight: 40 aliases: [/variables/file-variables/] toc: false --- {{% note "Rendering Local Files" %}} For information on creating shortcodes and templates that tap into Hugo's file-related feature set, see [Local File Templates](/templates/files/). {{% /note %}} The `.File` object contains the following fields: .File.Path : the original relative path of the page, relative to the content dir (e.g., `posts/foo.en.md`) .File.LogicalName : the name of the content file that represents a page (e.g., `foo.en.md`) .File.TranslationBaseName : the filename without extension or optional language identifier (e.g., `foo`) .File.ContentBaseName : is a either TranslationBaseName or name of containing folder if file is a leaf bundle. .File.BaseFileName : the filename without extension (e.g., `foo.en`) .File.Ext : the file extension of the content file (e.g., `md`). .File.Lang : the language associated with the given file if Hugo's [Multilingual features][multilingual] are enabled (e.g., `en`) .File.Dir : given the path `content/posts/dir1/dir2/`, the relative directory path of the content file will be returned (e.g., `posts/dir1/dir2/`). Note that the path separator (`\` or `/`) could be dependent on the operating system. .File.UniqueID : the MD5-checksum of the content file's path. [Multilingual]: /content-management/multilingual/ hugo-0.92.2/docs/content/en/variables/git.md000066400000000000000000000034171420147000300206230ustar00rootroot00000000000000--- title: Git Info Variables linktitle: Git Variables description: Get the last Git revision information for every content file. date: 2017-03-12 publishdate: 2017-03-12 lastmod: 2017-03-12 categories: [variables and params] keywords: [git] draft: false menu: docs: parent: "variables" weight: 70 weight: 70 sections_weight: 70 aliases: [/extras/gitinfo/] toc: false wip: false --- {{% note "`.GitInfo` Performance Considerations" %}} Hugo's Git integrations should be fairly performant but *can* increase your build time. This will depend on the size of your Git history. {{% /note %}} ## `.GitInfo` Prerequisites 1. The Hugo site must be in a Git-enabled directory. 2. The Git executable must be installed and in your system `PATH`. 3. The `.GitInfo` feature must be enabled in your Hugo project by passing `--enableGitInfo` flag on the command line or by setting `enableGitInfo` to `true` in your [site's configuration file][configuration]. ## The `.GitInfo` Object The `GitInfo` object contains the following fields: .AbbreviatedHash : the abbreviated commit hash (e.g., `866cbcc`) .AuthorName : the author's name, respecting [`.mailmap`](https://git-scm.com/docs/gitmailmap) .AuthorEmail : the author's email address, respecting [`.mailmap`](https://git-scm.com/docs/gitmailmap) .AuthorDate : the author date .Hash : the commit hash (e.g., `866cbccdab588b9908887ffd3b4f2667e94090c3`) .Subject : commit message subject (e.g., `tpl: Add custom index function`) ## `.Lastmod` If the `.GitInfo` feature is enabled, `.Lastmod` (on `Page`) is fetched from Git i.e. `.GitInfo.AuthorDate`. This behaviour can be changed by adding your own [front matter configuration for dates](/getting-started/configuration/#configure-front-matter). [configuration]: /getting-started/configuration/ hugo-0.92.2/docs/content/en/variables/hugo.md000066400000000000000000000030151420147000300207740ustar00rootroot00000000000000--- title: Hugo-specific Variables linktitle: Hugo Variables description: The `.Hugo` variable provides easy access to Hugo-related data. date: 2017-03-12 publishdate: 2017-03-12 lastmod: 2017-03-12 categories: [variables and params] keywords: [hugo,generator] draft: false menu: docs: parent: "variables" weight: 60 weight: 60 sections_weight: 60 aliases: [] toc: false wip: false --- {{% warning "Deprecated" %}} Page's `.Hugo` is deprecated and will be removed in a future release. Use the global `hugo` function. For example: `hugo.Generator`. {{% /warning %}} It contains the following fields: .Hugo.Generator : `` tag for the version of Hugo that generated the site. `.Hugo.Generator` outputs a *complete* HTML tag; e.g. `` .Hugo.Version : the current version of the Hugo binary you are using e.g. `0.13-DEV`
    .Hugo.Environment : the current running environment as defined through the `--environment` cli tag. .Hugo.CommitHash : the git commit hash of the current Hugo binary e.g. `0e8bed9ccffba0df554728b46c5bbf6d78ae5247` .Hugo.BuildDate : the compile date of the current Hugo binary formatted with RFC 3339 e.g. `2002-10-02T10:00:00-05:00`
    {{% note "Use the Hugo Generator Tag" %}} We highly recommend using `.Hugo.Generator` in your website's ``. `.Hugo.Generator` is included by default in all themes hosted on [themes.gohugo.io](https://themes.gohugo.io). The generator tag allows the Hugo team to track the usage and popularity of Hugo. {{% /note %}} hugo-0.92.2/docs/content/en/variables/menus.md000066400000000000000000000077231420147000300211730ustar00rootroot00000000000000--- title: Menu Entry Properties linktitle: Menu Entry Properties description: A menu entry in a menu-template has specific variables and functions to make menu management easier. date: 2017-03-12 publishdate: 2017-03-12 lastmod: 2017-03-12 categories: [variables and params] keywords: [menus] draft: false menu: docs: title: "variables defined by a menu entry" parent: "variables" weight: 50 weight: 50 sections_weight: 50 aliases: [/variables/menu/] toc: false --- A **menu entry** has the following properties available that can be used in a [menu template][menu-template]. ## Menu Entry Variables .Menu : _string_
    Name of the **menu** that contains this **menu entry**. .URL : _string_
    URL that the menu entry points to. The `url` key, if set for the menu entry, sets this value. If that key is not set, and if the menu entry is set in a page front-matter, this value defaults to the page's `.RelPermalink`. .Page : _\*Page_
    Reference to the [page object][page-object] associated with the menu entry. This will be non-nil if the menu entry is set via a page's front-matter and not via the site config. .PageRef {{< new-in "0.86.0" >}} : _string_
    Can be set if defined in site config and the menu entry refers to a Page. [site.GetPage](/functions/getpage/) will be used to do the page lookup. If this is set, you don't need to set the `URL`. .Name : _string_
    Name of the menu entry. The `name` key, if set for the menu entry, sets this value. If that key is not set, and if the menu entry is set in a page front-matter, this value defaults to the page's `.LinkTitle`. .Identifier : _string_
    Value of the `identifier` key if set for the menu entry. This value must be unique for each menu entry. **It is necessary to set a unique identifier manually if two or more menu entries have the same `.Name`.** .Pre : _template.HTML_
    Value of the `pre` key if set for the menu entry. This value typically contains a string representing HTML. .Post : _template.HTML_
    Value of the `post` key if set for the menu entry. This value typically contains a string representing HTML. .Weight : _int_
    Value of the `weight` key if set for the menu entry. By default the entries in a menu are sorted ascending by their `weight`. If that key is not set, and if the menu entry is set in a page front-matter, this value defaults to the page's `.Weight`. .Parent : _string_
    Name (or Identifier if present) of this menu entry's parent **menu entry**. The `parent` key, if set for the menu entry, sets this value. If this key is set, this menu entry nests under that parent entry, else it nests directly under the `.Menu`. .Children : _Menu_
    This value is auto-populated by Hugo. It is a collection of children menu entries, if any, under the current menu entry. ## Menu Entry Functions Menus also have the following functions available: .HasChildren : _boolean_
    Returns `true` if `.Children` is non-nil. .KeyName : _string_
    Returns the `.Identifier` if present, else returns the `.Name`. .IsEqual : _boolean_
    Returns `true` if the two compared menu entries represent the same menu entry. .IsSameResource : _boolean_
    Returns `true` if the two compared menu entries have the same `.URL`. .Title : _string_
    Link title, meant to be used in the `title` attribute of a menu entry's ``-tags. Returns the menu entry's `title` key if set. Else, if the menu entry was created through a page's front-matter, it returns the page's `.LinkTitle`. Else, it just returns an empty string. ## Other Menu-related Functions Additionally, here are some relevant methods available to menus on a page: .IsMenuCurrent : _(menu string, menuEntry *MenuEntry ) boolean_
    See [`.IsMenuCurrent` method](/functions/ismenucurrent/). .HasMenuCurrent : _(menu string, menuEntry *MenuEntry) boolean_
    See [`.HasMenuCurrent` method](/functions/hasmenucurrent/). [menu-template]: /templates/menu-templates/ [page-object]: /variables/page/ hugo-0.92.2/docs/content/en/variables/page.md000066400000000000000000000271541420147000300207600ustar00rootroot00000000000000--- title: Page Variables linktitle: description: Page-level variables are defined in a content file's front matter, derived from the content's file location, or extracted from the content body itself. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [variables and params] keywords: [pages] draft: false menu: docs: title: "variables defined by a page" parent: "variables" weight: 20 weight: 20 sections_weight: 20 aliases: [] toc: true --- The following is a list of page-level variables. Many of these will be defined in the front matter, derived from file location, or extracted from the content itself. {{% note "`.Scratch`" %}} See [`.Scratch`](/functions/scratch/) for page-scoped, writable variables. {{% /note %}} ## Page Variables .AlternativeOutputFormats : contains all alternative formats for a given page; this variable is especially useful `link rel` list in your site's ``. (See [Output Formats](/templates/output-formats/).) .Aliases : aliases of this page .BundleType : the [bundle] type: `leaf`, `branch`, or an empty string if the page is not a bundle. .Content : the content itself, defined below the front matter. .Data : the data specific to this type of page. .Date : the date associated with the page; `.Date` pulls from the `date` field in a content's front matter. See also `.ExpiryDate`, `.PublishDate`, and `.Lastmod`. .Description : the description for the page. .Dir : the path of the folder containing this content file. The path is relative to the `content` folder. .Draft : a boolean, `true` if the content is marked as a draft in the front matter. .ExpiryDate : the date on which the content is scheduled to expire; `.ExpiryDate` pulls from the `expirydate` field in a content's front matter. See also `.PublishDate`, `.Date`, and `.Lastmod`. .File : filesystem-related data for this content file. See also [File Variables][]. .FuzzyWordCount : the approximate number of words in the content. .Hugo : see [Hugo Variables](/variables/hugo/). .IsHome : `true` in the context of the [homepage](/templates/homepage/). .IsNode : always `false` for regular content pages. .IsPage : always `true` for regular content pages. .IsSection : `true` if [`.Kind`](/templates/section-templates/#page-kinds) is `section`. .IsTranslated : `true` if there are translations to display. .Keywords : the meta keywords for the content. .Kind : the page's *kind*. Possible return values are `page`, `home`, `section`, `taxonomy`, or `term`. Note that there are also `RSS`, `sitemap`, `robotsTXT`, and `404` kinds, but these are only available during the rendering of each of these respective page's kind and therefore *not* available in any of the `Pages` collections. .Language : a language object that points to the language's definition in the site `config`. `.Language.Lang` gives you the language code. .Lastmod : the date the content was last modified. `.Lastmod` pulls from the `lastmod` field in a content's front matter. - If `lastmod` is not set, and `.GitInfo` feature is disabled, the front matter `date` field will be used. - If `lastmod` is not set, and `.GitInfo` feature is enabled, `.GitInfo.AuthorDate` will be used instead. See also `.ExpiryDate`, `.Date`, `.PublishDate`, and [`.GitInfo`][gitinfo]. .LinkTitle : access when creating links to the content. If set, Hugo will use the `linktitle` from the front matter before `title`. .Next : Points up to the next [regular page](/variables/site/#site-pages) (sorted by Hugo's [default sort](/templates/lists#default-weight-date-linktitle-filepath)). Example: `{{with .Next}}{{.Permalink}}{{end}}`. Calling `.Next` from the first page returns `nil`. .NextInSection : Points up to the next [regular page](/variables/site/#site-pages) below the same top level section (e.g. in `/blog`)). Pages are sorted by Hugo's [default sort](/templates/lists#default-weight-date-linktitle-filepath). Example: `{{with .NextInSection}}{{.Permalink}}{{end}}`. Calling `.NextInSection` from the first page returns `nil`. .OutputFormats : contains all formats, including the current format, for a given page. Can be combined the with [`.Get` function](/functions/get/) to grab a specific format. (See [Output Formats](/templates/output-formats/).) .Pages : a collection of associated pages. This value will be `nil` within the context of regular content pages. See [`.Pages`](#pages). .Permalink : the Permanent link for this page; see [Permalinks](/content-management/urls/) .Plain : the Page content stripped of HTML tags and presented as a string. .PlainWords : the slice of strings that results from splitting .Plain into words, as defined in Go's [strings.Fields](https://golang.org/pkg/strings/#Fields). .Prev : Points down to the previous [regular page](/variables/site/#site-pages) (sorted by Hugo's [default sort](/templates/lists#default-weight-date-linktitle-filepath)). Example: `{{if .Prev}}{{.Prev.Permalink}}{{end}}`. Calling `.Prev` from the last page returns `nil`. .PrevInSection : Points down to the previous [regular page](/variables/site/#site-pages) below the same top level section (e.g. `/blog`). Pages are sorted by Hugo's [default sort](/templates/lists#default-weight-date-linktitle-filepath). Example: `{{if .PrevInSection}}{{.PrevInSection.Permalink}}{{end}}`. Calling `.PrevInSection` from the last page returns `nil`. .PublishDate : the date on which the content was or will be published; `.Publishdate` pulls from the `publishdate` field in a content's front matter. See also `.ExpiryDate`, `.Date`, and `.Lastmod`. .RSSLink (deprecated) : link to the page's RSS feed. This is deprecated. You should instead do something like this: `{{ with .OutputFormats.Get "RSS" }}{{ .RelPermalink }}{{ end }}`. .RawContent : raw markdown content without the front matter. Useful with [remarkjs.com]( https://remarkjs.com) .ReadingTime : the estimated time, in minutes, it takes to read the content. .Resources : resources such as images and CSS that are associated with this page .Ref : returns the permalink for a given reference (e.g., `.Ref "sample.md"`). `.Ref` does *not* handle in-page fragments correctly. See [Cross References](/content-management/cross-references/). .RelPermalink : the relative permanent link for this page. .RelRef : returns the relative permalink for a given reference (e.g., `RelRef "sample.md"`). `.RelRef` does *not* handle in-page fragments correctly. See [Cross References](/content-management/cross-references/). .Site : see [Site Variables](/variables/site/). .Sites : returns all sites (languages). A typical use case would be to link back to the main language: `
    ...`. .Sites.First : returns the site for the first language. If this is not a multilingual setup, it will return itself. .Summary : a generated summary of the content for easily showing a snippet in a summary view. The breakpoint can be set manually by inserting <!--more--> at the appropriate place in the content page, or the summary can be written independent of the page text. See [Content Summaries](/content-management/summaries/) for more details. .TableOfContents : the rendered [table of contents](/content-management/toc/) for the page. .Title : the title for this page. .Translations : a list of translated versions of the current page. See [Multilingual Mode](/content-management/multilingual/) for more information. .TranslationKey : the key used to map language translations of the current page. See [Multilingual Mode](/content-management/multilingual/) for more information. .Truncated : a boolean, `true` if the `.Summary` is truncated. Useful for showing a "Read more..." link only when necessary. See [Summaries](/content-management/summaries/) for more information. .Type : the [content type](/content-management/types/) of the content (e.g., `posts`). .UniqueID (deprecated) : the MD5-checksum of the content file's path. This variable is deprecated and will be removed, use `.File.UniqueID` instead. .Weight : assigned weight (in the front matter) to this content, used in sorting. .WordCount : the number of words in the content. ## Section Variables and Methods Also see [Sections](/content-management/sections/). {{< readfile file="/content/en/readfiles/sectionvars.md" markdown="true" >}} ## The `.Pages` Variable {#pages} `.Pages` is an alias to `.Data.Pages`. It is conventional to use the aliased form `.Pages`. ### `.Pages` compared to `.Site.Pages` {{< getcontent path="readfiles/pages-vs-site-pages.md" >}} ## Page-level Params Any other value defined in the front matter in a content file, including taxonomies, will be made available as part of the `.Params` variable. ``` --- title: My First Post date: 2017-02-20T15:26:23-06:00 categories: [one] tags: [two,three,four] ``` With the above front matter, the `tags` and `categories` taxonomies are accessible via the following: * `.Params.tags` * `.Params.categories` {{% note "Casing of Params" %}} Page-level `.Params` are *only* accessible in lowercase. {{% /note %}} The `.Params` variable is particularly useful for the introduction of user-defined front matter fields in content files. For example, a Hugo website on book reviews could have the following front matter in `/content/review/book01.md`: ``` --- ... affiliatelink: "http://www.my-book-link.here" recommendedby: "My Mother" ... --- ``` These fields would then be accessible to the `/themes/yourtheme/layouts/review/single.html` template through `.Params.affiliatelink` and `.Params.recommendedby`, respectively. Two common situations where this type of front matter field could be introduced is as a value of a certain attribute like `href=""` or by itself to be displayed as text to the website's visitors. {{< code file="/themes/yourtheme/layouts/review/single.html" >}}

    Buy this book

    It was recommended by {{ .Params.recommendedby }}.

    {{< /code >}} This template would render as follows, assuming you've set [`uglyURLs`](/content-management/urls/) to `false` in your [site `config`](/getting-started/configuration/): {{< output file="yourbaseurl/review/book01/index.html" >}}

    Buy this book

    It was recommended by my Mother.

    {{< /output >}} {{% note %}} See [Archetypes](/content-management/archetypes/) for consistency of `Params` across pieces of content. {{% /note %}} ### The `.Param` Method In Hugo, you can declare params in individual pages and globally for your entire website. A common use case is to have a general value for the site param and a more specific value for some of the pages (i.e., a header image): ``` {{ $.Param "header_image" }} ``` The `.Param` method provides a way to resolve a single value according to it's definition in a page parameter (i.e. in the content's front matter) or a site parameter (i.e., in your `config`). ### Access Nested Fields in Front Matter When front matter contains nested fields like the following: ``` --- author: given_name: John family_name: Feminella display_name: John Feminella --- ``` `.Param` can access these fields by concatenating the field names together with a dot: ``` {{ $.Param "author.display_name" }} ``` If your front matter contains a top-level key that is ambiguous with a nested key, as in the following case: ``` --- favorites.flavor: vanilla favorites: flavor: chocolate --- ``` The top-level key will be preferred. Therefore, the following method, when applied to the previous example, will print `vanilla` and not `chocolate`: ``` {{ $.Param "favorites.flavor" }} => vanilla ``` [gitinfo]: /variables/git/ [File Variables]: /variables/files/ [bundle]: {{< relref "content-management/page-bundles" >}} hugo-0.92.2/docs/content/en/variables/pages.md000066400000000000000000000021351420147000300211330ustar00rootroot00000000000000--- title: Pages Methods linktitle: description: Pages is the core page collection in Hugo and has many useful methods. date: 2019-10-20 categories: [variables and params] keywords: [pages] draft: false menu: docs: title: "methods defined on a page collection" parent: "variables" weight: 21 weight: 21 sections_weight: 20 aliases: [/pages] toc: true --- Also see [List templates](/templates/lists) for an overview of sort methods. ## .Next PAGE `.Next` and `.Prev` on `Pages` work similar to the methods with the same names on `.Page`, but are more flexible (and slightly slower) as they can be used on any page collection. `.Next` points **up** to the next page relative to the page sent in as the argument. Example: `{{with .Site.RegularPages.Next . }}{{.RelPermalink}}{{end}}`. Calling `.Next` with the first page in the collection returns `nil`. ## .Prev PAGE `.Prev` points **down** to the previous page relative to the page sent in as the argument. Example: `{{with .Site.RegularPages.Prev . }}{{.RelPermalink}}{{end}}`. Calling `.Prev` with the last page in the collection returns `nil`. hugo-0.92.2/docs/content/en/variables/shortcodes.md000066400000000000000000000033041420147000300222100ustar00rootroot00000000000000--- title: Shortcode Variables linktitle: Shortcode Variables description: Shortcodes can access page variables and also have their own specific built-in variables. date: 2017-03-12 publishdate: 2017-03-12 lastmod: 2017-03-12 categories: [variables and params] keywords: [shortcodes] draft: false menu: docs: parent: "variables" weight: 20 weight: 20 sections_weight: 20 aliases: [] toc: false --- [Shortcodes][shortcodes] have access to parameters delimited in the shortcode declaration via [`.Get`][getfunction], page- and site-level variables, and also the following shortcode-specific fields: .Name : Shortcode name. .Ordinal : Zero-based ordinal in relation to its parent. If the parent is the page itself, this ordinal will represent the position of this shortcode in the page content. .Parent : provides access to the parent shortcode context in nested shortcodes. This can be very useful for inheritance of common shortcode parameters from the root. .Position : Contains [filename and position](https://godoc.org/github.com/gohugoio/hugo/common/text#Position) for the shortcode in a page. Note that this can be relatively expensive to calculate, and is meant for error reporting. See [Error Handling in Shortcodes](/templates/shortcode-templates/#error-handling-in-shortcodes). .IsNamedParams : boolean that returns `true` when the shortcode in question uses [named rather than positional parameters][shortcodes] .Inner : represents the content between the opening and closing shortcode tags when a [closing shortcode][markdownshortcode] is used [getfunction]: /functions/get/ [markdownshortcode]: /content-management/shortcodes/#shortcodes-with-markdown [shortcodes]: /templates/shortcode-templates/ hugo-0.92.2/docs/content/en/variables/site.md000066400000000000000000000115041420147000300210000ustar00rootroot00000000000000--- title: Site Variables linktitle: Site Variables description: Many, but not all, site-wide variables are defined in your site's configuration. However, Hugo provides a number of built-in variables for convenient access to global values in your templates. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [variables and params] keywords: [global,site] draft: false menu: docs: parent: "variables" weight: 10 weight: 10 sections_weight: 10 aliases: [/variables/site-variables/] toc: true --- The following is a list of site-level (aka "global") variables. Many of these variables are defined in your site's [configuration file][config], whereas others are built into Hugo's core for convenient usage in your templates. ## Get the Site object from a partial All the methods below, e.g. `.Site.RegularPages` can also be reached via the global [`site`](/functions/site/) function, e.g. `site.RegularPages`, which can be handy in partials where the `Page` object isn't easily available. {{< new-in "0.53" >}}. ## Site Variables List .Site.AllPages : array of all pages, regardless of their translation. .Site.Author : a map of the authors as defined in the site configuration. .Site.BaseURL : the base URL for the site as defined in the site configuration. .Site.BuildDrafts : a boolean (default: `false`) to indicate whether to build drafts as defined in the site configuration. .Site.Copyright : a string representing the copyright of your website as defined in the site configuration. .Site.Data : custom data, see [Data Templates](/templates/data-templates/). .Site.DisqusShortname : a string representing the shortname of the Disqus shortcode as defined in the site configuration. .Site.GoogleAnalytics : a string representing your tracking code for Google Analytics as defined in the site configuration. .Site.Home : reference to the homepage's [page object](https://gohugo.io/variables/page/) .Site.IsMultiLingual : whether there are more than one language in this site. See [Multilingual](/content-management/multilingual/) for more information. .Site.IsServer : a boolean to indicate if the site is being served with Hugo's built-in server. See [`hugo server`](/commands/hugo_server/) for more information. .Site.Language.Lang : the language code of the current locale (e.g., `en`). .Site.Language.LanguageName : the full language name (e.g. `English`). .Site.Language.Weight : the weight that defines the order in the `.Site.Languages` list. .Site.Language : indicates the language currently being used to render the website. This object's attributes are set in site configurations' language definition. .Site.LanguageCode : a string representing the language tag as defined in the site configuration. .Site.LanguagePrefix : this can be used to prefix URLs to point to the correct language. It will even work when only one defined language. See also the functions [absLangURL](/functions/abslangurl/) and [relLangURL](/functions/rellangurl). .Site.Languages : an ordered list (ordered by defined weight) of languages. .Site.LastChange : a string representing the date/time of the most recent change to your site. This string is based on the [`date` variable in the front matter](/content-management/front-matter) of your content pages. .Site.Menus : all of the menus in the site. .Site.Pages : array of all content ordered by Date with the newest first. This array contains only the pages in the current language. See [`.Site.Pages`](#site-pages). .Site.RegularPages : a shortcut to the *regular* page collection. `.Site.RegularPages` is equivalent to `where .Site.Pages "Kind" "page"`. See [`.Site.Pages`](#site-pages). .Site.Sections : top-level directories of the site. .Site.Taxonomies : the [taxonomies](/taxonomies/usage/) for the entire site. Also see section [Use `.Site.Taxonomies` Outside of Taxonomy Templates](/variables/taxonomy/#use-sitetaxonomies-outside-of-taxonomy-templates). .Site.Title : a string representing the title of the site. ## The `.Site.Params` Variable `.Site.Params` is a container holding the values from the `params` section of your site configuration. ### Example: `.Site.Params` The following `config.[yaml|toml|json]` defines a site-wide param for `description`: {{< code-toggle file="config" >}} baseURL = "https://yoursite.example.com/" [params] description = "Tesla's Awesome Hugo Site" author = "Nikola Tesla" {{}} You can use `.Site.Params` in a [partial template](/templates/partials/) to call the default site description: {{< code file="layouts/partials/head.html" >}} {{< /code >}} ## The `.Site.Pages` Variable {#site-pages} ### `.Site.Pages` compared to `.Pages` {{< getcontent path="readfiles/pages-vs-site-pages.md" >}} [config]: /getting-started/configuration/ hugo-0.92.2/docs/content/en/variables/sitemap.md000066400000000000000000000012301420147000300214710ustar00rootroot00000000000000--- title: Sitemap Variables linktitle: Sitemap Variables description: date: 2017-03-12 publishdate: 2017-03-12 lastmod: 2017-03-12 categories: [variables and params] keywords: [sitemap] draft: false menu: docs: parent: "variables" weight: 80 weight: 80 sections_weight: 80 aliases: [] toc: false --- A sitemap is a `Page` and therefore has all the [page variables][pagevars] available to use sitemap templates. They also have the following sitemap-specific variables available to them: .Sitemap.ChangeFreq : the page change frequency .Sitemap.Priority : the priority of the page .Sitemap.Filename : the sitemap filename [pagevars]: /variables/page/hugo-0.92.2/docs/content/en/variables/taxonomy.md000066400000000000000000000054571420147000300217240ustar00rootroot00000000000000--- title: Taxonomy Variables linktitle: description: Taxonomy pages are of type `Page` and have all page-, site-, and list-level variables available to them. However, taxonomy terms templates have additional variables available to their templates. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 categories: [variables and params] keywords: [taxonomies,terms] draft: false menu: docs: parent: "variables" weight: 30 weight: 30 sections_weight: 30 aliases: [] toc: true --- ## Taxonomy Terms Page Variables [Taxonomy terms pages][taxonomytemplates] are of the type `Page` and have the following additional variables. For example, the following fields would be available in `layouts/_defaults/terms.html`, depending on how you organize your [taxonomy templates][taxonomytemplates]: .Data.Singular : The singular name of the taxonomy (e.g., `tags => tag`) .Data.Plural : The plural name of the taxonomy (e.g., `tags => tags`) .Data.Pages : The list of pages in the taxonomy .Data.Terms : The taxonomy itself .Data.Terms.Alphabetical : The taxonomy terms alphabetized .Data.Terms.ByCount : The Terms ordered by popularity Note that `.Data.Terms.Alphabetical` and `.Data.Terms.ByCount` can also be reversed: * `.Data.Terms.Alphabetical.Reverse` * `.Data.Terms.ByCount.Reverse` ## Use `.Site.Taxonomies` Outside of Taxonomy Templates The `.Site.Taxonomies` variable holds all the taxonomies defined site-wide. `.Site.Taxonomies` is a map of the taxonomy name to a list of its values (e.g., `"tags" -> ["tag1", "tag2", "tag3"]`). Each value, though, is not a string but rather a *Taxonomy variable*. ## The `.Taxonomy` Variable The `.Taxonomy` variable, available, for example, as `.Site.Taxonomies.tags`, contains the list of tags (values) and, for each tag, their corresponding content pages. ### Example Usage of `.Site.Taxonomies` The following [partial template][partials] will list all your site's taxonomies, each of their keys, and all the content assigned to each of the keys. For more examples of how to order and render your taxonomies, see [Taxonomy Templates][taxonomytemplates]. {{< code file="all-taxonomies-keys-and-pages.html" download="all-taxonomies-keys-and-pages.html" >}}
      {{ range $taxonomyname, $taxonomy := .Site.Taxonomies }}
    • {{ $taxonomyname }}
        {{ range $key, $value := $taxonomy }}
      • {{ $key }}
      • {{ end }}
    • {{ end }}
    {{< /code >}} [partials]: /templates/partials/ [taxonomytemplates]: /templates/taxonomy-templates/ hugo-0.92.2/docs/content/zh/000077500000000000000000000000001420147000300155605ustar00rootroot00000000000000hugo-0.92.2/docs/content/zh/_index.md000066400000000000000000000052241420147000300173530ustar00rootroot00000000000000--- title: "世界上最快的网站构建框架 The world’s fastest framework for building websites" date: 2017-03-02T12:00:00-05:00 features: - heading: Blistering Speed image_path: /images/icon-fast.svg tagline: What's modern about waiting for your site to build? copy: Hugo is the fastest tool of its kind. At <1 ms per page, the average site builds in less than a second. - heading: Robust Content Management image_path: /images/icon-content-management.svg tagline: Flexibility rules. Hugo is a content strategist's dream. copy: Hugo supports unlimited content types, taxonomies, menus, dynamic API-driven content, and more, all without plugins. - heading: Shortcodes image_path: /images/icon-shortcodes.svg tagline: Hugo's shortcodes are Markdown's hidden superpower. copy: We love the beautiful simplicity of markdown’s syntax, but there are times when we want more flexibility. Hugo shortcodes allow for both beauty and flexibility. - heading: Built-in Templates image_path: /images/icon-built-in-templates.svg tagline: Hugo has common patterns to get your work done quickly. copy: Hugo ships with pre-made templates to make quick work of SEO, commenting, analytics and other functions. One line of code, and you're done. - heading: Multilingual and i18n image_path: /images/icon-multilingual2.svg tagline: Polyglot baked in. copy: Hugo provides full i18n support for multi-language sites with the same straightforward development experience Hugo users love in single-language sites. - heading: Custom Outputs image_path: /images/icon-custom-outputs.svg tagline: HTML not enough? copy: Hugo allows you to output your content in multiple formats, including JSON or AMP, and makes it easy to create your own. sections: - heading: "100s of Themes" cta: Check out the Hugo's themes. link: https://themes.gohugo.io/ color_classes: bg-accent-color white image: /images/homepage-screenshot-hugo-themes.jpg copy: "Hugo provides a robust theming system that is easy to implement but capable of producing even the most complicated websites." - heading: "Capable Templating" cta: Get Started. link: templates/ color_classes: bg-primary-color-light black image: /images/home-page-templating-example.png copy: "Hugo's Go-based templating provides just the right amount of logic to build anything from the simple to complex. If you prefer Jade/Pug-like syntax, you can also use Amber, Ace, or any combination of the three." --- Hugo is one of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again. hugo-0.92.2/docs/content/zh/about/000077500000000000000000000000001420147000300166725ustar00rootroot00000000000000hugo-0.92.2/docs/content/zh/about/_index.md000066400000000000000000000005371420147000300204670ustar00rootroot00000000000000--- title: 关于 Hugo linktitle: 概览 description: Hugo 的特色、规划、许可和动力。 date: 2018-04-26 publishdate: 2018-04-26 lastmod: 2018-04-26 categories: [] keywords: [] menu: docs: parent: "about" weight: 1 weight: 1 draft: false aliases: [/about-hugo/,/docs/] toc: false --- Hugo 不是一般的静态网站生成器。 hugo-0.92.2/docs/content/zh/content-management/000077500000000000000000000000001420147000300213445ustar00rootroot00000000000000hugo-0.92.2/docs/content/zh/content-management/_index.md000066400000000000000000000013351420147000300231360ustar00rootroot00000000000000--- title: 内容管理 linktitle: 内容管理概览 description: Hugo 可以管理大型的静态网站,支持骨架、内容类型、菜单、引用、概要等等。 date: 2018-04-23 publishdate: 2018-04-23 lastmod: 2018-04-23 menu: docs: parent: "content-management" weight: 1 keywords: [source, organization] categories: [content management] weight: 01 #rem draft: false aliases: [/content/,/content/organization] toc: false isCJKLanguage: true --- 一个实用的静态网站生成器,需要超越“文件头” (front matter) 和模板的等基本功能,才能兼备可伸缩性和可管理性,满足用户所需。Hugo 不仅是给开发者设计的,也同样适用于内容管理员和写作人员。 hugo-0.92.2/docs/content/zh/documentation.md000066400000000000000000000013101420147000300207460ustar00rootroot00000000000000--- title: Hugo 说明文档 linktitle: Hugo description: Hugo is the world's fastest static website engine. It's written in Go (aka Golang) and developed by bep, spf13 and friends. date: 2017-02-01 publishdate: 2017-02-01 menu: main: parent: "section name" weight: 01 weight: 01 #rem draft: false slug: aliases: [] toc: false layout: documentation-home isCJKLanguage: true --- Hugo 号称**世界上最快的静态网站引擎**。它是以 Go (即 Golang) 编程语言所写成,并由 [bep](https://github.com/bep)、[spf13](https://github.com/spf13) 和[朋友们](https://github.com/gohugoio/hugo/graphs/contributors) 共同开发。 下面是我们说明文档中最常用和实用的章节: hugo-0.92.2/docs/content/zh/news/000077500000000000000000000000001420147000300165345ustar00rootroot00000000000000hugo-0.92.2/docs/content/zh/news/_index.md000066400000000000000000000000701420147000300203210ustar00rootroot00000000000000--- title: "Hugo 新闻" aliases: [/release-notes/] --- hugo-0.92.2/docs/content/zh/templates/000077500000000000000000000000001420147000300175565ustar00rootroot00000000000000hugo-0.92.2/docs/content/zh/templates/_index.md000066400000000000000000000006161420147000300213510ustar00rootroot00000000000000--- title: 模板 Templates linktitle: 模板概览 description: Go templating, template types and lookup order, shortcodes, and data. date: 2017-02-01 publishdate: 2017-02-01 lastmod: 2017-02-01 menu: docs: parent: "templates" weight: 01 weight: 01 #rem categories: [templates] keywords: [] draft: false aliases: [/templates/overview/,/templates/content] toc: false notesforauthors: --- hugo-0.92.2/docs/content/zh/templates/base.md000066400000000000000000000115501420147000300210140ustar00rootroot00000000000000--- title: Base 模板 and Blocks linktitle: description: The base and block constructs allow you to define the outer shell of your master templates (i.e., the chrome of the page). date: 2017-02-01 publishdate: 2018-08-11 lastmod: 2017-02-01 categories: [templates,fundamentals] keywords: [blocks,base] menu: docs: parent: "templates" weight: 20 weight: 20 sections_weight: 20 draft: false aliases: [/templates/blocks/,/templates/base-templates-and-blocks/] toc: true --- The `block` keyword allows you to define the outer shell of your pages' one or more master template(s) and then fill in or override portions as necessary. {{< youtube QVOMCYitLEc >}} ## Base Template Lookup Order The [lookup order][lookup] for base templates is as follows: 1. `/layouts/section/-baseof.html` 2. `/themes//layouts/section/-baseof.html` 3. `/layouts//baseof.html` 4. `/themes//layouts//baseof.html` 5. `/layouts/section/baseof.html` 6. `/themes//layouts/section/baseof.html` 7. `/layouts/_default/-baseof.html` 8. `/themes//layouts/_default/-baseof.html` 9. `/layouts/_default/baseof.html` 10. `/themes//layouts/_default/baseof.html` Variables are denoted by capitalized text set within `<>`. Note that Hugo's default behavior is for `type` to inherit from `section` unless otherwise specified. ### Example Base Template Lookup Order As an example, let's assume your site is using a theme called "mytheme" when rendering the section list for a `posts` section. Hugo picks `layout/section/posts.html` as the template for [rendering the section][]. The `{{define}}` block in this template tells Hugo that the template is an extension of a base template. Here is the lookup order for the `posts` base template: 1. `/layouts/section/posts-baseof.html` 2. `/themes/mytheme/layouts/section/posts-baseof.html` 3. `/layouts/posts/baseof.html` 4. `/themes/mytheme/layouts/posts/baseof.html` 5. `/layouts/section/baseof.html` 6. `/themes/mytheme/layouts/section/baseof.html` 7. `/layouts/_default/posts-baseof.html` 8. `/themes/mytheme/layouts/_default/posts-baseof.html` 9. `/layouts/_default/baseof.html` 10. `/themes/mytheme/layouts/_default/baseof.html` ## Define the Base Template The following defines a simple base template at `_default/baseof.html`. As a default template, it is the shell from which all your pages will be rendered unless you specify another `*baseof.html` closer to the beginning of the lookup order. {{< code file="layouts/_default/baseof.html" download="baseof.html" >}} {{ block "title" . }} <!-- Blocks may include default content. --> {{ .Site.Title }} {{ end }} {{ block "main" . }} {{ end }} {{ block "footer" . }} {{ end }} {{< /code >}} ## Override the Base Template From the above base template, you can define a [default list template][hugolists]. The default list template will inherit all of the code defined above and can then implement its own `"main"` block from: {{< code file="layouts/_default/list.html" download="list.html" >}} {{ define "main" }}

    Posts

    {{ range .Pages }}

    {{ .Title }}

    {{ .Content }}
    {{ end }} {{ end }} {{< /code >}} This replaces the contents of our (basically empty) "main" block with something useful for the list template. In this case, we didn't define a `"title"` block, so the contents from our base template remain unchanged in lists. {{% warning %}} Code that you put outside the block definitions *can* break your layout. This even includes HTML comments. For example: ``` {{ define "main" }} ...your code here {{ end }} ``` [See this thread from the Hugo discussion forums.](https://discourse.gohugo.io/t/baseof-html-block-templates-and-list-types-results-in-empty-pages/5612/6) {{% /warning %}} The following shows how you can override both the `"main"` and `"title"` block areas from the base template with code unique to your [default single page template][singletemplate]: {{< code file="layouts/_default/single.html" download="single.html" >}} {{ define "title" }} {{ .Title }} – {{ .Site.Title }} {{ end }} {{ define "main" }}

    {{ .Title }}

    {{ .Content }} {{ end }} {{< /code >}} [hugolists]: /templates/lists [lookup]: /templates/lookup-order/ [rendering the section]: /templates/section-templates/ [singletemplate]: /templates/single-page-templates/ hugo-0.92.2/docs/data/000077500000000000000000000000001420147000300143765ustar00rootroot00000000000000hugo-0.92.2/docs/data/articles.toml000066400000000000000000000545551420147000300171170ustar00rootroot00000000000000[[article]] title = "A visit to the Workshop: Hugo/Unix/Vim integration" url = "https://blog.afoolishmanifesto.com/posts/hugo-unix-vim-integration/" author = "fREW Schmidt" date = "2017-07-22" [[article]] title = "Hugo Easy Gallery - Automagical PhotoSwipe image gallery with a one-line shortcode" url = "https://www.liwen.id.au/heg/" author = "Li-Wen Yip" date = "2017-03-25" [[article]] title = "Automagical Image Gallery in Hugo with PhotoSwipe and jQuery" url = "https://www.liwen.id.au/photoswipe/" author = "Li-Wen Yip" date = "2017-03-04" [[article]] title = "Adding Isso Comments to Hugo" url = "https://stiobhart.net/2017-02-24-isso-comments/" author = "Stíobhart Matulevicz" date = "2017-02-24" [[article]] title = "Hugo Tutorial: How to Build & Host a (Very Fast) Static E-Commerce Site" url = "https://snipcart.com/blog/hugo-tutorial-static-site-ecommerce" author = "Snipcart" date = "2017-02-23" [[article]] title = "How to Password Protect a Hugo Site" url = "https://www.aerobatic.com/blog/password-protect-a-hugo-site/" author = "Aerobatic" date = "2017-02-19" [[article]] title = "Switching from WordPress to Hugo" url = "http://schnuddelhuddel.de/switching-from-wordpress-to-hugo/" author = "Mario Martelli" date = "2017-02-19" [[article]] title = "Zero to HTTP/2 with AWS and Hugo" url = "https://habd.as/zero-to-http-2-aws-hugo/" author = "Josh Habdas" date = "2017-02-16" [[article]] title = "Deploy a Hugo site to Aerobatic with CircleCI" url = "https://www.aerobatic.com/blog/hugo-github-circleci/" author = "Aerobatic" date = "2017-02-14" [[article]] title = "NPM scripts for building and deploying Hugo site" url = "https://www.aerobatic.com/blog/hugo-npm-buildtool-setup/" author = "Aerobatic" date = "2017-02-12" [[article]] title = "Getting started with Hugo and the plain-blog theme, on NearlyFreeSpeech.Net" url = "https://www.penwatch.net/cms/get_started_plain_blog/" author = "Li-aung “Lewis” Yip" date = "2017-02-12" [[article]] title = "Choose Hugo over Jekyll" url = "https://habd.as/choose-hugo-over-jekyll/" author = "Josh Habdas" date = "2017-02-10" [[article]] title = "Build a Hugo site using Cloud9 IDE and host on App Engine" url = "https://loyall.ch/lab/2017/01/build-a-static-website-with-cloud9-hugo-and-app-engine/" author = "Pascal Aubort" date = "2017-02-05" [[article]] title = "Hugo Continuous Deployment with Bitbucket Pipelines and Aerobatic" url = "https://www.aerobatic.com/blog/hugo-bitbucket-pipelines/" author = "Aerobatic" date = "2017-02-04" [[article]] title = "How to use Firebase to host a Hugo site" url = "https://code.selfmadefighter.com/post/static-site-firebase/" author = "Andrew Cuga" date= "2017-02-04" [[article]] title = "A publishing workflow for teams using static site generators" url = "https://www.keybits.net/post/publishing-workflow-for-teams-using-static-site-generators/" author = "Tom Atkins" date = "2017-01-02" [[article]] title = "How To Dynamically Use Google Fonts In A Hugo Website" url = "https://stoned.io/web-development/hugo/How-To-Dynamically-Use-Google-Fonts-In-A-Hugo-Website/" author = "Hash Borgir" date = "2016-10-27" [[article]] title = "Embedding Facebook In A Hugo Template" url = "https://stoned.io/web-development/hugo/Embedding-Facebook-In-A-Hugo-Template/" author = "Hash Borgir" date = "2016-10-22" [[article]] title = "通过 Gitlab-cl 将 Hugo blog 自动部署至 GitHub (Chinese, Continuous integration)" url = "https://zetaoyang.github.io/post/2016/10/17/gitlab-cl.html" author = "Zetao Yang" date = "2016-10-17" [[article]] title = "A Step-by-Step Guide: Hugo on Netlify" url = "https://www.netlify.com/blog/2016/09/21/a-step-by-step-guide-hugo-on-netlify/" author = "Eli Williamson" date = "2016-09-21" [[article]] title = "Building our site: From Django & WordPress to a static generator (Part I)" url = "https://tryolabs.com/blog/2016/09/20/building-our-site-django-wordpress-to-static-part-i/" author = "Alan Descoins" date = "2016-09-20" [[article]] title = "Webseitenmaschine - Statische Websites mit Hugo erzeugen (German, $)" url = "http://www.heise.de/ct/ausgabe/2016-12-Statische-Websites-mit-Hugo-erzeugen-3211704.html" author = "Christian Helmbold" date = "2016-05-27" [[article]] title = "Cómo hacer sitios web estáticos con Hugo y Go - Platzi (Video tutorial)" url = "https://www.youtube.com/watch?v=qaXXpdiCHXE" author = "Verónica López" date = "2016-04-06" [[article]] title = "CDNOverview: A CDN comparison site made with Hugo" url = "https://www.cloakfusion.com/cdnoverview-cdn-comparison-site-made-hugo/" author = "Thijs de Zoete" date = "2016-02-23" [[article]] title = "Hugo: A Modern WebSite Engine That Just Works" url = "https://github.com/shekhargulati/52-technologies-in-2016/blob/master/07-hugo/README.md" author = "Shekhar Gulati" date = "2016-02-14" [[article]] title = "Minify Hugo Generated HTML" url = "http://ratson.name/blog/minify-hugo-generated-html/" author = "Ratson" date = "2016-02-02" [[article]] title = "HugoのデプロイをWerckerからCircle CIに変更した - log" url = "http://log.deprode.net/logs/2016-01-17/" author = "Deprode" date = "2016-01-17" [[article]] title = "Static site generators: el futuro de las webs estáticas
    (Hugo, Jekyll, Flask y otros)" url = "http://sitelabs.es/static-site-generators-futuro-las-webs-estaticas/" author = "Eneko Sarasola" date = "2016-01-09" [[article]] title = "Writing a Lambda Function for Hugo" url = "https://blog.jolexa.net/post/writing-a-lambda-function-for-hugo/" author = "Jeremy Olexa" date = "2016-01-01" [[article]] title = "Ein Blog mit Hugo erstellen - Tutorial (Deutsch/German)" url = "http://privat.albicker.org/tags/hugo.html" author = "Bernhard Albicker" date = "2015-12-30" [[article]] title = "How to host Hugo static website generator on AWS Lambda" url = "http://bezdelev.com/post/hugo-aws-lambda-static-website/" author = "Ilya Bezdelev" date = "2015-12-15" [[article]] title = "Migrating from Pelican to Hugo" url = "http://www.softinio.com/post/migrating-from-pelican-to-hugo/" author = "Salar Rahmanian" date = "2015-11-29" [[article]] title = "Static Website Generators Reviewed: Jekyll, Middleman, Roots, Hugo" url = "http://www.smashingmagazine.com/2015/11/static-website-generators-jekyll-middleman-roots-hugo-review/" author = "Mathias Biilmann Christensen" date = "2015-11-16" [[article]] title = "How To Deploy a Hugo Site to Production with Git Hooks on Ubuntu 14.04" url = "https://www.digitalocean.com/community/tutorials/how-to-deploy-a-hugo-site-to-production-with-git-hooks-on-ubuntu-14-04" author = "Justin Ellingwood" date = "2015-11-12" [[article]] title = "How To Install and Use Hugo, a Static Site Generator, on Ubuntu 14.04" url = "https://www.digitalocean.com/community/tutorials/how-to-install-and-use-hugo-a-static-site-generator-on-ubuntu-14-04" author = "Justin Ellingwood" date = "2015-11-09" [[article]] title = "Switching from Wordpress to Hugo" url = "http://justinfx.com/2015/11/08/switching-from-wordpress-to-hugo/" author = "Justin Israel" date = "2015-11-08" [[article]] title = "Hands-on Experience with Hugo as a Static Site Generator" url = "http://usersnap.com/blog/hands-on-experience-with-hugo-static-site-generator/" author = "Thomas Peham" date = "2015-10-15" [[article]] title = "Statische Webseites mit Hugo erstellen/Vortrag mit Foliensatz (deutsch)" url = "http://sfd.koelnerlinuxtreffen.de/2015/HaraldWeidner/" author = "Harald Weidner" date = "2015-09-19" [[article]] title = "Moving from WordPress to Hugo" url = "http://abhipandey.com/2015/09/moving-to-hugo/" author = "Abhishek Pandey" date = "2015-09-15" [[article]] title = "通过webhook将Hugo自动部署至GitHub Pages和GitCafe Pages (Automated deployment)" url = "http://blog.coderzh.com/2015/09/13/use-webhook-automated-deploy-hugo/" author = "CoderZh" date = "2015-09-13" [[article]] title = "使用hugo搭建个人博客站点 (Using Hugo to build a personal blog site)" url = "http://blog.coderzh.com/2015/08/29/hugo/" author = "CoderZh" date = "2015-08-29" [[article]] title = "Good-Bye Wordpress, Hello Hugo! (German)" url = "http://blog.arminhanisch.de/2015/08/blog-migration-zu-hugo/" author = "Armin Hanisch" date = "2015-08-18" [[article]] title = "Générer votre site web statique avec Hugo (Generate your static site with Hugo)" url = "http://www.linux-pratique.com/?p=191" author = "Benoît Benedetti" date = "2015-06-26" [[article]] title = "Hugo向けの新しいテーマを作った (I created a new theme for Hugo)" url = "https://yet.unresolved.xyz/blog/2016/10/03/how-to-make-of-hugo-theme/" author = "Daisuke Tsuji" date = "2015-06-20" [[article]] title = "Hugo - Gerando um site com conteúdo estático. (Portuguese Brazil)" url = "http://blog.ffrizzo.com/posts/hugo/" author = "Fabiano Frizzo" date = "2015-06-02" [[article]] title = "An Introduction to Static Site Generators" url = "http://davidwalsh.name/introduction-static-site-generators" author = "Eduardo Bouças" date = "2015-05-20" [[article]] title = "Hugo Still Rules" url = "http://cheekycoder.com/2015/05/hugo-still-rules/" author = "Cheeky Coder" date = "2015-05-18" [[article]] title = "hugo - Static Site Generator" url = "http://gscacco.github.io/post/hugo/" author = "G Scaccoio" date = "2015-05-04" [[article]] title = "WindowsでHugoを使う" url = "http://ureta.net/2015/05/hugo-on-windows/" author = "うれ太郎" date = "2015-05-01" [[article]] title = "Hugoのshortcodesを用いてサイトにスライドなどを埋め込む" url = "http://blog.yucchiy.com/2015/04/29/hugo-shortcode/" author = "Yucchiy" date = "2015-04-29" [[article]] title = "HugoとCircleCIでGitHub PagesにBlogを公開してみたら超簡単だった" url = "http://hori-ryota.github.io/blog/create-blog-with-hugo-and-circleci/" author = "Hori Ryota" date = "2015-04-17" [[article]] title = "10 Best Static Site Generators" url = "http://beebom.com/2015/04/best-static-site-generators" author = "Aniruddha Mysore" date = "2015-04-06" [[article]] title = "Goodbye WordPress; Hello Hugo" url = "http://willwarren.com/2015/04/05/goodbye-wordpress-hello-hugo/" author = "Will Warren" date = "2015-04-05" [[article]] title = "Static Websites with Hugo on Google Cloud Storage" url = "http://www.moxie.io/post/static-websites-with-hugo-on-google-cloud-storage/" author = "Moxie Input/Output" date = "2015-04-02" [[article]] title = "De nuevo iniciando un blog" url = "https://alvarolizama.net/" author = "Alvaro Lizama" date = "2015-03-29" [[article]] title = "We moved our blog from Posthaven to Hugo after only three posts. Why?" url = "http://blog.hypriot.com/post/moved-from-posthaven-to-hugo/" author = "Hypriot" date = "2015-03-27" [[article]] title = "Top Static Site Generators in 2015" url = "http://superdevresources.com/static-site-generators-2015/" author = "Kanishk Kunal" date = "2015-03-12" [[article]] title = "Moving to Hugo" url = "http://abiosoft.com/moving-to-hugo/" author = "Abiola Ibrahim" date = "2015-03-08" [[article]] title = "Migrating a blog (yes, this one!) from Wordpress to Hugo" url = "http://justindunham.net/migrating-from-wordpress-to-hugo/" author = "Justin Dunham" date = "2015-02-13" [[article]] title = "blogをoctopressからHugoに乗り換えたメモ" url = "http://blog.jigyakkuma.org/2015/02/11/hugo/" author = "jigyakkuma" date = "2015-02-11" [[article]] title = "Hugoでブログをつくった" url = "http://porgy13.github.io/post/new-hugo-blog/" author = "porgy13" date = "2015-02-07" [[article]] title = "Hugoにブログを移行した" url = "http://keichi.net/post/first/" author = "Keichi Takahashi" date = "2015-02-04" [[article]] title = "Hugo静态网站生成器中文教程" url = "http://nanshu.wang/post/2015-01-31/" author = "Nanshu Wang" date = "2015-01-31" [[article]] title = "Hugo + Github Pages + Wercker CI = ¥0(無料)
    でコマンド 1 発(自動化)でサイト
    ・ブログを公開・運営・分析・収益化
    " url = "http://qiita.com/yoheimuta/items/8a619cac356bed89a4c9" author = "Yohei Yoshimuta" date = "2015-01-31" [[article]] title = "Running Hugo websites on anynines" url = "http://blog.anynines.com/running-hugo-websites-on-anynines/" author = "Julian Weber" date = "2015-01-30" [[article]] title = "MiddlemanからHugoへ移行した" url = "http://re-dzine.net/2015/01/hugo/" author = "Haruki Konishi" date = "2015-01-21" [[article]] title = "WordPress から Hugo に乗り換えました" url = "http://rakuishi.com/archives/wordpress-to-hugo/" author = "rakuishi" date = "2015-01-20" [[article]] title = "HUGOを使ってサイトを立ち上げる方法" url = "http://qiita.com/syui/items/869538099551f24acbbf" author = "Syui" date = "2015-01-17" [[article]] title = "Jekyllが許されるのは小学生までだよね" url = "http://t32k.me/mol/log/hugo/" author = "Ishimoto Koji" date = "2015-01-16" [[article]] title = "Getting started with Hugo" url = "http://anthonyfok.org/post/getting-started-with-hugo/" author = "Anthony Fok" date = "2015-01-12" [[article]] title = "把这个博客静态化了 (Migrate to Hugo)" url = "http://lich-eng.com/2015/01/03/migrate-to-hugo/" author = "Li Cheng" date = "2015-01-03" [[article]] title = "Porting my blog with Hugo" url = "http://blog.srackham.com/posts/porting-my-blog-with-hugo/" author = "Stuart Rackham" date = "2014-12-30" [[article]] title = "Hugoを使ってみたときのメモ" url = "http://machortz.github.io/posts/usinghugo/" author = "Machortz" date = "2014-12-29" [[article]] title = "OctopressからHugoへ移行した" url = "http://deeeet.com/writing/2014/12/25/hugo/" author = "Taichi Nakashima" date = "2014-12-25" [[article]] title = "Migrating to Hugo From Octopress" url = "http://nathanleclaire.com/blog/2014/12/22/migrating-to-hugo-from-octopress/" author = "Nathan LeClaire" date = "2014-12-22" [[article]] title = "Dynamic Pages with GoHugo.io" url = "http://cyrillschumacher.com/2014/12/21/dynamic-pages-with-gohugo.io/" author = "Cyrill Schumacher" date = "2014-12-21" [[article]] title = "6 Static Blog Generators That Aren’t Jekyll" url = "http://www.sitepoint.com/6-static-blog-generators-arent-jekyll/" author = "David Turnbull" date = "2014-12-08" [[article]] title = "Travel Blogging Setup" url = "http://www.stou.dk/2014/11/travel-blogging-setup/" author = "Rasmus Stougaard" date = "2014-11-23" [[article]] title = "Hosting A Hugo Website Behind Nginx" url = "http://www.bigbeeconsultants.co.uk/blog/hosting-hugo-website-behind-nginx" author = "Rick Beton" date = "2014-11-20" [[article]] title = "使用Hugo搭建免费个人Blog (How to use Hugo)" url = "http://ulricqin.com/post/how-to-use-hugo/" author = "Ulric Qin 秦晓辉" date = "2014-11-11" [[article]] title = "Built in Speed and Built for Speed by Hugo" url = "http://cheekycoder.com/2014/10/built-for-speed-by-hugo/" author = "Cheeky Coder" date = "2014-10-30" [[article]] title = "Hugo para crear sitios web estáticos" url = "http://www.webbizarro.com/noticias/1076/hugo-para-crear-sitios-web-estaticos/" author = "Web Bizarro" date = "2014-08-19" [[article]] title = "Going with hugo" url = "http://www.markuseliasson.se/article/going-with-hugo/" author = "Markus Eliasson" date = "2014-08-18" [[article]] title = "Benchmarking Jekyll, Hugo and Wintersmith" url = "http://fredrikloch.me/post/2014-08-12-Jekyll-and-its-alternatives-from-a-site-generation-point-of-view/" author = "Fredrik Loch" date = "2014-08-12" [[article]] title = "Goodbye Octopress, Hello Hugo!" url = "http://andreimihu.com/blog/2014/08/11/goodbye-octopress-hello-hugo/" author = "Andrei Mihu" date = "2014-08-11" [[article]] title = "Beautiful sites for Open Source projects" url = "http://beautifulopen.com/2014/08/09/hugo/" author = "Beautiful Open" date = "2014-08-09" [[article]] title = "Hugo: Beyond the Defaults" url = "http://npf.io/2014/08/hugo-beyond-the-defaults/" author = "Nate Finch" date = "2014-08-08" [[article]] title = "First Impressions of Hugo" url = "https://peteraba.com/blog/first-impressions-of-hugo/" author = "Peter Aba" date = "2014-06-06" [[article]] title = "New Site Workflow" url = "http://vurt.co.uk/post/new_website/" author = "Giles Paterson" date = "2014-08-05" [[article]] title = "How I Learned to Stop Worrying and Love the (Static) Web" url = "http://cognition.ca/post/about-hugo/" author = "Joshua McKenty" date = "2014-08-04" [[article]] title = "Hugo - Static Site Generator" url = "http://kenwoo.io/blog/hugo---static-site-generator/" author = "Kenny Woo" date = "2014-08-03" [[article]] title = "Hugo Is Friggin' Awesome" url = "http://npf.io/2014/08/hugo-is-awesome/" author = "Nate Finch" date = "2014-08-01" [[article]] title = "再次搬家 (Move from WordPress to Hugo)" url = "http://www.chingli.com/misc/move-from-wordpress-to-hugo/" author = "青砾 (chingli)" date = "2014-07-12" [[article]] title = "Embedding Gists in Hugo" url = "http://danmux.com/posts/embedded_gists/" author = "Dan Mull" date = "2014-07-05" [[article]] title = "An Introduction To Hugo" url = "http://www.cirrushosting.com/web-hosting-blog/an-introduction-to-hugo/" author = "Dan Silber" date = "2014-07-01" [[article]] title = "Moving to Hugo" url = "http://danmux.com/posts/hugo_based_blog/" author = "Dan Mull" date = "2014-05-29" [[article]] title = "开源之静态站点生成器排行榜
    (Leaderboard of open-source static website generators)" url = "http://code.csdn.net/news/2819909" author = "CSDN.net" date = "2014-05-23" [[article]] title = "Finally, a satisfying and effective blog setup" url = "http://michaelwhatcott.com/now-powered-by-hugo/" author = "Michael Whatcott" date = "2014-05-20" [[article]] title = "Hugo from scratch" url = "http://zackofalltrades.com/notes/2014/05/hugo-from-scratch/" author = "Zack Williams" date = "2014-05-18" [[article]] title = "Why I switched away from Jekyll" url = "http://www.jakejanuzelli.com/why-I-switched-away-from-jekyll/" author = "Jake Januzelli" date = "2014-05-10" [[article]] title = "Welcome our new blog" url = "http://blog.ninya.io/posts/welcome-our-new-blog/" author = "Ninya.io" date = "2014-04-11" [[article]] title = "Mission Not Accomplished" url = "http://johnsto.co.uk/blog/mission-not-accomplished/" author = "Dave Johnston" date = "2014-04-03" [[article]] title = "Hugo - A Static Site Builder in Go" url = "http://deepfriedcode.com/post/hugo/" author = "Deep Fried Code" date = "2014-03-30" [[article]] title = "Adventures in Angular Podcast" url = "http://devchat.tv/adventures-in-angular/003-aia-gdes" author = "Matias Niemela" date = "2014-03-28" [[article]] title = "Hugo" url = "http://bra.am/post/hugo/" author = "bra.am" date = "2014-03-23" [[article]] title = "Converting Blogger To Markdown" url = "http://trishagee.github.io/project/atom-to-hugo/" author = "Trisha Gee" date = "2014-03-20" [[article]] title = "Moving to Hugo Static Web Pages" url = "http://tepid.org/tech/hugo-web/" author = "Tobias Weingartner" date = "2014-03-16" [[article]] title = "New Blog Engine: Hugo" url = "https://blog.afoolishmanifesto.com/posts/hugo/" author = "fREW Schmidt" date = "2014-03-15" [[article]] title = "Hugo + gulp.js = Huggle" url = "http://ktmud.github.io/huggle/en/intro/)" author = "Jesse Yang 杨建超" date = "2014-03-08" [[article]] title = "Powered by Hugo" url = "http://kieranhealy.org/blog/archives/2014/02/24/powered-by-hugo/" author = "Kieran Healy" date = "2014-02-24" [[article]] title = "静的サイトを素早く構築するために
    GoLangで作られたジェネレータHugo
    " url = "http://hamasyou.com/blog/2014/02/21/hugo/" author = "
    Shogo Hamada
    濱田章吾
    " date = "2014-02-21" [[article]] title = "Latest Roundup of Useful Tools For Developers" url = "http://codegeekz.com/latest-roundup-of-useful-tools-for-developers/" author = "CodeGeekz" date = "2014-02-13" [[article]] title = "Hugo: Static Site Generator written in Go" url = "http://www.braveterry.com/2014/02/06/hugo-static-site-generator-written-in-go/" author = "Brave Terry" date = "2014-02-06" [[article]] title = "10 Useful HTML5 Tools for Web Designers and Developers" url = "http://designdizzy.com/10-useful-html5-tools-for-web-designers-and-developers/" author = "Design Dizzy" date = "2014-02-04" [[article]] title = "Hugo – Fast, Flexible Static Site Generator" url = "http://cube3x.com/hugo-fast-flexible-static-site-generator/" author = "Joby Joseph" date = "2014-01-18" [[article]] title = "Hugo: A new way to build static website" url = "http://www.w3update.com/opensource/hugo-a-new-way-to-build-static-website.html" author = "w3update" date = "2014-01-17" [[article]] title = "Xaprb now uses Hugo" url = "http://xaprb.com/blog/2014/01/15/using-hugo/" author = "Baron Schwartz" date = "2014-01-15" [[article]] title = "New jQuery Plugins And Resources That Web Designers Need" url = "http://www.designyourway.net/blog/resources/new-jquery-plugins-and-resources-that-web-designers-need/" author = "Design Your Way" date = "2014-01-01" [[article]] title = "On Blog Construction" url = "http://alexla.sh/post/on-blog-construction/" author = "Alexander Lash" date = "2013-12-27" [[article]] title = "Hugo" url = "http://onethingwell.org/post/69070926608/hugo" author = "One Thing Well" date = "2013-12-05" [[article]] title = "In Praise Of Hugo" url = "http://sound-guru.com/blog/post/hello-world/" author = "sound-guru.com" date = "2013-10-19" [[article]] title = "Hosting a blog on S3 and Cloudfront" url = "http://www.danesparza.net/2013/07/hosting-a-blog-on-s3-and-cloudfront/" author = "Dan Esparza" date = "2013-07-24" hugo-0.92.2/docs/data/docs.json000066400000000000000000004246401420147000300162330ustar00rootroot00000000000000{ "chroma": { "lexers": [ { "Name": "ABAP", "Aliases": [ "ABAP", "abap" ] }, { "Name": "ABNF", "Aliases": [ "abnf" ] }, { "Name": "ActionScript", "Aliases": [ "actionscript", "as" ] }, { "Name": "ActionScript 3", "Aliases": [ "actionscript3", "as", "as3" ] }, { "Name": "Ada", "Aliases": [ "ada", "ada2005", "ada95", "adb", "ads" ] }, { "Name": "AL", "Aliases": [ "al", "dal" ] }, { "Name": "Angular2", "Aliases": [ "ng2" ] }, { "Name": "ANTLR", "Aliases": [ "antlr" ] }, { "Name": "ApacheConf", "Aliases": [ "aconf", "apache", "apacheconf", "conf", "htaccess" ] }, { "Name": "APL", "Aliases": [ "apl" ] }, { "Name": "AppleScript", "Aliases": [ "applescript" ] }, { "Name": "Arduino", "Aliases": [ "arduino", "ino" ] }, { "Name": "ArmAsm", "Aliases": [ "S", "armasm", "s" ] }, { "Name": "Awk", "Aliases": [ "awk", "gawk", "mawk", "nawk" ] }, { "Name": "Ballerina", "Aliases": [ "bal", "ballerina" ] }, { "Name": "Base Makefile", "Aliases": [ "*", "bsdmake", "mak", "make", "makefile", "mf", "mk" ] }, { "Name": "Bash", "Aliases": [ "bash", "bash_*", "bashrc", "ebuild", "eclass", "env", "exheres-0", "exlib", "ksh", "sh", "shell", "zsh", "zshrc" ] }, { "Name": "BashSession", "Aliases": [ "bash-session", "console", "sh-session", "shell-session" ] }, { "Name": "Batchfile", "Aliases": [ "bat", "batch", "cmd", "dosbatch", "winbatch" ] }, { "Name": "BibTeX", "Aliases": [ "bib", "bibtex" ] }, { "Name": "BlitzBasic", "Aliases": [ "b3d", "bb", "blitzbasic", "bplus", "decls" ] }, { "Name": "BNF", "Aliases": [ "bnf" ] }, { "Name": "Brainfuck", "Aliases": [ "b", "bf", "brainfuck" ] }, { "Name": "C", "Aliases": [ "c", "h", "idc", "x[bp]m" ] }, { "Name": "C#", "Aliases": [ "c#", "cs", "csharp" ] }, { "Name": "C++", "Aliases": [ "C", "CPP", "H", "c++", "cc", "cp", "cpp", "cxx", "h++", "hh", "hpp", "hxx" ] }, { "Name": "Caddyfile", "Aliases": [ "caddy", "caddyfile" ] }, { "Name": "Caddyfile Directives", "Aliases": [ "caddy-d", "caddyfile-d", "caddyfile-directives" ] }, { "Name": "Cap'n Proto", "Aliases": [ "capnp" ] }, { "Name": "Cassandra CQL", "Aliases": [ "cassandra", "cql" ] }, { "Name": "Ceylon", "Aliases": [ "ceylon" ] }, { "Name": "CFEngine3", "Aliases": [ "cf", "cf3", "cfengine3" ] }, { "Name": "cfstatement", "Aliases": [ "cfs" ] }, { "Name": "ChaiScript", "Aliases": [ "chai", "chaiscript" ] }, { "Name": "Cheetah", "Aliases": [ "cheetah", "spitfire", "spt", "tmpl" ] }, { "Name": "Clojure", "Aliases": [ "clj", "clojure" ] }, { "Name": "CMake", "Aliases": [ "cmake", "txt" ] }, { "Name": "COBOL", "Aliases": [ "COB", "CPY", "cob", "cobol", "cpy" ] }, { "Name": "CoffeeScript", "Aliases": [ "coffee", "coffee-script", "coffeescript" ] }, { "Name": "Common Lisp", "Aliases": [ "cl", "common-lisp", "lisp" ] }, { "Name": "Coq", "Aliases": [ "coq", "v" ] }, { "Name": "Crystal", "Aliases": [ "cr", "crystal" ] }, { "Name": "CSS", "Aliases": [ "css" ] }, { "Name": "Cython", "Aliases": [ "cython", "pxd", "pxi", "pyrex", "pyx" ] }, { "Name": "D", "Aliases": [ "d", "di" ] }, { "Name": "Dart", "Aliases": [ "dart" ] }, { "Name": "Diff", "Aliases": [ "diff", "patch", "udiff" ] }, { "Name": "Django/Jinja", "Aliases": [ "django", "jinja" ] }, { "Name": "Docker", "Aliases": [ "docker", "dockerfile" ] }, { "Name": "DTD", "Aliases": [ "dtd" ] }, { "Name": "Dylan", "Aliases": [ "dyl", "dylan", "intr" ] }, { "Name": "EBNF", "Aliases": [ "ebnf" ] }, { "Name": "Elixir", "Aliases": [ "elixir", "ex", "exs" ] }, { "Name": "Elm", "Aliases": [ "elm" ] }, { "Name": "EmacsLisp", "Aliases": [ "el", "elisp", "emacs", "emacs-lisp" ] }, { "Name": "Erlang", "Aliases": [ "erl", "erlang", "es", "escript", "hrl" ] }, { "Name": "Factor", "Aliases": [ "factor" ] }, { "Name": "Fennel", "Aliases": [ "fennel", "fnl" ] }, { "Name": "Fish", "Aliases": [ "fish", "fishshell", "load" ] }, { "Name": "Forth", "Aliases": [ "forth", "frt", "fs", "fth" ] }, { "Name": "Fortran", "Aliases": [ "F03", "F90", "f03", "f90", "fortran" ] }, { "Name": "FortranFixed", "Aliases": [ "F", "f", "fortranfixed" ] }, { "Name": "FSharp", "Aliases": [ "fs", "fsharp", "fsi" ] }, { "Name": "GAS", "Aliases": [ "S", "asm", "gas", "s" ] }, { "Name": "GDScript", "Aliases": [ "gd", "gdscript" ] }, { "Name": "Genshi", "Aliases": [ "genshi", "kid", "xml+genshi", "xml+kid" ] }, { "Name": "Genshi HTML", "Aliases": [ "html+genshi", "html+kid" ] }, { "Name": "Genshi Text", "Aliases": [ "genshitext" ] }, { "Name": "Gherkin", "Aliases": [ "Cucumber", "FEATURE", "Gherkin", "cucumber", "feature", "gherkin" ] }, { "Name": "GLSL", "Aliases": [ "frag", "geo", "glsl", "vert" ] }, { "Name": "Gnuplot", "Aliases": [ "gnuplot", "plot", "plt" ] }, { "Name": "Go", "Aliases": [ "go", "golang" ] }, { "Name": "Go HTML Template", "Aliases": [ "go-html-template" ] }, { "Name": "Go Text Template", "Aliases": [ "go-text-template" ] }, { "Name": "GraphQL", "Aliases": [ "gql", "graphql", "graphqls" ] }, { "Name": "Groff", "Aliases": [ "1p", "3pm", "[1-9]", "groff", "man", "nroff" ] }, { "Name": "Groovy", "Aliases": [ "gradle", "groovy" ] }, { "Name": "Handlebars", "Aliases": [ "handlebars", "hbs" ] }, { "Name": "Haskell", "Aliases": [ "haskell", "hs" ] }, { "Name": "Haxe", "Aliases": [ "haxe", "hx", "hxsl" ] }, { "Name": "HCL", "Aliases": [ "hcl" ] }, { "Name": "Hexdump", "Aliases": [ "hexdump" ] }, { "Name": "HLB", "Aliases": [ "hlb" ] }, { "Name": "HTML", "Aliases": [ "htm", "html", "xhtml", "xslt" ] }, { "Name": "HTTP", "Aliases": [ "http" ] }, { "Name": "Hy", "Aliases": [ "hy", "hylang" ] }, { "Name": "Idris", "Aliases": [ "idr", "idris" ] }, { "Name": "Igor", "Aliases": [ "igor", "igorpro", "ipf" ] }, { "Name": "INI", "Aliases": [ "cfg", "dosini", "editorconfig", "gitconfig", "inf", "ini" ] }, { "Name": "Io", "Aliases": [ "io" ] }, { "Name": "J", "Aliases": [ "ijs", "j" ] }, { "Name": "Java", "Aliases": [ "java" ] }, { "Name": "JavaScript", "Aliases": [ "javascript", "js", "jsm", "mjs" ] }, { "Name": "JSON", "Aliases": [ "json" ] }, { "Name": "Julia", "Aliases": [ "jl", "julia" ] }, { "Name": "Jungle", "Aliases": [ "jungle" ] }, { "Name": "Kotlin", "Aliases": [ "kotlin", "kt" ] }, { "Name": "Lighttpd configuration file", "Aliases": [ "lighttpd", "lighty" ] }, { "Name": "LLVM", "Aliases": [ "ll", "llvm" ] }, { "Name": "Lua", "Aliases": [ "lua", "wlua" ] }, { "Name": "Mako", "Aliases": [ "mako", "mao" ] }, { "Name": "markdown", "Aliases": [ "markdown", "md", "mkd" ] }, { "Name": "Mason", "Aliases": [ "m", "mason", "mc", "mhtml", "mi" ] }, { "Name": "Mathematica", "Aliases": [ "cdf", "ma", "mathematica", "mma", "nb", "nbp" ] }, { "Name": "Matlab", "Aliases": [ "m", "matlab" ] }, { "Name": "mcfunction", "Aliases": [ "mcfunction" ] }, { "Name": "Meson", "Aliases": [ "build", "meson", "meson.build", "txt" ] }, { "Name": "Metal", "Aliases": [ "metal" ] }, { "Name": "MiniZinc", "Aliases": [ "MZN", "dzn", "fzn", "minizinc", "mzn" ] }, { "Name": "MLIR", "Aliases": [ "mlir" ] }, { "Name": "Modula-2", "Aliases": [ "def", "m2", "mod", "modula2" ] }, { "Name": "MonkeyC", "Aliases": [ "mc", "monkeyc" ] }, { "Name": "MorrowindScript", "Aliases": [ "morrowind", "mwscript" ] }, { "Name": "Myghty", "Aliases": [ "myghty", "myt" ] }, { "Name": "MySQL", "Aliases": [ "mysql", "sql" ] }, { "Name": "NASM", "Aliases": [ "ASM", "asm", "nasm" ] }, { "Name": "Newspeak", "Aliases": [ "newspeak", "ns2" ] }, { "Name": "Nginx configuration file", "Aliases": [ "conf", "nginx" ] }, { "Name": "Nim", "Aliases": [ "nim", "nimrod" ] }, { "Name": "Nix", "Aliases": [ "nix", "nixos" ] }, { "Name": "Objective-C", "Aliases": [ "h", "m", "obj-c", "objc", "objective-c", "objectivec" ] }, { "Name": "OCaml", "Aliases": [ "ml", "mli", "mll", "mly", "ocaml" ] }, { "Name": "Octave", "Aliases": [ "m", "octave" ] }, { "Name": "OnesEnterprise", "Aliases": [ "1S", "1S:Enterprise", "EPF", "ERF", "epf", "erf", "ones", "onesenterprise" ] }, { "Name": "OpenSCAD", "Aliases": [ "openscad", "scad" ] }, { "Name": "Org Mode", "Aliases": [ "org", "orgmode" ] }, { "Name": "PacmanConf", "Aliases": [ "conf", "pacmanconf" ] }, { "Name": "Perl", "Aliases": [ "perl", "pl", "pm", "t" ] }, { "Name": "PHP", "Aliases": [ "inc", "php", "php3", "php4", "php5", "php[345]" ] }, { "Name": "PHTML", "Aliases": [ "inc", "php", "php[345]", "phtml" ] }, { "Name": "Pig", "Aliases": [ "pig" ] }, { "Name": "PkgConfig", "Aliases": [ "pc", "pkgconfig" ] }, { "Name": "PL/pgSQL", "Aliases": [ "plpgsql" ] }, { "Name": "plaintext", "Aliases": [ "no-highlight", "plain", "text", "txt" ] }, { "Name": "Pony", "Aliases": [ "pony" ] }, { "Name": "PostgreSQL SQL dialect", "Aliases": [ "postgres", "postgresql" ] }, { "Name": "PostScript", "Aliases": [ "eps", "postscr", "postscript", "ps" ] }, { "Name": "POVRay", "Aliases": [ "inc", "pov" ] }, { "Name": "PowerQuery", "Aliases": [ "powerquery", "pq" ] }, { "Name": "PowerShell", "Aliases": [ "posh", "powershell", "ps1", "psd1", "psm1" ] }, { "Name": "Prolog", "Aliases": [ "ecl", "pl", "pro", "prolog" ] }, { "Name": "PromQL", "Aliases": [ "promql" ] }, { "Name": "Protocol Buffer", "Aliases": [ "proto", "protobuf" ] }, { "Name": "Puppet", "Aliases": [ "pp", "puppet" ] }, { "Name": "Python", "Aliases": [ "bazel", "bzl", "jy", "py", "py3", "pyi", "python", "python3", "pyw", "sage", "sc", "tac" ] }, { "Name": "Python 2", "Aliases": [ "py2", "python2" ] }, { "Name": "QBasic", "Aliases": [ "BAS", "bas", "basic", "qbasic" ] }, { "Name": "QML", "Aliases": [ "qbs", "qml" ] }, { "Name": "R", "Aliases": [ "R", "Renviron", "Rhistory", "Rprofile", "S", "r", "s", "splus" ] }, { "Name": "Racket", "Aliases": [ "racket", "rkt", "rktd", "rktl" ] }, { "Name": "Ragel", "Aliases": [ "ragel" ] }, { "Name": "Raku", "Aliases": [ "6pl", "6pm", "nqp", "p6", "p6l", "p6m", "perl6", "pl", "pl6", "pm", "pm6", "raku", "rakudoc", "rakumod", "rakutest", "t" ] }, { "Name": "react", "Aliases": [ "jsx", "react" ] }, { "Name": "ReasonML", "Aliases": [ "re", "reason", "reasonml", "rei" ] }, { "Name": "reg", "Aliases": [ "reg", "registry" ] }, { "Name": "reStructuredText", "Aliases": [ "rest", "restructuredtext", "rst" ] }, { "Name": "Rexx", "Aliases": [ "arexx", "rex", "rexx", "rx" ] }, { "Name": "Ruby", "Aliases": [ "duby", "gemspec", "rake", "rb", "rbw", "rbx", "ruby" ] }, { "Name": "Rust", "Aliases": [ "in", "rs", "rust" ] }, { "Name": "SAS", "Aliases": [ "SAS", "sas" ] }, { "Name": "Sass", "Aliases": [ "sass" ] }, { "Name": "Scala", "Aliases": [ "scala" ] }, { "Name": "Scheme", "Aliases": [ "scheme", "scm", "ss" ] }, { "Name": "Scilab", "Aliases": [ "sce", "sci", "scilab", "tst" ] }, { "Name": "SCSS", "Aliases": [ "scss" ] }, { "Name": "Sieve", "Aliases": [ "sieve", "siv" ] }, { "Name": "Smalltalk", "Aliases": [ "smalltalk", "squeak", "st" ] }, { "Name": "Smarty", "Aliases": [ "smarty", "tpl" ] }, { "Name": "Snobol", "Aliases": [ "snobol" ] }, { "Name": "Solidity", "Aliases": [ "sol", "solidity" ] }, { "Name": "SPARQL", "Aliases": [ "rq", "sparql" ] }, { "Name": "SQL", "Aliases": [ "sql" ] }, { "Name": "SquidConf", "Aliases": [ "conf", "squid", "squid.conf", "squidconf" ] }, { "Name": "Standard ML", "Aliases": [ "fun", "sig", "sml" ] }, { "Name": "Stylus", "Aliases": [ "styl", "stylus" ] }, { "Name": "Svelte", "Aliases": [ "svelte" ] }, { "Name": "Swift", "Aliases": [ "swift" ] }, { "Name": "SYSTEMD", "Aliases": [ "automount", "device", "dnssd", "link", "mount", "netdev", "network", "path", "scope", "service", "slice", "socket", "swap", "systemd", "target", "timer" ] }, { "Name": "systemverilog", "Aliases": [ "sv", "svh", "systemverilog" ] }, { "Name": "TableGen", "Aliases": [ "tablegen", "td" ] }, { "Name": "TASM", "Aliases": [ "ASM", "asm", "tasm" ] }, { "Name": "Tcl", "Aliases": [ "rvt", "tcl" ] }, { "Name": "Tcsh", "Aliases": [ "csh", "tcsh" ] }, { "Name": "Termcap", "Aliases": [ "src", "termcap" ] }, { "Name": "Terminfo", "Aliases": [ "src", "terminfo" ] }, { "Name": "Terraform", "Aliases": [ "terraform", "tf" ] }, { "Name": "TeX", "Aliases": [ "aux", "latex", "tex", "toc" ] }, { "Name": "Thrift", "Aliases": [ "thrift" ] }, { "Name": "TOML", "Aliases": [ "toml" ] }, { "Name": "TradingView", "Aliases": [ "tradingview", "tv" ] }, { "Name": "Transact-SQL", "Aliases": [ "t-sql", "tsql" ] }, { "Name": "Turing", "Aliases": [ "tu", "turing" ] }, { "Name": "Turtle", "Aliases": [ "ttl", "turtle" ] }, { "Name": "Twig", "Aliases": [ "twig" ] }, { "Name": "TypeScript", "Aliases": [ "ts", "tsx", "typescript" ] }, { "Name": "TypoScript", "Aliases": [ "ts", "typoscript" ] }, { "Name": "TypoScriptCssData", "Aliases": [ "typoscriptcssdata" ] }, { "Name": "TypoScriptHtmlData", "Aliases": [ "typoscripthtmldata" ] }, { "Name": "VB.net", "Aliases": [ "bas", "vb", "vb.net", "vbnet" ] }, { "Name": "verilog", "Aliases": [ "v", "verilog" ] }, { "Name": "VHDL", "Aliases": [ "vhd", "vhdl" ] }, { "Name": "VimL", "Aliases": [ "exrc", "gvimrc", "vim", "vimrc" ] }, { "Name": "vue", "Aliases": [ "vue", "vuejs" ] }, { "Name": "WDTE", "Aliases": [ "wdte" ] }, { "Name": "XML", "Aliases": [ "rss", "svg", "wsdl", "wsf", "xml", "xsd", "xsl", "xslt" ] }, { "Name": "Xorg", "Aliases": [ "conf", "xorg.conf" ] }, { "Name": "YAML", "Aliases": [ "yaml", "yml" ] }, { "Name": "YANG", "Aliases": [ "yang" ] }, { "Name": "Zig", "Aliases": [ "zig" ] } ] }, "config": { "markup": { "defaultMarkdownHandler": "goldmark", "highlight": { "style": "monokai", "codeFences": true, "noClasses": true, "lineNos": false, "lineNumbersInTable": true, "anchorLineNos": false, "lineAnchors": "", "lineNoStart": 1, "hl_Lines": "", "tabWidth": 4, "guessSyntax": false }, "tableOfContents": { "startLevel": 2, "endLevel": 3, "ordered": false }, "goldmark": { "renderer": { "hardWraps": false, "xhtml": false, "unsafe": false }, "parser": { "autoHeadingID": true, "autoHeadingIDType": "github", "attribute": { "title": true, "block": false } }, "extensions": { "typographer": true, "footnote": true, "definitionList": true, "table": true, "strikethrough": true, "linkify": true, "taskList": true } }, "blackFriday": { "smartypants": true, "smartypantsQuotesNBSP": false, "angledQuotes": false, "fractions": true, "hrefTargetBlank": false, "nofollowLinks": false, "noreferrerLinks": false, "smartDashes": true, "latexDashes": true, "taskLists": true, "plainIDAnchors": true, "extensions": null, "extensionsMask": null, "skipHTML": false, "footnoteAnchorPrefix": "", "footnoteReturnLinkContents": "" }, "asciidocExt": { "backend": "html5", "extensions": [], "attributes": {}, "noHeaderOrFooter": true, "safeMode": "unsafe", "sectionNumbers": false, "verbose": false, "trace": false, "failureLevel": "fatal", "workingFolderCurrent": false, "preserveTOC": false } }, "mergeStrategy": { "build": { "_merge": "none" }, "caches": { "_merge": "none" }, "cascade": { "_merge": "none" }, "frontmatter": { "_merge": "none" }, "imaging": { "_merge": "none" }, "languages": { "_merge": "none", "en": { "_merge": "none", "menus": { "_merge": "shallow" }, "params": { "_merge": "deep" } } }, "markup": { "_merge": "none" }, "mediatypes": { "_merge": "shallow" }, "menus": { "_merge": "shallow" }, "minify": { "_merge": "none" }, "module": { "_merge": "none" }, "outputformats": { "_merge": "shallow" }, "params": { "_merge": "deep" }, "permalinks": { "_merge": "none" }, "privacy": { "_merge": "none" }, "related": { "_merge": "none" }, "security": { "_merge": "none" }, "sitemap": { "_merge": "none" }, "taxonomies": { "_merge": "none" } }, "minify": { "minifyOutput": false, "disableHTML": false, "disableCSS": false, "disableJS": false, "disableJSON": false, "disableSVG": false, "disableXML": false, "tdewolff": { "html": { "keepComments": false, "keepConditionalComments": true, "keepDefaultAttrVals": true, "keepDocumentTags": true, "keepEndTags": true, "keepQuotes": false, "keepWhitespace": true }, "css": { "keepCSS2": true, "precision": 0 }, "js": { "precision": 0, "keepVarNames": false }, "json": { "precision": 0, "keepNumbers": false }, "svg": { "precision": 0 }, "xml": { "keepWhitespace": false } } }, "security": { "enableInlineShortcodes": false, "exec": { "allow": [ "^dart-sass-embedded$", "^go$", "^npx$", "^postcss$" ], "osEnv": [ "(?i)^(PATH|PATHEXT|APPDATA|TMP|TEMP|TERM)$" ] }, "funcs": { "getenv": [ "^HUGO_" ] }, "http": { "methods": [ "(?i)GET|POST" ], "urls": [ ".*" ] } } }, "media": { "types": [ { "mainType": "application", "subType": "javascript", "delimiter": ".", "firstSuffix": { "suffix": "js", "fullSuffix": ".js" }, "type": "application/javascript", "string": "application/javascript", "suffixes": [ "js" ] }, { "mainType": "application", "subType": "json", "delimiter": ".", "firstSuffix": { "suffix": "json", "fullSuffix": ".json" }, "type": "application/json", "string": "application/json", "suffixes": [ "json" ] }, { "mainType": "application", "subType": "manifest", "delimiter": ".", "firstSuffix": { "suffix": "webmanifest", "fullSuffix": ".webmanifest" }, "type": "application/manifest+json", "string": "application/manifest+json", "suffixes": [ "webmanifest" ] }, { "mainType": "application", "subType": "octet-stream", "delimiter": ".", "firstSuffix": { "suffix": "", "fullSuffix": "" }, "type": "application/octet-stream", "string": "application/octet-stream", "suffixes": [ "" ] }, { "mainType": "application", "subType": "pdf", "delimiter": ".", "firstSuffix": { "suffix": "pdf", "fullSuffix": ".pdf" }, "type": "application/pdf", "string": "application/pdf", "suffixes": [ "pdf" ] }, { "mainType": "application", "subType": "rss", "delimiter": ".", "firstSuffix": { "suffix": "xml", "fullSuffix": ".xml" }, "type": "application/rss+xml", "string": "application/rss+xml", "suffixes": [ "xml", "rss" ] }, { "mainType": "application", "subType": "toml", "delimiter": ".", "firstSuffix": { "suffix": "toml", "fullSuffix": ".toml" }, "type": "application/toml", "string": "application/toml", "suffixes": [ "toml" ] }, { "mainType": "application", "subType": "typescript", "delimiter": ".", "firstSuffix": { "suffix": "ts", "fullSuffix": ".ts" }, "type": "application/typescript", "string": "application/typescript", "suffixes": [ "ts" ] }, { "mainType": "application", "subType": "xml", "delimiter": ".", "firstSuffix": { "suffix": "xml", "fullSuffix": ".xml" }, "type": "application/xml", "string": "application/xml", "suffixes": [ "xml" ] }, { "mainType": "application", "subType": "yaml", "delimiter": ".", "firstSuffix": { "suffix": "yaml", "fullSuffix": ".yaml" }, "type": "application/yaml", "string": "application/yaml", "suffixes": [ "yaml", "yml" ] }, { "mainType": "font", "subType": "otf", "delimiter": ".", "firstSuffix": { "suffix": "otf", "fullSuffix": ".otf" }, "type": "font/otf", "string": "font/otf", "suffixes": [ "otf" ] }, { "mainType": "font", "subType": "ttf", "delimiter": ".", "firstSuffix": { "suffix": "ttf", "fullSuffix": ".ttf" }, "type": "font/ttf", "string": "font/ttf", "suffixes": [ "ttf" ] }, { "mainType": "image", "subType": "bmp", "delimiter": ".", "firstSuffix": { "suffix": "bmp", "fullSuffix": ".bmp" }, "type": "image/bmp", "string": "image/bmp", "suffixes": [ "bmp" ] }, { "mainType": "image", "subType": "gif", "delimiter": ".", "firstSuffix": { "suffix": "gif", "fullSuffix": ".gif" }, "type": "image/gif", "string": "image/gif", "suffixes": [ "gif" ] }, { "mainType": "image", "subType": "jpeg", "delimiter": ".", "firstSuffix": { "suffix": "jpg", "fullSuffix": ".jpg" }, "type": "image/jpeg", "string": "image/jpeg", "suffixes": [ "jpg", "jpeg", "jpe", "jif", "jfif" ] }, { "mainType": "image", "subType": "png", "delimiter": ".", "firstSuffix": { "suffix": "png", "fullSuffix": ".png" }, "type": "image/png", "string": "image/png", "suffixes": [ "png" ] }, { "mainType": "image", "subType": "svg", "delimiter": ".", "firstSuffix": { "suffix": "svg", "fullSuffix": ".svg" }, "type": "image/svg+xml", "string": "image/svg+xml", "suffixes": [ "svg" ] }, { "mainType": "image", "subType": "webp", "delimiter": ".", "firstSuffix": { "suffix": "webp", "fullSuffix": ".webp" }, "type": "image/webp", "string": "image/webp", "suffixes": [ "webp" ] }, { "mainType": "text", "subType": "calendar", "delimiter": ".", "firstSuffix": { "suffix": "ics", "fullSuffix": ".ics" }, "type": "text/calendar", "string": "text/calendar", "suffixes": [ "ics" ] }, { "mainType": "text", "subType": "css", "delimiter": ".", "firstSuffix": { "suffix": "css", "fullSuffix": ".css" }, "type": "text/css", "string": "text/css", "suffixes": [ "css" ] }, { "mainType": "text", "subType": "csv", "delimiter": ".", "firstSuffix": { "suffix": "csv", "fullSuffix": ".csv" }, "type": "text/csv", "string": "text/csv", "suffixes": [ "csv" ] }, { "mainType": "text", "subType": "html", "delimiter": ".", "firstSuffix": { "suffix": "html", "fullSuffix": ".html" }, "type": "text/html", "string": "text/html", "suffixes": [ "html" ] }, { "mainType": "text", "subType": "jsx", "delimiter": ".", "firstSuffix": { "suffix": "jsx", "fullSuffix": ".jsx" }, "type": "text/jsx", "string": "text/jsx", "suffixes": [ "jsx" ] }, { "mainType": "text", "subType": "plain", "delimiter": ".", "firstSuffix": { "suffix": "txt", "fullSuffix": ".txt" }, "type": "text/plain", "string": "text/plain", "suffixes": [ "txt" ] }, { "mainType": "text", "subType": "tsx", "delimiter": ".", "firstSuffix": { "suffix": "tsx", "fullSuffix": ".tsx" }, "type": "text/tsx", "string": "text/tsx", "suffixes": [ "tsx" ] }, { "mainType": "text", "subType": "x-sass", "delimiter": ".", "firstSuffix": { "suffix": "sass", "fullSuffix": ".sass" }, "type": "text/x-sass", "string": "text/x-sass", "suffixes": [ "sass" ] }, { "mainType": "text", "subType": "x-scss", "delimiter": ".", "firstSuffix": { "suffix": "scss", "fullSuffix": ".scss" }, "type": "text/x-scss", "string": "text/x-scss", "suffixes": [ "scss" ] }, { "mainType": "video", "subType": "3gpp", "delimiter": ".", "firstSuffix": { "suffix": "3gpp", "fullSuffix": ".3gpp" }, "type": "video/3gpp", "string": "video/3gpp", "suffixes": [ "3gpp", "3gp" ] }, { "mainType": "video", "subType": "mp4", "delimiter": ".", "firstSuffix": { "suffix": "mp4", "fullSuffix": ".mp4" }, "type": "video/mp4", "string": "video/mp4", "suffixes": [ "mp4" ] }, { "mainType": "video", "subType": "mpeg", "delimiter": ".", "firstSuffix": { "suffix": "mpg", "fullSuffix": ".mpg" }, "type": "video/mpeg", "string": "video/mpeg", "suffixes": [ "mpg", "mpeg" ] }, { "mainType": "video", "subType": "ogg", "delimiter": ".", "firstSuffix": { "suffix": "ogv", "fullSuffix": ".ogv" }, "type": "video/ogg", "string": "video/ogg", "suffixes": [ "ogv" ] }, { "mainType": "video", "subType": "webm", "delimiter": ".", "firstSuffix": { "suffix": "webm", "fullSuffix": ".webm" }, "type": "video/webm", "string": "video/webm", "suffixes": [ "webm" ] }, { "mainType": "video", "subType": "x-msvideo", "delimiter": ".", "firstSuffix": { "suffix": "avi", "fullSuffix": ".avi" }, "type": "video/x-msvideo", "string": "video/x-msvideo", "suffixes": [ "avi" ] } ] }, "output": { "formats": [ { "mediaType": "text/html", "name": "HTML", "path": "", "baseName": "index", "rel": "canonical", "protocol": "", "isPlainText": false, "isHTML": true, "noUgly": false, "notAlternative": false, "permalinkable": true, "weight": 10 }, { "mediaType": "text/html", "name": "AMP", "path": "amp", "baseName": "index", "rel": "amphtml", "protocol": "", "isPlainText": false, "isHTML": true, "noUgly": false, "notAlternative": false, "permalinkable": true, "weight": 0 }, { "mediaType": "text/css", "name": "CSS", "path": "", "baseName": "styles", "rel": "stylesheet", "protocol": "", "isPlainText": true, "isHTML": false, "noUgly": false, "notAlternative": true, "permalinkable": false, "weight": 0 }, { "mediaType": "text/csv", "name": "CSV", "path": "", "baseName": "index", "rel": "alternate", "protocol": "", "isPlainText": true, "isHTML": false, "noUgly": false, "notAlternative": false, "permalinkable": false, "weight": 0 }, { "mediaType": "text/calendar", "name": "Calendar", "path": "", "baseName": "index", "rel": "alternate", "protocol": "webcal://", "isPlainText": true, "isHTML": false, "noUgly": false, "notAlternative": false, "permalinkable": false, "weight": 0 }, { "mediaType": "application/json", "name": "JSON", "path": "", "baseName": "index", "rel": "alternate", "protocol": "", "isPlainText": true, "isHTML": false, "noUgly": false, "notAlternative": false, "permalinkable": false, "weight": 0 }, { "mediaType": "text/plain", "name": "ROBOTS", "path": "", "baseName": "robots", "rel": "alternate", "protocol": "", "isPlainText": true, "isHTML": false, "noUgly": false, "notAlternative": false, "permalinkable": false, "weight": 0 }, { "mediaType": "application/rss+xml", "name": "RSS", "path": "", "baseName": "index", "rel": "alternate", "protocol": "", "isPlainText": false, "isHTML": false, "noUgly": true, "notAlternative": false, "permalinkable": false, "weight": 0 }, { "mediaType": "application/xml", "name": "Sitemap", "path": "", "baseName": "sitemap", "rel": "sitemap", "protocol": "", "isPlainText": false, "isHTML": false, "noUgly": true, "notAlternative": false, "permalinkable": false, "weight": 0 }, { "mediaType": "application/manifest+json", "name": "WebAppManifest", "path": "", "baseName": "manifest", "rel": "manifest", "protocol": "", "isPlainText": true, "isHTML": false, "noUgly": false, "notAlternative": true, "permalinkable": false, "weight": 0 } ], "layouts": [ { "Example": "Single page in \"posts\" section", "Kind": "page", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/posts/single.html.html", "layouts/posts/single.html", "layouts/_default/single.html.html", "layouts/_default/single.html" ] }, { "Example": "Base template for single page in \"posts\" section", "Kind": "page", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/posts/single-baseof.html.html", "layouts/posts/baseof.html.html", "layouts/posts/single-baseof.html", "layouts/posts/baseof.html", "layouts/_default/single-baseof.html.html", "layouts/_default/baseof.html.html", "layouts/_default/single-baseof.html", "layouts/_default/baseof.html" ] }, { "Example": "Single page in \"posts\" section with layout set", "Kind": "page", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/posts/demolayout.html.html", "layouts/posts/single.html.html", "layouts/posts/demolayout.html", "layouts/posts/single.html", "layouts/_default/demolayout.html.html", "layouts/_default/single.html.html", "layouts/_default/demolayout.html", "layouts/_default/single.html" ] }, { "Example": "Base template for single page in \"posts\" section with layout set", "Kind": "page", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/posts/demolayout-baseof.html.html", "layouts/posts/single-baseof.html.html", "layouts/posts/baseof.html.html", "layouts/posts/demolayout-baseof.html", "layouts/posts/single-baseof.html", "layouts/posts/baseof.html", "layouts/_default/demolayout-baseof.html.html", "layouts/_default/single-baseof.html.html", "layouts/_default/baseof.html.html", "layouts/_default/demolayout-baseof.html", "layouts/_default/single-baseof.html", "layouts/_default/baseof.html" ] }, { "Example": "AMP single page", "Kind": "page", "OutputFormat": "AMP", "Suffix": "html", "Template Lookup Order": [ "layouts/posts/single.amp.html", "layouts/posts/single.html", "layouts/_default/single.amp.html", "layouts/_default/single.html" ] }, { "Example": "AMP single page, French language", "Kind": "page", "OutputFormat": "AMP", "Suffix": "html", "Template Lookup Order": [ "layouts/posts/single.fr.amp.html", "layouts/posts/single.amp.html", "layouts/posts/single.fr.html", "layouts/posts/single.html", "layouts/_default/single.fr.amp.html", "layouts/_default/single.amp.html", "layouts/_default/single.fr.html", "layouts/_default/single.html" ] }, { "Example": "Home page", "Kind": "home", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/index.html.html", "layouts/home.html.html", "layouts/list.html.html", "layouts/index.html", "layouts/home.html", "layouts/list.html", "layouts/_default/index.html.html", "layouts/_default/home.html.html", "layouts/_default/list.html.html", "layouts/_default/index.html", "layouts/_default/home.html", "layouts/_default/list.html" ] }, { "Example": "Base template for home page", "Kind": "home", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/index-baseof.html.html", "layouts/home-baseof.html.html", "layouts/list-baseof.html.html", "layouts/baseof.html.html", "layouts/index-baseof.html", "layouts/home-baseof.html", "layouts/list-baseof.html", "layouts/baseof.html", "layouts/_default/index-baseof.html.html", "layouts/_default/home-baseof.html.html", "layouts/_default/list-baseof.html.html", "layouts/_default/baseof.html.html", "layouts/_default/index-baseof.html", "layouts/_default/home-baseof.html", "layouts/_default/list-baseof.html", "layouts/_default/baseof.html" ] }, { "Example": "Home page with type set", "Kind": "home", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/demotype/index.html.html", "layouts/demotype/home.html.html", "layouts/demotype/list.html.html", "layouts/demotype/index.html", "layouts/demotype/home.html", "layouts/demotype/list.html", "layouts/index.html.html", "layouts/home.html.html", "layouts/list.html.html", "layouts/index.html", "layouts/home.html", "layouts/list.html", "layouts/_default/index.html.html", "layouts/_default/home.html.html", "layouts/_default/list.html.html", "layouts/_default/index.html", "layouts/_default/home.html", "layouts/_default/list.html" ] }, { "Example": "Base template for home page with type set", "Kind": "home", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/demotype/index-baseof.html.html", "layouts/demotype/home-baseof.html.html", "layouts/demotype/list-baseof.html.html", "layouts/demotype/baseof.html.html", "layouts/demotype/index-baseof.html", "layouts/demotype/home-baseof.html", "layouts/demotype/list-baseof.html", "layouts/demotype/baseof.html", "layouts/index-baseof.html.html", "layouts/home-baseof.html.html", "layouts/list-baseof.html.html", "layouts/baseof.html.html", "layouts/index-baseof.html", "layouts/home-baseof.html", "layouts/list-baseof.html", "layouts/baseof.html", "layouts/_default/index-baseof.html.html", "layouts/_default/home-baseof.html.html", "layouts/_default/list-baseof.html.html", "layouts/_default/baseof.html.html", "layouts/_default/index-baseof.html", "layouts/_default/home-baseof.html", "layouts/_default/list-baseof.html", "layouts/_default/baseof.html" ] }, { "Example": "Home page with layout set", "Kind": "home", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/demolayout.html.html", "layouts/index.html.html", "layouts/home.html.html", "layouts/list.html.html", "layouts/demolayout.html", "layouts/index.html", "layouts/home.html", "layouts/list.html", "layouts/_default/demolayout.html.html", "layouts/_default/index.html.html", "layouts/_default/home.html.html", "layouts/_default/list.html.html", "layouts/_default/demolayout.html", "layouts/_default/index.html", "layouts/_default/home.html", "layouts/_default/list.html" ] }, { "Example": "AMP home, French language", "Kind": "home", "OutputFormat": "AMP", "Suffix": "html", "Template Lookup Order": [ "layouts/index.fr.amp.html", "layouts/home.fr.amp.html", "layouts/list.fr.amp.html", "layouts/index.amp.html", "layouts/home.amp.html", "layouts/list.amp.html", "layouts/index.fr.html", "layouts/home.fr.html", "layouts/list.fr.html", "layouts/index.html", "layouts/home.html", "layouts/list.html", "layouts/_default/index.fr.amp.html", "layouts/_default/home.fr.amp.html", "layouts/_default/list.fr.amp.html", "layouts/_default/index.amp.html", "layouts/_default/home.amp.html", "layouts/_default/list.amp.html", "layouts/_default/index.fr.html", "layouts/_default/home.fr.html", "layouts/_default/list.fr.html", "layouts/_default/index.html", "layouts/_default/home.html", "layouts/_default/list.html" ] }, { "Example": "JSON home", "Kind": "home", "OutputFormat": "JSON", "Suffix": "json", "Template Lookup Order": [ "layouts/index.json.json", "layouts/home.json.json", "layouts/list.json.json", "layouts/index.json", "layouts/home.json", "layouts/list.json", "layouts/_default/index.json.json", "layouts/_default/home.json.json", "layouts/_default/list.json.json", "layouts/_default/index.json", "layouts/_default/home.json", "layouts/_default/list.json" ] }, { "Example": "RSS home", "Kind": "home", "OutputFormat": "RSS", "Suffix": "xml", "Template Lookup Order": [ "layouts/index.rss.xml", "layouts/home.rss.xml", "layouts/rss.xml", "layouts/list.rss.xml", "layouts/index.xml", "layouts/home.xml", "layouts/list.xml", "layouts/_default/index.rss.xml", "layouts/_default/home.rss.xml", "layouts/_default/rss.xml", "layouts/_default/list.rss.xml", "layouts/_default/index.xml", "layouts/_default/home.xml", "layouts/_default/list.xml", "layouts/_internal/_default/rss.xml" ] }, { "Example": "RSS section posts", "Kind": "section", "OutputFormat": "RSS", "Suffix": "xml", "Template Lookup Order": [ "layouts/posts/section.rss.xml", "layouts/posts/rss.xml", "layouts/posts/list.rss.xml", "layouts/posts/section.xml", "layouts/posts/list.xml", "layouts/section/section.rss.xml", "layouts/section/rss.xml", "layouts/section/list.rss.xml", "layouts/section/section.xml", "layouts/section/list.xml", "layouts/_default/section.rss.xml", "layouts/_default/rss.xml", "layouts/_default/list.rss.xml", "layouts/_default/section.xml", "layouts/_default/list.xml", "layouts/_internal/_default/rss.xml" ] }, { "Example": "Taxonomy in categories", "Kind": "taxonomy", "OutputFormat": "RSS", "Suffix": "xml", "Template Lookup Order": [ "layouts/categories/category.terms.rss.xml", "layouts/categories/terms.rss.xml", "layouts/categories/taxonomy.rss.xml", "layouts/categories/rss.xml", "layouts/categories/list.rss.xml", "layouts/categories/category.terms.xml", "layouts/categories/terms.xml", "layouts/categories/taxonomy.xml", "layouts/categories/list.xml", "layouts/category/category.terms.rss.xml", "layouts/category/terms.rss.xml", "layouts/category/taxonomy.rss.xml", "layouts/category/rss.xml", "layouts/category/list.rss.xml", "layouts/category/category.terms.xml", "layouts/category/terms.xml", "layouts/category/taxonomy.xml", "layouts/category/list.xml", "layouts/taxonomy/category.terms.rss.xml", "layouts/taxonomy/terms.rss.xml", "layouts/taxonomy/taxonomy.rss.xml", "layouts/taxonomy/rss.xml", "layouts/taxonomy/list.rss.xml", "layouts/taxonomy/category.terms.xml", "layouts/taxonomy/terms.xml", "layouts/taxonomy/taxonomy.xml", "layouts/taxonomy/list.xml", "layouts/_default/category.terms.rss.xml", "layouts/_default/terms.rss.xml", "layouts/_default/taxonomy.rss.xml", "layouts/_default/rss.xml", "layouts/_default/list.rss.xml", "layouts/_default/category.terms.xml", "layouts/_default/terms.xml", "layouts/_default/taxonomy.xml", "layouts/_default/list.xml", "layouts/_internal/_default/rss.xml" ] }, { "Example": "Term in categories", "Kind": "term", "OutputFormat": "RSS", "Suffix": "xml", "Template Lookup Order": [ "layouts/categories/term.rss.xml", "layouts/categories/category.rss.xml", "layouts/categories/taxonomy.rss.xml", "layouts/categories/rss.xml", "layouts/categories/list.rss.xml", "layouts/categories/term.xml", "layouts/categories/category.xml", "layouts/categories/taxonomy.xml", "layouts/categories/list.xml", "layouts/term/term.rss.xml", "layouts/term/category.rss.xml", "layouts/term/taxonomy.rss.xml", "layouts/term/rss.xml", "layouts/term/list.rss.xml", "layouts/term/term.xml", "layouts/term/category.xml", "layouts/term/taxonomy.xml", "layouts/term/list.xml", "layouts/taxonomy/term.rss.xml", "layouts/taxonomy/category.rss.xml", "layouts/taxonomy/taxonomy.rss.xml", "layouts/taxonomy/rss.xml", "layouts/taxonomy/list.rss.xml", "layouts/taxonomy/term.xml", "layouts/taxonomy/category.xml", "layouts/taxonomy/taxonomy.xml", "layouts/taxonomy/list.xml", "layouts/category/term.rss.xml", "layouts/category/category.rss.xml", "layouts/category/taxonomy.rss.xml", "layouts/category/rss.xml", "layouts/category/list.rss.xml", "layouts/category/term.xml", "layouts/category/category.xml", "layouts/category/taxonomy.xml", "layouts/category/list.xml", "layouts/_default/term.rss.xml", "layouts/_default/category.rss.xml", "layouts/_default/taxonomy.rss.xml", "layouts/_default/rss.xml", "layouts/_default/list.rss.xml", "layouts/_default/term.xml", "layouts/_default/category.xml", "layouts/_default/taxonomy.xml", "layouts/_default/list.xml", "layouts/_internal/_default/rss.xml" ] }, { "Example": "Section list for \"posts\" section", "Kind": "section", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/posts/posts.html.html", "layouts/posts/section.html.html", "layouts/posts/list.html.html", "layouts/posts/posts.html", "layouts/posts/section.html", "layouts/posts/list.html", "layouts/section/posts.html.html", "layouts/section/section.html.html", "layouts/section/list.html.html", "layouts/section/posts.html", "layouts/section/section.html", "layouts/section/list.html", "layouts/_default/posts.html.html", "layouts/_default/section.html.html", "layouts/_default/list.html.html", "layouts/_default/posts.html", "layouts/_default/section.html", "layouts/_default/list.html" ] }, { "Example": "Section list for \"posts\" section with type set to \"blog\"", "Kind": "section", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/blog/posts.html.html", "layouts/blog/section.html.html", "layouts/blog/list.html.html", "layouts/blog/posts.html", "layouts/blog/section.html", "layouts/blog/list.html", "layouts/posts/posts.html.html", "layouts/posts/section.html.html", "layouts/posts/list.html.html", "layouts/posts/posts.html", "layouts/posts/section.html", "layouts/posts/list.html", "layouts/section/posts.html.html", "layouts/section/section.html.html", "layouts/section/list.html.html", "layouts/section/posts.html", "layouts/section/section.html", "layouts/section/list.html", "layouts/_default/posts.html.html", "layouts/_default/section.html.html", "layouts/_default/list.html.html", "layouts/_default/posts.html", "layouts/_default/section.html", "layouts/_default/list.html" ] }, { "Example": "Section list for \"posts\" section with layout set to \"demoLayout\"", "Kind": "section", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/posts/demolayout.html.html", "layouts/posts/posts.html.html", "layouts/posts/section.html.html", "layouts/posts/list.html.html", "layouts/posts/demolayout.html", "layouts/posts/posts.html", "layouts/posts/section.html", "layouts/posts/list.html", "layouts/section/demolayout.html.html", "layouts/section/posts.html.html", "layouts/section/section.html.html", "layouts/section/list.html.html", "layouts/section/demolayout.html", "layouts/section/posts.html", "layouts/section/section.html", "layouts/section/list.html", "layouts/_default/demolayout.html.html", "layouts/_default/posts.html.html", "layouts/_default/section.html.html", "layouts/_default/list.html.html", "layouts/_default/demolayout.html", "layouts/_default/posts.html", "layouts/_default/section.html", "layouts/_default/list.html" ] }, { "Example": "Taxonomy list in categories", "Kind": "taxonomy", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/categories/category.terms.html.html", "layouts/categories/terms.html.html", "layouts/categories/taxonomy.html.html", "layouts/categories/list.html.html", "layouts/categories/category.terms.html", "layouts/categories/terms.html", "layouts/categories/taxonomy.html", "layouts/categories/list.html", "layouts/category/category.terms.html.html", "layouts/category/terms.html.html", "layouts/category/taxonomy.html.html", "layouts/category/list.html.html", "layouts/category/category.terms.html", "layouts/category/terms.html", "layouts/category/taxonomy.html", "layouts/category/list.html", "layouts/taxonomy/category.terms.html.html", "layouts/taxonomy/terms.html.html", "layouts/taxonomy/taxonomy.html.html", "layouts/taxonomy/list.html.html", "layouts/taxonomy/category.terms.html", "layouts/taxonomy/terms.html", "layouts/taxonomy/taxonomy.html", "layouts/taxonomy/list.html", "layouts/_default/category.terms.html.html", "layouts/_default/terms.html.html", "layouts/_default/taxonomy.html.html", "layouts/_default/list.html.html", "layouts/_default/category.terms.html", "layouts/_default/terms.html", "layouts/_default/taxonomy.html", "layouts/_default/list.html" ] }, { "Example": "Taxonomy term in categories", "Kind": "term", "OutputFormat": "HTML", "Suffix": "html", "Template Lookup Order": [ "layouts/categories/term.html.html", "layouts/categories/category.html.html", "layouts/categories/taxonomy.html.html", "layouts/categories/list.html.html", "layouts/categories/term.html", "layouts/categories/category.html", "layouts/categories/taxonomy.html", "layouts/categories/list.html", "layouts/term/term.html.html", "layouts/term/category.html.html", "layouts/term/taxonomy.html.html", "layouts/term/list.html.html", "layouts/term/term.html", "layouts/term/category.html", "layouts/term/taxonomy.html", "layouts/term/list.html", "layouts/taxonomy/term.html.html", "layouts/taxonomy/category.html.html", "layouts/taxonomy/taxonomy.html.html", "layouts/taxonomy/list.html.html", "layouts/taxonomy/term.html", "layouts/taxonomy/category.html", "layouts/taxonomy/taxonomy.html", "layouts/taxonomy/list.html", "layouts/category/term.html.html", "layouts/category/category.html.html", "layouts/category/taxonomy.html.html", "layouts/category/list.html.html", "layouts/category/term.html", "layouts/category/category.html", "layouts/category/taxonomy.html", "layouts/category/list.html", "layouts/_default/term.html.html", "layouts/_default/category.html.html", "layouts/_default/taxonomy.html.html", "layouts/_default/list.html.html", "layouts/_default/term.html", "layouts/_default/category.html", "layouts/_default/taxonomy.html", "layouts/_default/list.html" ] } ] }, "tpl": { "funcs": { "cast": { "ToFloat": { "Description": "ToFloat converts the given value to a float.", "Args": [ "v" ], "Aliases": [ "float" ], "Examples": [ [ "{{ \"1234\" | float | printf \"%T\" }}", "float64" ] ] }, "ToInt": { "Description": "ToInt converts the given value to an int.", "Args": [ "v" ], "Aliases": [ "int" ], "Examples": [ [ "{{ \"1234\" | int | printf \"%T\" }}", "int" ] ] }, "ToString": { "Description": "ToString converts the given value to a string.", "Args": [ "v" ], "Aliases": [ "string" ], "Examples": [ [ "{{ 1234 | string | printf \"%T\" }}", "string" ] ] } }, "compare": { "Conditional": { "Description": "Conditional can be used as a ternary operator.\nIt returns a if condition, else b.", "Args": [ "condition", "a", "b" ], "Aliases": [ "cond" ], "Examples": [ [ "{{ cond (eq (add 2 2) 4) \"2+2 is 4\" \"what?\" | safeHTML }}", "2+2 is 4" ] ] }, "Default": { "Description": "Default checks whether a given value is set and returns a default value if it\nis not. \"Set\" in this context means non-zero for numeric types and times;\nnon-zero length for strings, arrays, slices, and maps;\nany boolean or struct value; or non-nil for any other types.", "Args": [ "dflt", "given" ], "Aliases": [ "default" ], "Examples": [ [ "{{ \"Hugo Rocks!\" | default \"Hugo Rules!\" }}", "Hugo Rocks!" ], [ "{{ \"\" | default \"Hugo Rules!\" }}", "Hugo Rules!" ] ] }, "Eq": { "Description": "Eq returns the boolean truth of arg1 == arg2 || arg1 == arg3 || arg1 == arg4.", "Args": [ "first", "others" ], "Aliases": [ "eq" ], "Examples": [ [ "{{ if eq .Section \"blog\" }}current{{ end }}", "current" ] ] }, "Ge": { "Description": "Ge returns the boolean truth of arg1 \u003e= arg2 \u0026\u0026 arg1 \u003e= arg3 \u0026\u0026 arg1 \u003e= arg4.", "Args": [ "first", "others" ], "Aliases": [ "ge" ], "Examples": [ [ "{{ if ge .Hugo.Version \"0.36\" }}Reasonable new Hugo version!{{ end }}", "Reasonable new Hugo version!" ] ] }, "Gt": { "Description": "Gt returns the boolean truth of arg1 \u003e arg2 \u0026\u0026 arg1 \u003e arg3 \u0026\u0026 arg1 \u003e arg4.", "Args": [ "first", "others" ], "Aliases": [ "gt" ], "Examples": [] }, "Le": { "Description": "Le returns the boolean truth of arg1 \u003c= arg2 \u0026\u0026 arg1 \u003c= arg3 \u0026\u0026 arg1 \u003c= arg4.", "Args": [ "first", "others" ], "Aliases": [ "le" ], "Examples": [] }, "Lt": { "Description": "Lt returns the boolean truth of arg1 \u003c arg2 \u0026\u0026 arg1 \u003c arg3 \u0026\u0026 arg1 \u003c arg4.", "Args": [ "first", "others" ], "Aliases": [ "lt" ], "Examples": [] }, "Ne": { "Description": "Ne returns the boolean truth of arg1 != arg2 \u0026\u0026 arg1 != arg3 \u0026\u0026 arg1 != arg4.", "Args": [ "first", "others" ], "Aliases": [ "ne" ], "Examples": [] } }, "collections": { "After": { "Description": "After returns all the items after the first N in a rangeable list.", "Args": [ "index", "seq" ], "Aliases": [ "after" ], "Examples": [] }, "Append": { "Description": "Append appends the arguments up to the last one to the slice in the last argument.\nThis construct allows template constructs like this:\n {{ $pages = $pages | append $p2 $p1 }}\nNote that with 2 arguments where both are slices of the same type,\nthe first slice will be appended to the second:\n {{ $pages = $pages | append .Site.RegularPages }}", "Args": [ "args" ], "Aliases": [ "append" ], "Examples": [] }, "Apply": { "Description": "Apply takes a map, array, or slice and returns a new slice with the function fname applied over it.", "Args": [ "seq", "fname", "args" ], "Aliases": [ "apply" ], "Examples": [] }, "Complement": { "Description": "Complement gives the elements in the last element of seqs that are not in\nany of the others.\nAll elements of seqs must be slices or arrays of comparable types.\n\nThe reasoning behind this rather clumsy API is so we can do this in the templates:\n {{ $c := .Pages | complement $last4 }}", "Args": [ "seqs" ], "Aliases": [ "complement" ], "Examples": [ [ "{{ slice \"a\" \"b\" \"c\" \"d\" \"e\" \"f\" | complement (slice \"b\" \"c\") (slice \"d\" \"e\") }}", "[a f]" ] ] }, "Delimit": { "Description": "Delimit takes a given sequence and returns a delimited HTML string.\nIf last is passed to the function, it will be used as the final delimiter.", "Args": [ "seq", "delimiter", "last" ], "Aliases": [ "delimit" ], "Examples": [ [ "{{ delimit (slice \"A\" \"B\" \"C\") \", \" \" and \" }}", "A, B and C" ] ] }, "Dictionary": { "Description": "Dictionary creates a map[string]interface{} from the given parameters by\nwalking the parameters and treating them as key-value pairs. The number\nof parameters must be even.\nThe keys can be string slices, which will create the needed nested structure.", "Args": [ "values" ], "Aliases": [ "dict" ], "Examples": [] }, "EchoParam": { "Description": "EchoParam returns a given value if it is set; otherwise, it returns an\nempty string.", "Args": [ "a", "key" ], "Aliases": [ "echoParam" ], "Examples": [ [ "{{ echoParam .Params \"langCode\" }}", "en" ] ] }, "First": { "Description": "First returns the first N items in a rangeable list.", "Args": [ "limit", "seq" ], "Aliases": [ "first" ], "Examples": [] }, "Group": { "Description": "Group groups a set of elements by the given key.\nThis is currently only supported for Pages.", "Args": [ "key", "items" ], "Aliases": [ "group" ], "Examples": [] }, "In": { "Description": "In returns whether v is in the set l. l may be an array or slice.", "Args": [ "l", "v" ], "Aliases": [ "in" ], "Examples": [ [ "{{ if in \"this string contains a substring\" \"substring\" }}Substring found!{{ end }}", "Substring found!" ] ] }, "Index": { "Description": "Index returns the result of indexing its first argument by the following\narguments. Thus \"index x 1 2 3\" is, in Go syntax, x[1][2][3]. Each\nindexed item must be a map, slice, or array.\n\nCopied from Go stdlib src/text/template/funcs.go.\n\nWe deviate from the stdlib due to https://github.com/golang/go/issues/14751.\n\nTODO(moorereason): merge upstream changes.", "Args": [ "item", "args" ], "Aliases": [ "index" ], "Examples": [] }, "Intersect": { "Description": "Intersect returns the common elements in the given sets, l1 and l2. l1 and\nl2 must be of the same type and may be either arrays or slices.", "Args": [ "l1", "l2" ], "Aliases": [ "intersect" ], "Examples": [] }, "IsSet": { "Description": "IsSet returns whether a given array, channel, slice, or map has a key\ndefined.", "Args": [ "a", "key" ], "Aliases": [ "isSet", "isset" ], "Examples": [] }, "KeyVals": { "Description": "KeyVals creates a key and values wrapper.", "Args": [ "key", "vals" ], "Aliases": [ "keyVals" ], "Examples": [ [ "{{ keyVals \"key\" \"a\" \"b\" }}", "key: [a b]" ] ] }, "Last": { "Description": "Last returns the last N items in a rangeable list.", "Args": [ "limit", "seq" ], "Aliases": [ "last" ], "Examples": [] }, "Merge": { "Description": "Merge creates a copy of the final parameter and merges the preceding\nparameters into it in reverse order.\nCurrently only maps are supported. Key handling is case insensitive.", "Args": [ "params" ], "Aliases": [ "merge" ], "Examples": [ [ "{{ dict \"title\" \"Hugo Rocks!\" | collections.Merge (dict \"title\" \"Default Title\" \"description\" \"Yes, Hugo Rocks!\") | sort }}", "[Yes, Hugo Rocks! Hugo Rocks!]" ], [ "{{ merge (dict \"title\" \"Default Title\" \"description\" \"Yes, Hugo Rocks!\") (dict \"title\" \"Hugo Rocks!\") | sort }}", "[Yes, Hugo Rocks! Hugo Rocks!]" ], [ "{{ merge (dict \"title\" \"Default Title\" \"description\" \"Yes, Hugo Rocks!\") (dict \"title\" \"Hugo Rocks!\") (dict \"extra\" \"For reals!\") | sort }}", "[Yes, Hugo Rocks! For reals! Hugo Rocks!]" ] ] }, "NewScratch": { "Description": "NewScratch creates a new Scratch which can be used to store values in a\nthread safe way.", "Args": null, "Aliases": [ "newScratch" ], "Examples": [ [ "{{ $scratch := newScratch }}{{ $scratch.Add \"b\" 2 }}{{ $scratch.Add \"b\" 2 }}{{ $scratch.Get \"b\" }}", "4" ] ] }, "Querify": { "Description": "Querify encodes the given parameters in URL-encoded form (\"bar=baz\u0026foo=quux\") sorted by key.", "Args": [ "params" ], "Aliases": [ "querify" ], "Examples": [ [ "{{ (querify \"foo\" 1 \"bar\" 2 \"baz\" \"with spaces\" \"qux\" \"this\u0026that=those\") | safeHTML }}", "bar=2\u0026baz=with+spaces\u0026foo=1\u0026qux=this%26that%3Dthose" ], [ "\u003ca href=\"https://www.google.com?{{ (querify \"q\" \"test\" \"page\" 3) | safeURL }}\"\u003eSearch\u003c/a\u003e", "\u003ca href=\"https://www.google.com?page=3\u0026amp;q=test\"\u003eSearch\u003c/a\u003e" ], [ "{{ slice \"foo\" 1 \"bar\" 2 | querify | safeHTML }}", "bar=2\u0026foo=1" ] ] }, "Reverse": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Seq": { "Description": "Seq creates a sequence of integers. It's named and used as GNU's seq.\n\nExamples:\n 3 =\u003e 1, 2, 3\n 1 2 4 =\u003e 1, 3\n -3 =\u003e -1, -2, -3\n 1 4 =\u003e 1, 2, 3, 4\n 1 -2 =\u003e 1, 0, -1, -2", "Args": [ "args" ], "Aliases": [ "seq" ], "Examples": [ [ "{{ seq 3 }}", "[1 2 3]" ] ] }, "Shuffle": { "Description": "Shuffle returns the given rangeable list in a randomised order.", "Args": [ "seq" ], "Aliases": [ "shuffle" ], "Examples": [] }, "Slice": { "Description": "Slice returns a slice of all passed arguments.", "Args": [ "args" ], "Aliases": [ "slice" ], "Examples": [ [ "{{ slice \"B\" \"C\" \"A\" | sort }}", "[A B C]" ] ] }, "Sort": { "Description": "Sort returns a sorted sequence.", "Args": [ "seq", "args" ], "Aliases": [ "sort" ], "Examples": [] }, "SymDiff": { "Description": "SymDiff returns the symmetric difference of s1 and s2.\nArguments must be either a slice or an array of comparable types.", "Args": [ "s2", "s1" ], "Aliases": [ "symdiff" ], "Examples": [ [ "{{ slice 1 2 3 | symdiff (slice 3 4) }}", "[1 2 4]" ] ] }, "Union": { "Description": "Union returns the union of the given sets, l1 and l2. l1 and\nl2 must be of the same type and may be either arrays or slices.\nIf l1 and l2 aren't of the same type then l1 will be returned.\nIf either l1 or l2 is nil then the non-nil list will be returned.", "Args": [ "l1", "l2" ], "Aliases": [ "union" ], "Examples": [ [ "{{ union (slice 1 2 3) (slice 3 4 5) }}", "[1 2 3 4 5]" ] ] }, "Uniq": { "Description": "Uniq takes in a slice or array and returns a slice with subsequent\nduplicate elements removed.", "Args": [ "seq" ], "Aliases": [ "uniq" ], "Examples": [ [ "{{ slice 1 2 3 2 | uniq }}", "[1 2 3]" ] ] }, "Where": { "Description": "Where returns a filtered subset of a given data type.", "Args": [ "seq", "key", "args" ], "Aliases": [ "where" ], "Examples": [] } }, "crypto": { "HMAC": { "Description": "HMAC returns a cryptographic hash that uses a key to sign a message.", "Args": [ "h", "k", "m" ], "Aliases": [ "hmac" ], "Examples": [ [ "{{ hmac \"sha256\" \"Secret key\" \"Hello world, gophers!\" }}", "b6d11b6c53830b9d87036272ca9fe9d19306b8f9d8aa07b15da27d89e6e34f40" ] ] }, "MD5": { "Description": "MD5 hashes the given input and returns its MD5 checksum.", "Args": [ "in" ], "Aliases": [ "md5" ], "Examples": [ [ "{{ md5 \"Hello world, gophers!\" }}", "b3029f756f98f79e7f1b7f1d1f0dd53b" ], [ "{{ crypto.MD5 \"Hello world, gophers!\" }}", "b3029f756f98f79e7f1b7f1d1f0dd53b" ] ] }, "SHA1": { "Description": "SHA1 hashes the given input and returns its SHA1 checksum.", "Args": [ "in" ], "Aliases": [ "sha1" ], "Examples": [ [ "{{ sha1 \"Hello world, gophers!\" }}", "c8b5b0e33d408246e30f53e32b8f7627a7a649d4" ] ] }, "SHA256": { "Description": "SHA256 hashes the given input and returns its SHA256 checksum.", "Args": [ "in" ], "Aliases": [ "sha256" ], "Examples": [ [ "{{ sha256 \"Hello world, gophers!\" }}", "6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46" ] ] } }, "data": { "GetCSV": { "Description": "GetCSV expects a data separator and one or n-parts of a URL to a resource which\ncan either be a local or a remote one.\nThe data separator can be a comma, semi-colon, pipe, etc, but only one character.\nIf you provide multiple parts for the URL they will be joined together to the final URL.\nGetCSV returns nil or a slice slice to use in a short code.", "Args": [ "sep", "args" ], "Aliases": [ "getCSV" ], "Examples": [] }, "GetJSON": { "Description": "GetJSON expects one or n-parts of a URL to a resource which can either be a local or a remote one.\nIf you provide multiple parts they will be joined together to the final URL.\nGetJSON returns nil or parsed JSON to use in a short code.", "Args": [ "args" ], "Aliases": [ "getJSON" ], "Examples": [] } }, "debug": { "Dump": { "Description": "Dump returns a object dump of val as a string.\nNote that not every value passed to Dump will print so nicely, but\nwe'll improve on that. We recommend using the \"go\" Chroma lexer to format the output\nnicely.\nAlso note that the output from Dump may change from Hugo version to the next,\nso don't depend on a specific output.", "Args": [ "val" ], "Aliases": null, "Examples": [ [ "{{- $m := newScratch -}}\n{{- $m.Set \"Hugo\" \"Rocks!\" -}}\n{{- $m.Values | debug.Dump | safeHTML -}}", "map[string]interface {}{\n \"Hugo\": \"Rocks!\",\n}" ] ] } }, "encoding": { "Base64Decode": { "Description": "Base64Decode returns the base64 decoding of the given content.", "Args": [ "content" ], "Aliases": [ "base64Decode" ], "Examples": [ [ "{{ \"SGVsbG8gd29ybGQ=\" | base64Decode }}", "Hello world" ], [ "{{ 42 | base64Encode | base64Decode }}", "42" ] ] }, "Base64Encode": { "Description": "Base64Encode returns the base64 encoding of the given content.", "Args": [ "content" ], "Aliases": [ "base64Encode" ], "Examples": [ [ "{{ \"Hello world\" | base64Encode }}", "SGVsbG8gd29ybGQ=" ] ] }, "Jsonify": { "Description": "Jsonify encodes a given object to JSON. To pretty print the JSON, pass a map\nor dictionary of options as the first argument. Supported options are\n\"prefix\" and \"indent\". Each JSON element in the output will begin on a new\nline beginning with prefix followed by one or more copies of indent according\nto the indentation nesting.", "Args": [ "args" ], "Aliases": [ "jsonify" ], "Examples": [ [ "{{ (slice \"A\" \"B\" \"C\") | jsonify }}", "[\"A\",\"B\",\"C\"]" ], [ "{{ (slice \"A\" \"B\" \"C\") | jsonify (dict \"indent\" \" \") }}", "[\n \"A\",\n \"B\",\n \"C\"\n]" ] ] } }, "fmt": { "Errorf": { "Description": "Errorf formats according to a format specifier and logs an ERROR.\nIt returns an empty string.", "Args": [ "format", "a" ], "Aliases": [ "errorf" ], "Examples": [ [ "{{ errorf \"%s.\" \"failed\" }}", "" ] ] }, "Erroridf": { "Description": "Erroridf formats according to a format specifier and logs an ERROR and\nan information text that the error with the given ID can be suppressed in config.\nIt returns an empty string.", "Args": [ "id", "format", "a" ], "Aliases": [ "erroridf" ], "Examples": [ [ "{{ erroridf \"my-err-id\" \"%s.\" \"failed\" }}", "" ] ] }, "Print": { "Description": "Print returns string representation of the passed arguments.", "Args": [ "a" ], "Aliases": [ "print" ], "Examples": [ [ "{{ print \"works!\" }}", "works!" ] ] }, "Printf": { "Description": "Printf returns a formatted string representation of the passed arguments.", "Args": [ "format", "a" ], "Aliases": [ "printf" ], "Examples": [ [ "{{ printf \"%s!\" \"works\" }}", "works!" ] ] }, "Println": { "Description": "Println returns string representation of the passed arguments ending with a newline.", "Args": [ "a" ], "Aliases": [ "println" ], "Examples": [ [ "{{ println \"works!\" }}", "works!\n" ] ] }, "Warnf": { "Description": "Warnf formats according to a format specifier and logs a WARNING.\nIt returns an empty string.", "Args": [ "format", "a" ], "Aliases": [ "warnf" ], "Examples": [ [ "{{ warnf \"%s.\" \"warning\" }}", "" ] ] } }, "hugo": { "Deps": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Generator": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "IsExtended": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "IsProduction": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Version": { "Description": "", "Args": null, "Aliases": null, "Examples": null } }, "images": { "Brightness": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "ColorBalance": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Colorize": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Config": { "Description": "Config returns the image.Config for the specified path relative to the\nworking directory.", "Args": [ "path" ], "Aliases": [ "imageConfig" ], "Examples": [] }, "Contrast": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Filter": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Gamma": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "GaussianBlur": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Grayscale": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Hue": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Invert": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Overlay": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Pixelate": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Saturation": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Sepia": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Sigmoid": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Text": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "UnsharpMask": { "Description": "", "Args": null, "Aliases": null, "Examples": null } }, "inflect": { "Humanize": { "Description": "Humanize returns the humanized form of a single parameter.\n\nIf the parameter is either an integer or a string containing an integer\nvalue, the behavior is to add the appropriate ordinal.\n\n Example: \"my-first-post\" -\u003e \"My first post\"\n Example: \"103\" -\u003e \"103rd\"\n Example: 52 -\u003e \"52nd\"", "Args": [ "in" ], "Aliases": [ "humanize" ], "Examples": [ [ "{{ humanize \"my-first-post\" }}", "My first post" ], [ "{{ humanize \"myCamelPost\" }}", "My camel post" ], [ "{{ humanize \"52\" }}", "52nd" ], [ "{{ humanize 103 }}", "103rd" ] ] }, "Pluralize": { "Description": "Pluralize returns the plural form of a single word.", "Args": [ "in" ], "Aliases": [ "pluralize" ], "Examples": [ [ "{{ \"cat\" | pluralize }}", "cats" ] ] }, "Singularize": { "Description": "Singularize returns the singular form of a single word.", "Args": [ "in" ], "Aliases": [ "singularize" ], "Examples": [ [ "{{ \"cats\" | singularize }}", "cat" ] ] } }, "js": { "Build": { "Description": "", "Args": null, "Aliases": null, "Examples": null } }, "lang": { "FormatAccounting": { "Description": "FormatAccounting returns the currency representation of number for the given currency and precision\nfor the current language in accounting notation.\n\nThe return value is formatted with at least two decimal places.", "Args": [ "precision", "currency", "number" ], "Aliases": null, "Examples": [ [ "{{ 512.5032 | lang.FormatAccounting 2 \"NOK\" }}", "NOK512.50" ] ] }, "FormatCurrency": { "Description": "FormatCurrency returns the currency representation of number for the given currency and precision\nfor the current language.\n\nThe return value is formatted with at least two decimal places.", "Args": [ "precision", "currency", "number" ], "Aliases": null, "Examples": [ [ "{{ 512.5032 | lang.FormatCurrency 2 \"USD\" }}", "$512.50" ] ] }, "FormatNumber": { "Description": "FormatNumber formats number with the given precision for the current language.", "Args": [ "precision", "number" ], "Aliases": null, "Examples": [ [ "{{ 512.5032 | lang.FormatNumber 2 }}", "512.50" ] ] }, "FormatNumberCustom": { "Description": "FormatNumberCustom formats a number with the given precision using the\nnegative, decimal, and grouping options. The `options`\nparameter is a string consisting of `\u003cnegative\u003e \u003cdecimal\u003e \u003cgrouping\u003e`. The\ndefault `options` value is `- . ,`.\n\nNote that numbers are rounded up at 5 or greater.\nSo, with precision set to 0, 1.5 becomes `2`, and 1.4 becomes `1`.\n\nFor a simpler function that adapts to the current language, see FormatNumber.", "Args": [ "precision", "number", "options" ], "Aliases": null, "Examples": [ [ "{{ lang.FormatNumberCustom 2 12345.6789 }}", "12,345.68" ], [ "{{ lang.FormatNumberCustom 2 12345.6789 \"- , .\" }}", "12.345,68" ], [ "{{ lang.FormatNumberCustom 6 -12345.6789 \"- .\" }}", "-12345.678900" ], [ "{{ lang.FormatNumberCustom 0 -12345.6789 \"- . ,\" }}", "-12,346" ], [ "{{ -98765.4321 | lang.FormatNumberCustom 2 }}", "-98,765.43" ] ] }, "FormatPercent": { "Description": "FormatPercent formats number with the given precision for the current language.\nNote that the number is assumed to be a percentage.", "Args": [ "precision", "number" ], "Aliases": null, "Examples": [ [ "{{ 512.5032 | lang.FormatPercent 2 }}", "512.50%" ] ] }, "Merge": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "NumFmt": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Translate": { "Description": "Translate returns a translated string for id.", "Args": [ "id", "args" ], "Aliases": [ "i18n", "T" ], "Examples": [] } }, "math": { "Add": { "Description": "Add adds two numbers.", "Args": [ "a", "b" ], "Aliases": [ "add" ], "Examples": [ [ "{{add 1 2}}", "3" ] ] }, "Ceil": { "Description": "Ceil returns the least integer value greater than or equal to x.", "Args": [ "x" ], "Aliases": null, "Examples": [ [ "{{math.Ceil 2.1}}", "3" ] ] }, "Div": { "Description": "Div divides two numbers.", "Args": [ "a", "b" ], "Aliases": [ "div" ], "Examples": [ [ "{{div 6 3}}", "2" ] ] }, "Floor": { "Description": "Floor returns the greatest integer value less than or equal to x.", "Args": [ "x" ], "Aliases": null, "Examples": [ [ "{{math.Floor 1.9}}", "1" ] ] }, "Log": { "Description": "Log returns the natural logarithm of a number.", "Args": [ "a" ], "Aliases": null, "Examples": [ [ "{{math.Log 1}}", "0" ] ] }, "Max": { "Description": "Max returns the greater of two numbers.", "Args": [ "a", "b" ], "Aliases": null, "Examples": [ [ "{{math.Max 1 2 }}", "2" ] ] }, "Min": { "Description": "Min returns the smaller of two numbers.", "Args": [ "a", "b" ], "Aliases": null, "Examples": [ [ "{{math.Min 1 2 }}", "1" ] ] }, "Mod": { "Description": "Mod returns a % b.", "Args": [ "a", "b" ], "Aliases": [ "mod" ], "Examples": [ [ "{{mod 15 3}}", "0" ] ] }, "ModBool": { "Description": "ModBool returns the boolean of a % b. If a % b == 0, return true.", "Args": [ "a", "b" ], "Aliases": [ "modBool" ], "Examples": [ [ "{{modBool 15 3}}", "true" ] ] }, "Mul": { "Description": "Mul multiplies two numbers.", "Args": [ "a", "b" ], "Aliases": [ "mul" ], "Examples": [ [ "{{mul 2 3}}", "6" ] ] }, "Pow": { "Description": "Pow returns a raised to the power of b.", "Args": [ "a", "b" ], "Aliases": [ "pow" ], "Examples": [ [ "{{math.Pow 2 3}}", "8" ] ] }, "Round": { "Description": "Round returns the nearest integer, rounding half away from zero.", "Args": [ "x" ], "Aliases": null, "Examples": [ [ "{{math.Round 1.5}}", "2" ] ] }, "Sqrt": { "Description": "Sqrt returns the square root of a number.", "Args": [ "a" ], "Aliases": null, "Examples": [ [ "{{math.Sqrt 81}}", "9" ] ] }, "Sub": { "Description": "Sub subtracts two numbers.", "Args": [ "a", "b" ], "Aliases": [ "sub" ], "Examples": [ [ "{{sub 3 2}}", "1" ] ] } }, "openapi3": { "Unmarshal": { "Description": "", "Args": null, "Aliases": null, "Examples": [] } }, "os": { "FileExists": { "Description": "FileExists checks whether a file exists under the given path.", "Args": [ "i" ], "Aliases": [ "fileExists" ], "Examples": [ [ "{{ fileExists \"foo.txt\" }}", "false" ] ] }, "Getenv": { "Description": "Getenv retrieves the value of the environment variable named by the key.\nIt returns the value, which will be empty if the variable is not present.", "Args": [ "key" ], "Aliases": [ "getenv" ], "Examples": [] }, "ReadDir": { "Description": "ReadDir lists the directory contents relative to the configured WorkingDir.", "Args": [ "i" ], "Aliases": [ "readDir" ], "Examples": [ [ "{{ range (readDir \"files\") }}{{ .Name }}{{ end }}", "README.txt" ] ] }, "ReadFile": { "Description": "ReadFile reads the file named by filename relative to the configured WorkingDir.\nIt returns the contents as a string.\nThere is an upper size limit set at 1 megabytes.", "Args": [ "i" ], "Aliases": [ "readFile" ], "Examples": [ [ "{{ readFile \"files/README.txt\" }}", "Hugo Rocks!" ] ] }, "Stat": { "Description": "", "Args": null, "Aliases": null, "Examples": null } }, "partials": { "Include": { "Description": "Include executes the named partial.\nIf the partial contains a return statement, that value will be returned.\nElse, the rendered output will be returned:\nA string if the partial is a text/template, or template.HTML when html/template.", "Args": [ "name", "contextList" ], "Aliases": [ "partial" ], "Examples": [ [ "{{ partial \"header.html\" . }}", "\u003ctitle\u003eHugo Rocks!\u003c/title\u003e" ] ] }, "IncludeCached": { "Description": "IncludeCached executes and caches partial templates. The cache is created with name+variants as the key.", "Args": [ "name", "context", "variants" ], "Aliases": [ "partialCached" ], "Examples": [] } }, "path": { "Base": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Clean": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Dir": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Ext": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Join": { "Description": "Join joins any number of path elements into a single path, adding a\nseparating slash if necessary. All the input\npath elements are passed into filepath.ToSlash converting any Windows slashes\nto forward slashes.\nThe result is Cleaned; in particular,\nall empty strings are ignored.", "Args": [ "elements" ], "Aliases": null, "Examples": [ [ "{{ slice \"my/path\" \"filename.txt\" | path.Join }}", "my/path/filename.txt" ], [ "{{ path.Join \"my\" \"path\" \"filename.txt\" }}", "my/path/filename.txt" ], [ "{{ \"my/path/filename.txt\" | path.Ext }}", ".txt" ], [ "{{ \"my/path/filename.txt\" | path.Base }}", "filename.txt" ], [ "{{ \"my/path/filename.txt\" | path.Dir }}", "my/path" ] ] }, "Split": { "Description": "Split splits path immediately following the final slash,\nseparating it into a directory and file name component.\nIf there is no slash in path, Split returns an empty dir and\nfile set to path.\nThe input path is passed into filepath.ToSlash converting any Windows slashes\nto forward slashes.\nThe returned values have the property that path = dir+file.", "Args": [ "path" ], "Aliases": null, "Examples": [ [ "{{ \"/my/path/filename.txt\" | path.Split }}", "/my/path/|filename.txt" ], [ "{{ \"/my/path/filename.txt\" | path.Split }}", "/my/path/|filename.txt" ] ] } }, "reflect": { "IsMap": { "Description": "IsMap reports whether v is a map.", "Args": [ "v" ], "Aliases": null, "Examples": [ [ "{{ if reflect.IsMap (dict \"a\" 1) }}Map{{ end }}", "Map" ] ] }, "IsSlice": { "Description": "IsSlice reports whether v is a slice.", "Args": [ "v" ], "Aliases": null, "Examples": [ [ "{{ if reflect.IsSlice (slice 1 2 3) }}Slice{{ end }}", "Slice" ] ] } }, "resources": { "Babel": { "Description": "Babel processes the given Resource with Babel.", "Args": [ "args" ], "Aliases": [ "babel" ], "Examples": [] }, "Concat": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "ExecuteAsTemplate": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Fingerprint": { "Description": "Fingerprint transforms the given Resource with a MD5 hash of the content in\nthe RelPermalink and Permalink.", "Args": [ "args" ], "Aliases": [ "fingerprint" ], "Examples": [] }, "FromString": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Get": { "Description": "Get locates the filename given in Hugo's assets filesystem and\ncreates a Resource object that can be used for\nfurther transformations.", "Args": [ "filename" ], "Aliases": null, "Examples": [] }, "GetMatch": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "GetRemote": { "Description": "GetRemote gets the URL (via HTTP(s)) in the first argument in args and creates Resource object that can be used for\nfurther transformations.\n\nA second argument may be provided with an option map.\n\nNote: This method does not return any error as a second argument,\nfor any error situations the error can be checked in .Err.", "Args": [ "args" ], "Aliases": null, "Examples": [] }, "Match": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Minify": { "Description": "Minify minifies the given Resource using the MediaType to pick the correct\nminifier.", "Args": [ "r" ], "Aliases": [ "minify" ], "Examples": [] }, "PostCSS": { "Description": "PostCSS processes the given Resource with PostCSS", "Args": [ "args" ], "Aliases": [ "postCSS" ], "Examples": [] }, "PostProcess": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "ToCSS": { "Description": "ToCSS converts the given Resource to CSS. You can optional provide an Options\nobject or a target path (string) as first argument.", "Args": [ "args" ], "Aliases": [ "toCSS" ], "Examples": [] } }, "safe": { "CSS": { "Description": "CSS returns a given string as html/template CSS content.", "Args": [ "a" ], "Aliases": [ "safeCSS" ], "Examples": [ [ "{{ \"Bat\u0026Man\" | safeCSS | safeCSS }}", "Bat\u0026amp;Man" ] ] }, "HTML": { "Description": "HTML returns a given string as html/template HTML content.", "Args": [ "a" ], "Aliases": [ "safeHTML" ], "Examples": [ [ "{{ \"Bat\u0026Man\" | safeHTML | safeHTML }}", "Bat\u0026Man" ], [ "{{ \"Bat\u0026Man\" | safeHTML }}", "Bat\u0026Man" ] ] }, "HTMLAttr": { "Description": "HTMLAttr returns a given string as html/template HTMLAttr content.", "Args": [ "a" ], "Aliases": [ "safeHTMLAttr" ], "Examples": [] }, "JS": { "Description": "JS returns the given string as a html/template JS content.", "Args": [ "a" ], "Aliases": [ "safeJS" ], "Examples": [ [ "{{ \"(1*2)\" | safeJS | safeJS }}", "(1*2)" ] ] }, "JSStr": { "Description": "JSStr returns the given string as a html/template JSStr content.", "Args": [ "a" ], "Aliases": [ "safeJSStr" ], "Examples": [] }, "SanitizeURL": { "Description": "SanitizeURL returns a given string as html/template URL content.", "Args": [ "a" ], "Aliases": [ "sanitizeURL", "sanitizeurl" ], "Examples": [] }, "URL": { "Description": "URL returns a given string as html/template URL content.", "Args": [ "a" ], "Aliases": [ "safeURL" ], "Examples": [ [ "{{ \"http://gohugo.io\" | safeURL | safeURL }}", "http://gohugo.io" ] ] } }, "site": { "BaseURL": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Data": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Hugo": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "IsServer": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Language": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "LastChange": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Menus": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Pages": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Params": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "RegularPages": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "ServerPort": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Sites": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Taxonomies": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Title": { "Description": "", "Args": null, "Aliases": null, "Examples": null } }, "strings": { "Chomp": { "Description": "Chomp returns a copy of s with all trailing newline characters removed.", "Args": [ "s" ], "Aliases": [ "chomp" ], "Examples": [ [ "{{chomp \"\u003cp\u003eBlockhead\u003c/p\u003e\\n\" | safeHTML }}", "\u003cp\u003eBlockhead\u003c/p\u003e" ] ] }, "Contains": { "Description": "Contains reports whether substr is in s.", "Args": [ "s", "substr" ], "Aliases": null, "Examples": [ [ "{{ strings.Contains \"abc\" \"b\" }}", "true" ], [ "{{ strings.Contains \"abc\" \"d\" }}", "false" ] ] }, "ContainsAny": { "Description": "ContainsAny reports whether any Unicode code points in chars are within s.", "Args": [ "s", "chars" ], "Aliases": null, "Examples": [ [ "{{ strings.ContainsAny \"abc\" \"bcd\" }}", "true" ], [ "{{ strings.ContainsAny \"abc\" \"def\" }}", "false" ] ] }, "Count": { "Description": "Count counts the number of non-overlapping instances of substr in s.\nIf substr is an empty string, Count returns 1 + the number of Unicode code points in s.", "Args": [ "substr", "s" ], "Aliases": null, "Examples": [ [ "{{\"aabab\" | strings.Count \"a\" }}", "3" ] ] }, "CountRunes": { "Description": "CountRunes returns the number of runes in s, excluding whitespace.", "Args": [ "s" ], "Aliases": [ "countrunes" ], "Examples": [] }, "CountWords": { "Description": "CountWords returns the approximate word count in s.", "Args": [ "s" ], "Aliases": [ "countwords" ], "Examples": [] }, "FindRE": { "Description": "FindRE returns a list of strings that match the regular expression. By default all matches\nwill be included. The number of matches can be limited with an optional third parameter.", "Args": [ "expr", "content", "limit" ], "Aliases": [ "findRE" ], "Examples": [ [ "{{ findRE \"[G|g]o\" \"Hugo is a static side generator written in Go.\" \"1\" }}", "[go]" ] ] }, "FirstUpper": { "Description": "FirstUpper returns a string with the first character as upper case.", "Args": [ "s" ], "Aliases": null, "Examples": [ [ "{{ \"hugo rocks!\" | strings.FirstUpper }}", "Hugo rocks!" ] ] }, "HasPrefix": { "Description": "HasPrefix tests whether the input s begins with prefix.", "Args": [ "s", "prefix" ], "Aliases": [ "hasPrefix" ], "Examples": [ [ "{{ hasPrefix \"Hugo\" \"Hu\" }}", "true" ], [ "{{ hasPrefix \"Hugo\" \"Fu\" }}", "false" ] ] }, "HasSuffix": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Repeat": { "Description": "Repeat returns a new string consisting of count copies of the string s.", "Args": [ "n", "s" ], "Aliases": null, "Examples": [ [ "{{ \"yo\" | strings.Repeat 4 }}", "yoyoyoyo" ] ] }, "Replace": { "Description": "Replace returns a copy of the string s with all occurrences of old replaced\nwith new. The number of replacements can be limited with an optional fourth\nparameter.", "Args": [ "s", "old", "new", "limit" ], "Aliases": [ "replace" ], "Examples": [ [ "{{ replace \"Batman and Robin\" \"Robin\" \"Catwoman\" }}", "Batman and Catwoman" ], [ "{{ replace \"aabbaabb\" \"a\" \"z\" 2 }}", "zzbbaabb" ] ] }, "ReplaceRE": { "Description": "ReplaceRE returns a copy of s, replacing all matches of the regular\nexpression pattern with the replacement text repl. The number of replacements\ncan be limited with an optional fourth parameter.", "Args": [ "pattern", "repl", "s", "n" ], "Aliases": [ "replaceRE" ], "Examples": [ [ "{{ replaceRE \"a+b\" \"X\" \"aabbaabbab\" }}", "XbXbX" ], [ "{{ replaceRE \"a+b\" \"X\" \"aabbaabbab\" 1 }}", "Xbaabbab" ] ] }, "RuneCount": { "Description": "RuneCount returns the number of runes in s.", "Args": [ "s" ], "Aliases": null, "Examples": [] }, "SliceString": { "Description": "SliceString slices a string by specifying a half-open range with\ntwo indices, start and end. 1 and 4 creates a slice including elements 1 through 3.\nThe end index can be omitted, it defaults to the string's length.", "Args": [ "a", "startEnd" ], "Aliases": [ "slicestr" ], "Examples": [ [ "{{slicestr \"BatMan\" 0 3}}", "Bat" ], [ "{{slicestr \"BatMan\" 3}}", "Man" ] ] }, "Split": { "Description": "Split slices an input string into all substrings separated by delimiter.", "Args": [ "a", "delimiter" ], "Aliases": [ "split" ], "Examples": [] }, "Substr": { "Description": "Substr extracts parts of a string, beginning at the character at the specified\nposition, and returns the specified number of characters.\n\nIt normally takes two parameters: start and length.\nIt can also take one parameter: start, i.e. length is omitted, in which case\nthe substring starting from start until the end of the string will be returned.\n\nTo extract characters from the end of the string, use a negative start number.\n\nIn addition, borrowing from the extended behavior described at http://php.net/substr,\nif length is given and is negative, then that many characters will be omitted from\nthe end of string.", "Args": [ "a", "nums" ], "Aliases": [ "substr" ], "Examples": [ [ "{{substr \"BatMan\" 0 -3}}", "Bat" ], [ "{{substr \"BatMan\" 3 3}}", "Man" ] ] }, "Title": { "Description": "Title returns a copy of the input s with all Unicode letters that begin words\nmapped to their title case.", "Args": [ "s" ], "Aliases": [ "title" ], "Examples": [ [ "{{title \"Bat man\"}}", "Bat Man" ], [ "{{title \"somewhere over the rainbow\"}}", "Somewhere Over the Rainbow" ] ] }, "ToLower": { "Description": "ToLower returns a copy of the input s with all Unicode letters mapped to their\nlower case.", "Args": [ "s" ], "Aliases": [ "lower" ], "Examples": [ [ "{{lower \"BatMan\"}}", "batman" ] ] }, "ToUpper": { "Description": "ToUpper returns a copy of the input s with all Unicode letters mapped to their\nupper case.", "Args": [ "s" ], "Aliases": [ "upper" ], "Examples": [ [ "{{upper \"BatMan\"}}", "BATMAN" ] ] }, "Trim": { "Description": "Trim returns a string with all leading and trailing characters defined\ncontained in cutset removed.", "Args": [ "s", "cutset" ], "Aliases": [ "trim" ], "Examples": [ [ "{{ trim \"++Batman--\" \"+-\" }}", "Batman" ] ] }, "TrimLeft": { "Description": "TrimLeft returns a slice of the string s with all leading characters\ncontained in cutset removed.", "Args": [ "cutset", "s" ], "Aliases": null, "Examples": [ [ "{{ \"aabbaa\" | strings.TrimLeft \"a\" }}", "bbaa" ] ] }, "TrimPrefix": { "Description": "TrimPrefix returns s without the provided leading prefix string. If s doesn't\nstart with prefix, s is returned unchanged.", "Args": [ "prefix", "s" ], "Aliases": null, "Examples": [ [ "{{ \"aabbaa\" | strings.TrimPrefix \"a\" }}", "abbaa" ], [ "{{ \"aabbaa\" | strings.TrimPrefix \"aa\" }}", "bbaa" ] ] }, "TrimRight": { "Description": "TrimRight returns a slice of the string s with all trailing characters\ncontained in cutset removed.", "Args": [ "cutset", "s" ], "Aliases": null, "Examples": [ [ "{{ \"aabbaa\" | strings.TrimRight \"a\" }}", "aabb" ] ] }, "TrimSuffix": { "Description": "TrimSuffix returns s without the provided trailing suffix string. If s\ndoesn't end with suffix, s is returned unchanged.", "Args": [ "suffix", "s" ], "Aliases": null, "Examples": [ [ "{{ \"aabbaa\" | strings.TrimSuffix \"a\" }}", "aabba" ], [ "{{ \"aabbaa\" | strings.TrimSuffix \"aa\" }}", "aabb" ] ] }, "Truncate": { "Description": "Truncate truncates a given string to the specified length.", "Args": [ "a", "options" ], "Aliases": [ "truncate" ], "Examples": [ [ "{{ \"this is a very long text\" | truncate 10 \" ...\" }}", "this is a ..." ], [ "{{ \"With [Markdown](/markdown) inside.\" | markdownify | truncate 14 }}", "With \u003ca href=\"/markdown\"\u003eMarkdown …\u003c/a\u003e" ] ] } }, "templates": { "Exists": { "Description": "Exists returns whether the template with the given name exists.\nNote that this is the Unix-styled relative path including filename suffix,\ne.g. partials/header.html", "Args": [ "name" ], "Aliases": null, "Examples": [ [ "{{ if (templates.Exists \"partials/header.html\") }}Yes!{{ end }}", "Yes!" ], [ "{{ if not (templates.Exists \"partials/doesnotexist.html\") }}No!{{ end }}", "No!" ] ] } }, "time": { "AsTime": { "Description": "AsTime converts the textual representation of the datetime string into\na time.Time interface.", "Args": [ "v", "args" ], "Aliases": null, "Examples": [ [ "{{ (time \"2015-01-21\").Year }}", "2015" ] ] }, "Duration": { "Description": "Duration converts the given number to a time.Duration.\nUnit is one of nanosecond/ns, microsecond/us/µs, millisecond/ms, second/s, minute/m or hour/h.", "Args": [ "unit", "number" ], "Aliases": [ "duration" ], "Examples": [ [ "{{ mul 60 60 | duration \"second\" }}", "1h0m0s" ] ] }, "Format": { "Description": "Format converts the textual representation of the datetime string into\nthe other form or returns it of the time.Time value. These are formatted\nwith the layout string", "Args": [ "layout", "v" ], "Aliases": [ "dateFormat" ], "Examples": [ [ "dateFormat: {{ dateFormat \"Monday, Jan 2, 2006\" \"2015-01-21\" }}", "dateFormat: Wednesday, Jan 21, 2015" ] ] }, "Now": { "Description": "Now returns the current local time.", "Args": null, "Aliases": [ "now" ], "Examples": [] }, "ParseDuration": { "Description": "ParseDuration parses a duration string.\nA duration string is a possibly signed sequence of\ndecimal numbers, each with optional fraction and a unit suffix,\nsuch as \"300ms\", \"-1.5h\" or \"2h45m\".\nValid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".\nSee https://golang.org/pkg/time/#ParseDuration", "Args": [ "in" ], "Aliases": null, "Examples": [ [ "{{ \"1h12m10s\" | time.ParseDuration }}", "1h12m10s" ] ] } }, "transform": { "Emojify": { "Description": "Emojify returns a copy of s with all emoji codes replaced with actual emojis.\n\nSee http://www.emoji-cheat-sheet.com/", "Args": [ "s" ], "Aliases": [ "emojify" ], "Examples": [ [ "{{ \"I :heart: Hugo\" | emojify }}", "I ❤️ Hugo" ] ] }, "HTMLEscape": { "Description": "HTMLEscape returns a copy of s with reserved HTML characters escaped.", "Args": [ "s" ], "Aliases": [ "htmlEscape" ], "Examples": [ [ "{{ htmlEscape \"Cathal Garvey \u0026 The Sunshine Band \u003ccathal@foo.bar\u003e\" | safeHTML}}", "Cathal Garvey \u0026amp; The Sunshine Band \u0026lt;cathal@foo.bar\u0026gt;" ], [ "{{ htmlEscape \"Cathal Garvey \u0026 The Sunshine Band \u003ccathal@foo.bar\u003e\"}}", "Cathal Garvey \u0026amp;amp; The Sunshine Band \u0026amp;lt;cathal@foo.bar\u0026amp;gt;" ], [ "{{ htmlEscape \"Cathal Garvey \u0026 The Sunshine Band \u003ccathal@foo.bar\u003e\" | htmlUnescape | safeHTML }}", "Cathal Garvey \u0026 The Sunshine Band \u003ccathal@foo.bar\u003e" ] ] }, "HTMLUnescape": { "Description": "HTMLUnescape returns a copy of with HTML escape requences converted to plain\ntext.", "Args": [ "s" ], "Aliases": [ "htmlUnescape" ], "Examples": [ [ "{{ htmlUnescape \"Cathal Garvey \u0026amp; The Sunshine Band \u0026lt;cathal@foo.bar\u0026gt;\" | safeHTML}}", "Cathal Garvey \u0026 The Sunshine Band \u003ccathal@foo.bar\u003e" ], [ "{{\"Cathal Garvey \u0026amp;amp; The Sunshine Band \u0026amp;lt;cathal@foo.bar\u0026amp;gt;\" | htmlUnescape | htmlUnescape | safeHTML}}", "Cathal Garvey \u0026 The Sunshine Band \u003ccathal@foo.bar\u003e" ], [ "{{\"Cathal Garvey \u0026amp;amp; The Sunshine Band \u0026amp;lt;cathal@foo.bar\u0026amp;gt;\" | htmlUnescape | htmlUnescape }}", "Cathal Garvey \u0026amp; The Sunshine Band \u0026lt;cathal@foo.bar\u0026gt;" ], [ "{{ htmlUnescape \"Cathal Garvey \u0026amp; The Sunshine Band \u0026lt;cathal@foo.bar\u0026gt;\" | htmlEscape | safeHTML }}", "Cathal Garvey \u0026amp; The Sunshine Band \u0026lt;cathal@foo.bar\u0026gt;" ] ] }, "Highlight": { "Description": "Highlight returns a copy of s as an HTML string with syntax\nhighlighting applied.", "Args": [ "s", "lang", "opts" ], "Aliases": [ "highlight" ], "Examples": [] }, "Markdownify": { "Description": "Markdownify renders a given input from Markdown to HTML.", "Args": [ "s" ], "Aliases": [ "markdownify" ], "Examples": [ [ "{{ .Title | markdownify}}", "\u003cstrong\u003eBatMan\u003c/strong\u003e" ] ] }, "Plainify": { "Description": "Plainify returns a copy of s with all HTML tags removed.", "Args": [ "s" ], "Aliases": [ "plainify" ], "Examples": [ [ "{{ plainify \"Hello \u003cstrong\u003eworld\u003c/strong\u003e, gophers!\" }}", "Hello world, gophers!" ] ] }, "Remarshal": { "Description": "Remarshal is used in the Hugo documentation to convert configuration\nexamples from YAML to JSON, TOML (and possibly the other way around).\nThe is primarily a helper for the Hugo docs site.\nIt is not a general purpose YAML to TOML converter etc., and may\nchange without notice if it serves a purpose in the docs.\nFormat is one of json, yaml or toml.", "Args": [ "format", "data" ], "Aliases": null, "Examples": [ [ "{{ \"title = \\\"Hello World\\\"\" | transform.Remarshal \"json\" | safeHTML }}", "{\n \"title\": \"Hello World\"\n}\n" ] ] }, "Unmarshal": { "Description": "Unmarshal unmarshals the data given, which can be either a string, json.RawMessage\nor a Resource. Supported formats are JSON, TOML, YAML, and CSV.\nYou can optionally provide an options map as the first argument.", "Args": [ "args" ], "Aliases": [ "unmarshal" ], "Examples": [ [ "{{ \"hello = \\\"Hello World\\\"\" | transform.Unmarshal }}", "map[hello:Hello World]" ], [ "{{ \"hello = \\\"Hello World\\\"\" | resources.FromString \"data/greetings.toml\" | transform.Unmarshal }}", "map[hello:Hello World]" ] ] } }, "urls": { "AbsLangURL": { "Description": "AbsLangURL takes a given string and converts it to an absolute URL according\nto a page's position in the project directory structure and the current\nlanguage.", "Args": [ "a" ], "Aliases": [ "absLangURL" ], "Examples": [] }, "AbsURL": { "Description": "AbsURL takes a given string and converts it to an absolute URL.", "Args": [ "a" ], "Aliases": [ "absURL" ], "Examples": [] }, "Anchorize": { "Description": "Anchorize creates sanitized anchor names that are compatible with Blackfriday.", "Args": [ "a" ], "Aliases": [ "anchorize" ], "Examples": [ [ "{{ \"This is a title\" | anchorize }}", "this-is-a-title" ] ] }, "Parse": { "Description": "", "Args": null, "Aliases": null, "Examples": null }, "Ref": { "Description": "Ref returns the absolute URL path to a given content item.", "Args": [ "in", "args" ], "Aliases": [ "ref" ], "Examples": [] }, "RelLangURL": { "Description": "RelLangURL takes a given string and prepends the relative path according to a\npage's position in the project directory structure and the current language.", "Args": [ "a" ], "Aliases": [ "relLangURL" ], "Examples": [] }, "RelRef": { "Description": "RelRef returns the relative URL path to a given content item.", "Args": [ "in", "args" ], "Aliases": [ "relref" ], "Examples": [] }, "RelURL": { "Description": "RelURL takes a given string and prepends the relative path according to a\npage's position in the project directory structure.", "Args": [ "a" ], "Aliases": [ "relURL" ], "Examples": [] }, "URLize": { "Description": "URLize returns the given argument formatted as URL.", "Args": [ "a" ], "Aliases": [ "urlize" ], "Examples": [] } } } } } hugo-0.92.2/docs/data/homepagetweets.toml000066400000000000000000000301171420147000300203160ustar00rootroot00000000000000[[tweet]] name = "Heinrich Hartmann" twitter_handle = "@heinrichhartman" quote = "Working with @GoHugoIO is such a joy. Having worked with #Jekyll in the past, the near instant preview is a big win! Did not expect this to make such a huge difference." link = "https://twitter.com/heinrichhartman/status/1199736512264462341" date = 2019-11-12T00:00:00Z [[tweet]] name = "Joshua Steven‏‏" twitter_handle = "@jscarto" quote = "Can't overstate how much I enjoy @GoHugoIO. My site is relatively small, but *18 ms* to build the whole thing made template development and proofing a breeze." link = "https://twitter.com/jscarto/status/1039648827815485440" date = 2018-09-12T00:00:00Z [[tweet]] name = "Christophe Diericx" twitter_handle = "@spcrngr_" quote = "The more I use gohugo.io, the more I really like it. Super intuitive/powerful static site generator...great job @GoHugoIO" link = "https://twitter.com/spcrngr_/status/870863020905435136" date = 2017-06-03T00:00:00Z [[tweet]] name = "marcoscan" twitter_handle = "@marcoscan" quote = "Blog migrated from @WordPress to @GoHugoIO, with a little refresh of my theme, Vim shortcuts and a full featured deploy script #gohugo" link = "https://twitter.com/marcoscan/status/869661175960752129" date = 2017-05-30T00:00:00Z [[tweet]] name = "Sandra Kuipers" twitter_handle = "@SKuipersDesign" quote = "Who knew static site building could be fun 🤔 Learning #gohugo today" link = "https://twitter.com/SKuipersDesign/status/868796256902029312" date = 2017-05-28T00:00:00Z [[tweet]] name = "Netlify" twitter_handle = "@Netlify" quote = "Top Ten Static Site Generators of 2017. Congrats to the top 3: 1. @Jekyllrb 2. @GoHugoIO 3. @hexojs" link = "https://twitter.com/Netlify/status/868122279221362688" date = 2017-05-26T00:00:00Z [[tweet]] name = "Phil Hawksworth" twitter_handle = "@philhawksworth" quote = "I've been keen on #JAMStack for some time, but @GoHugoIO is wooing me all over again. Great fun to build with. And speeeeedy." link = "https://twitter.com/philhawksworth/status/866684170512326657" date = 2017-05-22T00:00:00Z [[tweet]] name = "Aras Pranckevicius" twitter_handle = "@aras_p" quote = "I've probably said it before...but having Hugo rebuild the whole website in 300ms is amazing. gohugo.io, #gohugo" link = "https://twitter.com/aras_p/status/861157286823288832" date = 2017-05-07T00:00:00Z [[tweet]] name = "Hans Beck" twitter_handle = "@EnrichedGamesHB" quote = "Diving deeper into @GoHugoIO. A lot of docs there, top work! But I've the impressed that #gohugo is far easier than its feels from the docs!" link = "https://twitter.com/EnrichedGamesHB/status/836854762440130560" date = 2017-03-01T00:00:00Z [[tweet]] name = "Alan Richardson" twitter_handle = "@eviltester" quote = "I migrated the @BlackOpsTesting .com website from docpad to Hugo last weekend. http://gohugo.io/ Super Fast HTML Generation @spf13 " link = "https://twitter.com/eviltester/status/553520335115808768" date = 2015-01-09T00:00:00Z [[tweet]] name = "Janez Čadež‏" twitter_handle = "@jamziSLO" quote = "Building @garazaFRI website in #hugo. This static site generator is soooo damn fast! #gohugo #golang" link = "https://twitter.com/jamziSLO/status/817720283977183234" date = 2017-01-07T00:00:00Z [[tweet]] name = "Execute‏‏" twitter_handle = "@executerun" quote = "Hah, #gohugo. I was working with #gohugo on #linux but now I realised how easy is to set-up it on #windows. Just need to add binary to #path!" link = "https://twitter.com/executerun/status/809753145270272005" date = 2016-12-16T00:00:00Z [[tweet]] name = "Baron Schwartz" twitter_handle = "@xaprb" quote = "Hugo is impressively capable. It's a static site generator by @spf13 written in #golang . Just upgraded to latest release; very powerful. " link = "https://twitter.com/xaprb/status/556894866488455169" date = 2015-01-18T00:00:00Z [[tweet]] name = "Dave Cottlehuber" twitter_handle = "@dch__" quote = "I just fell in love with #hugo, a static site/blog engine written by @spf13 in #golang + stellar docs" link = "https://twitter.com/dch__/status/460158115498176512" date = 2014-04-26T00:00:00Z [[tweet]] name = "David Caunt" twitter_handle = "@dcaunt" quote = "I had a play with Hugo and it was good, uses Markdown files for content" link = "https://twitter.com/dcaunt/statuses/406466996277374976" date = 2013-11-29T00:00:00Z [[tweet]] name = "David Gay" twitter_handle = "@oddshocks" quote = "Hugo is super-rad." link = "https://twitter.com/oddshocks/statuses/405083217893421056" date = 2013-11-25T00:00:00Z [[tweet]] name = "Diti" twitter_handle = "@DitiPengi" quote = "The dev version of Hugo is AWESOME! <3 I promise, I will try to learn go ASAP and help contribute to the project! Just too great!" link = "https://twitter.com/DitiPengi/status/472470974051676160" date = 2014-05-30T00:00:00Z [[tweet]] name = "Douglas Stephen " twitter_handle = "@DougStephenJr" quote = "Even as a long-time Octopress fan, I’ve gotta admit that this project Hugo looks very very cool" link = "https://twitter.com/DougStephenJr/statuses/364512471660249088" date = 2013-08-05T00:00:00Z [[tweet]] name = "Hugo Rodger-Brown" twitter_handle = "@hugorodgerbrown" quote = "Finally someone builds me my own static site generator" link = "https://twitter.com/hugorodgerbrown/statuses/364417910153818112" date = 2013-05-08T00:00:00Z [[tweet]] name = "Hugo Roy" twitter_handle = "@hugoroyd" quote = "Finally the answer to the question my parents have been asking: What does Hugo do?" link = "https://twitter.com/hugoroyd/status/501704796727173120" date = 2014-08-19T00:00:00Z [[tweet]] name = "Daniel Miessler" twitter_handle = "@DanielMiessler" quote = "Websites for named vulnerabilities should run on static site generator platforms like Hugo. Read-only + burst traffic = static." link = "https://twitter.com/DanielMiessler/status/704703841673957376" date = 2016-03-01T00:00:00Z [[tweet]] name = "Javier Segura" twitter_handle = "@jsegura" quote = "Another site generated with Hugo here! I'm getting in love with it." link = "https://twitter.com/jsegura/status/465978434154659841" date = 2014-05-12T00:00:00Z [[tweet]] name = "Jim Biancolo" twitter_handle = "@jimbiancolo" quote = "I’m loving the static site generator renaissance we are currently enjoying. Hugo is new, looks great, written in Go" link = "https://twitter.com/jimbiancolo/statuses/408678420348813314" date = 2013-05-12T00:00:00Z [[tweet]] name = "Jip J. Dekker" twitter_handle = "@jipjdekker" quote = "Building a personal website in Hugo. Works like a charm. And written in @golang!" link = "https://twitter.com/jipjdekker/status/413783548735152131" date = 2013-12-19T00:00:00Z [[tweet]] name = "Jose Gonzalvo" twitter_handle = "@jgonzalvo" quote = "Checking out Hugo; Loving it so far. Like Jekyll but not so blog-oriented and written in go" link = "https://twitter.com/jgonzalvo/statuses/408177855819173888" date = 2013-12-04T00:00:00Z [[tweet]] name = "Josh Matz" twitter_handle = "@joshmatz" quote = "A static site generator without the long build times? Yes, please!" link = "https://twitter.com/joshmatz/statuses/364437436870696960" date = 2013-08-05T00:00:00Z [[tweet]] name = "Kieran Healy" twitter_handle = "@kjhealy" quote = "OK, so in today's speed battle of static site generators, @spf13's hugo is kicking everyone's ass, by miles." link = "https://twitter.com/kjhealy/status/437349384809115648" date = 2014-02-22T00:00:00Z [[tweet]] name = "Ludovic Chabant" twitter_handle = "@ludovicchabant" quote = "Good work on Hugo, I’m impressed with the speed!" link = "https://twitter.com/ludovicchabant/statuses/408806199602053120" date = 2013-12-06T00:00:00Z [[tweet]] name = "Luke Holder" twitter_handle = "@lukeholder" quote = "this is AWESOME. a single little executable and so fast." link = "https://twitter.com/lukeholder/status/430352287936946176" date = 2014-02-03T00:00:00Z [[tweet]] name = "Markus Eliasson" twitter_handle = "@markuseliasson" quote = "Hugo is fast, dead simple to setup and well documented" link = "https://twitter.com/markuseliasson/status/501594865877008384" date = 2014-08-19T00:00:00Z [[tweet]] name = "mercime" twitter_handle = "@mercime_one" quote = "Hugo: Makes the Web Fun Again" link = "https://twitter.com/mercime_one/status/500547145087205377" date = 2014-08-16T00:00:00Z [[tweet]] name = "Michael Whatcott" twitter_handle = "@mdwhatcott" quote = "One more satisfied #Hugo blogger. Thanks @spf13 and friends!" link = "https://twitter.com/mdwhatcott/status/469980686531571712" date = 2014-05-23T00:00:00Z [[tweet]] name = "Nathan Toups" twitter_handle = "@rojoroboto" quote = "I love Hugo! My site is generated with it now http://rjrbt.io" link = "https://twitter.com/rojoroboto/status/423439915620106242" date = 2014-01-15T00:00:00Z [[tweet]] name = "Ruben Solvang" twitter_handle = "@messo85" quote = "#Hugo is the new @jekyllrb / @middlemanapp! Faster, easier and runs everywhere." link = "https://twitter.com/messo85/status/472825062027182081" date = 2014-05-31T00:00:00Z [[tweet]] name = "Ryan Martinsen" twitter_handle = "@popthestack" quote = "Also, I re-launched my blog (it looks the same as before) using Hugo, a *fast* static engine. Very happy with it. gohugo.io" link = "https://twitter.com/popthestack/status/549972754125307904" date = 2014-12-30T00:00:00Z [[tweet]] name = "The Lone Cuber" twitter_handle = "@TheLoneCuber" quote = "Jekyll is dead to me these days though... long live Hugo! Hugo is *by far* the best in its field. Thanks for making it happen." link = "https://twitter.com/TheLoneCuber/status/495716684456398848" date = 2014-08-02T00:00:00Z [[tweet]] name = "The Lone Cuber" twitter_handle = "@TheLoneCuber" quote = "Finally, a publishing platform that's a joy to use. #NoMoreBarriers" link = "https://twitter.com/TheLoneCuber/status/495731334711488512" date = 2014-08-02T00:00:00Z [[tweet]] name = "WorkHTML" twitter_handle = "@workhtml" quote = " #Hugo A very good alternative for #wordpress !!! A fast and modern static website engine gohugo.io " link = "https://twitter.com/workhtml/status/563064361301053440" date = 2015-02-04T00:00:00Z hugo-0.92.2/docs/data/titles.toml000066400000000000000000000000431420147000300165740ustar00rootroot00000000000000[Showcase] title = "Site Showcase" hugo-0.92.2/docs/go.mod000066400000000000000000000002101420147000300145640ustar00rootroot00000000000000module github.com/gohugoio/hugoDocs go 1.16 require github.com/gohugoio/gohugoioTheme v0.0.0-20211211134334-0fe25799bb58 // indirect hugo-0.92.2/docs/go.sum000066400000000000000000000076141420147000300146300ustar00rootroot00000000000000github.com/gohugoio/gohugoioTheme v0.0.0-20190808163145-07b3c0f73b02/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20191014144142-1f3a01deed7b h1:PWNjl46fvtz54PKO0BdiXOF6/4L/uCP0F3gtcCxGrJs= github.com/gohugoio/gohugoioTheme v0.0.0-20191014144142-1f3a01deed7b/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20191021162625-2e7250ca437d h1:D3DcaYkuJbotdWNNAQpQl37txX4HQ6R5uMHoxVmTw0w= github.com/gohugoio/gohugoioTheme v0.0.0-20191021162625-2e7250ca437d/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20200123151337-9475fd449324 h1:UZwHDYtGY0uOKIvcm2LWd+xfFxD3X5L222LIJdI5RE4= github.com/gohugoio/gohugoioTheme v0.0.0-20200123151337-9475fd449324/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20200123204146-589b4c309025 h1:ScYFARz+bHX1rEr1donVknhRdxGY/cwqK1hHvWEfrlc= github.com/gohugoio/gohugoioTheme v0.0.0-20200123204146-589b4c309025/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20200123205007-5d6620a0db26 h1:acXfduibbWxji9tW0WkLHbjcXFsnd5uIwXe0WfwOazg= github.com/gohugoio/gohugoioTheme v0.0.0-20200123205007-5d6620a0db26/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20200128164921-1d0bc5482051 h1:cS14MnUGS6xwWYfPNshimm8HdMCZiYBxWkCD0VnvgVw= github.com/gohugoio/gohugoioTheme v0.0.0-20200128164921-1d0bc5482051/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20200327225449-368f4cbef8d7 h1:cZ+ahAjSetbFv3aDJ9ipDbKyqaVlmkbSZ5cULgBTh+w= github.com/gohugoio/gohugoioTheme v0.0.0-20200327225449-368f4cbef8d7/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20200327231942-7f80b3d02bfa h1:kG+O/wT9UXomzp5eQiUuFVZ0l7YylAW6EVPLyjMxi/c= github.com/gohugoio/gohugoioTheme v0.0.0-20200327231942-7f80b3d02bfa/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20200328100657-2bfd5f8c6aee h1:PJZhCwnuVLyafDWNPSHk9iJvk6gEIvPRnycy7Pq3peA= github.com/gohugoio/gohugoioTheme v0.0.0-20200328100657-2bfd5f8c6aee/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20200518164958-62cbad03c40f h1:Ge3JACszSUyJW2Az9cJzWdo4PUqdijJA1RxoQSVMBSI= github.com/gohugoio/gohugoioTheme v0.0.0-20200518164958-62cbad03c40f/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20200518165806-0095b7b902a7 h1:Sy0hlWyZmFtdSY0Cobvw1ZYm3G1aR5+4DuFNRbMkh48= github.com/gohugoio/gohugoioTheme v0.0.0-20200518165806-0095b7b902a7/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20200711112515-b0dfe471654f h1:BWJyycs4HD7tUbaU8RIGeMay84bIBWRVVLE3yajPas4= github.com/gohugoio/gohugoioTheme v0.0.0-20200711112515-b0dfe471654f/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20210301124928-2c15837dfec3 h1:ShqzOFeeg54FPSuS6q8HSeTVgj2xNZRe/YS0jNbi21g= github.com/gohugoio/gohugoioTheme v0.0.0-20210301124928-2c15837dfec3/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20210409065807-6383d8cbaf65 h1:EJzierSWKqwsrUXU6MaFe0J97c0e5pzl5dBNRRrV2Nc= github.com/gohugoio/gohugoioTheme v0.0.0-20210409065807-6383d8cbaf65/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20210409071416-c88da48134b7 h1:uRCgPslaBgLYy4ANXBoPbBQVM8aNiHoxIZTKUXpkuUA= github.com/gohugoio/gohugoioTheme v0.0.0-20210409071416-c88da48134b7/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= github.com/gohugoio/gohugoioTheme v0.0.0-20211211125852-b85e21c1f3d6 h1:lAgdWrn8VEg0PrNCPX4DflCg2msDKpSYV6E8RTNV3N0= github.com/gohugoio/gohugoioTheme v0.0.0-20211211125852-b85e21c1f3d6/go.mod h1:kpw3SS48xZvLQGEXKu8u5XHgXkPvL8DX3oGa07+z8Bs= hugo-0.92.2/docs/hugo_stats.json000066400000000000000000000437261420147000300165540ustar00rootroot00000000000000{ "htmlElements": { "tags": [ "", "a", "article", "aside", "blockquote", "body", "br", "button", "circle", "code", "date", "dd", "div", "dl", "dt", "em", "figcaption", "figure", "footer", "form", "g", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hr", "html", "i", "iframe", "img", "li", "link", "main", "meta", "nav", "noscript", "ol", "p", "path", "pre", "script", "section", "small", "span", "strong", "style", "sup", "svg", "table", "tbody", "td", "thead", "time", "title", "tr", "ul" ], "classes": [ "!('about'", "!('content-management'", "!('contribute'", "!('functions'", "!('getting-started'", "!('hosting-and-deployment'", "!('modules'", "!('pipes'", "!('templates'", "!('tools'", "!('troubleshooting'", "!('variables'", "\u0026\u0026", "(false", "(true", "-ml-px", "-mr-12", "-mr-3", "-translate-x-3", "-translate-y-2", "absolute", "absolute-l", "active", "admonition", "admonition-content", "admonition-icon", "anchor", "b--moon-gray", "benchstat", "better", "bg-accent-color-dark", "bg-animate", "bg-black", "bg-carrot-500", "bg-cover", "bg-gradient-to-b", "bg-gray-100", "bg-gray-200", "bg-gray-300", "bg-gray-50", "bg-gray-600", "bg-gray-900", "bg-green-100", "bg-mango-300", "bg-mango-50", "bg-near-white", "bg-opacity-20", "bg-opacity-75", "bg-orange-500", "bg-steel-200", "bg-steel-500", "bg-steel-600", "bg-steel-800", "bg-steel-900", "bg-white", "blTK", "black", "block", "bmt1", "border", "border-0", "border-2", "border-b", "border-gray-100", "border-gray-200", "border-gray-300", "border-l", "border-none", "border-r", "border-solid", "border-t", "border-transparent", "bottom-0", "break-inside-avoid-l", "btn-primary", "c", "c1", "chroma", "clearfix", "cm", "code-copy-content", "code-toggle", "column-count-3-l", "column-gap-1-l", "configs", "copy", "cp", "cursor-pointer", "dark:bg-red-800", "dark:border-gray-800", "delta", "details", "dim", "disabled", "divide-gray-200", "divide-x", "err", "f2-fluid", "f6", "filename", "fill-current", "fixed", "fixed-lTK", "flex", "flex-1", "flex-auto", "flex-auto-ns", "flex-col", "flex-column", "flex-none", "flex-shrink-0", "flex-wrap", "fn", "focus:border-steel-500", "focus:outline-none", "focus:ring-1", "focus:ring-2", "focus:ring-inset", "focus:ring-offset-2", "focus:ring-steel-500", "focus:ring-white", "focus:z-10", "font-black", "font-bold", "font-extrabold", "font-extralight", "font-medium", "font-mono", "font-normal", "font-sans", "font-semibold", "footnote-backref", "footnote-ref", "footnotes", "from-primarydark", "gap-4", "ge", "grid", "grid-cols-1", "group", "grow", "gs", "gu", "h-0", "h-0.5", "h-10", "h-12", "h-16", "h-2", "h-32", "h-5", "h-6", "h-64", "h-8", "h-full", "h-screen", "h6", "hidden", "highlight", "hl", "hover", "hover-bg-green", "hover-bg-near-white", "hover-bg-primary-color", "hover-bg-primary-color-dark", "hover-blue", "hover:bg-gray-300", "hover:bg-gray-50", "hover:bg-steel-500", "hover:bg-steel-700", "hover:border", "hover:text-gray-200", "hover:text-gray-900", "hover:text-hotpink-400", "hover:text-hotpink-600", "hover:text-limegreen-900", "hover:text-royalblue-700", "hover:text-steel-500", "hover:text-white", "img", "in", "inline-block", "inline-flex", "inset-0", "inset-x-0", "instagram-media", "items-center", "items-start", "justify-between", "justify-center", "justify-end", "k", "kc", "kd", "kr", "kt", "l", "language-asciidoc", "language-bash", "language-go", "language-go-html-template", "language-go-text-template", "language-html", "language-js", "language-json", "language-markdown", "language-md", "language-ps1", "language-sh", "language-svg", "language-text", "language-toml", "language-txt", "language-xml", "language-yaml", "language-yml", "lazyload", "ld", "lead", "leading-none", "leading-normal", "leading-relaxed", "leading-snug", "leading-tight", "left-0", "lg:bg-steel-700", "lg:block", "lg:flex", "lg:flex-grow", "lg:flex-shrink-0", "lg:hidden", "lg:inline-block", "lg:items-center", "lg:max-w-lg", "lg:mb-0", "lg:mr-auto", "lg:mt-0", "lg:p-4", "lg:pb-5", "lg:prose-lg", "lg:pt-0", "lg:px-4", "lg:px-5", "lg:px-8", "lg:py-5", "lg:py-8", "lg:rounded-md", "lg:shadow-lg", "lg:space-x-4", "lg:text-5xl", "lg:w-1/2", "lg:w-1/4", "lg:w-1/5", "lg:w-11/12", "lg:w-3/5", "lg:w-4/5", "lg:w-auto", "light-gray", "link", "list-reset", "lnt", "lntable", "lntd", "m", "m-0", "m-1", "max-w-6xl", "max-w-lg", "max-w-xs", "mb-0", "mb-1", "mb-2", "mb-3", "mb-4", "mb-8", "mb5", "mb7", "md:flex", "md:flex-col", "md:flex-grow", "md:grid-cols-2", "md:mt-8", "md:pb-12", "menu))", "menu['about']", "menu['content-management']", "menu['contribute']", "menu['functions']", "menu['getting-started']", "menu['hosting-and-deployment']", "menu['modules']", "menu['pipes']", "menu['templates']", "menu['tools']", "menu['troubleshooting']", "menu['variables']", "mf", "mi", "min-h-screen", "min-w-0", "minor", "ml-1", "ml-10", "ml-4", "ml-6", "ml1", "mr-1.5", "mr-10", "mr-3", "mr-4", "mt-0", "mt-1", "mt-2", "mt-4", "mt-5", "mt-6", "mt-8", "mt3", "mt4", "mv2", "mv3", "mv4", "mv6", "mw-100", "mw5-l", "mx-auto", "my-0", "n", "na", "navbar-menu", "nb", "needs-js", "nested-blockquote", "nested-copy-seperator", "nested-img", "nested-links", "nested-linksTK", "nested-list-reset", "nf", "ni", "nightwind", "nightwind-prevent", "nightwind-prevent-block", "nn", "no-js", "no-underline", "nodelta", "note", "note-icon", "nt", "nt3", "nv", "nx", "o", "o-0", "o-80", "oldnew", "opacity-60", "open", "order-0", "order-0-l", "order-1", "order-1-l", "order-2", "output-content", "overflow-hidden", "overflow-x-scroll", "overflow-y-auto", "p", "p-0", "p-2", "p-3", "p-4", "p-5", "p-8", "pa4-m", "page-item", "page-link", "pagination", "pb-1", "pb-2", "pb-3", "pb-4", "pb-5", "pb-7", "pb-8", "pb2", "ph1", "ph2", "ph4", "pl-0", "pl-1", "pl-2", "pl-3", "pl-6", "pl5-l", "pr-2", "pr1", "primary-color", "prose", "pt-0", "pt-1", "pt-2", "pt-3", "pt-4", "pt-5", "pv1", "px-0", "px-2", "px-3", "px-4", "py-0", "py-0.5", "py-1.5", "py-2", "py-3", "py-4", "py-6", "relative", "right-0", "rounded", "rounded-full", "rounded-l-lg", "rounded-l-md", "rounded-lg", "rounded-md", "rounded-r-md", "row", "s", "s1", "s2", "san-serif", "se", "shadow", "shadow-lg", "shadow-md", "shadow-sm", "show", "sm:flex", "sm:grid-cols-2", "sm:mb-0", "sm:mt-0", "sm:mt-8", "sm:p-4", "sm:pb-0", "sm:pb-6", "sm:pt-3", "sm:pt-5", "sm:px-4", "sm:px-5", "sm:px-6", "sm:py-0", "sm:py-4", "sm:py-5", "sm:py-6", "sm:text-2xl", "sm:text-4xl", "sm:text-base", "sm:text-center", "sm:text-left", "sm:w-1/2", "sm:w-1/5", "sm:w-11/12", "sm:w-4/5", "space-x-4", "space-x-8", "space-y-1", "sr-only", "table", "table-bordered", "tc", "text-2xl", "text-3xl", "text-4xl", "text-5xl", "text-base", "text-black", "text-center", "text-gray-200", "text-gray-300", "text-gray-400", "text-gray-500", "text-gray-600", "text-gray-900", "text-lg", "text-limegreen-600", "text-limegreen-700", "text-mango-100", "text-mango-300", "text-md", "text-royalblue-500", "text-royalblue-600", "text-sm", "text-steel-100", "text-steel-500", "text-steel-900", "text-white", "text-xl", "text-xs", "tile", "tip", "tip-icon", "to-steel-800", "top-0", "top-2", "tracked", "tracking-normal", "tracking-tight", "transform", "twitter-tweet", "unchanged", "uppercase", "v-base", "v-mid", "v-top", "w", "w-1/5", "w-10", "w-11/12", "w-12", "w-14", "w-2", "w-2/3", "w-30-l", "w-32", "w-5", "w-50-m", "w-6", "w-64", "w-8", "w-80-nsTK", "w-96", "w-auto", "w-full", "w-two-third-l", "warning", "whitespace-no-wrap", "worse", "x", "xl:flex", "xl:flex-col", "z-0", "z-40", "z-999", "||" ], "ids": [ ".gitlab-ci.yml", "/blog/greatest-city/index.html", "/content/actors/bruce-willis/_index.md", "/layouts/shortcodes/img.html", "/layouts/shortcodes/vimeo.html", "/layouts/shortcodes/year.html", "/layouts/shortcodes/youtube.html", "/themes/yourtheme/layouts/review/single.html", "404.html", "TableOfContents", "addrobotstxt.sh", "all-taxonomies-keys-and-pages.html", "all-taxonomies.html", "archetype-example.sh", "archetypes/functions.md", "archetypes/newsletter.md", "articles.html", "asciicast-3mf1JGaN0AX0Z7j5kLGl3hSh8", "asciicast-7naKerRYUGVPj8kiDmdh5k5h9", "asciicast-BvJBsF6egk9c163bMsObhuNXj", "asciicast-ItACREbFgvJ0HjnSNeTknxWy9", "asciicast-Lc5iwTVny2kuUC8lqvNnL6oDU", "asciicast-eUojYCfRTZvkEiqc52fUsJRBR", "bad-url-sidebar-menu-output.html", "base-64-output.html", "base64-input.html", "baseof.html", "bf-config.toml", "bf-config.yml", "boxfile.yml", "breadcrumb.html", "check-title-length.html", "clone-herring-cove-theme.sh", "config.toml", "content-header.html", "content-image.md", "content/blog/greatest-city.md", "content/posts/_index.md", "content/posts/default-function-example.md", "content/posts/my-awesome-post.md", "content/posts/my-post.md", "content/posts/old-post.md", "content/posts/old-url.md", "content/tutorials/learn-html.md", "correct-url-sidebar-menu-output.html", "delimit-example-front-matter.toml", "delimit-page-tags-final-and-input.html", "delimit-page-tags-final-and-output.html", "delimit-page-tags-input.html", "delimit-page-tags-output.html", "disqus.html", "dot-notation-default-return-value.html", "dot-notation-default-value.html", "example-tweet-input.md", "example-tweet-output.html", "example-vimeo-input.md", "example-vimeo-output.html", "example-youtube-input-with-autoplay.md", "example-youtube-input-with-title.md", "example-youtube-input.md", "example-youtube-output.html", "example.com/posts/index.html", "example.com/quote/index.html", "external-links.svg", "figure-input-example.md", "figure-output-example.html", "first-and-where-together.html", "fn:1", "fn:2", "fnref:1", "fnref:2", "footer.html", "from-gh.sh", "gist-input.md", "gist-output.html", "gitignore.sh", "gohugoio", "grab-top-two-tags.html", "header.html", "highlight-example.md", "how-many-posts.html", "hugo-new-site.sh", "if-instead-of-default.html", "img-output.html", "index.html", "instagram-hide-caption-output.html", "instagram-input-hide-caption.md", "instagram-input.md", "install-brew.sh", "install-extended-with-chocolatey.ps1", "install-go.sh", "install-openssh.sh", "install-with-chocolatey.ps1", "install-with-homebrew.sh", "install-with-linuxbrew.sh", "install-with-macports.sh", "install.sh", "layout/_default/section.html", "layout/_default/single.html", "layouts/404.html", "layouts/_default/_markup/render-heading.html", "layouts/_default/_markup/render-image.html", "layouts/_default/_markup/render-link.html", "layouts/_default/baseof.html", "layouts/_default/li.html", "layouts/_default/list.html", "layouts/_default/section.html", "layouts/_default/single.html", "layouts/_default/summary.html", "layouts/_default/taxonomy.html", "layouts/index.html", "layouts/partials/all-taxonomies.html", "layouts/partials/alllanguages.html", "layouts/partials/bad-url-sidebar-menu.html", "layouts/partials/breadcrumb.html", "layouts/partials/by-date-reverse.html", "layouts/partials/by-date.html", "layouts/partials/by-expiry-date.html", "layouts/partials/by-group-by-page.html", "layouts/partials/by-last-mod.html", "layouts/partials/by-length.html", "layouts/partials/by-link-title.html", "layouts/partials/by-nested-param.html", "layouts/partials/by-page-date.html", "layouts/partials/by-page-expiry-date.html", "layouts/partials/by-page-field.html", "layouts/partials/by-page-lastmod.html", "layouts/partials/by-page-param-as-date.html", "layouts/partials/by-page-param.html", "layouts/partials/by-page-publish-date.html", "layouts/partials/by-publish-date.html", "layouts/partials/by-rating.html", "layouts/partials/by-title.html", "layouts/partials/by-weight.html", "layouts/partials/content-header.html", "layouts/partials/correct-url-sidebar-menu.html", "layouts/partials/default-order.html", "layouts/partials/disqus.html", "layouts/partials/footer.html", "layouts/partials/get-csv.html", "layouts/partials/groups.html", "layouts/partials/head.html", "layouts/partials/header.html", "layouts/partials/i18nlist.html", "layouts/partials/post-tag-link.html", "layouts/partials/post-tag-list.html", "layouts/partials/related.html", "layouts/partials/schemaorg-metadata.html", "layouts/partials/sidebar.html", "layouts/partials/svgs/external-links.svg", "layouts/partials/toc.html", "layouts/partials/twitter.html", "layouts/partials/upcoming-events.html", "layouts/posts/single.html", "layouts/robots.txt", "layouts/section/articles.html", "layouts/section/posts.html", "layouts/shortcodes/gallery.html", "layouts/shortcodes/img.html", "layouts/shortcodes/imgproc.html", "li.html", "links-to-all-tags.html", "list.html", "netlify.toml", "note-with-heading.html", "note-with-heading.md", "page-list-with-summaries.html", "partial-cached-example.html", "partials/templates/random-tweets.html", "post-tag-list.html", "prose", "push-wecker-to-gh.sh", "range-through-tags-w-global.html", "remove-herring-cove-git.sh", "robots.txt", "schemaorg-metadata.html", "section.html", "setup-gh-repo.sh", "shuffle-input.html", "shuffle-output.html", "sidebar.html", "single.html", "slice.html", "summary.html", "syntax-highlighted.html", "tags-range-with-page-variable.html", "taxonomy.html", "time-passed.html", "tip-output.html", "toc.html", "tutorials/learn-html/index.html", "tweets.html", "unix-to-month-integer.html", "upcoming-events.html", "using-tip.md", "variable-as-default-value.html", "vimeo-iframes.html", "warning-admonition-input.md", "warning-admonition-output.html", "wercker-build-step.yml", "wercker.yml", "where-intersect-variables.html", "with-instead-of-default.html", "yourbaseurl/review/book01/index.html", "youtube-embed.html" ] } }hugo-0.92.2/docs/layouts/000077500000000000000000000000001420147000300151655ustar00rootroot00000000000000hugo-0.92.2/docs/layouts/index.rss.xml000066400000000000000000000035311420147000300176260ustar00rootroot00000000000000 {{ .Site.Title }} – {{ .Title }} {{ .Permalink }} Recent Hugo news from gohugo.io Hugo -- gohugo.io{{ with .Site.LanguageCode }} {{.}}{{end}}{{ with .Site.Author.email }} {{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}{{end}}{{ with .Site.Author.email }} {{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}{{end}}{{ with .Site.Copyright }} {{.}}{{end}}{{ if not .Date.IsZero }} {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}{{ end }} {{ "img/hugo.png" | absURL }} GoHugo.io {{ .Permalink }} {{ with .OutputFormats.Get "RSS" }} {{ printf "" .Permalink .MediaType | safeHTML }} {{ end }} {{ range first 50 (where .Site.RegularPages "Type" "in" (slice "news" "showcase")) }} {{ .Section | title }}: {{ .Title }} {{ .Permalink }} {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }} {{ with .Site.Author.email }}{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}{{end}} {{ .Permalink }} {{ $img := (.Resources.ByType "image").GetMatch "*featured*" }} {{ with $img }} {{ $img := .Resize "640x" }} {{ printf "]]>" $img.Permalink $img.Width $img.Height | safeHTML }} {{ end }} {{ .Content | html }} {{ end }} hugo-0.92.2/docs/layouts/maintenance/000077500000000000000000000000001420147000300174475ustar00rootroot00000000000000hugo-0.92.2/docs/layouts/maintenance/list.html000066400000000000000000000060461420147000300213160ustar00rootroot00000000000000{{ define "main" }}
    {{ $byLastMod := .Site.RegularPages.ByLastmod }} {{ $recent := ($byLastMod | last 30).Reverse }} {{ $leastRecent := $byLastMod | first 10 }}

    Last Updated

    {{ partial "maintenance-pages-table" $recent }}

    Least Recently Updated

    {{ partial "maintenance-pages-table" $leastRecent }} {{/* Don't think this is possible with where directly. Should investigate. */}} {{ .Scratch.Set "todos" slice }} {{ range .Site.RegularPages }} {{ if .HasShortcode "todo" }} {{ $.Scratch.Add "todos" . }} {{ end }} {{ end }}

    Pages marked with TODO

    {{ partial "maintenance-pages-table" (.Scratch.Get "todos") }}

    Dependencies

    {{ range $index, $element := hugo.Deps }} {{ end }}
    # Owner Path Version Time Vendor
    {{ add $index 1 }} {{ with $element.Owner }}{{.Path }}{{ end }} {{ $element.Path }} {{ with $element.Replace}} => {{ .Path }} {{ end }} {{ $element.Version }} {{ with $element.Time }}{{ . }}{{ end }} {{ $element.Vendor }}
    {{ end }}hugo-0.92.2/docs/layouts/partials/000077500000000000000000000000001420147000300170045ustar00rootroot00000000000000hugo-0.92.2/docs/layouts/partials/maintenance-pages-table.html000066400000000000000000000012311420147000300243330ustar00rootroot00000000000000 {{ range . }} {{ end }}
    LastMod Link GitHub
    {{ .Lastmod.Format "2006-01-02" }} {{ .Title }} {{ with .GitInfo }}{{ .Subject }}{{ else }}Source{{ end }}
    hugo-0.92.2/docs/layouts/shortcodes/000077500000000000000000000000001420147000300173425ustar00rootroot00000000000000hugo-0.92.2/docs/layouts/shortcodes/asciicast.html000066400000000000000000000002261420147000300221730ustar00rootroot00000000000000{{ $id := .Get 0 }} hugo-0.92.2/docs/layouts/shortcodes/chroma-lexers.html000066400000000000000000000001711420147000300230000ustar00rootroot00000000000000
    {{ range .Site.Data.docs.chroma.lexers }}
    {{ .Name }}
    {{ delimit .Aliases ", " }}
    {{ end }}
    hugo-0.92.2/docs/layouts/shortcodes/code-toggle.html000066400000000000000000000070611420147000300224250ustar00rootroot00000000000000{{- /* Renders syntax-highlighted configuration data in JSON, TOML, and YAML formats. @param {string} config Section of site.Data.docs.config to render. Example: markup.highlight Default: "" @param {bool} copy Display a copy button. Default: true @param {string} file File name to display above the rendered code. Default: "" @param {bool} fm Does Inner represent front matter? Default: false @param {string} Inner Content between opening and closing shortcode tags. Default: "" @param {bool} skipHeader Omit top level key(s) when rendering a section of site.Data.docs.config. Default: false @returns {template.HTML} */ -}} {{- /* Initialize. */ -}} {{- $config := "" -}} {{- $copy := true -}} {{- $file := "" -}} {{- $fm := false -}} {{- $skipHeader := false -}} {{- /* Get parameters, defend against string booleans. */ -}} {{- if .Params -}} {{- $config = .Get "config" -}} {{- $file = .Get "file" -}} {{- if (isset .Params "copy") -}} {{- if in (slice true "true") (.Get "copy") -}} {{- $copy = true -}} {{- else -}} {{- $copy = false -}} {{- end -}} {{- end -}} {{- if (isset .Params "fm") -}} {{- if in (slice true "true") (.Get "fm") -}} {{- $fm = true -}} {{- else -}} {{- $fm = false -}} {{- end -}} {{- end -}} {{- if (isset .Params "skipHeader") -}} {{- if in (slice true "true") (.Get "skipHeader") -}} {{- $skipHeader = true -}} {{- else -}} {{- $skipHeader = false -}} {{- end -}} {{- end -}} {{- end -}} {{- /* Define constants. */ -}} {{- $delimiters := dict "toml" "+++" "yaml" "---" -}} {{- $langs := slice "yaml" "toml" "json" -}} {{- $placeHolder := "#-hugo-placeholder-#" -}} {{- /* Render. */ -}} {{- $code := "" -}} {{- with $config -}} {{- $file = $file | default "config" -}} {{- $sections := (split . ".") -}} {{- $configSection := index $.Site.Data.docs.config $sections -}} {{- $code = dict $sections $configSection -}} {{- if $skipHeader -}} {{- $code = $configSection -}} {{- end -}} {{- else -}} {{- $code = $.Inner -}} {{- end }}
    {{- with $file }}
    {{- . -}}{{- if not $fm -}}.{{- end -}}
    {{- end -}} {{- range $langs }}   {{- end }}
    {{- range $langs }}
    {{- $hCode := $code | transform.Remarshal . -}} {{- if and $fm (in (slice "toml" "yaml") .) -}} {{- $hCode = printf "%s\n%s\n%s" $placeHolder $hCode $placeHolder -}} {{- end -}} {{- $hCode = $hCode | replaceRE `\n+` "\n" }} {{ highlight $hCode . "" | replaceRE $placeHolder (index $delimiters .) | safeHTML }}
    {{- if $copy }} {{- /* Functionality located within filesaver.js The copy here is located in the css with .copy class so it can be replaced with JS on success */ -}} {{- end -}} {{- end }}
    hugo-0.92.2/docs/layouts/shortcodes/code.html000066400000000000000000000022731420147000300211460ustar00rootroot00000000000000{{ $file := .Get "file" }} {{ $codeLang := "" }} {{ $suffix := findRE "(\\.[^.]+)$" $file 1 }} {{ with $suffix }} {{ $codeLang = (index . 0 | strings.TrimPrefix ".") }} {{ end }} {{ with .Get "codeLang" }}{{ $codeLang = . }}{{ end }} {{ if eq $codeLang "html" }} {{ $codeLang = "go-html-template" }} {{ end }}
    {{- with $file -}}
    {{ . }}
    {{- end -}} {{ if ne (.Get "copy") "false" }} {{/* Functionality located within filesaver.js The copy here is located in the css with .copy class so it can be replaced with JS on success */}} {{ end }}
    {{ $inner := trim .Inner "\n" | safeHTML }} {{ if .Get "nocode" }}{{ $inner }}{{ else }}{{ with $codeLang }}{{ highlight $inner . "" }}{{ else }}
    {{ $inner }}
    {{ end }}{{ end }}
    hugo-0.92.2/docs/layouts/shortcodes/content-tree.html000066400000000000000000000007131420147000300226400ustar00rootroot00000000000000
    
            ├── blog
            │   ├── _index.md [section]
            │   ├── first-post.md [page]
            │   └── second-post
            │       ├── index.md [page bundle]
            │       └── photo.jpg [page resource]
            └── tags
                ├── _index.md [taxonomy]
                └── funny
                    └── _index.md [term]
        
    hugo-0.92.2/docs/layouts/shortcodes/datatable-filtered.html000066400000000000000000000016701420147000300237510ustar00rootroot00000000000000{{ $package := (index .Params 0) }} {{ $listname := (index .Params 1) }} {{ $filter := split (index .Params 2) " " }} {{ $filter1 := index $filter 0 }} {{ $filter2 := index $filter 1 }} {{ $filter3 := index $filter 2 }} {{ $list := (index (index .Site.Data.docs $package) $listname) }} {{ $fields := after 3 .Params }} {{ $list := where $list $filter1 $filter2 $filter3 }} {{ range $fields }} {{ end }} {{ range $list }} {{ range $k, $v := . }} {{ $.Scratch.Set $k $v }} {{ end }} {{ range $k, $v := $fields }} {{ end }} {{ end }}
    {{ . }}
    {{ $tdContent := $.Scratch.Get . }} {{ if eq $k 3 }} {{ printf "%v" $tdContent | strings.ReplaceRE `\[` "
    1. " | strings.ReplaceRE `\s` "
    2. " | strings.ReplaceRE `\]` "
    " | safeHTML }} {{ else }} {{ $tdContent }} {{ end}}
    hugo-0.92.2/docs/layouts/shortcodes/datatable.html000066400000000000000000000007161420147000300221550ustar00rootroot00000000000000{{ $package := (index .Params 0) }} {{ $listname := (index .Params 1) }} {{ $list := (index (index .Site.Data.docs $package) $listname) }} {{ $fields := after 2 .Params }} {{ range $fields }} {{ end }} {{ range $list }} {{ range $k, $v := . }} {{ $.Scratch.Set $k $v }} {{ end }} {{ range $fields }} {{ end }} {{ end }}
    {{ . }}
    {{ $.Scratch.Get . }}
    hugo-0.92.2/docs/layouts/shortcodes/directoryindex.html000066400000000000000000000005141420147000300232640ustar00rootroot00000000000000{{- $pathURL := .Get "pathURL" -}} {{- $path := .Get "path" -}} {{- $files := readDir $path -}} {{- range $files }} {{- end }}
    Size in bytes Name
    {{ .Size }} {{ .Name }}
    hugo-0.92.2/docs/layouts/shortcodes/docfile.html000066400000000000000000000011701420147000300216340ustar00rootroot00000000000000{{ $file := .Get 0}} {{ $filepath := $file }} {{ $syntax := index (split $file ".") 1 }} {{ $syntaxoverride := eq (len .Params) 2 }}
    {{$filepath}}
    {{- readFile $file -}}
    hugo-0.92.2/docs/layouts/shortcodes/exfile.html000066400000000000000000000016331420147000300215070ustar00rootroot00000000000000{{ $file := .Get 0}} {{ $filepath := replace $file "static/" ""}} {{ $syntax := index (split $file ".") 1 }} {{ $syntaxoverride := eq (len .Params) 2 }}
    {{$filepath}}
    {{- readFile $file -}}
    Source
    hugo-0.92.2/docs/layouts/shortcodes/exfm.html000066400000000000000000000016451420147000300211750ustar00rootroot00000000000000 {{ $file := .Get 0}} {{ $filepath := replace $file "static/" ""}} {{ $syntax := index (split $file ".") 1 }} {{ $syntaxoverride := eq (len .Params) 2 }}
    {{$filepath}}
    {{- readFile $file -}}
    Source
    hugo-0.92.2/docs/layouts/shortcodes/funcsig.html000066400000000000000000000002441420147000300216660ustar00rootroot00000000000000

    Syntax

        {{- .Inner -}}
    
    hugo-0.92.2/docs/layouts/shortcodes/getcontent.html000066400000000000000000000012231420147000300224000ustar00rootroot00000000000000 {{- $path := .Get "path" -}} {{ $glob := .Get "glob" -}} {{ $resources := slice -}} {{ with $glob -}} {{ $bundle := site.GetPage $path -}} {{ $resources = $bundle.Resources.Match $glob -}} {{ else -}} {{ $bundle := site.GetPage (path.Dir $path) -}} {{ $resources = $bundle.Resources.Match (path.Base $path) -}} {{ end -}} {{ range $resources -}} {{ .Content }} {{ end -}} hugo-0.92.2/docs/layouts/shortcodes/gh.html000066400000000000000000000005151420147000300206270ustar00rootroot00000000000000{{ range .Params }} {{ if eq (substr . 0 1) "@" }} {{ . }} {{ else if eq (substr . 0 2) "0x" }} {{ substr . 2 6 }} {{ else }} #{{ . }} {{ end }} {{ end }} hugo-0.92.2/docs/layouts/shortcodes/ghrepo.html000066400000000000000000000001101420147000300215040ustar00rootroot00000000000000GitHub repositoryhugo-0.92.2/docs/layouts/shortcodes/gomodules-info.html000066400000000000000000000012411420147000300231550ustar00rootroot00000000000000{{ $text := ` Most of the commands for **Hugo Modules** requires a newer version of Go installed (see https://golang.org/dl/) and the relevant VCS client (e.g. Git, see https://git-scm.com/downloads/ ). If you have an "older" site running on Netlify, you may have to set GO_VERSION to 1.12 in your Environment settings. For more information about Go Modules, see: * https://github.com/golang/go/wiki/Modules * https://blog.golang.org/using-go-modules ` }} hugo-0.92.2/docs/layouts/shortcodes/imgproc.html000066400000000000000000000015551420147000300216760ustar00rootroot00000000000000{{ $original := .Page.Resources.GetMatch (printf "*%s*" (.Get 0)) }} {{ $command := .Get 1 }} {{ $options := .Get 2 }} {{ if eq $command "Fit"}} {{ .Scratch.Set "image" ($original.Fit $options) }} {{ else if eq $command "Resize"}} {{ .Scratch.Set "image" ($original.Resize $options) }} {{ else if eq $command "Fill"}} {{ .Scratch.Set "image" ($original.Fill $options) }} {{ else }} {{ errorf "Invalid image processing command: Must be one of Fit, Fill or Resize."}} {{ end }} {{ $image := .Scratch.Get "image" }}
    {{ with .Inner }} {{ . }} {{ else }} .{{ $command }} "{{ $options }}" {{ end }}
    hugo-0.92.2/docs/layouts/shortcodes/module-mounts-note.html000066400000000000000000000002271420147000300240040ustar00rootroot00000000000000Also see [Module Mounts Config](/hugo-modules/configuration/#module-config-mounts) for an alternative way to configure this directory (from Hugo 0.56).hugo-0.92.2/docs/layouts/shortcodes/new-in.html000066400000000000000000000006331420147000300214270ustar00rootroot00000000000000{{ $version := .Get 0 }} {{ if not $version }} {{ errorf "Missing version in new-in shortcode "}} {{ end }} {{ $version = $version | strings.TrimPrefix "v" }} hugo-0.92.2/docs/layouts/shortcodes/nohighlight.html000066400000000000000000000000751420147000300225360ustar00rootroot00000000000000
    {{ .Inner }}
    hugo-0.92.2/docs/layouts/shortcodes/note.html000066400000000000000000000006021420147000300211730ustar00rootroot00000000000000{{ $_hugo_config := `{ "version": 1 }` }} hugo-0.92.2/docs/layouts/shortcodes/output.html000066400000000000000000000004241420147000300215700ustar00rootroot00000000000000{{$file := .Get "file"}} {{$icon := index (split $file ".") 1 }}
    {{$file}}
    {{- .Inner | string -}}
    hugo-0.92.2/docs/layouts/shortcodes/page-kinds.html000066400000000000000000000012221420147000300222470ustar00rootroot00000000000000| Kind | Description | Example | |----------------|--------------------------------------------------------------------|-------------------------------------------------------------------------------| | `home` | The landing page for the home page | `/index.html` | | `page` | The landing page for a given page | `my-post` page (`/posts/my-post/index.html`) | | `section` | The landing page of a given section | `posts` section (`/posts/index.html`) | | `taxonomy` | The landing page for a taxonomy | `tags` taxonomy (`/tags/index.html`) | | `term` | The landing page for one taxonomy's term | term `awesome` in `tags` taxonomy (`/tags/awesome/index.html`) | hugo-0.92.2/docs/layouts/shortcodes/readfile.html000066400000000000000000000004041420147000300220010ustar00rootroot00000000000000{{$file := .Get "file"}} {{- if eq (.Get "markdown") "true" -}} {{- $file | readFile | markdownify -}} {{- else if (.Get "highlight") -}} {{- highlight ($file | readFile) (.Get "highlight") "" -}} {{- else -}} {{ $file | readFile | safeHTML }} {{- end -}}hugo-0.92.2/docs/layouts/shortcodes/tip.html000066400000000000000000000005501420147000300210240ustar00rootroot00000000000000{{ $_hugo_config := `{ "version": 1 }` }} hugo-0.92.2/docs/layouts/shortcodes/todo.html000066400000000000000000000000301420147000300211660ustar00rootroot00000000000000{{ if .Inner }}{{ end }}hugo-0.92.2/docs/layouts/shortcodes/warning.html000066400000000000000000000005771420147000300217060ustar00rootroot00000000000000{{ $_hugo_config := `{ "version": 1 }` }} hugo-0.92.2/docs/layouts/shortcodes/yt.html000066400000000000000000000010641420147000300206650ustar00rootroot00000000000000
    {{if (.Get "thumbnail")}}
    {{else}}
    {{end}}
    {{ if (.Get "description") }}
    {{ .Get "description" | markdownify }}
    {{ end }}hugo-0.92.2/docs/layouts/template-func/000077500000000000000000000000001420147000300177315ustar00rootroot00000000000000hugo-0.92.2/docs/layouts/template-func/page.html000066400000000000000000000033611420147000300215360ustar00rootroot00000000000000{{ $pkg := .Params.package}} {{ $funcs := index site.Data.docs.tpl.funcs $pkg }} {{ range $k, $v := $funcs }} {{ if $v.Description }} {{ $func := printf "%s.%s" $pkg $k }} {{ $id := $func | anchorize | safeURL }}

    {{ $func }}

    {{ with $v.Description }}

    {{ . | $.RenderString | safeHTML }}

    {{ end }}

    Syntax

    {{ $pkg }}.{{ $k }} {{ with $v.Args }} {{ delimit $v.Args ", "}} {{ end }}
    {{ if $v.Examples }}

    Examples

    {{ end }} {{ range $v.Examples }} {{ $input := index . 0 }} {{ $result := index . 1 }} {{ $example := printf "%s ---> %s" $input $result }} {{ highlight $example "go-html-template" "" }} {{ end }} {{ with $v.Aliases }}

    Aliases

    {{ delimit . ", "}}

    {{ end }} {{ end }} {{ end }} hugo-0.92.2/docs/netlify.toml000066400000000000000000000013171420147000300160360ustar00rootroot00000000000000[build] publish = "public" command = "hugo --gc --minify" [context.production.environment] HUGO_VERSION = "0.91.2" HUGO_ENV = "production" HUGO_ENABLEGITINFO = "true" [context.split1] command = "hugo --gc --minify --enableGitInfo" [context.split1.environment] HUGO_VERSION = "0.91.2" HUGO_ENV = "production" [context.deploy-preview] command = "hugo --gc --minify --buildFuture -b $DEPLOY_PRIME_URL" [context.deploy-preview.environment] HUGO_VERSION = "0.91.2" [context.branch-deploy] command = "hugo --gc --minify -b $DEPLOY_PRIME_URL" [context.branch-deploy.environment] HUGO_VERSION = "0.91.2" [context.next.environment] HUGO_ENABLEGITINFO = "true" [[redirects]] from = "/npmjs/*" to = "/npmjs/" status = 200hugo-0.92.2/docs/pull-theme.sh000077500000000000000000000001701420147000300160760ustar00rootroot00000000000000#!/bin/bash git subtree pull --prefix=themes/gohugoioTheme/ git@github.com:gohugoio/gohugoioTheme.git master --squash hugo-0.92.2/docs/resources/000077500000000000000000000000001420147000300154775ustar00rootroot00000000000000hugo-0.92.2/docs/resources/.gitattributes000066400000000000000000000000621420147000300203700ustar00rootroot00000000000000*.* linguist-generated=true *.* -diff -mergehugo-0.92.2/docs/resources/_gen/000077500000000000000000000000001420147000300164075ustar00rootroot00000000000000hugo-0.92.2/docs/resources/_gen/assets/000077500000000000000000000000001420147000300177115ustar00rootroot00000000000000hugo-0.92.2/docs/resources/_gen/assets/css/000077500000000000000000000000001420147000300205015ustar00rootroot00000000000000hugo-0.92.2/docs/resources/_gen/assets/css/output/000077500000000000000000000000001420147000300220415ustar00rootroot00000000000000hugo-0.92.2/docs/resources/_gen/assets/css/output/css/000077500000000000000000000000001420147000300226315ustar00rootroot00000000000000app.css_d11fe7b62c27961c87ecd0f2490357b9.content000066400000000000000000003436661420147000300321310ustar00rootroot00000000000000hugo-0.92.2/docs/resources/_gen/assets/css/output/css@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:200;src:local('Muli Extra Light '),local('Muli-Extra Light'),url(/fonts/muli-latin-200.woff2) format('woff2'),url(/fonts/muli-latin-200.woff) format('woff')}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:200;src:local('Muli Extra Light italic'),local('Muli-Extra Lightitalic'),url(/fonts/muli-latin-200italic.woff2) format('woff2'),url(/fonts/muli-latin-200italic.woff) format('woff')}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:300;src:local('Muli Light '),local(Muli-Light),url(/fonts/muli-latin-300.woff2) format('woff2'),url(/fonts/muli-latin-300.woff) format('woff')}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:300;src:local('Muli Light italic'),local(Muli-Lightitalic),url(/fonts/muli-latin-300italic.woff2) format('woff2'),url(/fonts/muli-latin-300italic.woff) format('woff')}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:400;src:local('Muli Regular '),local(Muli-Regular),url(/fonts/muli-latin-400.woff2) format('woff2'),url(/fonts/muli-latin-400.woff) format('woff')}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:400;src:local('Muli Regular italic'),local(Muli-Regularitalic),url(/fonts/muli-latin-400italic.woff2) format('woff2'),url(/fonts/muli-latin-400italic.woff) format('woff')}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:600;src:local('Muli SemiBold '),local(Muli-SemiBold),url(/fonts/muli-latin-600.woff2) format('woff2'),url(/fonts/muli-latin-600.woff) format('woff')}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:600;src:local('Muli SemiBold italic'),local(Muli-SemiBolditalic),url(/fonts/muli-latin-600italic.woff2) format('woff2'),url(/fonts/muli-latin-600italic.woff) format('woff')}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:700;src:local('Muli Bold '),local(Muli-Bold),url(/fonts/muli-latin-700.woff2) format('woff2'),url(/fonts/muli-latin-700.woff) format('woff')}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:700;src:local('Muli Bold italic'),local(Muli-Bolditalic),url(/fonts/muli-latin-700italic.woff2) format('woff2'),url(/fonts/muli-latin-700italic.woff) format('woff')}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:800;src:local('Muli ExtraBold '),local(Muli-ExtraBold),url(/fonts/muli-latin-800.woff2) format('woff2'),url(/fonts/muli-latin-800.woff) format('woff')}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:800;src:local('Muli ExtraBold italic'),local(Muli-ExtraBolditalic),url(/fonts/muli-latin-800italic.woff2) format('woff2'),url(/fonts/muli-latin-800italic.woff) format('woff')}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:900;src:local('Muli Black '),local(Muli-Black),url(/fonts/muli-latin-900.woff2) format('woff2'),url(/fonts/muli-latin-900.woff) format('woff')}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:900;src:local('Muli Black italic'),local(Muli-Blackitalic),url(/fonts/muli-latin-900italic.woff2) format('woff2'),url(/fonts/muli-latin-900italic.woff) format('woff')}/*!TACHYONS v4.7.0 | http://tachyons.io*//*!normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css*/html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html,body,div,article,aside,section,main,nav,footer,header,form,fieldset,legend,pre,code,a,h1,h2,h3,h4,h5,h6,p,ul,ol,li,dl,dt,dd,blockquote,figcaption,figure,textarea,table,td,th,tr,input[type=email],input[type=number],input[type=password],input[type=tel],input[type=text],input[type=url],.border-box{-webkit-box-sizing:border-box;box-sizing:border-box}img{max-width:100%}.cover{background-size:cover!important}.contain{background-size:contain!important}@media screen and (min-width:30em){.cover-ns{background-size:cover!important}.contain-ns{background-size:contain!important}}@media screen and (min-width:30em) and (max-width:60em){.cover-m{background-size:cover!important}.contain-m{background-size:contain!important}}@media screen and (min-width:60em){.cover-l{background-size:cover!important}.contain-l{background-size:contain!important}}.bg-center{background-repeat:no-repeat;background-position:50%}.bg-top{background-repeat:no-repeat;background-position:50% 0}.bg-right{background-repeat:no-repeat;background-position:50% 100%}.bg-bottom{background-repeat:no-repeat;background-position:50% 100%}.bg-left{background-repeat:no-repeat;background-position:50% 0}@media screen and (min-width:30em){.bg-center-ns{background-repeat:no-repeat;background-position:50%}.bg-top-ns{background-repeat:no-repeat;background-position:50% 0}.bg-right-ns{background-repeat:no-repeat;background-position:50% 100%}.bg-bottom-ns{background-repeat:no-repeat;background-position:50% 100%}.bg-left-ns{background-repeat:no-repeat;background-position:50% 0}}@media screen and (min-width:30em) and (max-width:60em){.bg-center-m{background-repeat:no-repeat;background-position:50%}.bg-top-m{background-repeat:no-repeat;background-position:50% 0}.bg-right-m{background-repeat:no-repeat;background-position:50% 100%}.bg-bottom-m{background-repeat:no-repeat;background-position:50% 100%}.bg-left-m{background-repeat:no-repeat;background-position:50% 0}}@media screen and (min-width:60em){.bg-center-l{background-repeat:no-repeat;background-position:50%}.bg-top-l{background-repeat:no-repeat;background-position:50% 0}.bg-right-l{background-repeat:no-repeat;background-position:50% 100%}.bg-bottom-l{background-repeat:no-repeat;background-position:50% 100%}.bg-left-l{background-repeat:no-repeat;background-position:50% 0}}.ba{border-style:solid;border-width:1px}.bt{border-top-style:solid;border-top-width:1px}.br{border-right-style:solid;border-right-width:1px}.bb{border-bottom-style:solid;border-bottom-width:1px}.bl{border-left-style:solid;border-left-width:1px}.bn{border-style:none;border-width:0}@media screen and (min-width:30em){.ba-ns{border-style:solid;border-width:1px}.bt-ns{border-top-style:solid;border-top-width:1px}.br-ns{border-right-style:solid;border-right-width:1px}.bb-ns{border-bottom-style:solid;border-bottom-width:1px}.bl-ns{border-left-style:solid;border-left-width:1px}.bn-ns{border-style:none;border-width:0}}@media screen and (min-width:30em) and (max-width:60em){.ba-m{border-style:solid;border-width:1px}.bt-m{border-top-style:solid;border-top-width:1px}.br-m{border-right-style:solid;border-right-width:1px}.bb-m{border-bottom-style:solid;border-bottom-width:1px}.bl-m{border-left-style:solid;border-left-width:1px}.bn-m{border-style:none;border-width:0}}@media screen and (min-width:60em){.ba-l{border-style:solid;border-width:1px}.bt-l{border-top-style:solid;border-top-width:1px}.br-l{border-right-style:solid;border-right-width:1px}.bb-l{border-bottom-style:solid;border-bottom-width:1px}.bl-l{border-left-style:solid;border-left-width:1px}.bn-l{border-style:none;border-width:0}}.b--black{border-color:#000}.b--near-black{border-color:#111}.b--dark-gray{border-color:#333}.b--mid-gray{border-color:#555}.b--gray{border-color:#777}.b--silver{border-color:#999}.b--light-silver{border-color:#aaa}.b--moon-gray{border-color:#ccc}.b--light-gray{border-color:#eee}.b--near-white{border-color:#f4f4f4}.b--white{border-color:#fff}.b--white-90{border-color:rgba(255,255,255,.9)}.b--white-80{border-color:rgba(255,255,255,.8)}.b--white-70{border-color:rgba(255,255,255,.7)}.b--white-60{border-color:rgba(255,255,255,.6)}.b--white-50{border-color:rgba(255,255,255,.5)}.b--white-40{border-color:rgba(255,255,255,.4)}.b--white-30{border-color:rgba(255,255,255,.3)}.b--white-20{border-color:rgba(255,255,255,.2)}.b--white-10{border-color:rgba(255,255,255,.1)}.b--white-05{border-color:rgba(255,255,255,.05)}.b--white-025{border-color:rgba(255,255,255,.025)}.b--white-0125{border-color:rgba(255,255,255,.0125)}.b--black-90{border-color:rgba(0,0,0,.9)}.b--black-80{border-color:rgba(0,0,0,.8)}.b--black-70{border-color:rgba(0,0,0,.7)}.b--black-60{border-color:rgba(0,0,0,.6)}.b--black-50{border-color:rgba(0,0,0,.5)}.b--black-40{border-color:rgba(0,0,0,.4)}.b--black-30{border-color:rgba(0,0,0,.3)}.b--black-20{border-color:rgba(0,0,0,.2)}.b--black-10{border-color:rgba(0,0,0,.1)}.b--black-05{border-color:rgba(0,0,0,.05)}.b--black-025{border-color:rgba(0,0,0,.025)}.b--black-0125{border-color:rgba(0,0,0,.0125)}.b--dark-red{border-color:#e7040f}.b--red{border-color:#ff4136}.b--light-red{border-color:#ff725c}.b--orange{border-color:#ff6300}.b--gold{border-color:#ffb700}.b--yellow{border-color:gold}.b--light-yellow{border-color:#fbf1a9}.b--purple{border-color:#5e2ca5}.b--light-purple{border-color:#a463f2}.b--dark-pink{border-color:#d5008f}.b--hot-pink{border-color:#ff41b4}.b--pink{border-color:#ff80cc}.b--light-pink{border-color:#ffa3d7}.b--dark-green{border-color:#137752}.b--green{border-color:#19a974}.b--light-green{border-color:#9eebcf}.b--navy{border-color:#001b44}.b--dark-blue{border-color:#00449e}.b--blue{border-color:#0594cb}.b--light-blue{border-color:#96ccff}.b--lightest-blue{border-color:#cdecff}.b--washed-blue{border-color:#f6fffe}.b--washed-green{border-color:#e8fdf5}.b--washed-yellow{border-color:#fffceb}.b--washed-red{border-color:#ffdfdf}.b--transparent{border-color:transparent}.b--inherit{border-color:inherit}.br0{border-radius:0}.br1{border-radius:.125rem}.br2{border-radius:.25rem}.br3{border-radius:.5rem}.br4{border-radius:1rem}.br-100{border-radius:100%}.br-pill{border-radius:9999px}.br--bottom{border-top-left-radius:0;border-top-right-radius:0}.br--top{border-bottom-left-radius:0;border-bottom-right-radius:0}.br--right{border-top-left-radius:0;border-bottom-left-radius:0}.br--left{border-top-right-radius:0;border-bottom-right-radius:0}@media screen and (min-width:30em){.br0-ns{border-radius:0}.br1-ns{border-radius:.125rem}.br2-ns{border-radius:.25rem}.br3-ns{border-radius:.5rem}.br4-ns{border-radius:1rem}.br-100-ns{border-radius:100%}.br-pill-ns{border-radius:9999px}.br--bottom-ns{border-top-left-radius:0;border-top-right-radius:0}.br--top-ns{border-bottom-left-radius:0;border-bottom-right-radius:0}.br--right-ns{border-top-left-radius:0;border-bottom-left-radius:0}.br--left-ns{border-top-right-radius:0;border-bottom-right-radius:0}}@media screen and (min-width:30em) and (max-width:60em){.br0-m{border-radius:0}.br1-m{border-radius:.125rem}.br2-m{border-radius:.25rem}.br3-m{border-radius:.5rem}.br4-m{border-radius:1rem}.br-100-m{border-radius:100%}.br-pill-m{border-radius:9999px}.br--bottom-m{border-top-left-radius:0;border-top-right-radius:0}.br--top-m{border-bottom-left-radius:0;border-bottom-right-radius:0}.br--right-m{border-top-left-radius:0;border-bottom-left-radius:0}.br--left-m{border-top-right-radius:0;border-bottom-right-radius:0}}@media screen and (min-width:60em){.br0-l{border-radius:0}.br1-l{border-radius:.125rem}.br2-l{border-radius:.25rem}.br3-l{border-radius:.5rem}.br4-l{border-radius:1rem}.br-100-l{border-radius:100%}.br-pill-l{border-radius:9999px}.br--bottom-l{border-top-left-radius:0;border-top-right-radius:0}.br--top-l{border-bottom-left-radius:0;border-bottom-right-radius:0}.br--right-l{border-top-left-radius:0;border-bottom-left-radius:0}.br--left-l{border-top-right-radius:0;border-bottom-right-radius:0}}.b--dotted{border-style:dotted}.b--dashed{border-style:dashed}.b--solid{border-style:solid}.b--none{border-style:none}@media screen and (min-width:30em){.b--dotted-ns{border-style:dotted}.b--dashed-ns{border-style:dashed}.b--solid-ns{border-style:solid}.b--none-ns{border-style:none}}@media screen and (min-width:30em) and (max-width:60em){.b--dotted-m{border-style:dotted}.b--dashed-m{border-style:dashed}.b--solid-m{border-style:solid}.b--none-m{border-style:none}}@media screen and (min-width:60em){.b--dotted-l{border-style:dotted}.b--dashed-l{border-style:dashed}.b--solid-l{border-style:solid}.b--none-l{border-style:none}}.bw0{border-width:0}.bw1{border-width:.125rem}.bw2{border-width:.25rem}.bw3{border-width:.5rem}.bw4{border-width:1rem}.bw5{border-width:2rem}.bt-0{border-top-width:0}.br-0{border-right-width:0}.bb-0{border-bottom-width:0}.bl-0{border-left-width:0}@media screen and (min-width:30em){.bw0-ns{border-width:0}.bw1-ns{border-width:.125rem}.bw2-ns{border-width:.25rem}.bw3-ns{border-width:.5rem}.bw4-ns{border-width:1rem}.bw5-ns{border-width:2rem}.bt-0-ns{border-top-width:0}.br-0-ns{border-right-width:0}.bb-0-ns{border-bottom-width:0}.bl-0-ns{border-left-width:0}}@media screen and (min-width:30em) and (max-width:60em){.bw0-m{border-width:0}.bw1-m{border-width:.125rem}.bw2-m{border-width:.25rem}.bw3-m{border-width:.5rem}.bw4-m{border-width:1rem}.bw5-m{border-width:2rem}.bt-0-m{border-top-width:0}.br-0-m{border-right-width:0}.bb-0-m{border-bottom-width:0}.bl-0-m{border-left-width:0}}@media screen and (min-width:60em){.bw0-l{border-width:0}.bw1-l{border-width:.125rem}.bw2-l{border-width:.25rem}.bw3-l{border-width:.5rem}.bw4-l{border-width:1rem}.bw5-l{border-width:2rem}.bt-0-l{border-top-width:0}.br-0-l{border-right-width:0}.bb-0-l{border-bottom-width:0}.bl-0-l{border-left-width:0}}.shadow-1{-webkit-box-shadow:0 0 4px 2px rgba(0,0,0,.2);box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2{-webkit-box-shadow:0 0 8px 2px rgba(0,0,0,.2);box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3{-webkit-box-shadow:2px 2px 4px 2px rgba(0,0,0,.2);box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4{-webkit-box-shadow:2px 2px 8px 0 rgba(0,0,0,.2);box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5{-webkit-box-shadow:4px 4px 8px 0 rgba(0,0,0,.2);box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}@media screen and (min-width:30em){.shadow-1-ns{-webkit-box-shadow:0 0 4px 2px rgba(0,0,0,.2);box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2-ns{-webkit-box-shadow:0 0 8px 2px rgba(0,0,0,.2);box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3-ns{-webkit-box-shadow:2px 2px 4px 2px rgba(0,0,0,.2);box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4-ns{-webkit-box-shadow:2px 2px 8px 0 rgba(0,0,0,.2);box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5-ns{-webkit-box-shadow:4px 4px 8px 0 rgba(0,0,0,.2);box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}@media screen and (min-width:30em) and (max-width:60em){.shadow-1-m{-webkit-box-shadow:0 0 4px 2px rgba(0,0,0,.2);box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2-m{-webkit-box-shadow:0 0 8px 2px rgba(0,0,0,.2);box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3-m{-webkit-box-shadow:2px 2px 4px 2px rgba(0,0,0,.2);box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4-m{-webkit-box-shadow:2px 2px 8px 0 rgba(0,0,0,.2);box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5-m{-webkit-box-shadow:4px 4px 8px 0 rgba(0,0,0,.2);box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}@media screen and (min-width:60em){.shadow-1-l{-webkit-box-shadow:0 0 4px 2px rgba(0,0,0,.2);box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.shadow-2-l{-webkit-box-shadow:0 0 8px 2px rgba(0,0,0,.2);box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.shadow-3-l{-webkit-box-shadow:2px 2px 4px 2px rgba(0,0,0,.2);box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.shadow-4-l{-webkit-box-shadow:2px 2px 8px 0 rgba(0,0,0,.2);box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.shadow-5-l{-webkit-box-shadow:4px 4px 8px 0 rgba(0,0,0,.2);box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.top-1{top:1rem}.right-1{right:1rem}.bottom-1{bottom:1rem}.left-1{left:1rem}.top-2{top:2rem}.right-2{right:2rem}.bottom-2{bottom:2rem}.left-2{left:2rem}.top--1{top:-1rem}.right--1{right:-1rem}.bottom--1{bottom:-1rem}.left--1{left:-1rem}.top--2{top:-2rem}.right--2{right:-2rem}.bottom--2{bottom:-2rem}.left--2{left:-2rem}.absolute--fill{top:0;right:0;bottom:0;left:0}@media screen and (min-width:30em){.top-0-ns{top:0}.left-0-ns{left:0}.right-0-ns{right:0}.bottom-0-ns{bottom:0}.top-1-ns{top:1rem}.left-1-ns{left:1rem}.right-1-ns{right:1rem}.bottom-1-ns{bottom:1rem}.top-2-ns{top:2rem}.left-2-ns{left:2rem}.right-2-ns{right:2rem}.bottom-2-ns{bottom:2rem}.top--1-ns{top:-1rem}.right--1-ns{right:-1rem}.bottom--1-ns{bottom:-1rem}.left--1-ns{left:-1rem}.top--2-ns{top:-2rem}.right--2-ns{right:-2rem}.bottom--2-ns{bottom:-2rem}.left--2-ns{left:-2rem}.absolute--fill-ns{top:0;right:0;bottom:0;left:0}}@media screen and (min-width:30em) and (max-width:60em){.top-0-m{top:0}.left-0-m{left:0}.right-0-m{right:0}.bottom-0-m{bottom:0}.top-1-m{top:1rem}.left-1-m{left:1rem}.right-1-m{right:1rem}.bottom-1-m{bottom:1rem}.top-2-m{top:2rem}.left-2-m{left:2rem}.right-2-m{right:2rem}.bottom-2-m{bottom:2rem}.top--1-m{top:-1rem}.right--1-m{right:-1rem}.bottom--1-m{bottom:-1rem}.left--1-m{left:-1rem}.top--2-m{top:-2rem}.right--2-m{right:-2rem}.bottom--2-m{bottom:-2rem}.left--2-m{left:-2rem}.absolute--fill-m{top:0;right:0;bottom:0;left:0}}@media screen and (min-width:60em){.top-0-l{top:0}.left-0-l{left:0}.right-0-l{right:0}.bottom-0-l{bottom:0}.top-1-l{top:1rem}.left-1-l{left:1rem}.right-1-l{right:1rem}.bottom-1-l{bottom:1rem}.top-2-l{top:2rem}.left-2-l{left:2rem}.right-2-l{right:2rem}.bottom-2-l{bottom:2rem}.top--1-l{top:-1rem}.right--1-l{right:-1rem}.bottom--1-l{bottom:-1rem}.left--1-l{left:-1rem}.top--2-l{top:-2rem}.right--2-l{right:-2rem}.bottom--2-l{bottom:-2rem}.left--2-l{left:-2rem}.absolute--fill-l{top:0;right:0;bottom:0;left:0}}.cf:before,.cf:after{content:" ";display:table}.cf:after{clear:both}.cf{*zoom:1}.cl{clear:left}.cr{clear:right}.cb{clear:both}.cn{clear:none}@media screen and (min-width:30em){.cl-ns{clear:left}.cr-ns{clear:right}.cb-ns{clear:both}.cn-ns{clear:none}}@media screen and (min-width:30em) and (max-width:60em){.cl-m{clear:left}.cr-m{clear:right}.cb-m{clear:both}.cn-m{clear:none}}@media screen and (min-width:60em){.cl-l{clear:left}.cr-l{clear:right}.cb-l{clear:both}.cn-l{clear:none}}.dn{display:none}.di{display:inline}.db{display:block}.dib{display:inline-block}.dit{display:inline-table}.dt{display:table}.dtc{display:table-cell}.dt-row{display:table-row}.dt-row-group{display:table-row-group}.dt-column{display:table-column}.dt-column-group{display:table-column-group}.dt--fixed{table-layout:fixed;width:100%}@media screen and (min-width:30em){.dn-ns{display:none}.di-ns{display:inline}.db-ns{display:block}.dib-ns{display:inline-block}.dit-ns{display:inline-table}.dt-ns{display:table}.dtc-ns{display:table-cell}.dt-row-ns{display:table-row}.dt-row-group-ns{display:table-row-group}.dt-column-ns{display:table-column}.dt-column-group-ns{display:table-column-group}.dt--fixed-ns{table-layout:fixed;width:100%}}@media screen and (min-width:30em) and (max-width:60em){.dn-m{display:none}.di-m{display:inline}.db-m{display:block}.dib-m{display:inline-block}.dit-m{display:inline-table}.dt-m{display:table}.dtc-m{display:table-cell}.dt-row-m{display:table-row}.dt-row-group-m{display:table-row-group}.dt-column-m{display:table-column}.dt-column-group-m{display:table-column-group}.dt--fixed-m{table-layout:fixed;width:100%}}@media screen and (min-width:60em){.dn-l{display:none}.di-l{display:inline}.db-l{display:block}.dib-l{display:inline-block}.dit-l{display:inline-table}.dt-l{display:table}.dtc-l{display:table-cell}.dt-row-l{display:table-row}.dt-row-group-l{display:table-row-group}.dt-column-l{display:table-column}.dt-column-group-l{display:table-column-group}.dt--fixed-l{table-layout:fixed;width:100%}}.flex{display:-webkit-box;display:-ms-flexbox;display:flex}.inline-flex{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.flex-auto{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;min-width:0;min-height:0}.flex-none{-webkit-box-flex:0;-ms-flex:none;flex:none}.flex-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.flex-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.flex-wrap{-ms-flex-wrap:wrap;flex-wrap:wrap}.flex-nowrap{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse;flex-wrap:wrap-reverse}.flex-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}.flex-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.items-start{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.items-end{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.items-center{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.items-baseline{-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline}.items-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.self-start{-ms-flex-item-align:start;align-self:flex-start}.self-end{-ms-flex-item-align:end;align-self:flex-end}.self-center{-ms-flex-item-align:center;align-self:center}.self-baseline{-ms-flex-item-align:baseline;align-self:baseline}.self-stretch{-ms-flex-item-align:stretch;align-self:stretch}.justify-start{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.justify-end{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.justify-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.justify-between{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.justify-around{-ms-flex-pack:distribute;justify-content:space-around}.content-start{-ms-flex-line-pack:start;align-content:flex-start}.content-end{-ms-flex-line-pack:end;align-content:flex-end}.content-center{-ms-flex-line-pack:center;align-content:center}.content-between{-ms-flex-line-pack:justify;align-content:space-between}.content-around{-ms-flex-line-pack:distribute;align-content:space-around}.content-stretch{-ms-flex-line-pack:stretch;align-content:stretch}.order-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-last{-webkit-box-ordinal-group:100000;-ms-flex-order:99999;order:99999}.flex-grow-0{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0}.flex-grow-1{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.flex-shrink-0{-ms-flex-negative:0;flex-shrink:0}.flex-shrink-1{-ms-flex-negative:1;flex-shrink:1}@media screen and (min-width:30em){.flex-ns{display:-webkit-box;display:-ms-flexbox;display:flex}.inline-flex-ns{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.flex-auto-ns{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;min-width:0;min-height:0}.flex-none-ns{-webkit-box-flex:0;-ms-flex:none;flex:none}.flex-column-ns{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.flex-row-ns{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.flex-wrap-ns{-ms-flex-wrap:wrap;flex-wrap:wrap}.flex-nowrap-ns{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.flex-wrap-reverse-ns{-ms-flex-wrap:wrap-reverse;flex-wrap:wrap-reverse}.flex-column-reverse-ns{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}.flex-row-reverse-ns{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.items-start-ns{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.items-end-ns{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.items-center-ns{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.items-baseline-ns{-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline}.items-stretch-ns{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.self-start-ns{-ms-flex-item-align:start;align-self:flex-start}.self-end-ns{-ms-flex-item-align:end;align-self:flex-end}.self-center-ns{-ms-flex-item-align:center;align-self:center}.self-baseline-ns{-ms-flex-item-align:baseline;align-self:baseline}.self-stretch-ns{-ms-flex-item-align:stretch;align-self:stretch}.justify-start-ns{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.justify-end-ns{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.justify-center-ns{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.justify-between-ns{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.justify-around-ns{-ms-flex-pack:distribute;justify-content:space-around}.content-start-ns{-ms-flex-line-pack:start;align-content:flex-start}.content-end-ns{-ms-flex-line-pack:end;align-content:flex-end}.content-center-ns{-ms-flex-line-pack:center;align-content:center}.content-between-ns{-ms-flex-line-pack:justify;align-content:space-between}.content-around-ns{-ms-flex-line-pack:distribute;align-content:space-around}.content-stretch-ns{-ms-flex-line-pack:stretch;align-content:stretch}.order-0-ns{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1-ns{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2-ns{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3-ns{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4-ns{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5-ns{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6-ns{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7-ns{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8-ns{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-last-ns{-webkit-box-ordinal-group:100000;-ms-flex-order:99999;order:99999}.flex-grow-0-ns{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0}.flex-grow-1-ns{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.flex-shrink-0-ns{-ms-flex-negative:0;flex-shrink:0}.flex-shrink-1-ns{-ms-flex-negative:1;flex-shrink:1}}@media screen and (min-width:30em) and (max-width:60em){.flex-m{display:-webkit-box;display:-ms-flexbox;display:flex}.inline-flex-m{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.flex-auto-m{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;min-width:0;min-height:0}.flex-none-m{-webkit-box-flex:0;-ms-flex:none;flex:none}.flex-column-m{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.flex-row-m{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.flex-wrap-m{-ms-flex-wrap:wrap;flex-wrap:wrap}.flex-nowrap-m{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.flex-wrap-reverse-m{-ms-flex-wrap:wrap-reverse;flex-wrap:wrap-reverse}.flex-column-reverse-m{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}.flex-row-reverse-m{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.items-start-m{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.items-end-m{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.items-center-m{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.items-baseline-m{-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline}.items-stretch-m{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.self-start-m{-ms-flex-item-align:start;align-self:flex-start}.self-end-m{-ms-flex-item-align:end;align-self:flex-end}.self-center-m{-ms-flex-item-align:center;align-self:center}.self-baseline-m{-ms-flex-item-align:baseline;align-self:baseline}.self-stretch-m{-ms-flex-item-align:stretch;align-self:stretch}.justify-start-m{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.justify-end-m{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.justify-center-m{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.justify-between-m{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.justify-around-m{-ms-flex-pack:distribute;justify-content:space-around}.content-start-m{-ms-flex-line-pack:start;align-content:flex-start}.content-end-m{-ms-flex-line-pack:end;align-content:flex-end}.content-center-m{-ms-flex-line-pack:center;align-content:center}.content-between-m{-ms-flex-line-pack:justify;align-content:space-between}.content-around-m{-ms-flex-line-pack:distribute;align-content:space-around}.content-stretch-m{-ms-flex-line-pack:stretch;align-content:stretch}.order-0-m{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1-m{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2-m{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3-m{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4-m{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5-m{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6-m{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7-m{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8-m{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-last-m{-webkit-box-ordinal-group:100000;-ms-flex-order:99999;order:99999}.flex-grow-0-m{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0}.flex-grow-1-m{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.flex-shrink-0-m{-ms-flex-negative:0;flex-shrink:0}.flex-shrink-1-m{-ms-flex-negative:1;flex-shrink:1}}@media screen and (min-width:60em){.flex-l{display:-webkit-box;display:-ms-flexbox;display:flex}.inline-flex-l{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.flex-auto-l{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;min-width:0;min-height:0}.flex-none-l{-webkit-box-flex:0;-ms-flex:none;flex:none}.flex-column-l{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.flex-row-l{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.flex-wrap-l{-ms-flex-wrap:wrap;flex-wrap:wrap}.flex-nowrap-l{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.flex-wrap-reverse-l{-ms-flex-wrap:wrap-reverse;flex-wrap:wrap-reverse}.flex-column-reverse-l{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}.flex-row-reverse-l{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.items-start-l{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.items-end-l{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.items-center-l{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.items-baseline-l{-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline}.items-stretch-l{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.self-start-l{-ms-flex-item-align:start;align-self:flex-start}.self-end-l{-ms-flex-item-align:end;align-self:flex-end}.self-center-l{-ms-flex-item-align:center;align-self:center}.self-baseline-l{-ms-flex-item-align:baseline;align-self:baseline}.self-stretch-l{-ms-flex-item-align:stretch;align-self:stretch}.justify-start-l{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.justify-end-l{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.justify-center-l{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.justify-between-l{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.justify-around-l{-ms-flex-pack:distribute;justify-content:space-around}.content-start-l{-ms-flex-line-pack:start;align-content:flex-start}.content-end-l{-ms-flex-line-pack:end;align-content:flex-end}.content-center-l{-ms-flex-line-pack:center;align-content:center}.content-between-l{-ms-flex-line-pack:justify;align-content:space-between}.content-around-l{-ms-flex-line-pack:distribute;align-content:space-around}.content-stretch-l{-ms-flex-line-pack:stretch;align-content:stretch}.order-0-l{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1-l{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2-l{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3-l{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4-l{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5-l{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6-l{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7-l{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8-l{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-last-l{-webkit-box-ordinal-group:100000;-ms-flex-order:99999;order:99999}.flex-grow-0-l{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0}.flex-grow-1-l{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.flex-shrink-0-l{-ms-flex-negative:0;flex-shrink:0}.flex-shrink-1-l{-ms-flex-negative:1;flex-shrink:1}}.fl{float:left;_display:inline}.fr{float:right;_display:inline}.fn{float:none}@media screen and (min-width:30em){.fl-ns{float:left;_display:inline}.fr-ns{float:right;_display:inline}.fn-ns{float:none}}@media screen and (min-width:30em) and (max-width:60em){.fl-m{float:left;_display:inline}.fr-m{float:right;_display:inline}.fn-m{float:none}}@media screen and (min-width:60em){.fl-l{float:left;_display:inline}.fr-l{float:right;_display:inline}.fn-l{float:none}}.i{font-style:italic}.fs-normal{font-style:normal}@media screen and (min-width:30em){.i-ns{font-style:italic}.fs-normal-ns{font-style:normal}}@media screen and (min-width:30em) and (max-width:60em){.i-m{font-style:italic}.fs-normal-m{font-style:normal}}@media screen and (min-width:60em){.i-l{font-style:italic}.fs-normal-l{font-style:normal}}.normal{font-weight:400}.b{font-weight:700}.fw1{font-weight:100}.fw2{font-weight:200}.fw3{font-weight:300}.fw4{font-weight:400}.fw5{font-weight:500}.fw6{font-weight:600}.fw7{font-weight:700}.fw8{font-weight:800}.fw9{font-weight:900}@media screen and (min-width:30em){.normal-ns{font-weight:400}.b-ns{font-weight:700}.fw1-ns{font-weight:100}.fw2-ns{font-weight:200}.fw3-ns{font-weight:300}.fw4-ns{font-weight:400}.fw5-ns{font-weight:500}.fw6-ns{font-weight:600}.fw7-ns{font-weight:700}.fw8-ns{font-weight:800}.fw9-ns{font-weight:900}}@media screen and (min-width:30em) and (max-width:60em){.normal-m{font-weight:400}.b-m{font-weight:700}.fw1-m{font-weight:100}.fw2-m{font-weight:200}.fw3-m{font-weight:300}.fw4-m{font-weight:400}.fw5-m{font-weight:500}.fw6-m{font-weight:600}.fw7-m{font-weight:700}.fw8-m{font-weight:800}.fw9-m{font-weight:900}}@media screen and (min-width:60em){.normal-l{font-weight:400}.b-l{font-weight:700}.fw1-l{font-weight:100}.fw2-l{font-weight:200}.fw3-l{font-weight:300}.fw4-l{font-weight:400}.fw5-l{font-weight:500}.fw6-l{font-weight:600}.fw7-l{font-weight:700}.fw8-l{font-weight:800}.fw9-l{font-weight:900}}.input-reset{-webkit-appearance:none;-moz-appearance:none}.button-reset::-moz-focus-inner,.input-reset::-moz-focus-inner{border:0;padding:0}.h1{height:1rem}.h2{height:2rem}.h3{height:4rem}.h4{height:8rem}.h5{height:16rem}.h-25{height:25%}.h-50{height:50%}.h-75{height:75%}.h-100{height:100%}.min-h-100{min-height:100%}.vh-25{height:25vh}.vh-50{height:50vh}.vh-75{height:75vh}.vh-100{height:100vh}.min-vh-100{min-height:100vh}.h-auto{height:auto}.h-inherit{height:inherit}@media screen and (min-width:30em){.h1-ns{height:1rem}.h2-ns{height:2rem}.h3-ns{height:4rem}.h4-ns{height:8rem}.h5-ns{height:16rem}.h-25-ns{height:25%}.h-50-ns{height:50%}.h-75-ns{height:75%}.h-100-ns{height:100%}.min-h-100-ns{min-height:100%}.vh-25-ns{height:25vh}.vh-50-ns{height:50vh}.vh-75-ns{height:75vh}.vh-100-ns{height:100vh}.min-vh-100-ns{min-height:100vh}.h-auto-ns{height:auto}.h-inherit-ns{height:inherit}}@media screen and (min-width:30em) and (max-width:60em){.h1-m{height:1rem}.h2-m{height:2rem}.h3-m{height:4rem}.h4-m{height:8rem}.h5-m{height:16rem}.h-25-m{height:25%}.h-50-m{height:50%}.h-75-m{height:75%}.h-100-m{height:100%}.min-h-100-m{min-height:100%}.vh-25-m{height:25vh}.vh-50-m{height:50vh}.vh-75-m{height:75vh}.vh-100-m{height:100vh}.min-vh-100-m{min-height:100vh}.h-auto-m{height:auto}.h-inherit-m{height:inherit}}@media screen and (min-width:60em){.h1-l{height:1rem}.h2-l{height:2rem}.h3-l{height:4rem}.h4-l{height:8rem}.h5-l{height:16rem}.h-25-l{height:25%}.h-50-l{height:50%}.h-75-l{height:75%}.h-100-l{height:100%}.min-h-100-l{min-height:100%}.vh-25-l{height:25vh}.vh-50-l{height:50vh}.vh-75-l{height:75vh}.vh-100-l{height:100vh}.min-vh-100-l{min-height:100vh}.h-auto-l{height:auto}.h-inherit-l{height:inherit}}.tracked{letter-spacing:.1em}.tracked-tight{letter-spacing:-.05em}.tracked-mega{letter-spacing:.25em}@media screen and (min-width:30em){.tracked-ns{letter-spacing:.1em}.tracked-tight-ns{letter-spacing:-.05em}.tracked-mega-ns{letter-spacing:.25em}}@media screen and (min-width:30em) and (max-width:60em){.tracked-m{letter-spacing:.1em}.tracked-tight-m{letter-spacing:-.05em}.tracked-mega-m{letter-spacing:.25em}}@media screen and (min-width:60em){.tracked-l{letter-spacing:.1em}.tracked-tight-l{letter-spacing:-.05em}.tracked-mega-l{letter-spacing:.25em}}.lh-solid{line-height:1}.lh-title{line-height:1.25}.lh-copy{line-height:1.5}@media screen and (min-width:30em){.lh-solid-ns{line-height:1}.lh-title-ns{line-height:1.25}.lh-copy-ns{line-height:1.5}}@media screen and (min-width:30em) and (max-width:60em){.lh-solid-m{line-height:1}.lh-title-m{line-height:1.25}.lh-copy-m{line-height:1.5}}@media screen and (min-width:60em){.lh-solid-l{line-height:1}.lh-title-l{line-height:1.25}.lh-copy-l{line-height:1.5}}.link{text-decoration:none;-webkit-transition:color .15s ease-in;transition:color .15s ease-in}.link:link,.link:visited{-webkit-transition:color .15s ease-in;transition:color .15s ease-in}.link:hover{-webkit-transition:color .15s ease-in;transition:color .15s ease-in}.link:active{-webkit-transition:color .15s ease-in;transition:color .15s ease-in}.link:focus{-webkit-transition:color .15s ease-in;transition:color .15s ease-in;outline:1px dotted currentColor}.list{list-style-type:none}.mw-100{max-width:100%}.mw1{max-width:1rem}.mw2{max-width:2rem}.mw3{max-width:4rem}.mw4{max-width:8rem}.mw5{max-width:16rem}.mw6{max-width:32rem}.mw7{max-width:48rem}.mw8{max-width:64rem}.mw9{max-width:96rem}.mw-none{max-width:none}@media screen and (min-width:30em){.mw-100-ns{max-width:100%}.mw1-ns{max-width:1rem}.mw2-ns{max-width:2rem}.mw3-ns{max-width:4rem}.mw4-ns{max-width:8rem}.mw5-ns{max-width:16rem}.mw6-ns{max-width:32rem}.mw7-ns{max-width:48rem}.mw8-ns{max-width:64rem}.mw9-ns{max-width:96rem}.mw-none-ns{max-width:none}}@media screen and (min-width:30em) and (max-width:60em){.mw-100-m{max-width:100%}.mw1-m{max-width:1rem}.mw2-m{max-width:2rem}.mw3-m{max-width:4rem}.mw4-m{max-width:8rem}.mw5-m{max-width:16rem}.mw6-m{max-width:32rem}.mw7-m{max-width:48rem}.mw8-m{max-width:64rem}.mw9-m{max-width:96rem}.mw-none-m{max-width:none}}@media screen and (min-width:60em){.mw-100-l{max-width:100%}.mw1-l{max-width:1rem}.mw2-l{max-width:2rem}.mw3-l{max-width:4rem}.mw4-l{max-width:8rem}.mw5-l{max-width:16rem}.mw6-l{max-width:32rem}.mw7-l{max-width:48rem}.mw8-l{max-width:64rem}.mw9-l{max-width:96rem}.mw-none-l{max-width:none}}.w1{width:1rem}.w2{width:2rem}.w3{width:4rem}.w4{width:8rem}.w5{width:16rem}.w-10{width:10%}.w-20{width:20%}.w-25{width:25%}.w-30{width:30%}.w-33{width:33%}.w-34{width:34%}.w-40{width:40%}.w-50{width:50%}.w-60{width:60%}.w-70{width:70%}.w-75{width:75%}.w-80{width:80%}.w-90{width:90%}.w-100{width:100%}.w-third{width:33.33333%}.w-two-thirds{width:66.66667%}.w-auto{width:auto}@media screen and (min-width:30em){.w1-ns{width:1rem}.w2-ns{width:2rem}.w3-ns{width:4rem}.w4-ns{width:8rem}.w5-ns{width:16rem}.w-10-ns{width:10%}.w-20-ns{width:20%}.w-25-ns{width:25%}.w-30-ns{width:30%}.w-33-ns{width:33%}.w-34-ns{width:34%}.w-40-ns{width:40%}.w-50-ns{width:50%}.w-60-ns{width:60%}.w-70-ns{width:70%}.w-75-ns{width:75%}.w-80-ns{width:80%}.w-90-ns{width:90%}.w-100-ns{width:100%}.w-third-ns{width:33.33333%}.w-two-thirds-ns{width:66.66667%}.w-auto-ns{width:auto}}@media screen and (min-width:30em) and (max-width:60em){.w1-m{width:1rem}.w2-m{width:2rem}.w3-m{width:4rem}.w4-m{width:8rem}.w5-m{width:16rem}.w-10-m{width:10%}.w-20-m{width:20%}.w-25-m{width:25%}.w-30-m{width:30%}.w-33-m{width:33%}.w-34-m{width:34%}.w-40-m{width:40%}.w-50-m{width:50%}.w-60-m{width:60%}.w-70-m{width:70%}.w-75-m{width:75%}.w-80-m{width:80%}.w-90-m{width:90%}.w-100-m{width:100%}.w-third-m{width:33.33333%}.w-two-thirds-m{width:66.66667%}.w-auto-m{width:auto}}@media screen and (min-width:60em){.w1-l{width:1rem}.w2-l{width:2rem}.w3-l{width:4rem}.w4-l{width:8rem}.w5-l{width:16rem}.w-10-l{width:10%}.w-20-l{width:20%}.w-25-l{width:25%}.w-30-l{width:30%}.w-33-l{width:33%}.w-34-l{width:34%}.w-40-l{width:40%}.w-50-l{width:50%}.w-60-l{width:60%}.w-70-l{width:70%}.w-75-l{width:75%}.w-80-l{width:80%}.w-90-l{width:90%}.w-100-l{width:100%}.w-third-l{width:33.33333%}.w-two-thirds-l{width:66.66667%}.w-auto-l{width:auto}}.overflow-visible{overflow:visible}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-auto{overflow:auto}.overflow-x-visible{overflow-x:visible}.overflow-x-hidden{overflow-x:hidden}.overflow-x-scroll{overflow-x:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-visible{overflow-y:visible}.overflow-y-hidden{overflow-y:hidden}.overflow-y-scroll{overflow-y:scroll}.overflow-y-auto{overflow-y:auto}@media screen and (min-width:30em){.overflow-visible-ns{overflow:visible}.overflow-hidden-ns{overflow:hidden}.overflow-scroll-ns{overflow:scroll}.overflow-auto-ns{overflow:auto}.overflow-x-visible-ns{overflow-x:visible}.overflow-x-hidden-ns{overflow-x:hidden}.overflow-x-scroll-ns{overflow-x:scroll}.overflow-x-auto-ns{overflow-x:auto}.overflow-y-visible-ns{overflow-y:visible}.overflow-y-hidden-ns{overflow-y:hidden}.overflow-y-scroll-ns{overflow-y:scroll}.overflow-y-auto-ns{overflow-y:auto}}@media screen and (min-width:30em) and (max-width:60em){.overflow-visible-m{overflow:visible}.overflow-hidden-m{overflow:hidden}.overflow-scroll-m{overflow:scroll}.overflow-auto-m{overflow:auto}.overflow-x-visible-m{overflow-x:visible}.overflow-x-hidden-m{overflow-x:hidden}.overflow-x-scroll-m{overflow-x:scroll}.overflow-x-auto-m{overflow-x:auto}.overflow-y-visible-m{overflow-y:visible}.overflow-y-hidden-m{overflow-y:hidden}.overflow-y-scroll-m{overflow-y:scroll}.overflow-y-auto-m{overflow-y:auto}}@media screen and (min-width:60em){.overflow-visible-l{overflow:visible}.overflow-hidden-l{overflow:hidden}.overflow-scroll-l{overflow:scroll}.overflow-auto-l{overflow:auto}.overflow-x-visible-l{overflow-x:visible}.overflow-x-hidden-l{overflow-x:hidden}.overflow-x-scroll-l{overflow-x:scroll}.overflow-x-auto-l{overflow-x:auto}.overflow-y-visible-l{overflow-y:visible}.overflow-y-hidden-l{overflow-y:hidden}.overflow-y-scroll-l{overflow-y:scroll}.overflow-y-auto-l{overflow-y:auto}}.static{position:static}.relative{position:relative}.absolute{position:absolute}.fixed{position:fixed}@media screen and (min-width:30em){.static-ns{position:static}.relative-ns{position:relative}.absolute-ns{position:absolute}.fixed-ns{position:fixed}}@media screen and (min-width:30em) and (max-width:60em){.static-m{position:static}.relative-m{position:relative}.absolute-m{position:absolute}.fixed-m{position:fixed}}@media screen and (min-width:60em){.static-l{position:static}.relative-l{position:relative}.absolute-l{position:absolute}.fixed-l{position:fixed}}.o-100{opacity:1}.o-90{opacity:.9}.o-80{opacity:.8}.o-70{opacity:.7}.o-60{opacity:.6}.o-50{opacity:.5}.o-40{opacity:.4}.o-30{opacity:.3}.o-20{opacity:.2}.o-10{opacity:.1}.o-05{opacity:.05}.o-025{opacity:.025}.o-0{opacity:0}.black-90{color:rgba(0,0,0,.9)}.black-80{color:rgba(0,0,0,.8)}.black-70{color:rgba(0,0,0,.7)}.black-60{color:rgba(0,0,0,.6)}.black-50{color:rgba(0,0,0,.5)}.black-40{color:rgba(0,0,0,.4)}.black-30{color:rgba(0,0,0,.3)}.black-20{color:rgba(0,0,0,.2)}.black-10{color:rgba(0,0,0,.1)}.black-05{color:rgba(0,0,0,.05)}.white-90{color:rgba(255,255,255,.9)}.white-80{color:rgba(255,255,255,.8)}.white-70{color:rgba(255,255,255,.7)}.white-60{color:rgba(255,255,255,.6)}.white-50{color:rgba(255,255,255,.5)}.white-40{color:rgba(255,255,255,.4)}.white-30{color:rgba(255,255,255,.3)}.white-20{color:rgba(255,255,255,.2)}.white-10{color:rgba(255,255,255,.1)}.black{color:#000}.near-black{color:#111}.dark-gray{color:#333}.mid-gray{color:#555}.gray{color:#777}.silver{color:#999}.light-silver{color:#aaa}.moon-gray{color:#ccc}.light-gray{color:#eee}.near-white{color:#f4f4f4}.white{color:#fff}.dark-red{color:#e7040f}.red{color:#ff4136}.light-red{color:#ff725c}.orange{color:#ff6300}.gold{color:#ffb700}.yellow{color:gold}.light-yellow{color:#fbf1a9}.purple{color:#5e2ca5}.light-purple{color:#a463f2}.dark-pink{color:#d5008f}.hot-pink{color:#ff41b4}.pink{color:#ff80cc}.light-pink{color:#ffa3d7}.dark-green{color:#137752}.green{color:#19a974}.light-green{color:#9eebcf}.navy{color:#001b44}.dark-blue{color:#00449e}.blue{color:#0594cb}.light-blue{color:#96ccff}.lightest-blue{color:#cdecff}.washed-blue{color:#f6fffe}.washed-green{color:#e8fdf5}.washed-yellow{color:#fffceb}.washed-red{color:#ffdfdf}.color-inherit{color:inherit}.bg-black-90{background-color:rgba(0,0,0,.9)}.bg-black-80{background-color:rgba(0,0,0,.8)}.bg-black-70{background-color:rgba(0,0,0,.7)}.bg-black-60{background-color:rgba(0,0,0,.6)}.bg-black-50{background-color:rgba(0,0,0,.5)}.bg-black-40{background-color:rgba(0,0,0,.4)}.bg-black-30{background-color:rgba(0,0,0,.3)}.bg-black-20{background-color:rgba(0,0,0,.2)}.bg-black-10{background-color:rgba(0,0,0,.1)}.bg-black-05{background-color:rgba(0,0,0,.05)}.bg-white-90{background-color:rgba(255,255,255,.9)}.bg-white-80{background-color:rgba(255,255,255,.8)}.bg-white-70{background-color:rgba(255,255,255,.7)}.bg-white-60{background-color:rgba(255,255,255,.6)}.bg-white-50{background-color:rgba(255,255,255,.5)}.bg-white-40{background-color:rgba(255,255,255,.4)}.bg-white-30{background-color:rgba(255,255,255,.3)}.bg-white-20{background-color:rgba(255,255,255,.2)}.bg-white-10{background-color:rgba(255,255,255,.1)}.bg-black{background-color:#000}.bg-near-black{background-color:#111}.bg-dark-gray{background-color:#333}.bg-mid-gray{background-color:#555}.bg-gray{background-color:#777}.bg-silver{background-color:#999}.bg-light-silver{background-color:#aaa}.bg-moon-gray{background-color:#ccc}.bg-light-gray{background-color:#eee}.bg-near-white{background-color:#f4f4f4}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.bg-dark-red{background-color:#e7040f}.bg-red{background-color:#ff4136}.bg-light-red{background-color:#ff725c}.bg-orange{background-color:#ff6300}.bg-gold{background-color:#ffb700}.bg-yellow{background-color:gold}.bg-light-yellow{background-color:#fbf1a9}.bg-purple{background-color:#5e2ca5}.bg-light-purple{background-color:#a463f2}.bg-dark-pink{background-color:#d5008f}.bg-hot-pink{background-color:#ff41b4}.bg-pink{background-color:#ff80cc}.bg-light-pink{background-color:#ffa3d7}.bg-dark-green{background-color:#137752}.bg-green{background-color:#19a974}.bg-light-green{background-color:#9eebcf}.bg-navy{background-color:#001b44}.bg-dark-blue{background-color:#00449e}.bg-blue{background-color:#0594cb}.bg-light-blue{background-color:#96ccff}.bg-lightest-blue{background-color:#cdecff}.bg-washed-blue{background-color:#f6fffe}.bg-washed-green{background-color:#e8fdf5}.bg-washed-yellow{background-color:#fffceb}.bg-washed-red{background-color:#ffdfdf}.bg-inherit{background-color:inherit}.hover-black:hover,.hover-black:focus{color:#000}.hover-near-black:hover,.hover-near-black:focus{color:#111}.hover-dark-gray:hover,.hover-dark-gray:focus{color:#333}.hover-mid-gray:hover,.hover-mid-gray:focus{color:#555}.hover-gray:hover,.hover-gray:focus{color:#777}.hover-silver:hover,.hover-silver:focus{color:#999}.hover-light-silver:hover,.hover-light-silver:focus{color:#aaa}.hover-moon-gray:hover,.hover-moon-gray:focus{color:#ccc}.hover-light-gray:hover,.hover-light-gray:focus{color:#eee}.hover-near-white:hover,.hover-near-white:focus{color:#f4f4f4}.hover-white:hover,.hover-white:focus{color:#fff}.hover-black-90:hover,.hover-black-90:focus{color:rgba(0,0,0,.9)}.hover-black-80:hover,.hover-black-80:focus{color:rgba(0,0,0,.8)}.hover-black-70:hover,.hover-black-70:focus{color:rgba(0,0,0,.7)}.hover-black-60:hover,.hover-black-60:focus{color:rgba(0,0,0,.6)}.hover-black-50:hover,.hover-black-50:focus{color:rgba(0,0,0,.5)}.hover-black-40:hover,.hover-black-40:focus{color:rgba(0,0,0,.4)}.hover-black-30:hover,.hover-black-30:focus{color:rgba(0,0,0,.3)}.hover-black-20:hover,.hover-black-20:focus{color:rgba(0,0,0,.2)}.hover-black-10:hover,.hover-black-10:focus{color:rgba(0,0,0,.1)}.hover-white-90:hover,.hover-white-90:focus{color:rgba(255,255,255,.9)}.hover-white-80:hover,.hover-white-80:focus{color:rgba(255,255,255,.8)}.hover-white-70:hover,.hover-white-70:focus{color:rgba(255,255,255,.7)}.hover-white-60:hover,.hover-white-60:focus{color:rgba(255,255,255,.6)}.hover-white-50:hover,.hover-white-50:focus{color:rgba(255,255,255,.5)}.hover-white-40:hover,.hover-white-40:focus{color:rgba(255,255,255,.4)}.hover-white-30:hover,.hover-white-30:focus{color:rgba(255,255,255,.3)}.hover-white-20:hover,.hover-white-20:focus{color:rgba(255,255,255,.2)}.hover-white-10:hover,.hover-white-10:focus{color:rgba(255,255,255,.1)}.hover-inherit:hover,.hover-inherit:focus{color:inherit}.hover-bg-black:hover,.hover-bg-black:focus{background-color:#000}.hover-bg-near-black:hover,.hover-bg-near-black:focus{background-color:#111}.hover-bg-dark-gray:hover,.hover-bg-dark-gray:focus{background-color:#333}.hover-bg-mid-gray:hover,.hover-bg-mid-gray:focus{background-color:#555}.hover-bg-gray:hover,.hover-bg-gray:focus{background-color:#777}.hover-bg-silver:hover,.hover-bg-silver:focus{background-color:#999}.hover-bg-light-silver:hover,.hover-bg-light-silver:focus{background-color:#aaa}.hover-bg-moon-gray:hover,.hover-bg-moon-gray:focus{background-color:#ccc}.hover-bg-light-gray:hover,.hover-bg-light-gray:focus{background-color:#eee}.hover-bg-near-white:hover,.hover-bg-near-white:focus{background-color:#f4f4f4}.hover-bg-white:hover,.hover-bg-white:focus{background-color:#fff}.hover-bg-transparent:hover,.hover-bg-transparent:focus{background-color:transparent}.hover-bg-black-90:hover,.hover-bg-black-90:focus{background-color:rgba(0,0,0,.9)}.hover-bg-black-80:hover,.hover-bg-black-80:focus{background-color:rgba(0,0,0,.8)}.hover-bg-black-70:hover,.hover-bg-black-70:focus{background-color:rgba(0,0,0,.7)}.hover-bg-black-60:hover,.hover-bg-black-60:focus{background-color:rgba(0,0,0,.6)}.hover-bg-black-50:hover,.hover-bg-black-50:focus{background-color:rgba(0,0,0,.5)}.hover-bg-black-40:hover,.hover-bg-black-40:focus{background-color:rgba(0,0,0,.4)}.hover-bg-black-30:hover,.hover-bg-black-30:focus{background-color:rgba(0,0,0,.3)}.hover-bg-black-20:hover,.hover-bg-black-20:focus{background-color:rgba(0,0,0,.2)}.hover-bg-black-10:hover,.hover-bg-black-10:focus{background-color:rgba(0,0,0,.1)}.hover-bg-white-90:hover,.hover-bg-white-90:focus{background-color:rgba(255,255,255,.9)}.hover-bg-white-80:hover,.hover-bg-white-80:focus{background-color:rgba(255,255,255,.8)}.hover-bg-white-70:hover,.hover-bg-white-70:focus{background-color:rgba(255,255,255,.7)}.hover-bg-white-60:hover,.hover-bg-white-60:focus{background-color:rgba(255,255,255,.6)}.hover-bg-white-50:hover,.hover-bg-white-50:focus{background-color:rgba(255,255,255,.5)}.hover-bg-white-40:hover,.hover-bg-white-40:focus{background-color:rgba(255,255,255,.4)}.hover-bg-white-30:hover,.hover-bg-white-30:focus{background-color:rgba(255,255,255,.3)}.hover-bg-white-20:hover,.hover-bg-white-20:focus{background-color:rgba(255,255,255,.2)}.hover-bg-white-10:hover,.hover-bg-white-10:focus{background-color:rgba(255,255,255,.1)}.hover-dark-red:hover,.hover-dark-red:focus{color:#e7040f}.hover-red:hover,.hover-red:focus{color:#ff4136}.hover-light-red:hover,.hover-light-red:focus{color:#ff725c}.hover-orange:hover,.hover-orange:focus{color:#ff6300}.hover-gold:hover,.hover-gold:focus{color:#ffb700}.hover-yellow:hover,.hover-yellow:focus{color:gold}.hover-light-yellow:hover,.hover-light-yellow:focus{color:#fbf1a9}.hover-purple:hover,.hover-purple:focus{color:#5e2ca5}.hover-light-purple:hover,.hover-light-purple:focus{color:#a463f2}.hover-dark-pink:hover,.hover-dark-pink:focus{color:#d5008f}.hover-hot-pink:hover,.hover-hot-pink:focus{color:#ff41b4}.hover-pink:hover,.hover-pink:focus{color:#ff80cc}.hover-light-pink:hover,.hover-light-pink:focus{color:#ffa3d7}.hover-dark-green:hover,.hover-dark-green:focus{color:#137752}.hover-green:hover,.hover-green:focus{color:#19a974}.hover-light-green:hover,.hover-light-green:focus{color:#9eebcf}.hover-navy:hover,.hover-navy:focus{color:#001b44}.hover-dark-blue:hover,.hover-dark-blue:focus{color:#00449e}.hover-blue:hover,.hover-blue:focus{color:#0594cb}.hover-light-blue:hover,.hover-light-blue:focus{color:#96ccff}.hover-lightest-blue:hover,.hover-lightest-blue:focus{color:#cdecff}.hover-washed-blue:hover,.hover-washed-blue:focus{color:#f6fffe}.hover-washed-green:hover,.hover-washed-green:focus{color:#e8fdf5}.hover-washed-yellow:hover,.hover-washed-yellow:focus{color:#fffceb}.hover-washed-red:hover,.hover-washed-red:focus{color:#ffdfdf}.hover-bg-dark-red:hover,.hover-bg-dark-red:focus{background-color:#e7040f}.hover-bg-red:hover,.hover-bg-red:focus{background-color:#ff4136}.hover-bg-light-red:hover,.hover-bg-light-red:focus{background-color:#ff725c}.hover-bg-orange:hover,.hover-bg-orange:focus{background-color:#ff6300}.hover-bg-gold:hover,.hover-bg-gold:focus{background-color:#ffb700}.hover-bg-yellow:hover,.hover-bg-yellow:focus{background-color:gold}.hover-bg-light-yellow:hover,.hover-bg-light-yellow:focus{background-color:#fbf1a9}.hover-bg-purple:hover,.hover-bg-purple:focus{background-color:#5e2ca5}.hover-bg-light-purple:hover,.hover-bg-light-purple:focus{background-color:#a463f2}.hover-bg-dark-pink:hover,.hover-bg-dark-pink:focus{background-color:#d5008f}.hover-bg-hot-pink:hover,.hover-bg-hot-pink:focus{background-color:#ff41b4}.hover-bg-pink:hover,.hover-bg-pink:focus{background-color:#ff80cc}.hover-bg-light-pink:hover,.hover-bg-light-pink:focus{background-color:#ffa3d7}.hover-bg-dark-green:hover,.hover-bg-dark-green:focus{background-color:#137752}.hover-bg-green:hover,.hover-bg-green:focus{background-color:#19a974}.hover-bg-light-green:hover,.hover-bg-light-green:focus{background-color:#9eebcf}.hover-bg-navy:hover,.hover-bg-navy:focus{background-color:#001b44}.hover-bg-dark-blue:hover,.hover-bg-dark-blue:focus{background-color:#00449e}.hover-bg-blue:hover,.hover-bg-blue:focus{background-color:#0594cb}.hover-bg-light-blue:hover,.hover-bg-light-blue:focus{background-color:#96ccff}.hover-bg-lightest-blue:hover,.hover-bg-lightest-blue:focus{background-color:#cdecff}.hover-bg-washed-blue:hover,.hover-bg-washed-blue:focus{background-color:#f6fffe}.hover-bg-washed-green:hover,.hover-bg-washed-green:focus{background-color:#e8fdf5}.hover-bg-washed-yellow:hover,.hover-bg-washed-yellow:focus{background-color:#fffceb}.hover-bg-washed-red:hover,.hover-bg-washed-red:focus{background-color:#ffdfdf}.hover-bg-inherit:hover,.hover-bg-inherit:focus{background-color:inherit}.pa0{padding:0}.pa1{padding:.25rem}.pa2{padding:.5rem}.pa3{padding:1rem}.pa4{padding:2rem}.pa5{padding:4rem}.pa6{padding:8rem}.pa7{padding:16rem}.pl0{padding-left:0}.pl1{padding-left:.25rem}.pl2{padding-left:.5rem}.pl3{padding-left:1rem}.pl4{padding-left:2rem}.pl5{padding-left:4rem}.pl6{padding-left:8rem}.pl7{padding-left:16rem}.pr0{padding-right:0}.pr1{padding-right:.25rem}.pr2{padding-right:.5rem}.pr3{padding-right:1rem}.pr4{padding-right:2rem}.pr5{padding-right:4rem}.pr6{padding-right:8rem}.pr7{padding-right:16rem}.pb0{padding-bottom:0}.pb1{padding-bottom:.25rem}.pb2{padding-bottom:.5rem}.pb3{padding-bottom:1rem}.pb4{padding-bottom:2rem}.pb5{padding-bottom:4rem}.pb6{padding-bottom:8rem}.pb7{padding-bottom:16rem}.pt0{padding-top:0}.pt1{padding-top:.25rem}.pt2{padding-top:.5rem}.pt3{padding-top:1rem}.pt4{padding-top:2rem}.pt5{padding-top:4rem}.pt6{padding-top:8rem}.pt7{padding-top:16rem}.pv0{padding-top:0;padding-bottom:0}.pv1{padding-top:.25rem;padding-bottom:.25rem}.pv2{padding-top:.5rem;padding-bottom:.5rem}.pv3{padding-top:1rem;padding-bottom:1rem}.pv4{padding-top:2rem;padding-bottom:2rem}.pv5{padding-top:4rem;padding-bottom:4rem}.pv6{padding-top:8rem;padding-bottom:8rem}.pv7{padding-top:16rem;padding-bottom:16rem}.ph0{padding-left:0;padding-right:0}.ph1{padding-left:.25rem;padding-right:.25rem}.ph2{padding-left:.5rem;padding-right:.5rem}.ph3{padding-left:1rem;padding-right:1rem}.ph4{padding-left:2rem;padding-right:2rem}.ph5{padding-left:4rem;padding-right:4rem}.ph6{padding-left:8rem;padding-right:8rem}.ph7{padding-left:16rem;padding-right:16rem}.ma0{margin:0}.ma1{margin:.25rem}.ma2{margin:.5rem}.ma3{margin:1rem}.ma4{margin:2rem}.ma5{margin:4rem}.ma6{margin:8rem}.ma7{margin:16rem}.ml0{margin-left:0}.ml1{margin-left:.25rem}.ml2{margin-left:.5rem}.ml3{margin-left:1rem}.ml4{margin-left:2rem}.ml5{margin-left:4rem}.ml6{margin-left:8rem}.ml7{margin-left:16rem}.mr0{margin-right:0}.mr1{margin-right:.25rem}.mr2{margin-right:.5rem}.mr3{margin-right:1rem}.mr4{margin-right:2rem}.mr5{margin-right:4rem}.mr6{margin-right:8rem}.mr7{margin-right:16rem}.mb0{margin-bottom:0}.mb1{margin-bottom:.25rem}.mb2{margin-bottom:.5rem}.mb3{margin-bottom:1rem}.mb4{margin-bottom:2rem}.mb5{margin-bottom:4rem}.mb6{margin-bottom:8rem}.mb7{margin-bottom:16rem}.mt0{margin-top:0}.mt1{margin-top:.25rem}.mt2{margin-top:.5rem}.mt3{margin-top:1rem}.mt4{margin-top:2rem}.mt5{margin-top:4rem}.mt6{margin-top:8rem}.mt7{margin-top:16rem}.mv0{margin-top:0;margin-bottom:0}.mv1{margin-top:.25rem;margin-bottom:.25rem}.mv2{margin-top:.5rem;margin-bottom:.5rem}.mv3{margin-top:1rem;margin-bottom:1rem}.mv4{margin-top:2rem;margin-bottom:2rem}.mv5{margin-top:4rem;margin-bottom:4rem}.mv6{margin-top:8rem;margin-bottom:8rem}.mv7{margin-top:16rem;margin-bottom:16rem}.mh0{margin-left:0;margin-right:0}.mh1{margin-left:.25rem;margin-right:.25rem}.mh2{margin-left:.5rem;margin-right:.5rem}.mh3{margin-left:1rem;margin-right:1rem}.mh4{margin-left:2rem;margin-right:2rem}.mh5{margin-left:4rem;margin-right:4rem}.mh6{margin-left:8rem;margin-right:8rem}.mh7{margin-left:16rem;margin-right:16rem}@media screen and (min-width:30em){.pa0-ns{padding:0}.pa1-ns{padding:.25rem}.pa2-ns{padding:.5rem}.pa3-ns{padding:1rem}.pa4-ns{padding:2rem}.pa5-ns{padding:4rem}.pa6-ns{padding:8rem}.pa7-ns{padding:16rem}.pl0-ns{padding-left:0}.pl1-ns{padding-left:.25rem}.pl2-ns{padding-left:.5rem}.pl3-ns{padding-left:1rem}.pl4-ns{padding-left:2rem}.pl5-ns{padding-left:4rem}.pl6-ns{padding-left:8rem}.pl7-ns{padding-left:16rem}.pr0-ns{padding-right:0}.pr1-ns{padding-right:.25rem}.pr2-ns{padding-right:.5rem}.pr3-ns{padding-right:1rem}.pr4-ns{padding-right:2rem}.pr5-ns{padding-right:4rem}.pr6-ns{padding-right:8rem}.pr7-ns{padding-right:16rem}.pb0-ns{padding-bottom:0}.pb1-ns{padding-bottom:.25rem}.pb2-ns{padding-bottom:.5rem}.pb3-ns{padding-bottom:1rem}.pb4-ns{padding-bottom:2rem}.pb5-ns{padding-bottom:4rem}.pb6-ns{padding-bottom:8rem}.pb7-ns{padding-bottom:16rem}.pt0-ns{padding-top:0}.pt1-ns{padding-top:.25rem}.pt2-ns{padding-top:.5rem}.pt3-ns{padding-top:1rem}.pt4-ns{padding-top:2rem}.pt5-ns{padding-top:4rem}.pt6-ns{padding-top:8rem}.pt7-ns{padding-top:16rem}.pv0-ns{padding-top:0;padding-bottom:0}.pv1-ns{padding-top:.25rem;padding-bottom:.25rem}.pv2-ns{padding-top:.5rem;padding-bottom:.5rem}.pv3-ns{padding-top:1rem;padding-bottom:1rem}.pv4-ns{padding-top:2rem;padding-bottom:2rem}.pv5-ns{padding-top:4rem;padding-bottom:4rem}.pv6-ns{padding-top:8rem;padding-bottom:8rem}.pv7-ns{padding-top:16rem;padding-bottom:16rem}.ph0-ns{padding-left:0;padding-right:0}.ph1-ns{padding-left:.25rem;padding-right:.25rem}.ph2-ns{padding-left:.5rem;padding-right:.5rem}.ph3-ns{padding-left:1rem;padding-right:1rem}.ph4-ns{padding-left:2rem;padding-right:2rem}.ph5-ns{padding-left:4rem;padding-right:4rem}.ph6-ns{padding-left:8rem;padding-right:8rem}.ph7-ns{padding-left:16rem;padding-right:16rem}.ma0-ns{margin:0}.ma1-ns{margin:.25rem}.ma2-ns{margin:.5rem}.ma3-ns{margin:1rem}.ma4-ns{margin:2rem}.ma5-ns{margin:4rem}.ma6-ns{margin:8rem}.ma7-ns{margin:16rem}.ml0-ns{margin-left:0}.ml1-ns{margin-left:.25rem}.ml2-ns{margin-left:.5rem}.ml3-ns{margin-left:1rem}.ml4-ns{margin-left:2rem}.ml5-ns{margin-left:4rem}.ml6-ns{margin-left:8rem}.ml7-ns{margin-left:16rem}.mr0-ns{margin-right:0}.mr1-ns{margin-right:.25rem}.mr2-ns{margin-right:.5rem}.mr3-ns{margin-right:1rem}.mr4-ns{margin-right:2rem}.mr5-ns{margin-right:4rem}.mr6-ns{margin-right:8rem}.mr7-ns{margin-right:16rem}.mb0-ns{margin-bottom:0}.mb1-ns{margin-bottom:.25rem}.mb2-ns{margin-bottom:.5rem}.mb3-ns{margin-bottom:1rem}.mb4-ns{margin-bottom:2rem}.mb5-ns{margin-bottom:4rem}.mb6-ns{margin-bottom:8rem}.mb7-ns{margin-bottom:16rem}.mt0-ns{margin-top:0}.mt1-ns{margin-top:.25rem}.mt2-ns{margin-top:.5rem}.mt3-ns{margin-top:1rem}.mt4-ns{margin-top:2rem}.mt5-ns{margin-top:4rem}.mt6-ns{margin-top:8rem}.mt7-ns{margin-top:16rem}.mv0-ns{margin-top:0;margin-bottom:0}.mv1-ns{margin-top:.25rem;margin-bottom:.25rem}.mv2-ns{margin-top:.5rem;margin-bottom:.5rem}.mv3-ns{margin-top:1rem;margin-bottom:1rem}.mv4-ns{margin-top:2rem;margin-bottom:2rem}.mv5-ns{margin-top:4rem;margin-bottom:4rem}.mv6-ns{margin-top:8rem;margin-bottom:8rem}.mv7-ns{margin-top:16rem;margin-bottom:16rem}.mh0-ns{margin-left:0;margin-right:0}.mh1-ns{margin-left:.25rem;margin-right:.25rem}.mh2-ns{margin-left:.5rem;margin-right:.5rem}.mh3-ns{margin-left:1rem;margin-right:1rem}.mh4-ns{margin-left:2rem;margin-right:2rem}.mh5-ns{margin-left:4rem;margin-right:4rem}.mh6-ns{margin-left:8rem;margin-right:8rem}.mh7-ns{margin-left:16rem;margin-right:16rem}}@media screen and (min-width:30em) and (max-width:60em){.pa0-m{padding:0}.pa1-m{padding:.25rem}.pa2-m{padding:.5rem}.pa3-m{padding:1rem}.pa4-m{padding:2rem}.pa5-m{padding:4rem}.pa6-m{padding:8rem}.pa7-m{padding:16rem}.pl0-m{padding-left:0}.pl1-m{padding-left:.25rem}.pl2-m{padding-left:.5rem}.pl3-m{padding-left:1rem}.pl4-m{padding-left:2rem}.pl5-m{padding-left:4rem}.pl6-m{padding-left:8rem}.pl7-m{padding-left:16rem}.pr0-m{padding-right:0}.pr1-m{padding-right:.25rem}.pr2-m{padding-right:.5rem}.pr3-m{padding-right:1rem}.pr4-m{padding-right:2rem}.pr5-m{padding-right:4rem}.pr6-m{padding-right:8rem}.pr7-m{padding-right:16rem}.pb0-m{padding-bottom:0}.pb1-m{padding-bottom:.25rem}.pb2-m{padding-bottom:.5rem}.pb3-m{padding-bottom:1rem}.pb4-m{padding-bottom:2rem}.pb5-m{padding-bottom:4rem}.pb6-m{padding-bottom:8rem}.pb7-m{padding-bottom:16rem}.pt0-m{padding-top:0}.pt1-m{padding-top:.25rem}.pt2-m{padding-top:.5rem}.pt3-m{padding-top:1rem}.pt4-m{padding-top:2rem}.pt5-m{padding-top:4rem}.pt6-m{padding-top:8rem}.pt7-m{padding-top:16rem}.pv0-m{padding-top:0;padding-bottom:0}.pv1-m{padding-top:.25rem;padding-bottom:.25rem}.pv2-m{padding-top:.5rem;padding-bottom:.5rem}.pv3-m{padding-top:1rem;padding-bottom:1rem}.pv4-m{padding-top:2rem;padding-bottom:2rem}.pv5-m{padding-top:4rem;padding-bottom:4rem}.pv6-m{padding-top:8rem;padding-bottom:8rem}.pv7-m{padding-top:16rem;padding-bottom:16rem}.ph0-m{padding-left:0;padding-right:0}.ph1-m{padding-left:.25rem;padding-right:.25rem}.ph2-m{padding-left:.5rem;padding-right:.5rem}.ph3-m{padding-left:1rem;padding-right:1rem}.ph4-m{padding-left:2rem;padding-right:2rem}.ph5-m{padding-left:4rem;padding-right:4rem}.ph6-m{padding-left:8rem;padding-right:8rem}.ph7-m{padding-left:16rem;padding-right:16rem}.ma0-m{margin:0}.ma1-m{margin:.25rem}.ma2-m{margin:.5rem}.ma3-m{margin:1rem}.ma4-m{margin:2rem}.ma5-m{margin:4rem}.ma6-m{margin:8rem}.ma7-m{margin:16rem}.ml0-m{margin-left:0}.ml1-m{margin-left:.25rem}.ml2-m{margin-left:.5rem}.ml3-m{margin-left:1rem}.ml4-m{margin-left:2rem}.ml5-m{margin-left:4rem}.ml6-m{margin-left:8rem}.ml7-m{margin-left:16rem}.mr0-m{margin-right:0}.mr1-m{margin-right:.25rem}.mr2-m{margin-right:.5rem}.mr3-m{margin-right:1rem}.mr4-m{margin-right:2rem}.mr5-m{margin-right:4rem}.mr6-m{margin-right:8rem}.mr7-m{margin-right:16rem}.mb0-m{margin-bottom:0}.mb1-m{margin-bottom:.25rem}.mb2-m{margin-bottom:.5rem}.mb3-m{margin-bottom:1rem}.mb4-m{margin-bottom:2rem}.mb5-m{margin-bottom:4rem}.mb6-m{margin-bottom:8rem}.mb7-m{margin-bottom:16rem}.mt0-m{margin-top:0}.mt1-m{margin-top:.25rem}.mt2-m{margin-top:.5rem}.mt3-m{margin-top:1rem}.mt4-m{margin-top:2rem}.mt5-m{margin-top:4rem}.mt6-m{margin-top:8rem}.mt7-m{margin-top:16rem}.mv0-m{margin-top:0;margin-bottom:0}.mv1-m{margin-top:.25rem;margin-bottom:.25rem}.mv2-m{margin-top:.5rem;margin-bottom:.5rem}.mv3-m{margin-top:1rem;margin-bottom:1rem}.mv4-m{margin-top:2rem;margin-bottom:2rem}.mv5-m{margin-top:4rem;margin-bottom:4rem}.mv6-m{margin-top:8rem;margin-bottom:8rem}.mv7-m{margin-top:16rem;margin-bottom:16rem}.mh0-m{margin-left:0;margin-right:0}.mh1-m{margin-left:.25rem;margin-right:.25rem}.mh2-m{margin-left:.5rem;margin-right:.5rem}.mh3-m{margin-left:1rem;margin-right:1rem}.mh4-m{margin-left:2rem;margin-right:2rem}.mh5-m{margin-left:4rem;margin-right:4rem}.mh6-m{margin-left:8rem;margin-right:8rem}.mh7-m{margin-left:16rem;margin-right:16rem}}@media screen and (min-width:60em){.pa0-l{padding:0}.pa1-l{padding:.25rem}.pa2-l{padding:.5rem}.pa3-l{padding:1rem}.pa4-l{padding:2rem}.pa5-l{padding:4rem}.pa6-l{padding:8rem}.pa7-l{padding:16rem}.pl0-l{padding-left:0}.pl1-l{padding-left:.25rem}.pl2-l{padding-left:.5rem}.pl3-l{padding-left:1rem}.pl4-l{padding-left:2rem}.pl5-l{padding-left:4rem}.pl6-l{padding-left:8rem}.pl7-l{padding-left:16rem}.pr0-l{padding-right:0}.pr1-l{padding-right:.25rem}.pr2-l{padding-right:.5rem}.pr3-l{padding-right:1rem}.pr4-l{padding-right:2rem}.pr5-l{padding-right:4rem}.pr6-l{padding-right:8rem}.pr7-l{padding-right:16rem}.pb0-l{padding-bottom:0}.pb1-l{padding-bottom:.25rem}.pb2-l{padding-bottom:.5rem}.pb3-l{padding-bottom:1rem}.pb4-l{padding-bottom:2rem}.pb5-l{padding-bottom:4rem}.pb6-l{padding-bottom:8rem}.pb7-l{padding-bottom:16rem}.pt0-l{padding-top:0}.pt1-l{padding-top:.25rem}.pt2-l{padding-top:.5rem}.pt3-l{padding-top:1rem}.pt4-l{padding-top:2rem}.pt5-l{padding-top:4rem}.pt6-l{padding-top:8rem}.pt7-l{padding-top:16rem}.pv0-l{padding-top:0;padding-bottom:0}.pv1-l{padding-top:.25rem;padding-bottom:.25rem}.pv2-l{padding-top:.5rem;padding-bottom:.5rem}.pv3-l{padding-top:1rem;padding-bottom:1rem}.pv4-l{padding-top:2rem;padding-bottom:2rem}.pv5-l{padding-top:4rem;padding-bottom:4rem}.pv6-l{padding-top:8rem;padding-bottom:8rem}.pv7-l{padding-top:16rem;padding-bottom:16rem}.ph0-l{padding-left:0;padding-right:0}.ph1-l{padding-left:.25rem;padding-right:.25rem}.ph2-l{padding-left:.5rem;padding-right:.5rem}.ph3-l{padding-left:1rem;padding-right:1rem}.ph4-l{padding-left:2rem;padding-right:2rem}.ph5-l{padding-left:4rem;padding-right:4rem}.ph6-l{padding-left:8rem;padding-right:8rem}.ph7-l{padding-left:16rem;padding-right:16rem}.ma0-l{margin:0}.ma1-l{margin:.25rem}.ma2-l{margin:.5rem}.ma3-l{margin:1rem}.ma4-l{margin:2rem}.ma5-l{margin:4rem}.ma6-l{margin:8rem}.ma7-l{margin:16rem}.ml0-l{margin-left:0}.ml1-l{margin-left:.25rem}.ml2-l{margin-left:.5rem}.ml3-l{margin-left:1rem}.ml4-l{margin-left:2rem}.ml5-l{margin-left:4rem}.ml6-l{margin-left:8rem}.ml7-l{margin-left:16rem}.mr0-l{margin-right:0}.mr1-l{margin-right:.25rem}.mr2-l{margin-right:.5rem}.mr3-l{margin-right:1rem}.mr4-l{margin-right:2rem}.mr5-l{margin-right:4rem}.mr6-l{margin-right:8rem}.mr7-l{margin-right:16rem}.mb0-l{margin-bottom:0}.mb1-l{margin-bottom:.25rem}.mb2-l{margin-bottom:.5rem}.mb3-l{margin-bottom:1rem}.mb4-l{margin-bottom:2rem}.mb5-l{margin-bottom:4rem}.mb6-l{margin-bottom:8rem}.mb7-l{margin-bottom:16rem}.mt0-l{margin-top:0}.mt1-l{margin-top:.25rem}.mt2-l{margin-top:.5rem}.mt3-l{margin-top:1rem}.mt4-l{margin-top:2rem}.mt5-l{margin-top:4rem}.mt6-l{margin-top:8rem}.mt7-l{margin-top:16rem}.mv0-l{margin-top:0;margin-bottom:0}.mv1-l{margin-top:.25rem;margin-bottom:.25rem}.mv2-l{margin-top:.5rem;margin-bottom:.5rem}.mv3-l{margin-top:1rem;margin-bottom:1rem}.mv4-l{margin-top:2rem;margin-bottom:2rem}.mv5-l{margin-top:4rem;margin-bottom:4rem}.mv6-l{margin-top:8rem;margin-bottom:8rem}.mv7-l{margin-top:16rem;margin-bottom:16rem}.mh0-l{margin-left:0;margin-right:0}.mh1-l{margin-left:.25rem;margin-right:.25rem}.mh2-l{margin-left:.5rem;margin-right:.5rem}.mh3-l{margin-left:1rem;margin-right:1rem}.mh4-l{margin-left:2rem;margin-right:2rem}.mh5-l{margin-left:4rem;margin-right:4rem}.mh6-l{margin-left:8rem;margin-right:8rem}.mh7-l{margin-left:16rem;margin-right:16rem}}.na1{margin:-.25rem}.na2{margin:-.5rem}.na3{margin:-1rem}.na4{margin:-2rem}.na5{margin:-4rem}.na6{margin:-8rem}.na7{margin:-16rem}.nl1{margin-left:-.25rem}.nl2{margin-left:-.5rem}.nl3{margin-left:-1rem}.nl4{margin-left:-2rem}.nl5{margin-left:-4rem}.nl6{margin-left:-8rem}.nl7{margin-left:-16rem}.nr1{margin-right:-.25rem}.nr2{margin-right:-.5rem}.nr3{margin-right:-1rem}.nr4{margin-right:-2rem}.nr5{margin-right:-4rem}.nr6{margin-right:-8rem}.nr7{margin-right:-16rem}.nb1{margin-bottom:-.25rem}.nb2{margin-bottom:-.5rem}.nb3{margin-bottom:-1rem}.nb4{margin-bottom:-2rem}.nb5{margin-bottom:-4rem}.nb6{margin-bottom:-8rem}.nb7{margin-bottom:-16rem}.nt1{margin-top:-.25rem}.nt2{margin-top:-.5rem}.nt3{margin-top:-1rem}.nt4{margin-top:-2rem}.nt5{margin-top:-4rem}.nt6{margin-top:-8rem}.nt7{margin-top:-16rem}@media screen and (min-width:30em){.na1-ns{margin:-.25rem}.na2-ns{margin:-.5rem}.na3-ns{margin:-1rem}.na4-ns{margin:-2rem}.na5-ns{margin:-4rem}.na6-ns{margin:-8rem}.na7-ns{margin:-16rem}.nl1-ns{margin-left:-.25rem}.nl2-ns{margin-left:-.5rem}.nl3-ns{margin-left:-1rem}.nl4-ns{margin-left:-2rem}.nl5-ns{margin-left:-4rem}.nl6-ns{margin-left:-8rem}.nl7-ns{margin-left:-16rem}.nr1-ns{margin-right:-.25rem}.nr2-ns{margin-right:-.5rem}.nr3-ns{margin-right:-1rem}.nr4-ns{margin-right:-2rem}.nr5-ns{margin-right:-4rem}.nr6-ns{margin-right:-8rem}.nr7-ns{margin-right:-16rem}.nb1-ns{margin-bottom:-.25rem}.nb2-ns{margin-bottom:-.5rem}.nb3-ns{margin-bottom:-1rem}.nb4-ns{margin-bottom:-2rem}.nb5-ns{margin-bottom:-4rem}.nb6-ns{margin-bottom:-8rem}.nb7-ns{margin-bottom:-16rem}.nt1-ns{margin-top:-.25rem}.nt2-ns{margin-top:-.5rem}.nt3-ns{margin-top:-1rem}.nt4-ns{margin-top:-2rem}.nt5-ns{margin-top:-4rem}.nt6-ns{margin-top:-8rem}.nt7-ns{margin-top:-16rem}}@media screen and (min-width:30em) and (max-width:60em){.na1-m{margin:-.25rem}.na2-m{margin:-.5rem}.na3-m{margin:-1rem}.na4-m{margin:-2rem}.na5-m{margin:-4rem}.na6-m{margin:-8rem}.na7-m{margin:-16rem}.nl1-m{margin-left:-.25rem}.nl2-m{margin-left:-.5rem}.nl3-m{margin-left:-1rem}.nl4-m{margin-left:-2rem}.nl5-m{margin-left:-4rem}.nl6-m{margin-left:-8rem}.nl7-m{margin-left:-16rem}.nr1-m{margin-right:-.25rem}.nr2-m{margin-right:-.5rem}.nr3-m{margin-right:-1rem}.nr4-m{margin-right:-2rem}.nr5-m{margin-right:-4rem}.nr6-m{margin-right:-8rem}.nr7-m{margin-right:-16rem}.nb1-m{margin-bottom:-.25rem}.nb2-m{margin-bottom:-.5rem}.nb3-m{margin-bottom:-1rem}.nb4-m{margin-bottom:-2rem}.nb5-m{margin-bottom:-4rem}.nb6-m{margin-bottom:-8rem}.nb7-m{margin-bottom:-16rem}.nt1-m{margin-top:-.25rem}.nt2-m{margin-top:-.5rem}.nt3-m{margin-top:-1rem}.nt4-m{margin-top:-2rem}.nt5-m{margin-top:-4rem}.nt6-m{margin-top:-8rem}.nt7-m{margin-top:-16rem}}@media screen and (min-width:60em){.na1-l{margin:-.25rem}.na2-l{margin:-.5rem}.na3-l{margin:-1rem}.na4-l{margin:-2rem}.na5-l{margin:-4rem}.na6-l{margin:-8rem}.na7-l{margin:-16rem}.nl1-l{margin-left:-.25rem}.nl2-l{margin-left:-.5rem}.nl3-l{margin-left:-1rem}.nl4-l{margin-left:-2rem}.nl5-l{margin-left:-4rem}.nl6-l{margin-left:-8rem}.nl7-l{margin-left:-16rem}.nr1-l{margin-right:-.25rem}.nr2-l{margin-right:-.5rem}.nr3-l{margin-right:-1rem}.nr4-l{margin-right:-2rem}.nr5-l{margin-right:-4rem}.nr6-l{margin-right:-8rem}.nr7-l{margin-right:-16rem}.nb1-l{margin-bottom:-.25rem}.nb2-l{margin-bottom:-.5rem}.nb3-l{margin-bottom:-1rem}.nb4-l{margin-bottom:-2rem}.nb5-l{margin-bottom:-4rem}.nb6-l{margin-bottom:-8rem}.nb7-l{margin-bottom:-16rem}.nt1-l{margin-top:-.25rem}.nt2-l{margin-top:-.5rem}.nt3-l{margin-top:-1rem}.nt4-l{margin-top:-2rem}.nt5-l{margin-top:-4rem}.nt6-l{margin-top:-8rem}.nt7-l{margin-top:-16rem}}.collapse{border-collapse:collapse;border-spacing:0}.striped--light-silver:nth-child(odd){background-color:#aaa}.striped--moon-gray:nth-child(odd){background-color:#ccc}.striped--light-gray:nth-child(odd){background-color:#eee}.striped--near-white:nth-child(odd){background-color:#f4f4f4}.stripe-light:nth-child(odd){background-color:rgba(255,255,255,.1)}.stripe-dark:nth-child(odd){background-color:rgba(0,0,0,.1)}.strike{text-decoration:line-through}.underline{text-decoration:underline}.no-underline{text-decoration:none}@media screen and (min-width:30em){.strike-ns{text-decoration:line-through}.underline-ns{text-decoration:underline}.no-underline-ns{text-decoration:none}}@media screen and (min-width:30em) and (max-width:60em){.strike-m{text-decoration:line-through}.underline-m{text-decoration:underline}.no-underline-m{text-decoration:none}}@media screen and (min-width:60em){.strike-l{text-decoration:line-through}.underline-l{text-decoration:underline}.no-underline-l{text-decoration:none}}.tl{text-align:left}.tr{text-align:right}.tc{text-align:center}.tj{text-align:justify}@media screen and (min-width:30em){.tl-ns{text-align:left}.tr-ns{text-align:right}.tc-ns{text-align:center}.tj-ns{text-align:justify}}@media screen and (min-width:30em) and (max-width:60em){.tl-m{text-align:left}.tr-m{text-align:right}.tc-m{text-align:center}.tj-m{text-align:justify}}@media screen and (min-width:60em){.tl-l{text-align:left}.tr-l{text-align:right}.tc-l{text-align:center}.tj-l{text-align:justify}}.ttc{text-transform:capitalize}.ttl{text-transform:lowercase}.ttu{text-transform:uppercase}.ttn{text-transform:none}@media screen and (min-width:30em){.ttc-ns{text-transform:capitalize}.ttl-ns{text-transform:lowercase}.ttu-ns{text-transform:uppercase}.ttn-ns{text-transform:none}}@media screen and (min-width:30em) and (max-width:60em){.ttc-m{text-transform:capitalize}.ttl-m{text-transform:lowercase}.ttu-m{text-transform:uppercase}.ttn-m{text-transform:none}}@media screen and (min-width:60em){.ttc-l{text-transform:capitalize}.ttl-l{text-transform:lowercase}.ttu-l{text-transform:uppercase}.ttn-l{text-transform:none}}.f-6,.f-headline{font-size:6rem}.f-5,.f-subheadline{font-size:5rem}.f1{font-size:3rem}.f2{font-size:2.25rem}.f3{font-size:1.5rem}.f4{font-size:1.25rem}.f5{font-size:1rem}.f6{font-size:.875rem}.f7{font-size:.75rem}@media screen and (min-width:30em){.f-6-ns,.f-headline-ns{font-size:6rem}.f-5-ns,.f-subheadline-ns{font-size:5rem}.f1-ns{font-size:3rem}.f2-ns{font-size:2.25rem}.f3-ns{font-size:1.5rem}.f4-ns{font-size:1.25rem}.f5-ns{font-size:1rem}.f6-ns{font-size:.875rem}.f7-ns{font-size:.75rem}}@media screen and (min-width:30em) and (max-width:60em){.f-6-m,.f-headline-m{font-size:6rem}.f-5-m,.f-subheadline-m{font-size:5rem}.f1-m{font-size:3rem}.f2-m{font-size:2.25rem}.f3-m{font-size:1.5rem}.f4-m{font-size:1.25rem}.f5-m{font-size:1rem}.f6-m{font-size:.875rem}.f7-m{font-size:.75rem}}@media screen and (min-width:60em){.f-6-l,.f-headline-l{font-size:6rem}.f-5-l,.f-subheadline-l{font-size:5rem}.f1-l{font-size:3rem}.f2-l{font-size:2.25rem}.f3-l{font-size:1.5rem}.f4-l{font-size:1.25rem}.f5-l{font-size:1rem}.f6-l{font-size:.875rem}.f7-l{font-size:.75rem}}.measure{max-width:30em}.measure-wide{max-width:34em}.measure-narrow{max-width:20em}.indent{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps{-webkit-font-feature-settings:"c2sc";font-feature-settings:"c2sc";font-variant:small-caps}.truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media screen and (min-width:30em){.measure-ns{max-width:30em}.measure-wide-ns{max-width:34em}.measure-narrow-ns{max-width:20em}.indent-ns{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps-ns{-webkit-font-feature-settings:"c2sc";font-feature-settings:"c2sc";font-variant:small-caps}.truncate-ns{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}@media screen and (min-width:30em) and (max-width:60em){.measure-m{max-width:30em}.measure-wide-m{max-width:34em}.measure-narrow-m{max-width:20em}.indent-m{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps-m{-webkit-font-feature-settings:"c2sc";font-feature-settings:"c2sc";font-variant:small-caps}.truncate-m{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}@media screen and (min-width:60em){.measure-l{max-width:30em}.measure-wide-l{max-width:34em}.measure-narrow-l{max-width:20em}.indent-l{text-indent:1em;margin-top:0;margin-bottom:0}.small-caps-l{-webkit-font-feature-settings:"c2sc";font-feature-settings:"c2sc";font-variant:small-caps}.truncate-l{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}.overflow-container{overflow-y:scroll}.center{margin-right:auto;margin-left:auto}.mr-auto{margin-right:auto}.ml-auto{margin-left:auto}@media screen and (min-width:30em){.center-ns{margin-right:auto;margin-left:auto}.mr-auto-ns{margin-right:auto}.ml-auto-ns{margin-left:auto}}@media screen and (min-width:30em) and (max-width:60em){.center-m{margin-right:auto;margin-left:auto}.mr-auto-m{margin-right:auto}.ml-auto-m{margin-left:auto}}@media screen and (min-width:60em){.center-l{margin-right:auto;margin-left:auto}.mr-auto-l{margin-right:auto}.ml-auto-l{margin-left:auto}}.clip{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}@media screen and (min-width:30em){.clip-ns{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}}@media screen and (min-width:30em) and (max-width:60em){.clip-m{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}}@media screen and (min-width:60em){.clip-l{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}}.ws-normal{white-space:normal}.nowrap{white-space:nowrap}.pre{white-space:pre}@media screen and (min-width:30em){.ws-normal-ns{white-space:normal}.nowrap-ns{white-space:nowrap}.pre-ns{white-space:pre}}@media screen and (min-width:30em) and (max-width:60em){.ws-normal-m{white-space:normal}.nowrap-m{white-space:nowrap}.pre-m{white-space:pre}}@media screen and (min-width:60em){.ws-normal-l{white-space:normal}.nowrap-l{white-space:nowrap}.pre-l{white-space:pre}}.v-base{vertical-align:baseline}.v-mid{vertical-align:middle}.v-top{vertical-align:top}.v-btm{vertical-align:bottom}@media screen and (min-width:30em){.v-base-ns{vertical-align:baseline}.v-mid-ns{vertical-align:middle}.v-top-ns{vertical-align:top}.v-btm-ns{vertical-align:bottom}}@media screen and (min-width:30em) and (max-width:60em){.v-base-m{vertical-align:baseline}.v-mid-m{vertical-align:middle}.v-top-m{vertical-align:top}.v-btm-m{vertical-align:bottom}}@media screen and (min-width:60em){.v-base-l{vertical-align:baseline}.v-mid-l{vertical-align:middle}.v-top-l{vertical-align:top}.v-btm-l{vertical-align:bottom}}.dim{opacity:1;-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.dim:hover,.dim:focus{opacity:.5;-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.dim:active{opacity:.8;-webkit-transition:opacity .15s ease-out;transition:opacity .15s ease-out}.glow{-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.glow:hover,.glow:focus{opacity:1;-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.hide-child .child{opacity:0;-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.hide-child:hover .child,.hide-child:focus .child,.hide-child:active .child{opacity:1;-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.underline-hover:hover,.underline-hover:focus{text-decoration:underline}.grow{-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:-webkit-transform .25s ease-out;transition:-webkit-transform .25s ease-out;transition:transform .25s ease-out;transition:transform .25s ease-out,-webkit-transform .25s ease-out}.grow:hover,.grow:focus{-webkit-transform:scale(1.05);transform:scale(1.05)}.grow:active{-webkit-transform:scale(.90);transform:scale(.90)}.grow-large{-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:-webkit-transform .25s ease-in-out;transition:-webkit-transform .25s ease-in-out;transition:transform .25s ease-in-out;transition:transform .25s ease-in-out,-webkit-transform .25s ease-in-out}.grow-large:hover,.grow-large:focus{-webkit-transform:scale(1.2);transform:scale(1.2)}.grow-large:active{-webkit-transform:scale(.95);transform:scale(.95)}.pointer:hover{cursor:pointer}.shadow-hover{cursor:pointer;position:relative;-webkit-transition:all .5s cubic-bezier(0.165,0.84,0.44,1);transition:all .5s cubic-bezier(0.165,0.84,0.44,1)}.shadow-hover::after{content:'';-webkit-box-shadow:0 0 16px 2px rgba(0,0,0,.2);box-shadow:0 0 16px 2px rgba(0,0,0,.2);border-radius:inherit;opacity:0;position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1;-webkit-transition:opacity .5s cubic-bezier(0.165,0.84,0.44,1);transition:opacity .5s cubic-bezier(0.165,0.84,0.44,1)}.shadow-hover:hover::after,.shadow-hover:focus::after{opacity:1}.bg-animate,.bg-animate:hover,.bg-animate:focus{-webkit-transition:background-color .15s ease-in-out;transition:background-color .15s ease-in-out}.z-0{z-index:0}.z-1{z-index:1}.z-2{z-index:2}.z-3{z-index:3}.z-4{z-index:4}.z-5{z-index:5}.z-999{z-index:999}.z-9999{z-index:9999}.z-max{z-index:2147483647}.z-inherit{z-index:inherit}.z-initial{z-index:auto;z-index:initial}.z-unset{z-index:unset}.nested-copy-line-height p,.nested-copy-line-height ul,.nested-copy-line-height ol{line-height:1.5}.nested-headline-line-height h1,.nested-headline-line-height h2,.nested-headline-line-height h3,.nested-headline-line-height h4,.nested-headline-line-height h5,.nested-headline-line-height h6{line-height:1.25}.nested-list-reset ul,.nested-list-reset ol{padding-left:0;margin-left:0;list-style-type:none}.nested-copy-indent p+p{text-indent:1em;margin-top:0;margin-bottom:0}.nested-copy-separator p+p{margin-top:1.5em}.nested-img img{width:100%;max-width:100%;display:block}.nested-links a{color:#0594cb;-webkit-transition:color .15s ease-in;transition:color .15s ease-in}.nested-links a:hover,.nested-links a:focus{color:#96ccff;-webkit-transition:color .15s ease-in;transition:color .15s ease-in}.header-link:after{position:relative;left:.5em;opacity:0;font-size:.8em;-moz-transition:opacity .2s ease-in-out .1s;-ms-transition:opacity .2s ease-in-out .1s}h2:hover .header-link,h3:hover .header-link,h4:hover .header-link,h5:hover .header-link,h6:hover .header-link{opacity:1}.animated{-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}.animated-delay-1{-webkit-animation-delay:.5s;animation-delay:.5s}.note,.warning{border-left-width:4px;border-left-style:solid;position:relative;border-color:#0594cb;display:block}.note #exclamation-icon,.warning #exclamation-icon{fill:#0594cb;position:absolute;top:35%;left:-12px}.admonition-content{display:block;margin:0;padding:.125em 1em;margin-top:2em;margin-bottom:2em;overflow-x:auto;background-color:rgba(0,0,0,.05)}.hide-child-menu .child-menu{display:none}.hide-child-menu:hover .child-menu,.hide-child-menu:focus .child-menu,.hide-child-menu:active .child-menu{display:block}.documentation-copy h2{margin-top:3em}.documentation-copy h2.minor{font-size:inherit;margin-top:inherit;border-bottom:none}.searchbox{display:inline-block;position:relative;width:200px;height:32px!important;white-space:nowrap;-webkit-box-sizing:border-box;box-sizing:border-box;visibility:visible!important}.searchbox .algolia-autocomplete{display:block;width:100%;height:100%}.searchbox__wrapper{width:100%;height:100%;z-index:999;position:relative}.searchbox__input{display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:background .4s ease,-webkit-box-shadow .4s ease;transition:background .4s ease,-webkit-box-shadow .4s ease;transition:box-shadow .4s ease,background .4s ease;transition:box-shadow .4s ease,background .4s ease,-webkit-box-shadow .4s ease;border:0;border-radius:16px;-webkit-box-shadow:inset 0 0 0 1px #ccc;box-shadow:inset 0 0 0 1px #ccc;background:#fff!important;padding:0 26px 0 32px;width:100%;height:100%;vertical-align:middle;white-space:normal;font-size:12px;-webkit-appearance:none;-moz-appearance:none;appearance:none}.searchbox__input::-webkit-search-cancel-button,.searchbox__input::-webkit-search-decoration,.searchbox__input::-webkit-search-results-button,.searchbox__input::-webkit-search-results-decoration{display:none}.searchbox__input:hover{-webkit-box-shadow:inset 0 0 0 1px #b3b3b3;box-shadow:inset 0 0 0 1px #b3b3b3}.searchbox__input:active,.searchbox__input:focus{outline:0;-webkit-box-shadow:inset 0 0 0 1px #aaa;box-shadow:inset 0 0 0 1px #aaa;background:#fff}.searchbox__input::-webkit-input-placeholder{color:#aaa}.searchbox__input:-ms-input-placeholder{color:#aaa}.searchbox__input::-ms-input-placeholder{color:#aaa}.searchbox__input::placeholder{color:#aaa}.searchbox__submit{position:absolute;top:0;margin:0;border:0;border-radius:16px 0 0 16px;background-color:rgba(69,142,225,0);padding:0;width:32px;height:100%;vertical-align:middle;text-align:center;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;right:inherit;left:0}.searchbox__submit:before{display:inline-block;margin-right:-4px;height:100%;vertical-align:middle;content:""}.searchbox__submit:active,.searchbox__submit:hover{cursor:pointer}.searchbox__submit:focus{outline:0}.searchbox__submit svg{width:14px;height:14px;vertical-align:middle;fill:#6d7e96}.searchbox__reset{display:block;position:absolute;top:8px;right:8px;margin:0;border:0;background:0 0;cursor:pointer;padding:0;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;fill:rgba(0,0,0,.5)}.searchbox__reset.hide{display:none}.searchbox__reset:focus{outline:0}.searchbox__reset svg{display:block;margin:4px;width:8px;height:8px}.searchbox__input:valid~.searchbox__reset{display:block;-webkit-animation-name:sbx-reset-in;animation-name:sbx-reset-in;-webkit-animation-duration:.15s;animation-duration:.15s}@-webkit-keyframes sbx-reset-in{0%{-webkit-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0);opacity:0}to{-webkit-transform:none;transform:none;opacity:1}}@keyframes sbx-reset-in{0%{-webkit-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0);opacity:0}to{-webkit-transform:none;transform:none;opacity:1}}.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu{right:0!important;left:inherit!important}.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu:before{right:48px}.algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu{left:0!important;right:inherit!important}.algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu:before{left:48px}.algolia-autocomplete .ds-dropdown-menu{top:-6px;border-radius:4px;margin:6px 0 0;padding:0;text-align:left;height:auto;position:relative;background:transparent;border:none;z-index:999;max-width:600px;min-width:500px;-webkit-box-shadow:0 1px 0 0 rgba(0,0,0,.2),0 2px 3px 0 rgba(0,0,0,.1);box-shadow:0 1px 0 0 rgba(0,0,0,.2),0 2px 3px 0 rgba(0,0,0,.1)}.algolia-autocomplete .ds-dropdown-menu:before{display:block;position:absolute;content:"";width:14px;height:14px;background:#fff;z-index:1000;top:-7px;border-top:1px solid #d9d9d9;border-right:1px solid #d9d9d9;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);border-radius:2px}.algolia-autocomplete .ds-dropdown-menu .ds-suggestions{position:relative;z-index:1000;margin-top:8px}.algolia-autocomplete .ds-dropdown-menu .ds-suggestions a:hover{text-decoration:none}.algolia-autocomplete .ds-dropdown-menu .ds-suggestion{cursor:pointer}.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion.suggestion-layout-simple,.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion:not(.suggestion-layout-simple) .algolia-docsearch-suggestion--content{background-color:rgba(69,142,225,.05)}.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-]{position:relative;border:1px solid #d9d9d9;background:#fff;border-radius:4px;overflow:auto;padding:0 8px 8px}.algolia-autocomplete .ds-dropdown-menu *{-webkit-box-sizing:border-box;box-sizing:border-box}.algolia-autocomplete .algolia-docsearch-suggestion{display:block;position:relative;padding:0 8px;background:#fff;color:#02060c;overflow:hidden}.algolia-autocomplete .algolia-docsearch-suggestion--highlight{color:#174d8c;background:rgba(143,187,237,.1);padding:.1em .05em}.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl0 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl1 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{padding:0 0 1px;background:inherit;-webkit-box-shadow:inset 0 -2px 0 0 rgba(69,142,225,.8);box-shadow:inset 0 -2px 0 0 rgba(69,142,225,.8);color:inherit}.algolia-autocomplete .algolia-docsearch-suggestion--content{display:block;float:right;width:70%;position:relative;padding:5.33333px 0 5.33333px 10.66667px;cursor:pointer}.algolia-autocomplete .algolia-docsearch-suggestion--content:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ddd;left:-1px}.algolia-autocomplete .algolia-docsearch-suggestion--category-header{position:relative;border-bottom:1px solid #ddd;display:none;margin-top:8px;padding:4px 0;font-size:1em;color:#33363d}.algolia-autocomplete .algolia-docsearch-suggestion--wrapper{width:100%;float:left;padding:8px 0 0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column{float:left;width:30%;text-align:right;position:relative;padding:5.33333px 10.66667px;color:#a4a7ae;font-size:.9em;word-wrap:break-word}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ddd;right:0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-inline{display:none}.algolia-autocomplete .algolia-docsearch-suggestion--title{margin-bottom:4px;color:#02060c;font-size:.9em;font-weight:700}.algolia-autocomplete .algolia-docsearch-suggestion--text{display:block;line-height:1.2em;font-size:.85em;color:#63676d}.algolia-autocomplete .algolia-docsearch-suggestion--no-results{width:100%;padding:8px 0;text-align:center;font-size:1.2em}.algolia-autocomplete .algolia-docsearch-suggestion--no-results:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion code{padding:1px 5px;font-size:90%;border:none;color:#222;background-color:#ebebeb;border-radius:3px;font-family:Menlo,Monaco,Consolas,Courier New,monospace}.algolia-autocomplete .algolia-docsearch-suggestion code .algolia-docsearch-suggestion--highlight{background:0 0}.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--category-header,.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary{display:block}@media(min-width:768px){.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{display:block}}@media(max-width:768px){.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{display:inline-block;width:auto;float:left;padding:0;color:#02060c;font-size:.9em;font-weight:700;text-align:left;opacity:.5}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:after{content:"|"}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content{display:inline-block;width:auto;text-align:left;float:left;padding:0}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content:before{display:none}}.algolia-autocomplete .suggestion-layout-simple.algolia-docsearch-suggestion{border-bottom:1px solid #eee;padding:8px;margin:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content{width:100%;padding:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content:before{display:none}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header{margin:0;padding:0;display:block;width:100%;border:none}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl0,.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1{opacity:.6;font-size:.85em}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1:before{background-image:url(data:image/svg+xml;utf8;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCAyMCAzOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMS40OSA0LjMxbDE0IDE2LjEyNi4wMDItMi42MjQtMTQgMTYuMDc0LTEuMzE0IDEuNTEgMy4wMTcgMi42MjYgMS4zMTMtMS41MDggMTQtMTYuMDc1IDEuMTQyLTEuMzEzLTEuMTQtMS4zMTMtMTQtMTYuMTI1TDMuMi4xOC4xOCAyLjhsMS4zMSAxLjUxeiIgZmlsbC1ydWxlPSJldmVub2RkIiBmaWxsPSIjMWQzNjU3IiAvPjwvc3ZnPg==);content:"";width:10px;height:10px;display:inline-block}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--wrapper{width:100%;float:left;margin:0;padding:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--duplicate-content,.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--subcategory-inline{display:none!important}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title{margin:0;color:#458ee1;font-size:.9em;font-weight:400}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title:before{content:"#";font-weight:700;color:#458ee1;display:inline-block}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text{margin:4px 0 0;display:block;line-height:1.4em;padding:5.33333px 8px;background:#f8f8f8;font-size:.85em;opacity:.8}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{color:#3f4145;font-weight:700;-webkit-box-shadow:none;box-shadow:none}.algolia-autocomplete .algolia-docsearch-footer{width:134px;height:20px;z-index:2000;margin-top:10.66667px;float:right;font-size:0;line-height:0}.algolia-autocomplete .algolia-docsearch-footer--logo{background-image:url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iMTY4IiBoZWlnaHQ9IjI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PHBhdGggZD0iTTc4Ljk4OC45MzhoMTYuNTk0YTIuOTY4IDIuOTY4LjAgMCAxIDIuOTY2IDIuOTY2VjIwLjVhMi45NjcgMi45NjcuMCAwIDEtMi45NjYgMi45NjRINzguOTg4YTIuOTY3IDIuOTY3LjAgMCAxLTIuOTY2LTIuOTY0VjMuODk3QTIuOTYxIDIuOTYxLjAgMCAxIDc4Ljk4OC45Mzh6bTQxLjkzNyAxNy44NjZjLTQuMzg2LjAyLTQuMzg2LTMuNTQtNC4zODYtNC4xMDZsLS4wMDctMTMuMzM2IDIuNjc1LS40MjR2MTMuMjU0YzAgLjMyMi4wIDIuMzU4IDEuNzE4IDIuMzY0djIuMjQ4em0tMTAuODQ2LTIuMThjLjgyMS4wIDEuNDMtLjA0NyAxLjg1NS0uMTI5di0yLjcxOWE2LjMzNCA2LjMzNC4wIDAgMC0xLjU3NC0uMTk5IDUuNyA1LjcuMCAwIDAtLjg5Ny4wNjkgMi42OTkgMi42OTkuMCAwIDAtLjgxNC4yNGMtLjI0LjExNi0uNDM5LjI4LS41ODIuNDkxLS4xNS4yMTItLjIxOS4zMzUtLjIxOS42NTYuMC42MjguMjE5Ljk5MS42MTYgMS4yM3MuOTM4LjM2MiAxLjYxNS4zNjJ6bS0uMjMzLTkuN2MuODgzLjAgMS42MjkuMTA5IDIuMjMxLjMyOC42MDIuMjE4IDEuMDg4LjUyNSAxLjQ0NC45MTUuMzYzLjM5Ni42MDkuOTIyLjc2IDEuNDgzLjE1Ny41Ni4yMzIgMS4xNzUuMjMyIDEuODV2Ni44NzRhMzIuNSAzMi41LjAgMCAxLTEuODY4LjMxNGMtLjgzNC4xMjMtMS43NzIuMTg1LTIuODEzLjE4NS0uNjkuMC0xLjMyNy0uMDY5LTEuODk1LS4xOThhNC4wMDEgNC4wMDEuMCAwIDEtMS40NzEtLjYzNiAzLjA4NSAzLjA4NS4wIDAgMS0uOTUxLTEuMTM0Yy0uMjI2LS40NjUtLjM0My0xLjEyLS4zNDMtMS44MDMuMC0uNjU2LjEzLTEuMDczLjM4NC0xLjUyNWEzLjI0IDMuMjQuMCAwIDEgMS4wNDctMS4xMDZjLjQ0NS0uMjg3Ljk1LS40OTIgMS41MzItLjYxNWE4LjggOC44LjAgMCAxIDEuODItLjE4NSA4LjQwNCA4LjQwNC4wIDAgMSAxLjk3Mi4yNHYtLjQzOGMwLS4zMDctLjAzNS0uNi0uMTEtLjg3NGExLjg4IDEuODguMCAwIDAtLjM4NC0uNzMgMS43ODQgMS43ODQuMCAwIDAtLjcyNC0uNDkzIDMuMTY0IDMuMTY0LjAgMCAwLTEuMTQzLS4yMDVjLS42MTYuMC0xLjE3Ny4wNzUtMS42OS4xNjRhNy43MzUgNy43MzUuMCAwIDAtMS4yNi4zMDdsLS4zMjEtMi4xOTJjLjMzNS0uMTE3LjgzNC0uMjMzIDEuNDc4LS4zNDlhMTAuOTggMTAuOTguMCAwIDEgMi4wNzMtLjE3OHptNTIuODQyIDkuNjI2Yy44MjIuMCAxLjQzLS4wNDggMS44NTQtLjEzVjEzLjdhNi4zNDcgNi4zNDcuMCAwIDAtMS41NzQtLjE5OWMtLjI5NC4wLS41OTUuMDIxLS44OTYuMDY5YTIuNyAyLjcuMCAwIDAtLjgxNC4yNCAxLjQ2IDEuNDYuMCAwIDAtLjU4Mi40OTFjLS4xNS4yMTItLjIxOC4zMzUtLjIxOC42NTYuMC42MjguMjE4Ljk5MS42MTUgMS4yMy40MDQuMjQ1LjkzOC4zNjIgMS42MTUuMzYyem0tLjIyNi05LjY5NGMuODgzLjAgMS42MjkuMTA4IDIuMjMxLjMyNy42MDIuMjE5IDEuMDg4LjUyNiAxLjQ0NC45MTUuMzU1LjM5LjYwOS45MjMuNzU5IDEuNDgzYTYuOCA2LjguMCAwIDEgLjIzMyAxLjg1MnY2Ljg3M2MtLjQxLjA4OC0xLjAzNC4xOS0xLjg2OC4zMTQtLjgzNC4xMjMtMS43NzIuMTg0LTIuODEzLjE4NC0uNjkuMC0xLjMyNy0uMDY4LTEuODk1LS4xOThhNC4wMDEgNC4wMDEuMCAwIDEtMS40NzEtLjYzNSAzLjA4NSAzLjA4NS4wIDAgMS0uOTUxLTEuMTM0Yy0uMjI2LS40NjUtLjM0My0xLjEyLS4zNDMtMS44MDQuMC0uNjU2LjEzLTEuMDczLjM4NC0xLjUyNC4yNi0uNDUuNjA4LS44MiAxLjA0Ny0xLjEwNy40NDUtLjI4Ni45NS0uNDkxIDEuNTMyLS42MTRhOC44MDMgOC44MDMuMCAwIDEgMi43NTEtLjEzYy4zMjkuMDM0LjY3MS4wOTYgMS4wNC4xODV2LS40MzdhMy4zIDMuMy4wIDAgMC0uMTA5LS44NzUgMS44NzMgMS44NzMuMCAwIDAtLjM4NC0uNzMxIDEuNzg0IDEuNzg0LjAgMCAwLS43MjQtLjQ5MiAzLjE2NSAzLjE2NS4wIDAgMC0xLjE0My0uMjA1Yy0uNjE2LjAtMS4xNzcuMDc1LTEuNjkuMTY0YTcuNzUgNy43NS4wIDAgMC0xLjI2LjMwN2wtLjMyMS0yLjE5M2MuMzM1LS4xMTYuODM0LS4yMzIgMS40NzgtLjM0OGExMS42MzMgMTEuNjMzLjAgMCAxIDIuMDczLS4xNzd6bS04LjAzNC0xLjI3MWExLjYyNiAxLjYyNi4wIDAgMS0xLjYyOC0xLjYyYzAtLjg5NS43MjUtMS42MiAxLjYyOC0xLjYyLjkwNC4wIDEuNjMuNzI1IDEuNjMgMS42Mi4wLjg5NS0uNzMzIDEuNjItMS42MyAxLjYyem0xLjM0OCAxMy4yMmgtMi42ODlWNy4yN2wyLjY5LS40MjN2MTEuOTU2em0tNC43MTQuMGMtNC4zODYuMDItNC4zODYtMy41NC00LjM4Ni00LjEwN2wtLjAwOC0xMy4zMzYgMi42NzYtLjQyNHYxMy4yNTRjMCAuMzIyLjAgMi4zNTggMS43MTggMi4zNjR2Mi4yNDh6bS04LjY5OC01LjkwM2MwLTEuMTU2LS4yNTMtMi4xMTktLjc0Ni0yLjc4OC0uNDkzLS42NzctMS4xODMtMS4wMS0yLjA2Ny0xLjAxLS44ODIuMC0xLjU3NC4zMzMtMi4wNjUgMS4wMS0uNDkzLjY3Ni0uNzMzIDEuNjMyLS43MzMgMi43ODguMCAxLjE2OC4yNDYgMS45NTMuNzQgMi42My40OTIuNjgzIDEuMTgzIDEuMDE4IDIuMDY2IDEuMDE4Ljg4Mi4wIDEuNTc0LS4zNDIgMi4wNjctMS4wMTkuNDkyLS42ODMuNzM4LTEuNDYuNzM4LTIuNjN6bTIuNzM3LS4wMDdjMCAuOTAyLS4xMyAxLjU4NC0uMzk3IDIuMzNhNS41MiA1LjUyLjAgMCAxLTEuMTI4IDEuOTA2IDQuOTg2IDQuOTg2LjAgMCAxLTEuNzUyIDEuMjIzYy0uNjg1LjI4Ni0xLjczOS40NS0yLjI2NS40NS0uNTI4LS4wMDYtMS41NzQtLjE1Ny0yLjI1Mi0uNDVhNS4wOTYgNS4wOTYuMCAwIDEtMS43NDQtMS4yMjNjLS40ODctLjUyNy0uODYzLTEuMTYyLTEuMTM3LTEuOTA2YTYuMzQ1IDYuMzQ1LjAgMCAxLS40MS0yLjMzYzAtLjkwMi4xMjMtMS43Ny4zOTctMi41MDhhNS41NTQgNS41NTQuMCAwIDEgMS4xNS0xLjg5MiA1LjEzMyA1LjEzMy4wIDAgMSAxLjc1LTEuMjE2Yy42NzktLjI4NyAxLjQyNS0uNDIzIDIuMjMyLS40MjMuODA4LjAgMS41NTMuMTQyIDIuMjM3LjQyM2E0Ljg4IDQuODguMCAwIDEgMS43NTMgMS4yMTYgNS42NDQgNS42NDQuMCAwIDEgMS4xMzUgMS44OTJjLjI4Ny43MzguNDMxIDEuNjA2LjQzMSAyLjUwOHptLTIwLjEzOC4wYzAgMS4xMi4yNDYgMi4zNjMuNzM4IDIuODgyLjQ5My41MiAxLjEzLjc4IDEuOTEuNzguNDI0LjAuODI4LS4wNjIgMS4yMDQtLjE3OC4zNzctLjExNi42NzctLjI1My45MTctLjQxN1Y5LjMzYTEwLjQ3NiAxMC40NzYuMCAwIDAtMS43NjYtLjIyNmMtLjk3MS0uMDI4LTEuNzEuMzctMi4yMyAxLjAwNC0uNTEzLjYzNi0uNzczIDEuNzUtLjc3MyAyLjc4OHptNy40MzggNS4yNzRjMCAxLjgyNC0uNDY2IDMuMTU2LTEuNDA0IDQuMDA0LS45MzYuODQ2LTIuMzY3IDEuMjctNC4yOTYgMS4yNy0uNzA1LjAtMi4xNy0uMTM3LTMuMzQtLjM5NmwuNDMxLTIuMTE4Yy45OC4yMDUgMi4yNzIuMjYgMi45NS4yNiAxLjA3NC4wIDEuODQtLjIxOSAyLjI5OS0uNjU2LjQ1OS0uNDM3LjY4NC0xLjA4Ni42ODQtMS45NDh2LS40MzdhOC4wNyA4LjA3LjAgMCAxLTEuMDQ3LjM5N2MtLjQzLjEzLS45My4xOTgtMS40OTIuMTk4LS43MzkuMC0xLjQxLS4xMTYtMi4wMTgtLjM0OWE0LjIwNiA0LjIwNi4wIDAgMS0xLjU2Ny0xLjAyNWMtLjQzMS0uNDUtLjc3NC0xLjAxNy0xLjAxMy0xLjY5NC0uMjQtLjY3Ny0uMzYzLTEuODg1LS4zNjMtMi43NzMuMC0uODM0LjEzLTEuODguMzg0LTIuNTc3LjI2LS42OTYuNjI5LTEuMjk4IDEuMTI5LTEuNzk2LjQ5My0uNDk4IDEuMDk1LS44ODEgMS44LTEuMTYyYTYuNjA1IDYuNjA1LjAgMCAxIDIuNDI4LS40NTdjLjg3LjAgMS42Ny4xMDkgMi40NS4yNC43OC4xMjkgMS40NDQuMjY1IDEuOTg1LjQxNVYxOC4xN3oiIGZpbGw9IiM1NDY4ZmYiLz48cGF0aCBkPSJNNi45NzIgNi42Nzd2MS42MjdjLS43MTItLjQ0Ni0xLjUyLS42Ny0yLjQyNS0uNjctLjU4NS4wLTEuMDQ1LjEzLTEuMzguMzkxYTEuMjQgMS4yNC4wIDAgMC0uNTAyIDEuMDNjMCAuNDI1LjE2NC43NjUuNDk0IDEuMDIuMzMuMjU2LjgzNS41MzIgMS41MTYuODMuNDQ3LjE5Mi43OTUuMzU2IDEuMDQ1LjQ5NS4yNS4xMzguNTM3LjMzMi44NjIuNTgyLjMyNC4yNS41NjMuNTQ4LjcxOC44OTQuMTU0LjM0NS4yMy43NDEuMjMgMS4xODguMC45NDctLjMzNCAxLjY5MS0xLjAwNCAyLjIzNC0uNjcuNTQyLTEuNTM3LjgxNC0yLjYwMS44MTQtMS4xOC4wLTIuMTYtLjIyOS0yLjkzNi0uNjg2di0xLjcwOGMuODQuNjI4IDEuODE0Ljk0MiAyLjkyLjk0Mi41ODUuMCAxLjA0OC0uMTM2IDEuMzg4LS40MDcuMzQtLjI3MS41MS0uNjQ2LjUxLTEuMTI1LjAtLjI4Ny0uMS0uNTUtLjMwMi0uNzktLjIwMy0uMjQtLjQyLS40Mi0uNjU1LS41NDItLjIzNC0uMTIzLS41ODUtLjI5LTEuMDUzLS41MDNhNjEuMjcgNjEuMjcuMCAwIDEtLjU4Mi0uMjcxIDEzLjY3IDEzLjY3LjAgMCAxLS41NS0uMjg3IDQuMjc1IDQuMjc1LjAgMCAxLS41NjctLjM1MSA2LjkyIDYuOTIuMCAwIDEtLjQ1NS0uNGMtLjE4LS4xNy0uMzEtLjM0LS4zOS0uNTEtLjA4LS4xNy0uMTU1LS4zNy0uMjI0LS41OThhMi41NTMgMi41NTMuMCAwIDEtLjEwNC0uNzQyYzAtLjkxNS4zMzMtMS42MzguOTk4LTIuMTcuNjY0LS41MzIgMS41MjMtLjc5OCAyLjU3Ni0uNzk4Ljk2OC4wIDEuNzkzLjE3IDIuNDczLjUxem03LjQ2OCA1LjY5NnYtLjI4N2MtLjAyMi0uNjA3LS4xODctMS4wODgtLjQ5NS0xLjQ0NC0uMzA5LS4zNTctLjc1LS41MzUtMS4zMjQtLjUzNS0uNTMyLjAtLjk5LjE5NC0xLjM3My41ODMtLjM4Mi4zODgtLjYyMi45NDktLjcxNyAxLjY4M2gzLjkwOXptMS4wMDUgMi43OTJ2MS40MDRjLS41OTYuMzQtMS4zODMuNTEtMi4zNjIuNTEtMS4yNTUuMC0yLjI1NS0uMzc3LTMtMS4xMzItLjc0NC0uNzU1LTEuMTE2LTEuNzQ0LTEuMTE2LTIuOTY4LjAtMS4yOTcuMzQtMi4zMTYgMS4wMjEtMy4wNTUuNjgtLjc0IDEuNTQ4LTEuMTEgMi42LTEuMTEgMS4wMzMuMCAxLjg1Mi4zMjMgMi40NTguOTY2LjYwNi42NDQuOTEgMS41NzIuOTEgMi43ODQuMC4zMy0uMDMzLjY3Ni0uMDk2IDEuMDM4aC01LjMxNGMuMTA3LjcwMi40MDUgMS4yMzkuODk0IDEuNjExLjQ5LjM3MiAxLjEwNi41NTggMS44NS41NTguODYyLjAgMS41OC0uMjAyIDIuMTU1LS42MDZ6bTYuNjA1LTEuNzdoLTEuMjEyYy0uNTk2LjAtMS4wNDUuMTE2LTEuMzQ5LjM1LS4zMDMuMjM0LS40NTQuNTMyLS40NTQuODk0LjAuMzcyLjExNy42NjQuMzUuODc3LjIzNS4yMTMuNTc1LjMyIDEuMDIyLjMyLjUxLjAuOTEyLS4xNDIgMS4yMDQtLjQyNC4yOTMtLjI4MS40NC0uNjUxLjQ0LTEuMTA4di0uOTF6bS00LjA2OC0yLjU1NFY5LjMyNWMuNjI3LS4zNjEgMS40NTctLjU0MiAyLjQ4OS0uNTQyIDIuMTE2LjAgMy4xNzUgMS4wMjYgMy4xNzUgMy4wOFYxN2gtMS41NDh2LS45NTdjLS40MTUuNjgtMS4xNDMgMS4wMi0yLjE4NiAxLjAyLS43NjYuMC0xLjM4LS4yMi0xLjg0My0uNjYxLS40NjItLjQ0Mi0uNjk0LTEuMDAzLS42OTQtMS42ODQuMC0uNzc2LjI5My0xLjM4Ljg3OC0xLjgxLjU4NS0uNDMxIDEuNDA0LS42NDcgMi40NTctLjY0N2gxLjM0VjExLjhjMC0uNTU0LS4xMzMtLjk3MS0uMzk5LTEuMjUzLS4yNjYtLjI4Mi0uNzA3LS40MjMtMS4zMjQtLjQyM2E0LjA3IDQuMDcuMCAwIDAtMi4zNDUuNzE4em05LjMzMy0xLjkzdjEuNDJjLjM5NC0xIDEuMTAxLTEuNSAyLjEyMy0xLjUuMTQ4LjAuMzEzLjAxNi40OTQuMDQ4djEuNTMxYTEuODg1IDEuODg1LjAgMCAwLS43NS0uMTQzYy0uNTQyLjAtLjk4OS4yNC0xLjM0LjcxOC0uMzUxLjQ3OS0uNTI3IDEuMDQ4LS41MjcgMS43MDdWMTdoLTEuNTYzVjguOTFoMS41NjN6bTUuMDEgNC4wODRjLjAyMi44Mi4yNzIgMS40OTIuNzUgMi4wMTkuNDc5LjUyNiAxLjE1Ljc5IDIuMDEuNzkuNjM5LjAgMS4yMzUtLjE3NiAxLjc4OC0uNTI3djEuNDA0Yy0uNTIxLjMxOS0xLjE4Ni40NzktMS45OTUuNDc5LTEuMjY1LjAtMi4yNzYtLjQtMy4wMzEtMS4xOTctLjc1NS0uNzk4LTEuMTMzLTEuNzkyLTEuMTMzLTIuOTg0LjAtMS4xNi4zOC0yLjE1MSAxLjE0LTIuOTc1Ljc2MS0uODI1IDEuNzktMS4yMzcgMy4wODgtMS4yMzcuNzAyLjAgMS4zNDYuMTQ5IDEuOTMuNDQ3djEuNDM2YTMuMjQyIDMuMjQyLjAgMCAwLTEuNzctLjQ5NWMtLjg0LjAtMS41MTMuMjY2LTIuMDE5Ljc5OC0uNTA1LjUzMi0uNzU4IDEuMjEzLS43NTggMi4wNDJ6TTQwLjI0IDUuNzJ2NC41NzljLjQ1OC0xIDEuMjkzLTEuNSAyLjUwNS0xLjUuNzg3LjAgMS40Mi4yNDUgMS44OTkuNzM0LjQ3OS40OS43MTggMS4xNy43MTggMi4wNDJWMTdoLTEuNTY0di01LjEwNmMwLS41NTMtLjE0LS45OC0uNDIyLTEuMjg0LS4yODItLjMwMy0uNjUyLS40NTUtMS4xMS0uNDU1LS41MzEuMC0xLjAwMi4yMDItMS40MTEuNjA2LS40MS40MDUtLjYxNSAxLjAyMi0uNjE1IDEuODUxVjE3aC0xLjU2M1Y1LjcyaDEuNTYzem0xNC45NjYgMTAuMDJjLjU5Ni4wIDEuMDk2LS4yNTMgMS41LS43NTguNDA0LS41MDYuNjA2LTEuMTU3LjYwNi0xLjk1NS4wLS45MTUtLjIwMi0xLjYyLS42MDYtMi4xMTQtLjQwNC0uNDk1LS45Mi0uNzQyLTEuNTQ4LS43NDItLjU1My4wLTEuMDUuMjI0LTEuNDkxLjY3LS40NDIuNDQ3LS42NjIgMS4xMzMtLjY2MiAyLjA1OC4wLjk1OC4yMTIgMS42Ny42MzggMi4xMzguNDI1LjQ2OS45NDYuNzAzIDEuNTYzLjcwM3pNNTMuMDA0IDUuNzJ2NC40MmMuNTc0LS44OTQgMS4zODgtMS4zNDEgMi40NC0xLjM0MSAxLjAyMi4wIDEuODU3LjM4MyAyLjUwNiAxLjE0OS42NDkuNzY2Ljk3MyAxLjc4MS45NzMgMy4wNDcuMCAxLjEzOC0uMzA5IDIuMTA5LS45MjUgMi45MTItLjYxNy44MDMtMS40NjMgMS4yMDUtMi41MzcgMS4yMDUtMS4wNzUuMC0xLjg5NC0uNDQ3LTIuNDU3LTEuMzRWMTdoLTEuNThWNS43MmgxLjU4em05LjkwOCAxMS4xMDQtMy4yMjMtNy45MTNoMS43MzlsMS4wMDUgMi42MzIgMS4yNiAzLjQxNWMuMDk2LS4zMi40OC0xLjQ1OCAxLjE1LTMuNDE1bC45MDktMi42MzJoMS42NmwtMi45MiA3Ljg2NmMtLjc3NyAyLjA3NC0xLjk2MyAzLjExLTMuNTU5IDMuMTFhMi45MiAyLjkyLjAgMCAxLS43MzQtLjA3OXYtMS4zNGMuMTcuMDQyLjM1MS4wNjQuNTQzLjA2NCAxLjAzMi4wIDEuNzU1LS41NyAyLjE3LTEuNzA4eiIgZmlsbD0iIzVkNjQ5NCIvPjxwYXRoIGQ9Ik04OS42MzIgNS45Njd2LS43NzJhLjk3OC45NzguMCAwIDAtLjk3OC0uOTc3aC0yLjI4YS45NzguOTc4LjAgMCAwLS45NzguOTc3di43OTNjMCAuMDg4LjA4Mi4xNS4xNzEuMTNhNy4xMjcgNy4xMjcuMCAwIDEgMS45ODQtLjI4Yy42NS4wIDEuMjk1LjA4OCAxLjkxNy4yNTkuMDgyLjAyLjE2NC0uMDQuMTY0LS4xM20tNi4yNDggMS4wMS0uMzktLjM4OWEuOTc3Ljk3Ny4wIDAgMC0xLjM4Mi4wbC0uNDY1LjQ2NWEuOTczLjk3My4wIDAgMCAwIDEuMzhsLjM4My4zODNjLjA2Mi4wNjEuMTUuMDQ3LjIwNS0uMDE0LjIyNi0uMzA3LjQ3Mi0uNjAxLjc0Ni0uODc0LjI4MS0uMjguNTY4LS41MjYuODgzLS43NTEuMDY4LS4wNDIuMDc1LS4xMzcuMDItLjJtNC4xNiAyLjQ1M3YzLjM0MWMwIC4wOTYuMTA0LjE2NS4xOTIuMTE3bDIuOTctMS41MzdjLjA2OC0uMDM0LjA4OS0uMTE3LjA1NS0uMTg0YTMuNjk1IDMuNjk1LjAgMCAwLTMuMDgtMS44NjZjLS4wNjguMC0uMTM2LjA1NC0uMTM2LjEzbTAgOC4wNDhhNC40ODkgNC40ODkuMCAwIDEtNC40OS00LjQ4MiA0LjQ4OCA0LjQ4OC4wIDAgMSA0LjQ5LTQuNDgyIDQuNDg4IDQuNDg4LjAgMCAxIDQuNDg5IDQuNDgyIDQuNDg0IDQuNDg0LjAgMCAxLTQuNDkgNC40ODJtMC0xMC44NWE2LjM2MyA2LjM2My4wIDEgMCAwIDEyLjcyOSA2LjM3IDYuMzcuMCAwIDAgNi4zNzItNi4zNjggNi4zNTggNi4zNTguMCAwIDAtNi4zNzEtNi4zNiIgZmlsbD0iI2ZmZiIvPjwvZz48L3N2Zz4=);background-repeat:no-repeat;background-position:50%;background-size:100%;overflow:hidden;text-indent:-9000px;padding:0!important;width:100%;height:100%;display:block}.overflow-x-scroll{-webkit-overflow-scrolling:touch}.row{-webkit-transition:450ms -webkit-transform;transition:450ms -webkit-transform;transition:450ms transform;transition:450ms transform,450ms -webkit-transform;font-size:0}.tile{-webkit-transition:450ms all;transition:450ms all}.details{background:-webkit-gradient(linear,left bottom,left top,from(rgba(0,0,0,.9)),to(rgba(0,0,0,0)));background:linear-gradient(to top,rgba(0,0,0,.9) 0%,rgba(0,0,0,0) 100%);-webkit-transition:450ms opacity;transition:450ms opacity}.tile:hover .details{opacity:1}.row:hover .tile{opacity:.3}.row:hover .tile:hover{opacity:1}.chroma .lntable pre{padding:0;margin:0;border:0}.chroma .lntable pre code{padding:0;margin:0}pre,.pre{overflow-x:auto;overflow-y:hidden;overflow:scroll}code{padding:.2em;margin:0;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}pre code{display:block;padding:1.5em;font-size:.875rem;line-height:2;overflow-x:auto}pre{background-color:#fff;color:#333;white-space:pre;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none;position:relative;border-width:1px;border-color:#ccc;border-style:solid}.highlight pre{background-color:inherit;color:inherit;padding:.5em;font-size:.875rem}.copy:after{content:"Copy"}.copied:after{content:"Copied"}@media screen and (min-width:60em){.full-width,pre.expand:hover{margin-right:-30vw;max-width:100vw}}.code-block .line-numbers-rows{background:#2f3a46;border:none;bottom:-50px;color:#98a4b3;left:-178px;padding:50px 0;top:-50px;width:138px}.code-block .line-numbers-rows>span:before{color:inherit;padding-right:30px}.tab-button{margin-bottom:1px;position:relative;z-index:1;color:#333;border-color:#ccc;outline:none;background-color:#fff}.tab-pane code{background:#f1f2f2;border-radius:0}.tab-pane .chroma{background:0 0;padding:0}.tab-button.active{border-bottom-color:#f1f2f2;background-color:#f1f2f2}.tab-content .tab-pane{display:none}.tab-content .tab-pane.active{display:block}.tab-content .copy,.tab-content .copied{display:none}.tab-content .tab-pane.active+.copy,.tab-content .tab-pane.active+.copied{display:block}.primary-color{color:#0594cb}.bg-primary-color{background-color:#0594cb}.hover-bg-primary-color:hover{background-color:#0594cb}.primary-color-dark{color:#0a1922}.bg-primary-color-dark{background-color:#0a1922}.hover-bg-primary-color-dark:hover{background-color:#0a1922}.primary-color-light{color:#f9f9f9}.bg-primary-color-light{background-color:#f9f9f9}.hover-bg-primary-color-light:hover{background-color:#f9f9f9}.accent-color{color:#ebb951}.bg-accent-color{background-color:#ebb951}.hover-bg-accent-color:hover{background-color:#ebb951}.accent-color-light{color:#ff4088}.hover-accent-color-light:hover{color:#ff4088}.bg-accent-color-light{background-color:#ff4088}.hover-bg-accent-color-light:hover{background-color:#ff4088}.accent-color-dark{color:#33ba91}.bg-accent-color-dark{background-color:#33ba91}.hover-bg-accent-color-dark:hover{background-color:#33ba91}.text-color-primary{color:#373737}.text-on-primary-color{color:#fff}.text-color-secondary{color:#ccc}.text-color-disabled{color:#f7f7f7}.divider-color{color:#f6f6f6}.warn-color{color:red}.nested-links a{color:#0594cb;text-decoration:none}.column-count-2{-webkit-column-count:1;column-count:1}.column-gap-1{-webkit-column-gap:0;column-gap:0}.break-inside-avoid{-webkit-column-break-inside:auto;break-inside:auto}@media screen and (min-width:60em){.column-count-3-l{-webkit-column-count:3;column-count:3}.column-count-2-l{-webkit-column-count:2;column-count:2}.column-gap-1-l{-webkit-column-gap:1;column-gap:1}.break-inside-avoid-l{-webkit-column-break-inside:avoid;break-inside:avoid}}.prose ul,.prose ol{margin-bottom:2em}.prose ul li,.prose ol li{margin-bottom:.5em}.prose li:hover{background-color:#eee}.prose ::selection{background:#0594cb;color:#fff}body{line-height:1.45}p{margin-bottom:1.3em}h1,h2,h3,h4{margin:1.414em 0 .5em;line-height:1.2}h1{margin-top:0;font-size:2.441em}h2{font-size:1.953em}h3{font-size:1.563em}h4{font-size:1.25em}small,.font_small{font-size:.8em}.prose table{width:100%;margin-bottom:3em;border-collapse:collapse;border-spacing:0;font-size:1em;border:1px solid #eee}.prose table th{background-color:#0594cb;border-bottom:1px solid #0594cb;color:#fff;font-weight:400;text-align:left;padding:.375em .5em}.prose table td,.prose table tc{padding:.75em .5em;text-align:left;border-right:1px solid #eee}.prose table tr:nth-child(even){background-color:#eee}dl dt{font-weight:700;font-size:1.125rem}dd{margin:.5em 0 2em;padding:0}.f2-fluid{font-size:2.25rem}@media screen and (min-width:60em){.f2-fluid{font-size:1.25rem;font-size:calc(0.70833rem + 0.83333vw)}}code,.code,pre code,.highlight pre{font-family:inconsolata,Menlo,Monaco,courier new,monospace}.sans-serif{font-family:muli,avenir,helvetica neue,helvetica,ubuntu,roboto,noto,segoe ui,arial,sans-serif}.serif{font-family:Palatino,palatino linotype,palatino lt std,book antiqua,Georgia,serif}.courier{font-family:courier next,courier,monospace}.helvetica{font-family:helvetica neue,helvetica,sans-serif}.avenir{font-family:avenir next,avenir,sans-serif}.athelas{font-family:athelas,georgia,serif}.georgia{font-family:georgia,serif}.times{font-family:times,serif}.bodoni{font-family:bodoni mt,serif}.calisto{font-family:calisto mt,serif}.garamond{font-family:garamond,serif}.baskerville{font-family:baskerville,serif}.pagination{margin:3rem 0}.pagination li{display:inline-block;margin-right:.375rem;font-size:.875rem;margin-bottom:2.5em}.pagination li a{padding:.5rem .625rem;background-color:#fff;color:#333;border:1px solid #ddd;border-radius:3px;text-decoration:none}.pagination li.disabled{display:none}.pagination li.active a:link,.pagination li.active a:active,.pagination li.active a:visited{background-color:#ddd}#TableOfContents ul li ul li ul li{display:none}#TableOfContents ul li{color:#000;display:block;margin-bottom:.375em;line-height:1.375}#TableOfContents ul li a{width:100%;padding:.25em .375em;margin-left:-.375em}#TableOfContents ul li a:hover{background-color:#999;color:#fff}.no-js .needs-js{opacity:0}.js .needs-js{opacity:1;-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.facebook,.twitter,.instagram,.youtube{fill:#bababa}.facebook:hover{fill:#3b5998}.twitter{fill:#55acee}.twitter:hover{fill:#bababa}.instagram:hover{fill:#e95950}.youtube:hover{fill:#b00}@media(min-width:75em){[data-scrolldir=down] .sticky{position:fixed;top:100px;right:0}[data-scrolldir=up] .sticky{position:fixed;top:100px;right:0}}.fill-current{fill:currentColor}.chroma{background-color:#fff}.chroma .err{color:#a61717;background-color:#e3d2d2}.chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.chroma .hl{display:block;width:100%;background-color:#ffc}.chroma .lnt{margin-right:.4em;padding:0 .4em}.chroma .ln{margin-right:.4em;padding:0 .4em}.chroma .k{font-weight:700}.chroma .kc{font-weight:700}.chroma .kd{font-weight:700}.chroma .kn{font-weight:700}.chroma .kp{font-weight:700}.chroma .kr{font-weight:700}.chroma .kt{color:#458;font-weight:700}.chroma .na{color:teal}.chroma .nb{color:#999}.chroma .nc{color:#458;font-weight:700}.chroma .no{color:teal}.chroma .ni{color:purple}.chroma .ne{color:#900;font-weight:700}.chroma .nf{color:#900;font-weight:700}.chroma .nn{color:#555}.chroma .nt{color:navy}.chroma .nv{color:teal}.chroma .s{color:#b84}.chroma .sa{color:#b84}.chroma .sb{color:#b84}.chroma .sc{color:#b84}.chroma .dl{color:#b84}.chroma .sd{color:#b84}.chroma .s2{color:#b84}.chroma .se{color:#b84}.chroma .sh{color:#b84}.chroma .si{color:#b84}.chroma .sx{color:#b84}.chroma .sr{color:olive}.chroma .s1{color:#b84}.chroma .ss{color:#b84}.chroma .m{color:#099}.chroma .mb{color:#099}.chroma .mf{color:#099}.chroma .mh{color:#099}.chroma .mi{color:#099}.chroma .il{color:#099}.chroma .mo{color:#099}.chroma .o{font-weight:700}.chroma .ow{font-weight:700}.chroma .c{color:#998;font-style:italic}.chroma .ch{color:#998;font-style:italic}.chroma .cm{color:#998;font-style:italic}.chroma .c1{color:#998;font-style:italic}.chroma .cs{color:#999;font-weight:700;font-style:italic}.chroma .cp{color:#999;font-weight:700}.chroma .cpf{color:#999;font-weight:700}.chroma .gd{color:#000;background-color:#fdd}.chroma .ge{font-style:italic}.chroma .gr{color:#a00}.chroma .gh{color:#999}.chroma .gi{color:#000;background-color:#dfd}.chroma .go{color:#888}.chroma .gp{color:#555}.chroma .gs{font-weight:700}.chroma .gu{color:#aaa}.chroma .gt{color:#a00}.chroma .w{color:#bbb}.nested-blockquote blockquote{border-left:4px solid #0594cb;padding-left:1em}.mw-90{max-width:90%}hugo-0.92.2/docs/resources/_gen/assets/css/output/css/app.css_d11fe7b62c27961c87ecd0f2490357b9.json000066400000000000000000000003061420147000300314640ustar00rootroot00000000000000{"Target":"output/css/app.min.2ac9b5935f7ff7709fe13c2b042a4a2d49fa96fb508e3e8870019ee9b72cf329.css","MediaType":"text/css","Data":{"Integrity":"sha256-Ksm1k19/93Cf4TwrBCpKLUn6lvtQjj6IcAGe6bcs8yk="}}hugo-0.92.2/docs/resources/_gen/assets/js/000077500000000000000000000000001420147000300203255ustar00rootroot00000000000000hugo-0.92.2/docs/resources/_gen/assets/js/output/000077500000000000000000000000001420147000300216655ustar00rootroot00000000000000hugo-0.92.2/docs/resources/_gen/assets/js/output/js/000077500000000000000000000000001420147000300223015ustar00rootroot00000000000000hugo-0.92.2/docs/resources/_gen/assets/js/output/js/app.js_8848f55d07695b7ff7188138f23d69e3.content000066400000000000000000004734541420147000300313220ustar00rootroot00000000000000!function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([function(e,t,n){!function(t,n){var r=function(e,t){"use strict";if(!t.getElementsByClassName)return;var n,r,i=t.documentElement,s=e.Date,o=e.HTMLPictureElement,a=e.addEventListener,c=e.setTimeout,u=e.requestAnimationFrame||c,l=e.requestIdleCallback,h=/^picture$/i,d=["load","error","lazyincluded","_lazyloaded"],f={},p=Array.prototype.forEach,g=function(e,t){return f[t]||(f[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),f[t].test(e.getAttribute("class")||"")&&f[t]},m=function(e,t){g(e,t)||e.setAttribute("class",(e.getAttribute("class")||"").trim()+" "+t)},v=function(e,t){var n;(n=g(e,t))&&e.setAttribute("class",(e.getAttribute("class")||"").replace(n," "))},y=function(e,t,n){var r=n?"addEventListener":"removeEventListener";n&&y(e,t),d.forEach(function(n){e[r](n,t)})},b=function(e,r,i,s,o){var a=t.createEvent("Event");return i||(i={}),i.instance=n,a.initEvent(r,!s,!o),a.detail=i,e.dispatchEvent(a),a},w=function(t,n){var i;!o&&(i=e.picturefill||r.pf)?(n&&n.src&&!t.getAttribute("srcset")&&t.setAttribute("srcset",n.src),i({reevaluate:!0,elements:[t]})):n&&n.src&&(t.src=n.src)},_=function(e,t){return(getComputedStyle(e,null)||{})[t]},E=function(e,t,n){for(n=n||e.offsetWidth;n0)&&"visible"!=_(s,"overflow")&&(r=s.getBoundingClientRect(),o=R>r.left&&kr.top-1&&T500&&i.clientWidth>500?500:370),L=r.expand,I=L*r.expFactor),H2&&f>2&&!t.hidden?(H=I,q=0):H=f>1&&q>1&&B<6?L:0;for(;s=d&&(T=a.top)<=O&&(R=a.right)>=d*D&&(k=a.left)<=A&&(M||R||k||T)&&(r.loadHidden||"hidden"!=_(m[s],"visibility"))&&(u&&B<3&&!p&&(f<3||q<4)||F(m[s],h))){if(X(m[s]),l=!0,B>9)break}else!l&&u&&!c&&B<4&&q<4&&f>2&&(o[0]||r.preloadAfterLoad)&&(o[0]||!p&&(M||R||k||T||"auto"!=m[s].getAttribute(r.sizesAttr)))&&(c=o[0]||m[s]);else X(m[s]);c&&!l&&X(c)}},K=function(e){var t,n=0,i=r.throttleDelay,o=r.ricTimeout,a=function(){t=!1,n=s.now(),e()},u=l&&o>49?function(){l(a,{timeout:o}),o!==r.ricTimeout&&(o=r.ricTimeout)}:S(function(){c(a)},!0);return function(e){var r;(e=!0===e)&&(o=33),t||(t=!0,(r=i-(s.now()-n))<0&&(r=0),e||r<9?u():c(u,r))}}(U),V=function(e){m(e.target,r.loadedClass),v(e.target,r.loadingClass),y(e.target,W),b(e.target,"lazyloaded")},J=S(V),W=function(e){J({target:e.target})},G=function(e){var t,n=e.getAttribute(r.srcsetAttr);(t=r.customMedia[e.getAttribute("data-media")||e.getAttribute("media")])&&e.setAttribute("media",t),n&&e.setAttribute("srcset",n)},Q=S(function(e,t,n,i,s){var o,a,u,l,f,g;(f=b(e,"lazybeforeunveil",t)).defaultPrevented||(i&&(n?m(e,r.autosizesClass):e.setAttribute("sizes",i)),a=e.getAttribute(r.srcsetAttr),o=e.getAttribute(r.srcAttr),s&&(u=e.parentNode,l=u&&h.test(u.nodeName||"")),g=t.firesLoad||"src"in e&&(a||o||l),f={target:e},g&&(y(e,z,!0),clearTimeout(d),d=c(z,2500),m(e,r.loadingClass),y(e,W,!0)),l&&p.call(u.getElementsByTagName("source"),G),a?e.setAttribute("srcset",a):o&&!l&&(j.test(e.nodeName)?function(e,t){try{e.contentWindow.location.replace(t)}catch(n){e.src=t}}(e,o):e.src=o),s&&(a||l)&&w(e,{src:o})),e._lazyRace&&delete e._lazyRace,v(e,r.lazyClass),x(function(){(!g||e.complete&&e.naturalWidth>1)&&(g?z(f):B--,V(f))},!0)}),X=function(e){var t,n=P.test(e.nodeName),i=n&&(e.getAttribute(r.sizesAttr)||e.getAttribute("sizes")),s="auto"==i;(!s&&u||!n||!e.getAttribute("src")&&!e.srcset||e.complete||g(e,r.errorClass)||!g(e,r.lazyClass))&&(t=b(e,"lazyunveilread").detail,s&&N.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,B++,Q(e,t,s,i,n))},Z=function(){if(!u)if(s.now()-E<999)c(Z,999);else{var e=C(function(){r.loadMode=3,K()});u=!0,r.loadMode=3,K(),a("scroll",function(){3==r.loadMode&&(r.loadMode=2),e()},!0)}};return{_:function(){E=s.now(),n.elements=t.getElementsByClassName(r.lazyClass),o=t.getElementsByClassName(r.lazyClass+" "+r.preloadClass),D=r.hFac,a("scroll",K,!0),a("resize",K,!0),e.MutationObserver?new MutationObserver(K).observe(i,{childList:!0,subtree:!0,attributes:!0}):(i.addEventListener("DOMNodeInserted",K,!0),i.addEventListener("DOMAttrModified",K,!0),setInterval(K,999)),a("hashchange",K,!0),["focus","mouseover","click","load","transitionend","animationend","webkitAnimationEnd"].forEach(function(e){t.addEventListener(e,K,!0)}),/d$|^c/.test(t.readyState)?Z():(a("load",Z),t.addEventListener("DOMContentLoaded",K),c(Z,2e4)),n.elements.length?(U(),x._lsFlush()):K()},checkElems:K,unveil:X}}(),N=function(){var e,n=S(function(e,t,n,r){var i,s,o;if(e._lazysizesWidth=r,r+="px",e.setAttribute("sizes",r),h.test(t.nodeName||""))for(i=t.getElementsByTagName("source"),s=0,o=i.length;s0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText,this.container="object"===r(e.container)?e.container:document.body}},{key:"listenClick",value:function(e){var t=this;this.listener=(0,a.default)(e,"click",function(e){return t.onClick(e)})}},{key:"onClick",value:function(e){var t=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new s.default({action:this.action(t),target:this.target(t),text:this.text(t),container:this.container,trigger:t,emitter:this})}},{key:"defaultAction",value:function(e){return l("action",e)}},{key:"defaultTarget",value:function(e){var t=l("target",e);if(t)return document.querySelector(t)}},{key:"defaultText",value:function(e){return l("text",e)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],t="string"==typeof e?[e]:e,n=!!document.queryCommandSupported;return t.forEach(function(e){n=n&&!!document.queryCommandSupported(e)}),n}}]),t}();function l(e,t){var n="data-clipboard-"+e;if(t.hasAttribute(n))return t.getAttribute(n)}e.exports=u},function(e,t,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action=e.action,this.container=e.container,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var e=this,t="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[t?"right":"left"]="-9999px";var n=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=n+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=(0,s.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=(0,s.default)(this.target),this.copyText()}},{key:"copyText",value:function(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function(e){this.emitter.emit(e?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(e){if(void 0!==e){if(!e||"object"!==(void 0===e?"undefined":r(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function(){return this._target}}]),e}();e.exports=o},function(e,t){e.exports=function(e){var t;if("SELECT"===e.nodeName)e.focus(),t=e.value;else if("INPUT"===e.nodeName||"TEXTAREA"===e.nodeName){var n=e.hasAttribute("readonly");n||e.setAttribute("readonly",""),e.select(),e.setSelectionRange(0,e.value.length),n||e.removeAttribute("readonly"),t=e.value}else{e.hasAttribute("contenteditable")&&e.focus();var r=window.getSelection(),i=document.createRange();i.selectNodeContents(e),r.removeAllRanges(),r.addRange(i),t=r.toString()}return t}},function(e,t){function n(){}n.prototype={on:function(e,t,n){var r=this.e||(this.e={});return(r[e]||(r[e]=[])).push({fn:t,ctx:n}),this},once:function(e,t,n){var r=this;function i(){r.off(e,i),t.apply(n,arguments)}return i._=t,this.on(e,i,n)},emit:function(e){for(var t=[].slice.call(arguments,1),n=((this.e||(this.e={}))[e]||[]).slice(),r=0,i=n.length;r0&&n.parentNode.classList.add("expand")}}},function(e,t,n){n(9)({apiKey:"167e7998590aebda7f9fedcf86bc4a55",indexName:"hugodocs",inputSelector:"#search-input",debug:!0})},function(e,t,n){ /*! docsearch 2.6.1 | © Algolia | github.com/algolia/docsearch */ !function(t,n){e.exports=n()}("undefined"!=typeof self&&self,function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=22)}([function(e,t,n){"use strict";var r=n(1);function i(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}e.exports={isArray:null,isFunction:null,isObject:null,bind:null,each:null,map:null,mixin:null,isMsie:function(e){if(void 0===e&&(e=navigator.userAgent),/(msie|trident)/i.test(e)){var t=e.match(/(msie |rv:)(\d+(.\d+)?)/i);if(t)return t[2]}return!1},escapeRegExChars:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isNumber:function(e){return"number"==typeof e},toStr:function(e){return void 0===e||null===e?"":e+""},cloneDeep:function(e){var t=this.mixin({},e),n=this;return this.each(t,function(e,r){e&&(n.isArray(e)?t[r]=[].concat(e):n.isObject(e)&&(t[r]=n.cloneDeep(e)))}),t},error:function(e){throw new Error(e)},every:function(e,t){var n=!0;return e?(this.each(e,function(r,i){if(!(n=t.call(null,r,i,e)))return!1}),!!n):n},any:function(e,t){var n=!1;return e?(this.each(e,function(r,i){if(t.call(null,r,i,e))return n=!0,!1}),n):n},getUniqueId:function(){var e=0;return function(){return e++}}(),templatify:function(e){if(this.isFunction(e))return e;var t=r.element(e);return"SCRIPT"===t.prop("tagName")?function(){return t.text()}:function(){return String(e)}},defer:function(e){setTimeout(e,0)},noop:function(){},formatPrefix:function(e,t){return t?"":e+"-"},className:function(e,t,n){return(n?"":".")+e+t},escapeHighlightedString:function(e,t,n){t=t||"";var r=document.createElement("div");r.appendChild(document.createTextNode(t)),n=n||"";var s=document.createElement("div");s.appendChild(document.createTextNode(n));var o=document.createElement("div");return o.appendChild(document.createTextNode(e)),o.innerHTML.replace(RegExp(i(r.innerHTML),"g"),t).replace(RegExp(i(s.innerHTML),"g"),n)}}},function(e,t,n){"use strict";e.exports={element:null}},function(e,t){var n=Object.prototype.hasOwnProperty,r=Object.prototype.toString;e.exports=function(e,t,i){if("[object Function]"!==r.call(t))throw new TypeError("iterator must be a function");var s=e.length;if(s===+s)for(var o=0;o was loaded but did not call our provided callback"),JSONPScriptError:s("JSONPScriptError"," hugo-0.92.2/examples/blog/layouts/partials/header.html000066400000000000000000000006221420147000300227330ustar00rootroot00000000000000 {{ partial "meta.html" . }} {{ .Title }} - {{ .Site.BaseURL }} {{ partial "header.includes.html" . }} {{ with .OutputFormats.Get "RSS" -}} {{ printf "" .Permalink .MediaType $.Site.Title | safeHTML }} {{- end }} hugo-0.92.2/examples/blog/layouts/partials/header.includes.html000066400000000000000000000002471420147000300245430ustar00rootroot00000000000000 hugo-0.92.2/examples/blog/layouts/partials/menu.html000066400000000000000000000016141420147000300224510ustar00rootroot00000000000000

    Connect. Socialize.

    Hey, listen!
    You should modify the layouts/partials/menu.html template and include your own profile links.
    hugo-0.92.2/examples/blog/layouts/partials/meta.html000066400000000000000000000004531420147000300224330ustar00rootroot00000000000000 hugo-0.92.2/examples/blog/layouts/partials/navbar.html000066400000000000000000000020441420147000300227540ustar00rootroot00000000000000 hugo-0.92.2/examples/blog/layouts/post/000077500000000000000000000000001420147000300177635ustar00rootroot00000000000000hugo-0.92.2/examples/blog/layouts/post/li.html000066400000000000000000000002301420147000300212500ustar00rootroot00000000000000
  3. {{ .Title}}
    posted on {{ .Date.Format "January 2, 2006" }}
  4. hugo-0.92.2/examples/blog/layouts/post/list.html000066400000000000000000000012051420147000300216220ustar00rootroot00000000000000{{ partial "header.html" . }} {{ partial "navbar.html" . }}
    Blog Post Archive
      {{ range .Data.Pages }} {{ .Render "li" }} {{ end}}
    {{ partial "menu.html" . }}
    {{ partial "footer.copyright.html" . }}
    {{ partial "footer.html" . }} hugo-0.92.2/examples/blog/layouts/post/single.html000066400000000000000000000023211420147000300221300ustar00rootroot00000000000000{{ partial "header.html" . }} {{ partial "navbar.html" . }}

    {{ .Title }}
    {{ .Description }}


    {{ .Content }}

    {{ .Date.Format "January 2, 2006" }}
    {{ .WordCount }} words


    Categories
      {{ range .Params.categories }}
    • {{ . }}
    • {{ end }}

    Tags
    {{ range .Params.tags }}{{ . }} {{ end }}
    {{ partial "menu.html" . }}
    {{ partial "footer.copyright.html" . }}
    {{ partial "footer.html" . }} hugo-0.92.2/examples/blog/layouts/post/summary.html000066400000000000000000000006011420147000300223430ustar00rootroot00000000000000

    {{ .Title }} Posted on {{ .Date.Format "Jan 2, 2006" }}
    {{ .Description }}


    {{ .Summary }}

    Read More
    hugo-0.92.2/examples/blog/layouts/tags/000077500000000000000000000000001420147000300177345ustar00rootroot00000000000000hugo-0.92.2/examples/blog/layouts/tags/list.html000066400000000000000000000012441420147000300215760ustar00rootroot00000000000000{{ partial "header.html" . }} {{ partial "navbar.html" . }}
    Items with tag {{ .Title | lower }}
      {{ range .Data.Pages }} {{ .Render "li" }} {{ end}}
    {{ partial "menu.html" . }}
    {{ partial "footer.copyright.html" . }}
    {{ partial "footer.html" . }} hugo-0.92.2/examples/blog/static/000077500000000000000000000000001420147000300165655ustar00rootroot00000000000000hugo-0.92.2/examples/blog/static/css/000077500000000000000000000000001420147000300173555ustar00rootroot00000000000000hugo-0.92.2/examples/blog/static/css/bootstrap.min.css000066400000000000000000003714211420147000300226760ustar00rootroot00000000000000@import url("https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,700italic,400,300,700");/*! * bootswatch v3.3.6 * Homepage: http://bootswatch.com * Copyright 2012-2015 Thomas Park * Licensed under MIT * Based on Bootstrap *//*! * Bootstrap v3.3.6 (http://getbootstrap.com) * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;-webkit-box-shadow:none !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#222222;background-color:#ffffff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#008cba;text-decoration:none}a:hover,a:focus{color:#008cba;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:0}.img-thumbnail{padding:4px;line-height:1.4;background-color:#ffffff;border:1px solid #dddddd;border-radius:0;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:21px;margin-bottom:21px;border:0;border-top:1px solid #dddddd}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;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}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:300;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999999}h1,.h1,h2,.h2,h3,.h3{margin-top:21px;margin-bottom:10.5px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10.5px;margin-bottom:10.5px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:39px}h2,.h2{font-size:32px}h3,.h3{font-size:26px}h4,.h4{font-size:19px}h5,.h5{font-size:15px}h6,.h6{font-size:13px}p{margin:0 0 10.5px}.lead{margin-bottom:21px;font-size:17px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:22.5px}}small,.small{font-size:80%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#999999}.text-primary{color:#008cba}a.text-primary:hover,a.text-primary:focus{color:#006687}.text-success{color:#43ac6a}a.text-success:hover,a.text-success:focus{color:#358753}.text-info{color:#5bc0de}a.text-info:hover,a.text-info:focus{color:#31b0d5}.text-warning{color:#e99002}a.text-warning:hover,a.text-warning:focus{color:#b67102}.text-danger{color:#f04124}a.text-danger:hover,a.text-danger:focus{color:#d32a0e}.bg-primary{color:#fff;background-color:#008cba}a.bg-primary:hover,a.bg-primary:focus{background-color:#006687}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9.5px;margin:42px 0 21px;border-bottom:1px solid #dddddd}ul,ol{margin-top:0;margin-bottom:10.5px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:21px}dt,dd{line-height:1.4}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10.5px 21px;margin:0 0 21px;font-size:18.75px;border-left:5px solid #dddddd}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.4;color:#6f6f6f}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #dddddd;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:21px;font-style:normal;line-height:1.4}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:0}kbd{padding:2px 4px;font-size:90%;color:#ffffff;background-color:#333333;border-radius:0;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:10px;margin:0 0 10.5px;font-size:14px;line-height:1.4;word-break:break-all;word-wrap:break-word;color:#333333;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:0}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0%}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0%}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0%}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0%}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#999999;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:21px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.4;vertical-align:top;border-top:1px solid #dddddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #dddddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #dddddd}.table .table{background-color:#ffffff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #dddddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #dddddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15.75px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #dddddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:21px;font-size:22.5px;line-height:inherit;color:#333333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:9px;font-size:15px;line-height:1.4;color:#6f6f6f}.form-control{display:block;width:100%;height:39px;padding:8px 12px;font-size:15px;line-height:1.4;color:#6f6f6f;background-color:#ffffff;background-image:none;border:1px solid #cccccc;border-radius:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#999999;opacity:1}.form-control:-ms-input-placeholder{color:#999999}.form-control::-webkit-input-placeholder{color:#999999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eeeeee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:39px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:36px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:60px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:21px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:9px;padding-bottom:9px;margin-bottom:0;min-height:36px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:36px;padding:8px 12px;font-size:12px;line-height:1.5;border-radius:0}select.input-sm{height:36px;line-height:36px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:36px;padding:8px 12px;font-size:12px;line-height:1.5;border-radius:0}.form-group-sm select.form-control{height:36px;line-height:36px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:36px;min-height:33px;padding:9px 12px;font-size:12px;line-height:1.5}.input-lg{height:60px;padding:16px 20px;font-size:19px;line-height:1.3333333;border-radius:0}select.input-lg{height:60px;line-height:60px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:60px;padding:16px 20px;font-size:19px;line-height:1.3333333;border-radius:0}.form-group-lg select.form-control{height:60px;line-height:60px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:60px;min-height:40px;padding:17px 20px;font-size:19px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:48.75px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:39px;height:39px;line-height:39px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:60px;height:60px;line-height:60px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:36px;height:36px;line-height:36px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#43ac6a}.has-success .form-control{border-color:#43ac6a;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#358753;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #85d0a1;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #85d0a1}.has-success .input-group-addon{color:#43ac6a;border-color:#43ac6a;background-color:#dff0d8}.has-success .form-control-feedback{color:#43ac6a}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#e99002}.has-warning .form-control{border-color:#e99002;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#b67102;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #febc53;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #febc53}.has-warning .input-group-addon{color:#e99002;border-color:#e99002;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#e99002}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#f04124}.has-error .form-control{border-color:#f04124;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#d32a0e;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #f79483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #f79483}.has-error .input-group-addon{color:#f04124;border-color:#f04124;background-color:#f2dede}.has-error .form-control-feedback{color:#f04124}.has-feedback label~.form-control-feedback{top:26px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#626262}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:9px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:30px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:9px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:17px;font-size:19px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:9px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:8px 12px;font-size:15px;line-height:1.4;border-radius:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333333;background-color:#e7e7e7;border-color:#cccccc}.btn-default:focus,.btn-default.focus{color:#333333;background-color:#cecece;border-color:#8c8c8c}.btn-default:hover{color:#333333;background-color:#cecece;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333333;background-color:#cecece;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333333;background-color:#bcbcbc;border-color:#8c8c8c}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#e7e7e7;border-color:#cccccc}.btn-default .badge{color:#e7e7e7;background-color:#333333}.btn-primary{color:#ffffff;background-color:#008cba;border-color:#0079a1}.btn-primary:focus,.btn-primary.focus{color:#ffffff;background-color:#006687;border-color:#001921}.btn-primary:hover{color:#ffffff;background-color:#006687;border-color:#004b63}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#ffffff;background-color:#006687;border-color:#004b63}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#ffffff;background-color:#004b63;border-color:#001921}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#008cba;border-color:#0079a1}.btn-primary .badge{color:#008cba;background-color:#ffffff}.btn-success{color:#ffffff;background-color:#43ac6a;border-color:#3c9a5f}.btn-success:focus,.btn-success.focus{color:#ffffff;background-color:#358753;border-color:#183e26}.btn-success:hover{color:#ffffff;background-color:#358753;border-color:#2b6e44}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#ffffff;background-color:#358753;border-color:#2b6e44}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#ffffff;background-color:#2b6e44;border-color:#183e26}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#43ac6a;border-color:#3c9a5f}.btn-success .badge{color:#43ac6a;background-color:#ffffff}.btn-info{color:#ffffff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#ffffff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#ffffff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#ffffff;background-color:#31b0d5;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#ffffff;background-color:#269abc;border-color:#1b6d85}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#ffffff}.btn-warning{color:#ffffff;background-color:#e99002;border-color:#d08002}.btn-warning:focus,.btn-warning.focus{color:#ffffff;background-color:#b67102;border-color:#513201}.btn-warning:hover{color:#ffffff;background-color:#b67102;border-color:#935b01}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#ffffff;background-color:#b67102;border-color:#935b01}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#ffffff;background-color:#935b01;border-color:#513201}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#e99002;border-color:#d08002}.btn-warning .badge{color:#e99002;background-color:#ffffff}.btn-danger{color:#ffffff;background-color:#f04124;border-color:#ea2f10}.btn-danger:focus,.btn-danger.focus{color:#ffffff;background-color:#d32a0e;border-color:#731708}.btn-danger:hover{color:#ffffff;background-color:#d32a0e;border-color:#b1240c}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#ffffff;background-color:#d32a0e;border-color:#b1240c}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#ffffff;background-color:#b1240c;border-color:#731708}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#f04124;border-color:#ea2f10}.btn-danger .badge{color:#f04124;background-color:#ffffff}.btn-link{color:#008cba;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#008cba;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:16px 20px;font-size:19px;line-height:1.3333333;border-radius:0}.btn-sm,.btn-group-sm>.btn{padding:8px 12px;font-size:12px;line-height:1.5;border-radius:0}.btn-xs,.btn-group-xs>.btn{padding:4px 6px;font-size:12px;line-height:1.5;border-radius:0}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:0.35s;-o-transition-duration:0.35s;transition-duration:0.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:15px;text-align:left;background-color:#ffffff;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.15);border-radius:0;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);-webkit-background-clip:padding-box;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9.5px 0;overflow:hidden;background-color:rgba(0,0,0,0.2)}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.4;color:#555555;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#eeeeee}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;outline:0;background-color:#008cba}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.4;color:#999999;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:60px;padding:16px 20px;font-size:19px;line-height:1.3333333;border-radius:0}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:60px;line-height:60px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:36px;padding:8px 12px;font-size:12px;line-height:1.5;border-radius:0}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:36px;line-height:36px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:8px 12px;font-size:15px;font-weight:normal;line-height:1;color:#6f6f6f;text-align:center;background-color:#eeeeee;border:1px solid #cccccc;border-radius:0}.input-group-addon.input-sm{padding:8px 12px;font-size:12px;border-radius:0}.input-group-addon.input-lg{padding:16px 20px;font-size:19px;border-radius:0}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eeeeee}.nav>li.disabled>a{color:#999999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eeeeee;border-color:#008cba}.nav .nav-divider{height:1px;margin:9.5px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #dddddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.4;border:1px solid transparent;border-radius:0 0 0 0}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#6f6f6f;background-color:#ffffff;border:1px solid #dddddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #dddddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #dddddd;border-radius:0 0 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#ffffff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:0}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#ffffff;background-color:#008cba}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #dddddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #dddddd;border-radius:0 0 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#ffffff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:45px;margin-bottom:21px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:0}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:12px 15px;font-size:19px;line-height:21px;height:45px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:5.5px;margin-bottom:5.5px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:0}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:6px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:21px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:21px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:12px;padding-bottom:12px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:3px;margin-bottom:3px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:3px;margin-bottom:3px}.navbar-btn.btn-sm{margin-top:4.5px;margin-bottom:4.5px}.navbar-btn.btn-xs{margin-top:11.5px;margin-bottom:11.5px}.navbar-text{margin-top:12px;margin-bottom:12px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#333333;border-color:#222222}.navbar-default .navbar-brand{color:#ffffff}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#ffffff;background-color:transparent}.navbar-default .navbar-text{color:#ffffff}.navbar-default .navbar-nav>li>a{color:#ffffff}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#ffffff;background-color:#272727}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#ffffff;background-color:#272727}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#cccccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:transparent}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:transparent}.navbar-default .navbar-toggle .icon-bar{background-color:#ffffff}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#222222}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#272727;color:#ffffff}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#ffffff}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#ffffff;background-color:#272727}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#ffffff;background-color:#272727}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#cccccc;background-color:transparent}}.navbar-default .navbar-link{color:#ffffff}.navbar-default .navbar-link:hover{color:#ffffff}.navbar-default .btn-link{color:#ffffff}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#ffffff}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#cccccc}.navbar-inverse{background-color:#008cba;border-color:#006687}.navbar-inverse .navbar-brand{color:#ffffff}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-text{color:#ffffff}.navbar-inverse .navbar-nav>li>a{color:#ffffff}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#ffffff;background-color:#006687}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#ffffff;background-color:#006687}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:transparent}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:transparent}.navbar-inverse .navbar-toggle .icon-bar{background-color:#ffffff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#007196}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#006687;color:#ffffff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#006687}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#006687}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#ffffff}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#ffffff;background-color:#006687}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#ffffff;background-color:#006687}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444444;background-color:transparent}}.navbar-inverse .navbar-link{color:#ffffff}.navbar-inverse .navbar-link:hover{color:#ffffff}.navbar-inverse .btn-link{color:#ffffff}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#ffffff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444444}.breadcrumb{padding:8px 15px;margin-bottom:21px;list-style:none;background-color:#f5f5f5;border-radius:0}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#999999}.breadcrumb>.active{color:#333333}.pagination{display:inline-block;padding-left:0;margin:21px 0;border-radius:0}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:8px 12px;line-height:1.4;text-decoration:none;color:#008cba;background-color:transparent;border:1px solid transparent;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:0;border-top-left-radius:0}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:0;border-top-right-radius:0}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#008cba;background-color:#eeeeee;border-color:transparent}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#ffffff;background-color:#008cba;border-color:transparent;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999999;background-color:#ffffff;border-color:transparent;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:16px 20px;font-size:19px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:0;border-top-left-radius:0}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:0;border-top-right-radius:0}.pagination-sm>li>a,.pagination-sm>li>span{padding:8px 12px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:0;border-top-left-radius:0}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:0;border-top-right-radius:0}.pager{padding-left:0;margin:21px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:transparent;border:1px solid transparent;border-radius:3px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eeeeee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999999;background-color:transparent;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#ffffff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#008cba}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#006687}.label-success{background-color:#43ac6a}.label-success[href]:hover,.label-success[href]:focus{background-color:#358753}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#e99002}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#b67102}.label-danger{background-color:#f04124}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#d32a0e}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#ffffff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#008cba;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#ffffff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#008cba;background-color:#ffffff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#fafafa}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:23px;font-weight:200}.jumbotron>hr{border-top-color:#e1e1e1}.container .jumbotron,.container-fluid .jumbotron{border-radius:0;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:68px}}.thumbnail{display:block;padding:4px;margin-bottom:21px;line-height:1.4;background-color:#ffffff;border:1px solid #dddddd;border-radius:0;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#008cba}.thumbnail .caption{padding:9px;color:#222222}.alert{padding:15px;margin-bottom:21px;border:1px solid transparent;border-radius:0}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#43ac6a;border-color:#3c9a5f;color:#ffffff}.alert-success hr{border-top-color:#358753}.alert-success .alert-link{color:#e6e6e6}.alert-info{background-color:#5bc0de;border-color:#3db5d8;color:#ffffff}.alert-info hr{border-top-color:#2aabd2}.alert-info .alert-link{color:#e6e6e6}.alert-warning{background-color:#e99002;border-color:#d08002;color:#ffffff}.alert-warning hr{border-top-color:#b67102}.alert-warning .alert-link{color:#e6e6e6}.alert-danger{background-color:#f04124;border-color:#ea2f10;color:#ffffff}.alert-danger hr{border-top-color:#d32a0e}.alert-danger .alert-link{color:#e6e6e6}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:21px;margin-bottom:21px;background-color:#f5f5f5;border-radius:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:21px;color:#ffffff;text-align:center;background-color:#008cba;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#43ac6a}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#e99002}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#f04124}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#ffffff;border:1px solid #dddddd}.list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}a.list-group-item,button.list-group-item{color:#555555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eeeeee;color:#999999;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#999999}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#ffffff;background-color:#008cba;border-color:#008cba}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#87e1ff}.list-group-item-success{color:#43ac6a;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#43ac6a}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#43ac6a;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#43ac6a;border-color:#43ac6a}.list-group-item-info{color:#5bc0de;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#5bc0de}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#5bc0de;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.list-group-item-warning{color:#e99002;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#e99002}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#e99002;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#e99002;border-color:#e99002}.list-group-item-danger{color:#f04124;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#f04124}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#f04124;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#f04124;border-color:#f04124}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:21px;background-color:#ffffff;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:-1;border-top-left-radius:-1}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:17px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #dddddd;border-bottom-right-radius:-1;border-bottom-left-radius:-1}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:-1;border-top-left-radius:-1}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:-1;border-bottom-left-radius:-1}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:-1;border-top-left-radius:-1}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:-1;border-top-right-radius:-1}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:-1}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:-1}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:-1;border-bottom-left-radius:-1}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:-1;border-bottom-right-radius:-1}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:-1}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:-1}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #dddddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:21px}.panel-group .panel{margin-bottom:0;border-radius:0}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #dddddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #dddddd}.panel-default{border-color:#dddddd}.panel-default>.panel-heading{color:#333333;background-color:#f5f5f5;border-color:#dddddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#dddddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#dddddd}.panel-primary{border-color:#008cba}.panel-primary>.panel-heading{color:#ffffff;background-color:#008cba;border-color:#008cba}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#008cba}.panel-primary>.panel-heading .badge{color:#008cba;background-color:#ffffff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#008cba}.panel-success{border-color:#3c9a5f}.panel-success>.panel-heading{color:#ffffff;background-color:#43ac6a;border-color:#3c9a5f}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#3c9a5f}.panel-success>.panel-heading .badge{color:#43ac6a;background-color:#ffffff}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#3c9a5f}.panel-info{border-color:#3db5d8}.panel-info>.panel-heading{color:#ffffff;background-color:#5bc0de;border-color:#3db5d8}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#3db5d8}.panel-info>.panel-heading .badge{color:#5bc0de;background-color:#ffffff}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#3db5d8}.panel-warning{border-color:#d08002}.panel-warning>.panel-heading{color:#ffffff;background-color:#e99002;border-color:#d08002}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d08002}.panel-warning>.panel-heading .badge{color:#e99002;background-color:#ffffff}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d08002}.panel-danger{border-color:#ea2f10}.panel-danger>.panel-heading{color:#ffffff;background-color:#f04124;border-color:#ea2f10}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ea2f10}.panel-danger>.panel-heading .badge{color:#f04124;background-color:#ffffff}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ea2f10}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#fafafa;border:1px solid #e8e8e8;border-radius:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:0}.well-sm{padding:9px;border-radius:0}.close{float:right;font-size:22.5px;font-weight:bold;line-height:1;color:#ffffff;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#ffffff;text-decoration:none;cursor:pointer;opacity:0.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#ffffff;border:1px solid #999999;border:1px solid rgba(0,0,0,0.2);border-radius:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);-webkit-background-clip:padding-box;background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:0.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.4}.modal-body{position:relative;padding:20px}.modal-footer{padding:20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.4;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:0.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;background-color:#333333;border-radius:0}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#333333}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#333333}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#333333}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#333333}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#333333}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#333333}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#333333}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#333333}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.4;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:15px;background-color:#333333;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #333333;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:15px;background-color:#333333;border-bottom:1px solid #262626;border-radius:-1 -1 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#000000;border-top-color:rgba(0,0,0,0.05);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#333333}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#000000;border-right-color:rgba(0,0,0,0.05)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#333333}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#000000;border-bottom-color:rgba(0,0,0,0.05);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#333333}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#000000;border-left-color:rgba(0,0,0,0.05)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#333333;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:0.5;filter:alpha(opacity=50);font-size:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.5)), to(rgba(0,0,0,0.0001)));background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.0001)), to(rgba(0,0,0,0.5)));background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #ffffff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#ffffff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.navbar{border:none;font-size:13px;font-weight:300}.navbar .navbar-toggle:hover .icon-bar{background-color:#b3b3b3}.navbar-collapse{border-top-color:rgba(0,0,0,0.2);-webkit-box-shadow:none;box-shadow:none}.navbar .btn{padding-top:6px;padding-bottom:6px}.navbar-form{margin-top:7px;margin-bottom:5px}.navbar-form .form-control{height:auto;padding:4px 6px}.navbar .dropdown-menu{border:none}.navbar .dropdown-menu>li>a,.navbar .dropdown-menu>li>a:focus{background-color:transparent;font-size:13px;font-weight:300}.navbar .dropdown-header{color:rgba(255,255,255,0.5)}.navbar-default .dropdown-menu{background-color:#333333}.navbar-default .dropdown-menu>li>a,.navbar-default .dropdown-menu>li>a:focus{color:#ffffff}.navbar-default .dropdown-menu>li>a:hover,.navbar-default .dropdown-menu>.active>a,.navbar-default .dropdown-menu>.active>a:hover{background-color:#272727}.navbar-inverse .dropdown-menu{background-color:#008cba}.navbar-inverse .dropdown-menu>li>a,.navbar-inverse .dropdown-menu>li>a:focus{color:#ffffff}.navbar-inverse .dropdown-menu>li>a:hover,.navbar-inverse .dropdown-menu>.active>a,.navbar-inverse .dropdown-menu>.active>a:hover{background-color:#006687}.btn{padding:8px 12px}.btn-lg{padding:16px 20px}.btn-sm{padding:8px 12px}.btn-xs{padding:4px 6px}.btn-group .btn~.dropdown-toggle{padding-left:16px;padding-right:16px}.btn-group .dropdown-menu{border-top-width:0}.btn-group.dropup .dropdown-menu{border-top-width:1px;border-bottom-width:0;margin-bottom:0}.btn-group .dropdown-toggle.btn-default~.dropdown-menu{background-color:#e7e7e7;border-color:#cccccc}.btn-group .dropdown-toggle.btn-default~.dropdown-menu>li>a{color:#333333}.btn-group .dropdown-toggle.btn-default~.dropdown-menu>li>a:hover{background-color:#d3d3d3}.btn-group .dropdown-toggle.btn-primary~.dropdown-menu{background-color:#008cba;border-color:#0079a1}.btn-group .dropdown-toggle.btn-primary~.dropdown-menu>li>a{color:#ffffff}.btn-group .dropdown-toggle.btn-primary~.dropdown-menu>li>a:hover{background-color:#006d91}.btn-group .dropdown-toggle.btn-success~.dropdown-menu{background-color:#43ac6a;border-color:#3c9a5f}.btn-group .dropdown-toggle.btn-success~.dropdown-menu>li>a{color:#ffffff}.btn-group .dropdown-toggle.btn-success~.dropdown-menu>li>a:hover{background-color:#388f58}.btn-group .dropdown-toggle.btn-info~.dropdown-menu{background-color:#5bc0de;border-color:#46b8da}.btn-group .dropdown-toggle.btn-info~.dropdown-menu>li>a{color:#ffffff}.btn-group .dropdown-toggle.btn-info~.dropdown-menu>li>a:hover{background-color:#39b3d7}.btn-group .dropdown-toggle.btn-warning~.dropdown-menu{background-color:#e99002;border-color:#d08002}.btn-group .dropdown-toggle.btn-warning~.dropdown-menu>li>a{color:#ffffff}.btn-group .dropdown-toggle.btn-warning~.dropdown-menu>li>a:hover{background-color:#c17702}.btn-group .dropdown-toggle.btn-danger~.dropdown-menu{background-color:#f04124;border-color:#ea2f10}.btn-group .dropdown-toggle.btn-danger~.dropdown-menu>li>a{color:#ffffff}.btn-group .dropdown-toggle.btn-danger~.dropdown-menu>li>a:hover{background-color:#dc2c0f}.lead{color:#6f6f6f}cite{font-style:italic}blockquote{border-left-width:1px;color:#6f6f6f}blockquote.pull-right{border-right-width:1px}blockquote small{font-size:12px;font-weight:300}table{font-size:12px}label,.control-label,.help-block,.checkbox,.radio{font-size:12px;font-weight:normal}input[type="radio"],input[type="checkbox"]{margin-top:1px}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{border-color:transparent}.nav-tabs>li>a{background-color:#e7e7e7;color:#222222}.nav-tabs .caret{border-top-color:#222222;border-bottom-color:#222222}.nav-pills{font-weight:300}.breadcrumb{border:1px solid #dddddd;border-radius:3px;font-size:10px;font-weight:300;text-transform:uppercase}.pagination{font-size:12px;font-weight:300;color:#999999}.pagination>li>a,.pagination>li>span{margin-left:4px;color:#999999}.pagination>.active>a,.pagination>.active>span{color:#fff}.pagination>li>a,.pagination>li:first-child>a,.pagination>li:last-child>a,.pagination>li>span,.pagination>li:first-child>span,.pagination>li:last-child>span{border-radius:3px}.pagination-lg>li>a,.pagination-lg>li>span{padding-left:22px;padding-right:22px}.pagination-sm>li>a,.pagination-sm>li>span{padding:0 5px}.pager{font-size:12px;font-weight:300;color:#999999}.list-group{font-size:12px;font-weight:300}.close{opacity:0.4;text-decoration:none;text-shadow:none}.close:hover,.close:focus{opacity:1}.alert{font-size:12px;font-weight:300}.alert .alert-link{font-weight:normal;color:#fff;text-decoration:underline}.label{padding-left:1em;padding-right:1em;border-radius:0;font-weight:300}.label-default{background-color:#e7e7e7;color:#333333}.badge{font-weight:300}.progress{height:22px;padding:2px;background-color:#f6f6f6;border:1px solid #ccc;-webkit-box-shadow:none;box-shadow:none}.dropdown-menu{padding:0;margin-top:0;font-size:12px}.dropdown-menu>li>a{padding:12px 15px}.dropdown-header{padding-left:15px;padding-right:15px;font-size:9px;text-transform:uppercase}.popover{color:#fff;font-size:12px;font-weight:300}.panel-heading,.panel-footer{border-top-right-radius:0;border-top-left-radius:0}.panel-default .close{color:#222222}.modal .close{color:#222222}hugo-0.92.2/examples/blog/static/css/custom.css000066400000000000000000000003321420147000300213770ustar00rootroot00000000000000body { margin-top: 75px; /* 100px is double the height of the navbar - I made it a big larger for some more space - keep it at 50px at least if you want to use the fixed top nav */ } footer { margin: 50px 0; }hugo-0.92.2/examples/blog/static/css/font-awesome.css000066400000000000000000001007211420147000300224740ustar00rootroot00000000000000/*! * Font Awesome 4.5.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.5.0'); src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.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 { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } .fa-rotate-180 { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); -webkit-transform: rotate(180deg); -ms-transform: rotate(180deg); transform: rotate(180deg); } .fa-rotate-270 { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); -webkit-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); } .fa-flip-horizontal { 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 { 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: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-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-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"; } hugo-0.92.2/examples/blog/static/fonts/000077500000000000000000000000001420147000300177165ustar00rootroot00000000000000hugo-0.92.2/examples/blog/static/fonts/FontAwesome.otf000066400000000000000000003261701420147000300226700ustar00rootroot00000000000000OTTO  CFF R?EPAR*0OS/22zU`cmapL.head 6hhea nD$hmtxw|h maxpvP0name'x8postX  FontAwesomeC   U6U6 -r-k ",04<>EGMT\_ehmqy}#)4>HT_lp{ '4=GRYfoy &,39COVcoz"/5;FPUZes}&+16<EOW_hmqv| )04=DPX\aju(,26GYhy %16;>EMUckox    $ 5 G V g l p v    & * - 0 3 6 9 < ? B F O _ c u     & 5 B Q a f m t y    ! % ) - 1 5 9 = A H L P T X \ ` d h l p t x |       % , 3 7 ; ? C G K O V Z ^ b f j n r v z ~   !%)-159=AEJNRVZ^bfjnrvz~ "&*.26:>BFJNRVZ^bfjnrvz~ "&*.2alglassmusicsearchenvelopeheartstarstar_emptyuserfilmth_largethth_listokremovezoom_inzoom_outoffsignalcogtrashhomefile_alttimeroaddownload_altdownloaduploadinboxplay_circlerepeatrefreshlist_altlockflagheadphonesvolume_offvolume_downvolume_upqrcodebarcodetagtagsbookbookmarkprintcamerafontbolditalictext_heighttext_widthalign_leftalign_centeralign_rightalign_justifylistindent_leftindent_rightfacetime_videopicturepencilmap_markeradjusttinteditsharecheckmovestep_backwardfast_backwardbackwardplaypausestopforwardfast_forwardstep_forwardejectchevron_leftchevron_rightplus_signminus_signremove_signok_signquestion_signinfo_signscreenshotremove_circleok_circleban_circlearrow_leftarrow_rightarrow_uparrow_downshare_altresize_fullresize_smallexclamation_signgiftleaffireeye_openeye_closewarning_signplanecalendarrandomcommentmagnetchevron_upchevron_downretweetshopping_cartfolder_closefolder_openresize_verticalresize_horizontalbar_charttwitter_signfacebook_signcamera_retrokeycogscommentsthumbs_up_altthumbs_down_altstar_halfheart_emptysignoutlinkedin_signpushpinexternal_linksignintrophygithub_signupload_altlemonphonecheck_emptybookmark_emptyphone_signtwitterfacebookgithubunlockcredit_cardrsshddbullhornbellcertificatehand_righthand_lefthand_uphand_downcircle_arrow_leftcircle_arrow_rightcircle_arrow_upcircle_arrow_downglobewrenchtasksfilterbriefcasefullscreennotequalinfinitylessequalgrouplinkcloudbeakercutcopypaper_clipsavesign_blankreorderulolstrikethroughunderlinetablemagictruckpinterestpinterest_signgoogle_plus_signgoogle_plusmoneycaret_downcaret_upcaret_leftcaret_rightcolumnssortsort_downsort_upenvelope_altlinkedinundolegaldashboardcomment_altcomments_altboltsitemapumbrellapastelight_bulbexchangecloud_downloadcloud_uploaduser_mdstethoscopesuitcasebell_altcoffeefoodfile_text_altbuildinghospitalambulancemedkitfighter_jetbeerh_signf0fedouble_angle_leftdouble_angle_rightdouble_angle_updouble_angle_downangle_leftangle_rightangle_upangle_downdesktoplaptoptabletmobile_phonecircle_blankquote_leftquote_rightspinnercirclereplygithub_altfolder_close_altfolder_open_altexpand_altcollapse_altsmilefrownmehgamepadkeyboardflag_altflag_checkeredterminalcodereply_allstar_half_emptylocation_arrowcropcode_forkunlink_279exclamationsuperscriptsubscript_283puzzle_piecemicrophonemicrophone_offshieldcalendar_emptyfire_extinguisherrocketmaxcdnchevron_sign_leftchevron_sign_rightchevron_sign_upchevron_sign_downhtml5css3anchorunlock_altbullseyeellipsis_horizontalellipsis_vertical_303play_signticketminus_sign_altcheck_minuslevel_uplevel_downcheck_signedit_sign_312share_signcompasscollapsecollapse_top_317eurgbpusdinrjpyrubkrwbtcfilefile_textsort_by_alphabet_329sort_by_attributessort_by_attributes_altsort_by_ordersort_by_order_alt_334_335youtube_signyoutubexingxing_signyoutube_playdropboxstackexchangeinstagramflickradnf171bitbucket_signtumblrtumblr_signlong_arrow_downlong_arrow_uplong_arrow_leftlong_arrow_rightapplewindowsandroidlinuxdribbleskypefoursquaretrellofemalemalegittipsun_366archivebugvkweiborenren_372stack_exchange_374arrow_circle_alt_left_376dot_circle_alt_378vimeo_square_380plus_square_o_382_383_384_385_386_387_388_389uniF1A0f1a1_392_393f1a4_395_396_397_398_399_400f1ab_402_403_404uniF1B1_406_407_408_409_410_411_412_413_414_415_416_417_418_419uniF1C0uniF1C1_422_423_424_425_426_427_428_429_430_431_432_433_434uniF1D0uniF1D1uniF1D2_438_439uniF1D5uniF1D6uniF1D7_443_444_445_446_447_448_449uniF1E0_451_452_453_454_455_456_457_458_459_460_461_462_463_464uniF1F0_466_467f1f3_469_470_471_472_473_474_475_476f1fc_478_479_480_481_482_483_484_485_486_487_488_489_490_491_492_493_494f210_496f212_498_499_500_501_502_503_504_505_506_507_508_509venus_511_512_513_514_515_516_517_518_519_520_521_522_523_524_525_526_527_528_529_530_531_532_533_534_535_536_537_538_539_540_541_542_543_544_545_546_547_548_549_550_551_552_553_554_555_556_557_558_559_560_561_562_563_564_565_566_567_568_569f260f261_572f263_574_575_576_577_578_579_580_581_582_583_584_585_586_587_588_589_590_591_592_593_594_595_596_597_598f27euniF280uniF281_602_603_604uniF285uniF286_607_608_609_610_611_612_613_614_615_616_617_618_619_620_621_622_623_624_625_626_627_628_629Copyright Dave Gandy 2015. All rights reserved.FontAwesome aoC  %)M16=_fmqu|:>BFRhl'07>CjZ^)5:>CGKPTY]   & - 1 : E Q U \ b h m      ) , ; @ G u y   ! ( 0 [ e q     B F R [ i n s w ~   " , 1 6 > C H g  %19@GNTn $)>LR^jx} -9>EINSh}(09>CLSWdk} %+39=CJPU]bipu|#16DIOX_ensy %-28=BGLQ\akr}+ ! T fAVS @? x lfPzz  c 4 B KH K\j l vvo K KW l '  l  /@EXXE+y}}yKd:+EXXE 33 33 (  `lT~~  4 fT @4 s ) .TO@O << / 2 A 5P y_ V- ? G c < A  M HU ; C < e8 }y hnnhhnd  (T$ E  5 nh h w  y} } y}}yy}}y^ w ʆiimdod $@~ Kz&w{yyw}| |}xz{wa&zK $|'˒a . 9 - |zKz||zKz|K   ff ~ ) T* U " Z $   o ! ) T  [=s T , }yTy}}yT  VT- T? `V hh h@@h |z b c k  j]^hYE֊ׅB ?Gߩмqٴ̟'(͔͂z'w!q=wVF7HJ?xs]C$ 8 8 . 3CC   z  W (K$ hn .TO a T0   tkQE;wOVVOcZwE;ɩL1HD hnnhhnnh =  J ! TT TT} [ A ;(=ZXWG/9;/_Mknmn9:YIƑP`q~d_i iii G! } . 9 l - F/Bi NPuc]T!o>9U G @X V``V}~d3fTw@t(suwN5~w}+}PV q y}>  rcrr jih t <<rcrr rrcr     tp    yyrrrry * t D$$D !5   ! MQ :< 0A  &T+ 5e 11e BB  quuqqu;;uq tH t ZKS  { * }t / `   `uttu~w STdJ,]շ49 arwwvyr/ (DB%$AΌ 4 4 x T s wrr   Ez*6z*E!  0  D$$D _  yy >T 8 ;; ' : y  TT_Ld g__gg__g ,l [ ˻WL @ E##EE##E  ~w] NTQ    o"7l $> j s   P : G 0    << x G z{ y}|z !5 $$   l c c   $ EQj ip q~ 1   @h c  t44t :z{ `M`M   - t) & ( y} E##E i tB   ^ ɽYM s%$  *10 B ~v `V ; =  @@ yT 5 !4 ,$P++ 0 h  0   r  ^ w  z zz{  \$"WT f  ` S Z  j   )Wbit     }hv,0/vdpW  X 0 8 F  h\_h3`7cSg4^ 3U^ VIM I | !?!""m"""#h$$%%&':'()X)**A*}+.++,&,f,,-[-k-./002)2=223Y34 4G456B7C788H89s99::;5;<=<=>?@ABB]BBGVGGH4HIIIIIKKLKM[MNO?OGO[OPQSSbSTwU*UVOVW`WhWpWWWWXX XYY;Z$ZZ[2[\\]&^^h^^_`V``aAaabccddde$eMe~eeeeefffYffg>gGg]guhh hziEij"j$j&jqjjkNl0lmOmjmn@noowpqqKqqr0r}sYst2ttu9uvvFvwvvw?wxTxxxyy{yzwzz{ {}{|+|||}%}d}}~=P7>.0;=1|Ab#*/+B%V;jR!B'?h$:'aPÉŏzưǙ_ȿq˟b́ϓ$)lաV׳ءq0ۥb޼cG8]^>:<?lBsH[Na z    ,   ^  t>".GqsuA1 A nA 3 !""#N$[$%F%&&R&&'( (*;+,g-f./0001M334557B789z::;X=>?O?f??@@k@AAB2BpBC[CDCE+EEFGGHXHIJJJJK KLMJMN#NNNNNNNNNNTt TT4c 4 z..ȮhKhh3c # ^uiƭRl  @- ? FMffMZnnw   c  `Vc~ofa[Y  T=  @suw#$L>$#69JX"!!`V+/EE+V1RE __r@3CC3e \ ; p]  ksu[ztg U1 q9 [[9:QQ:Mqksu[ztg U1l vVlXXlVv6*336W) Ki l  i4e @ { { { { \ R T1R `VV``VTV`ԜT1\ R T1 TV``VT R  TV``VT TVTV``VT  ^y$%'+ hhjyy''+ +  ttB KH ttH K\tt jtt=  H K\j= n tW&S:aR`S:a))6 z6)õ`a;R`W&tP;;QEEQQEEQь STT@kmzK}zaEV" nmloL{yry}{{OJNll~n|i&js^^[{m~mkNo|y|rz{Kpijki\f_i]QM[!|Lz~rǑ̒Ȫ'fgiM    ([popHH4h l nnt, s~oJ,lW`aGahc~v~AHHF!4t4tt 4# ){||||N g|5pp Ty~}y:y~Tppur5|gccn_Tz} y}}zT Tdgf[wXX[fe? tqT% T TT TTlT~~ 8 6(' TT6k,T,ThXhYm}}chhcqj}}iVgvW wxrwwvttv# c w!SY;;PylD&)'C3 Y4# T[ t}|}zcesd,.9/F- . T4 T"Q>W"SX5z|[,9FZ3} T[ _ " "" T@Ա Q @3CC3e TTT T+ kT^^^^Tkwh ]bt\jK__=1lno1"-SKq~n}s{x}zsz: ;3n L T T/WW/!(ZMj: kBP K* k+8V=_GxɁHKxMG_8+  Me e N-hnog? ?go e N-hnog? ?go_QPox}yCQ(Csyrp}t{xodPQ_K n{}|zx8 S``*S8 qxozo||{}s}|{n:  K     ;x ʪʪꪫʪ骫kihvvvijiʌq|1|w|||1| g1| | | | Q kllqʁ qijivvviijp )p 8_^X*DtcX_^sjii}jttjjhs, g|vtywxog`vf/TFw.qra\zzzaM{tswxyzzVc,sj|wut{tv\h2p]yx}xzuxWi:mY{pvzs~{sww}e_^#:/r8u 4S 4K 4"Kme,,eBV4K"44"4\t4T? 4t* T33333333T4tXr=EE=UIrXt` ( l PT, ie%/,xxx(((#Ɏ wR'VbgfVpoqqq{\/j}}Yh^?DFG@EatV@ha%-n<scsŔO5*VJM(0x[[_}~ %;AHW{'Qbgfg FIGf=R!Gv^]^z8'n\PuH#hPMqJK{-ЊxġMMN[ĐơϦԖУ!!!x$ǁΓmr;ni~GhftnOlFKwz6 ;p6p_ph6hpo;_}oh6h6}_Ǐ\|}Cy ^^^LuZq< R eptcCDC  ǐ]|zb||}3mrS667W, "< R ~yv}u ] y]h vp|zwwzv {y{  |p hy ' 9 -' 9 c -' 9 [ y ' 9 -t' 9 [ y . 9 -. 9 c -. 9 [ y EEEt  @\ tX=l TX \ T: H k utX {tz{~'&9+ T'T& T&:'' )TG4444Tl  |z@ g4ka@ @  xD~~UT448~sjiij}st:944::,mM NLT_p’tH @M ϠHGwwsr@ mXXj:bkkcv`~:jX;Y;l-&@yyL _  S+,,||~KK. fccL +4444400f,,fMff// gl }{|y~wj. |z@ "L   {zt{tqT4 7\3ulz* p4Tqt   l KK.  fccL {kkYkkkYkkkkYkBBk   } 0 ` .  ` gs EfZE Z SfZEZZZZrZhlvlr|h@h|kc @_G_[ kc @  ZC ZZ ZZrwhZ c  ZC Z  @C }rrw_rZZ w. ::zzzzr:: ' zz:::: zzJb $Z !  Jhn~ k}2zz11zIIII{zzz1IIIIIIII1zzz{IIII{zv zz{z&vv,+&1zz6 k4y}}yTeTN T4,#Q?`\pnZt ҫȧPKgjzx}wy\O~#7@TKT k4< T.4O+.4O8C 4 4 44 `$$` $`${ $$w $`$9  #Zk==k# #kZ==Zk#9 #k==kZ#w #k==k#[ ]  &&  &&  &&  &&kK# g %''%% ::!8#  %56&{SjjQh[=<<=>o>n ^CT}s@skiij}sstDjt }sTӸ~ssjiik}ss@@st jtTC^OGGOTsDjs@t  K8sjiij~stsDks@sTC^ǸTs KT8@sjiij}ttT Ttjiij}tsA@sDjt t ,jl t,Qa! KtkvqCt kt Ԅ k <<p+>|Ri/8Crb{Zja_qV  P_ 44T( V``V N tY c  T s ^ nc  TT1 noqqon1 !5  Tft//tq:v++n+*mm*+n33+ äyppv-) mERQDEQ6 ERQDEQҌQE9},~ q 2srqt-}}N}}~ZTYprr~n pwefc~rrq/s~|~M}~,soppndmfnen s -}N1kmo/DD\ l y[  p6$7dI.3Tfo1\s\k <^  U/Sk ?Ÿj-@  +6 @ Dɝ·lZ'#ik}ts')2OKebh`i_mdG1dq^ nm]a".e G.3GNOH 6  t@K̬-*osr^ ?<k篞 Y xxytR]ssvkc\k}\vs򺊧1fzk~rvdOJ.eY$n:mo^ nq1d_`cJl2)t}ǏymD g  @KM>M>KR4)<5Mnɿ<5)4RP p];  dr3CT ~ϧX'T& ~ϧ4 {{{J{J IYU:=YϿڼWG j8Ke`bz|vw{ ̋{&,(i"z 4t4ToN T480QEEQQEEQ08: (y{wA[ _ l & . T/TL _@ DD D N DDl  + ^GofC3Tz ^Go  ^!Y1/)Yb1+ o ԹV``VRzf|Xm}[YKKkK+++K+K$>+++k˙̚zfR_L<L aNi`ʆ ŕXP+ ! t]r[t ˺?ApDU88Dp?? \pTTz{{z~TT# T~ Tp !8ZZ.n82Y\uZHm{(r^-Ʒ֫Ϧ [ {wx^^]Up[c\ˀtbdee  $fb%aa>"ipuleǞëѯ wC3. 4+ t 3&   w&;*226;*u qXsIm[FHNMo;otpлͩ&oxtt_Jdwry0Ayu{&Ay  (TQrLyJγʣMfEpB}P7.G$%Frrs3Xo[{TO(QVY`1(mpnnvww ."4X+prq/#>VK?ʹķSp.v/nQ1h/ p%]8rwsp TTT]]TT4V+T ,[ ) j @ @ @Q ttf g   TGzi.],++,]i{{}zyjpnjry''{{~{y#joicciq#44VV4@Ա Q 2t1v~z1vF4YtHAAHZEtYrtpԊ  c 4TttfT EuFF6!1=۴ n_F( RD\\ T$4` .G^SSG^J(@twT3fX V``V}~d3fTw@t(EQT!yTk`wrPNxyprNV[Pwrqqyxyprrwwr[PNrpyxxyprNP[rwwrrpyxyprrwP[VNrpyxNPrw}PNVVNPx_ 4.TO l FPPFs\k >\V?Ckk++JL@ =3`?.Qm\ibgbjnG5[^ nfuel.=  _ .Gc4`C>[B atĹixFP+֫ঽtttuV]]B1 s [GngimQ`?34=_`b    =acf}|}KKYS#L "K V?Ck1B]]Vvuut+PFxiԹta ?MQYKK}|}fca=    b`_=43?`QmigجnG[w  ʰ"l ZB xxyatRt]ssvikcx\j_qFPPFGOLJ++kkC>[J G! kfufs ^ [5Gjnbgbi\m.Q?`3<    =؉ˠSL@JQQ{z@r0060  {zz{QQW  00TQQ{QQ %0{z% 00{QQb QQT {z 00y &QQd QQ {z E݂v <<>Gww|&xjUt=N,BQ?FE    {tq z z w44@  44te takw$$Ti Tqt{stoy$$$$tqT4 TA $$v v$$# T-T$$* Wn|`_]#v:[vVi\\iVv6*446Y TWu܎v#6]_`uuu0n1W@^;Y  TT`4S2S@ zyrrrrybcyjdL djyddysqSUmtvwjoXV``VXojvwtnrry@dd> ybcyrrUnTddUA??BnUU'&UVlA?>CTddUmի3STk@< ?BUbcTmԨ'&* J,>i KQtd_O>Kj }|},D!/G  # # @*! ! @i##flA\3T3T K"~xF͇F6)-1?pWSRWn?=%(EUmþBB_XS-(mU6EF(%=?VXp򎬇F˞y\&sqb]NENewdG&NS6}dNDwO0]bqNñџsSe&GF\}w~vt:4+q4CKtېE,5  4dYztdV4VAlff,,fflAV4S T? Vi?fflAV4L444L4|+fLdUS55TTd..Ġ ..||eWT6LL6UVe[o!"m\à B)%h;=h&)CMe0 0 4VԚ44S ? 4{}~bx4TԱ TQ kmeeBV4@? kc kc Tttt\ Gl 4B 3 E Gl 4B 3 E T 3 E  h $@7_H,`djXg]SˈScfzhebpR3^v"Om(;.?GdFjPyi7voMyyy4 @(!?:::  (l T@sTz|@=\ @3/{pkgGR[".__ušȟmNgG&߅ȂAP_ATeAa6226^%OLJnpsosxZWS]{`lcmcbnXzyY\a\^cbhnnpszf%_whY+W~ cv͉ΒИhv9!݉}t{D$p_Civ9U:j\i9%9) o'0qi? ?@ieM#&nYA ,Ómxwr]9 FfH4 ze`c``c#NW[S 9Z))));7eefeefeefee)l  {r|sv>(T+J~ff~JJ~ff~J`  P ( _4 ,[ q nTT{zTTlTT TT  o 4 f@ @ Tq nTq n mjingr;<7 M7#?#77 <:fime B4@ V7)0[/1/^//10#sEAA*,?m6"mF=(G`$.ƣ 0n ;;YS<! 8sjiel{ppmoy,,yrrUg[giyxtq]um~~~~mu]qtyxgi[gUrry,,+ ompp{leijtt, MTTM@u^9v:p%"M$%MڑhiMMTTMT&&&&@;$yz%:@ %%_ T DddDWXYV_lw}v~v*AdD[  yo6$7p ^~ )?cwrvy~x]͈}|*YvvT  +TT? VԿT T+V``VS ? V+TT+? V+TT+?   XvvuuvvHNNHHN?0   1j j/ b zb zeU=k?0 ) $ 4S 4T˱ TQ K4ime,,~V4T? #x:4tT.H pF E 4KqHaZxuuvwtD6O'xODwuxaq\_ II_ \DD$2?? nzykjstz{ztsjmy}z{JlQeűťž̛{yn׭ |zT|a T`t3 `Tz|* tE TQ tC tu* 4z}|yt Tty}u tT4T?hnnhiN[cG=B^60QEEQQEhuI7#e  #7upjj_pB:1 !5ܾئ_Wc[7+447W 5!1 7EpF m;4U?ua[t RҢ&F & RD[apdu茆0 U;4mph]@ @h֦t t KH wK K$4` (@twT3fX V``V}~d3fTw@t(EQT!yT)T1 K5!( Phh4 tT ?0 4nh0 4nh0 :Bp|צ_)\tEQF!44K$T/T* ttT3T/T3T/ t" "KT|zKz||zKz|FT|zKz||zKz||zKz||zKz|2 E 4c @_4 ,[ It" "2 "=4 kS T? K+ KԱ Q + *Q _UVTk,[ )x` MWWl2M4" T. 4 4hZwrrlZZrrwZh4!""( "T[ 4l 4̒4" TtkH w44K k)tK +4Kk44Tt+kkTkTsTskkTkTt44Kk4 Ftˋ |g>DRTT˫kTTktkKh@@hTTx Tb b d d 4 Jb $Z W Z4 ~]  ~] Zx x P tIIP 4I I t] ~YY Y P IP I )g|ze3C4KGf9-K ) 4ԋT fT kE Q T ԃ`t4+V`@Ӷ+A: a 4ԃT Q TC3v  d_gg_ d4T Q TT` A EQ 6 Ԗ TNT@"RDEQRDEQb@TT@QE^ EQҌXx z  @T b'&Qk *j4a,t{ztC8qbbb{y{x{K  t44t224\<-7ʗ7-tD&c+zi0&H. 0,-##s& &2iGz@@RQT+c& &t  l c tV``V V`T5TTTK 4 &)l |~aiEjVulѬo70 XDQ547mGGT4+ &naxjigxi j(C(jgjixhi5'=='5G5 n5Y'=='5YihC ix5  T_-T5 )TT< TTr TTAOTTA 8TTC KM`M  M yy p< ZL )xIpm F m t:+tm F 4m  :+m F m HF m  F m F m F m ` :+t$as ^ na jM Pdioo '.X@Qh  @\  s]QT3T)&  Y ff ff zM{yz zyz  %tJjZ!! !"н $yf+/Y kzX,Hn|}1d Z\IێĬ TTTpK =b/tQ( 0>mUzxwyysq ggKgywxzpTmӨ'&h~zUB>>CnUU'&TUmC>>CTz~p> y 7Q( 0>/+=  K : Khnnh% T,[ P% t, wohhonhhn S3@B< ;|#&%6Nkj>hW@ x}pU3@@B< Y;|$&%6Nli>hW y|p* 9Iv]Yfh{osjeV]]nw uKJQT*FhltnݖݘƎqDA5%!*QTFhulstnl_a99:P~݀*Pk9okթ ? ]]?  DvD)D$$DK? ?CI 9 .. 9~`n ? TAENK ^ )T% 7;L9\XpqTT_4 9 $9 x#4@a T+}~| z knr]J'V{ke{ohc-#/&|~T+ `t{yS;RQPIODwt{K6K tqn;<-=vvkhF@8k!!7 ZZ ZZ9 %! ka!7 %  9 ZZ !7 7 % ZZ9 ZZ! 7 ZZ 9 9 %X ?6IY(uC XVYx\b66 PeSGQGz5:5'DN5(TKKT( Ta 4Q~~'1 A3ZpT2T7׷i ` ,9_7XT4  / TZA1 ~P(~uQ1  Q1.g TTt/ G]]CkVY  M yyL ? ? % UTUTUUTUTUsM- |a99az~ z |33z} z99S k <<`C3+ L 9{sYsn{xput}T4T~T>Tw}4TTru|utpxnurT}ynnA7  9 gggg9 % T(@WWS+}}F簰ɋf,,fMff zq{ttz{v7 % vxt~ t 4G{zs{4O!mFNB9x*}}~5W]4xG ttTc## yussu~uvqxTzTQK y7}TxvvxzT}xqvu~K zTxqvu~ussuTTt< T.TOT}yf dyDs4>$0K_|h)!Ch&5`Q?vk}>P * z|% e@1* %$?nPDsQ](E5UW+M3T)3w'T<|#P >}ykאSS8x_uaz`{{sk=Vjs#$6$$q @{_,1!T!1NH( t()$t t* $tTq ;>TP NH\ @3uk1@:6zi 4QG%/쎔|~}.)|}~}*1~|3"C3d4}3;e:}38i1..`zJ1Z.cbb.jjlh8ʟgk&wl`lK`\..H̢W/&~kSڡ#ڨZDpA4Ikl,,}V``VS @? V`k,,}llp8V`V``VS @? t T T )8 }3 | H4 )8 1H4 2 }3 | t)8 Q4^4^T4T^4kQ4>t)8 4QT4T>TTQ4>TTQ4G s=)8 І ma G =)8 d   4Tgnohgo! 4' 4 ,-3#؋Gt `aMPQOddlli`g]_Q+ fjoojhovuf\#ͥȅ֤ TnhgooghnG40  q~ )|mxrze`I3}y?z#\fLuOvhimohjo Q]`ldOQPMatGmqvin4^ːΆ—̀ƏnX+}j{xtzj1HLzii|E;;]SHv|~}Iqzxcypst}qv5Hίp}Gq|z{t}ypjip~rx}xoddnyr~Wvuyi0izj60w7~Q[`R|R[~wߋƻő|ą`P805]A]|s|z|WW[ dm}yrxq~jiqy}~rxndI mpr|rv|{H l Dzك{цԨ_~q|||||f|mm|t^]Z'X"-Ibgiwknvv}(]jvgrxhklm[2+*mxfwj]Ynwwy{hsfy\\hqxAzireV$G4]t~%]~smn}ft]fcqyJ>LNMMNwK=KQx<rCu)k,##,)CrrutturӠ,#ˮ&~'+'}~~}}3 +t4b4tD809mi%if+qU3? ==BRippiip!~b^^jcjc~9?>99>?9elleBel9Ble9Bd2222v< <g  k&]&8t#4#4-_G_G r 9*Hb=gh`̀, ް5-"MM/8(x,(90KDzіɕOTOm̀ցQ\Y5Yy{))+)jxYhmG{IUsV7=o{vu! z'f@o&d1caaPEb4"f|aunO鿦ɯ˱nno5.OB\WQĦdRۛ~-aOpbKI2C@lU[s^Yoc`̄ƃ~ƒΑ~vD,@aD1"@3byЀѐl"k"rbsIr3p1o1]_qewG1('$:er)n'y*ԧӥؘؒ6;2]zt[uns PDcl|P~_q<}Nx0k<Nkpti"d-"`#69VѺDMV"TAK$ `~tJ t~~@`@~t ttQ t~򕃘t~~t <t~qqPV]]tסжihhMD;ZQuItI[nt]FEQZ-[+@@*e-8;@@4uvǹߤ p7ZYCYCq5( >>>-r>->j7)1auabtavzyvvzyu:uzyvvzyvLR]]SBR]ĸB]Sx*.NZwR]ĹwwR]ĹwǼ|CNGCCG|pNC!C,313, q|]RS]^RBR]Ĺw$䔻kiᦿůI7Y=+kt}n~x?z}}}b;u{{~YP KS{TSm{qiTAsFGKiwzwo_ewkjZ˒lshztu|Цyu"5@'\ϊ؊sqٱ.&7e}|_g͗5|qD|unlaK]~diqqquzw|wʎó^=~Şv}M,7QupzTS(pzKYNGJ b/ѓcctup4K6gp1zyyr7Y}{w\ @wxFis}txyoGqt sp^)X )iz=JFdf|oL{1$+#~[G0`SQRne*wXjsIx[Ͽ^d7,vX9 ZY deҦt-tE##E)o}}4u{zu\ O#nWvZh,lt:$4Zsj{rglb1XldvG'bQ^{yqa|x|{jjs}.Ӣѡ?IY–Kk.#4)sV 1| XRf 7n]Mw]^}ǟxwVo] ytyywyB A'!3EMM!#] ([B4WtImnxWxWtIWȇ$rzӎlQ3J>Rq_(%vv==)G/H{uAR6=zkwlkkwllaelj{RI7 A5ifsgffsh./gge0lF kmiE#=[Z\Z#=EOiNQ@QyQ@QzE&}9ً܉{H[1N[GCJۋz"q*g2EKa"81&*a/rwxrrwT(v]*I0 330H 3 Tz|4# T|a 5T4# T?~~TzwwvxT24K Y 6 dpF47zw8,lr7RZ(x[ts[{+;f DK^Fxukrlqv}K ?(&PX+)#JU ^mmm jgenyiYW»ëP7iSպԤÎ˒rSppoG.B%r tTt TQ4( Zdz{ IP 4* . l  tQ) K* [s`C3+ L )4՘ΖT˫KT]HAF-"Kg_yz}>Q~{{~؉}zy_gK飳ܩn_ZZp_bn:vkbA*t%ndʋ̫44m4tbm++44kkLJJl.d |{|8S"1ÞH=|}}6TV5wSLTT=g}}RIcZYccYZccYZccYZc \pcdwywxRj.j.Rcoͭ}t qZbZZcbYZc\L gSVIm> k.L.k?+llH\\HlZ釧鏼0T T kcthjz{{z7LvvK7isùĨwлQahaahhaai?Ul[Ĺ]SZ +)**MOvrqvvq 25 3 + qv6!Mr342oqv*  )```NW{WM}|XLyR]^SS]TTVQ~ùù]SS]^SS]WQURTTl 4''tTTttTTtT a`aa`aMk`8aMakap`a9M<97Ba8M97Bagg[o2 @2 CG%:`dhbgbۏ֯Ȱ:%G?G%;adhbgbN;%GH 7@ Q Yr3FZXaXxwx_blkx B) K%Lo3BJwu~kuxuk?Oz!xyxvzAY Ϲ[Djmhl|{{̡ԡԈ֊ j8ч5T&9E Z$j@b<r(B{]<6TY uZ|iJC^E,g_zsyubՖӪu^@q-1ݛzJ1jI1jgTiԻ EY}MF{M`@]~tvtz,~@Y=U/0Aqtתdz}PPxvtnos~}mzVz-cObPru[N S=)id<&li@XsŒՍ0ZZ6:3W4U_U266WBN@ h[aj6GUv@cLj^HI,+T(jjc+,54+,mmZZ;ZZ۽+,33m0vH9*/o⩩+,44>4 q{7$//)9wh 0m+,54+,44,,nZܼۋZ,,>'l4n,,44,,44,,mZ;ZZZZ;Z+,/o-D/#5>'}n00nm,,54,,44,,ۋZZ;ZZ+,jJѲ"^ z}i{ѧ錐zss^myzSvnnU{uuwz~˜ڦLvewe :rnwt]R{ϝȹ̯\jtazm|}l~~nh~uN?MamJ}fg^%llI%uXBlznxj|Z6{&1~\NULܿI4'6kZ6nNwa T v  `77lf,,fAV4 PW?tqCCC44@4 ,-i ; KT C KT; KT; Ky}}yKy}}yT6 96 y}}yKy}}yT6 ttpfeOefxxxxeOeffeOe  8  *`7Q `6w% Y4W%*% X4j%1g6` Q7*` D4 Y%*&4 X%WT#EE#\[^hnT^\z.}TNNNiYT}||||}TYyi[U\`uTT + @ 8TjMQMQMQWm[FN$l\TT{zzzz{TT\vl]X$FN\vl]X4[^vTtZ TtZ Vo8>A , '>&&2uQeGWn!eq=s)b?ɽX/c o E`(yk2@ /POlAAg e1j*.Nz+8a{z{aY%#y=<==<=<<*```^+LPzlX1Az/-6D&@I`_B   44!3}|~jk/k;j:/d;jkjL`+ T'h uY54Y\55\Z56\~  q@-& T&kD>m2W._Z8nE 5<hLhLQRSu'/>0Agz8(ҒӑP0KC'ZL{o_uOn ɋ#xW{D ߥpBdȋeE)3 +57wp 44tTz  z 4'c7E 7D 44 cT(K7K7D ' t aXt Xt al&'y &'Y  } Y&'} y&'} bKHJjp̃Έb[ aouwr~'89{={mx<*e>okjqpi{AR*7}xE|}jp]VY0-|xpaime{}ld""p*}|blv\&A}xfa) po"_m3m"3s¿8~~}~hs׌ $zctc^_Pvv~w~yf{h{ Z~}}}}}||{|Z} z}{10df}itj\KMuTuzy~00kzzz <!!o !<Ǒml!D4CPWhЌnjʕ|vw||ryIs7h3^1c:gJlXJU>]wD&_nr6Hgdalor@/K&``m}",y }z~|{@Ë)ҧ̞ȭBO`)y)o3hm^Zx:F!4i 1J{z~v$${z~J1 E8)3y{||y38)E1 !4gVQG ?33A HWT! 5|x$5!~ !4t/|h7S.1l~gd`;!Ъwgvph  !4;TTT      PfAVS @? x lfPzz $ c ;44rn99l>SO~~zzK!4 EQj 1g F!44v{v}JJ}X}w}vw}Xe}w}JJ}wevaʁӎyLzzyӈzzyuYaaff6&̶Q HyA~`Dޟ(#PgQ+<3%!!!S|BDMhߺ ђ.-.-.lHs-U7sH<JJJ?H&Urs&l~v~||||~v}~rrrr}d ^)[OK0-npq D:)rJ?t~rIFo9$"%9/iüIIR^rdclmkԧ2*:8)0\pFN[BA\ŸghgGDDl)3=L > jRVVVTPQSyVVV:RjVVyVTPQSVxVVyÁ•VVRj xmŁyVVjRttF4xPp? px4MFqqqqv|y*|8 G}AIrw-u\? 5'p$ PY84I5K G3#T1!I%>HGUB&- -%bbd&-JRprvQiu,t~՗Ӣ9RMgĬx{}ާEvhrjplJ- ?&n@5dbbI,ueui`M6 fXPljiijlPXlf`M6`ZiRuL};pommop|;LRZM6`m[ [ƗM6Ġ|}+vjS&zzgMRjhed9oICAA~CtIo}d{fxgj ;v+Iz5&o? mjhĬ7;jjjjjjjj> \O+:xOa_UTS˄@gftXRweWWk :{z{zzy"J<%wly}jhw|m'!+\! ոϡnMbx7tttpopyjef{m~ Ǻ iii yzyWuf^ V]g`[[f_\ `Ujf#b'^jTm4=yBF$3P:kS43g߫ޯG@pFAw@UMMM%O&iWtLXU_ogBF bWR?d/yH(#-:=;ra``^_^rrukedA~ R?‰“wnmm(?+RVB=jȕwS<;QE>?F X`X4! 55 pqsa_^U^HKʲJpwm7ųu~`//:q~iykkkkkkgfhopypoon0 +(\fmjő¡CB{gtzldg{S)ik-z/Rɮ٫ސq,Þ2=5qnYVL9+3zZ$;;#}MwzVqzvy^oyzzUggTUT¯¯gT{fggTgg¯ggUggUTUgTffgUgggg!Mm#[8ICnyy|죢Ԟ[TI&%7~~Tvtsrv61psYMwpv~Tv~tsrvlUXqsk%]rn ;;YS<!  w? ? U bXkC_}g555333g}cm6ﳽmv%f~~O~~~a}g767/./h~bn1lp.[Rh5kuZi/4oe ^Wf7h7jvWi'2nfz#zCpisL2r@;pEVP<Q;Odlw}#>}x ƭ 4tt ttTttk7>jVRH %HVj[HR>7E##EجHE##E[ ++ +  heXuS + þuh  + ++ SXe  %  +  9/ː/4Gj{fj}^11^rt|qj|$$P|jBGrbrrKK& j Sˤr(Ge~1~w~~w~1 zz0v~0 KQ+( 0NT:< +0A +~w~10  dd> mcFr@:}77:@ڳm-T0>2tM2V33V2Y&Lt>T0-KKKKKKKKTtSTSTS@5gn~STSTS$5 H~HfJT gnT<}~}2TT~}</ Q(4tQ(\ Y:YY%$~~$%YY:YZ$%**44ool8II8oo44**%$Zu*  +  uHd8lhTwwvym\_u5^/7hVfJC22C=+JVhX[<*N?Y3: ]#"S:Y3N%I%%%%F%"F%F%"mmm%@5z"mmmmFFVmyjjgwrPE]}~Su8ӗ)xm6 |uw}un]~')kp{u~ y nkuptogo>4y}Ϧ)Q4  gyr=7TRyytvz3*WJttx~8tA&ysjmm}՗ J T  0 5c 0ta  eepZp %$ B((BP! (''$$ GG(GGs$$zhl?9%$ _{_{b= $ MM M MM MEQQEEQQEM0  q~ $  EQl  lT^_|_j-Z7BG:?)_s:y8CXccs{~syyyyzyoto֎~@,="H(`dine|Anq˗NJܨ,+@מaI Ɓ8%m^9^9&^5 LZ_mOMrqs7bh%7fUiU>!Vvj1 zA@LF){B90kMKpo}q4^i4c2!b˱̩,|l-ƒs|eW"}fڋ\GQ+L~bGDCd5.26J:#:t|mcUJmopmvn]TB4B@Dd$rvJL88˿}~=.|Նs=xzo<BY$lŖ›/¸le3k{ut~irgk{ut(ӥ`xnqx}p[!T77:_\\]k]: rZwxo_(|MfmWisu͐0|u~Lvkcpy}~uz{y\ƊosTuwurl{~CBm]SbVBMjʞwywkws~~zqXIHI}Ons@WJ-E`Ǜx|}jxĨ@6'r[vyo_|MgmWisu͐!t~~yqWIHI}!?|zvYaOD Vhx/Ym1V:FMFVmY%0DF/bbF9@O)nH4(nO9Y"Ω̵i&L̔+`~tvqazpubw& SJZu\ek pkfY ,F):J\^GZgmn|@~~rNvƯri_z{wow{vy}psV1}nso(>}>ptlN[XKH[ͨ>0 "?4'::''::',Ah"ttLR AS1 Sc1J@ֶgLXpjZ  =PBBPOA AOD=̹|ͻMV˹$QG̟^ͫw_BG.O`IΤwϓRϺT}c 3" @"7<`ߊmQ1ryt 8spvu:@rfqvu:@r_F />L6L!+Ohhhh[Nc92;1 y,((, mm<}nik<ytgn(Bnlmv2gW@TPQ~wezuEu@ :PBBPNBG=_"Z*y@u!_M"_HDJiQwrSrNG2JDt( w\Dx]nrTrN:BNcTX.]^ggTW-|cQf@+((+ll>vII<5 YaqT;Qvy{QŷbZ Y`qT;Rwz{Q9RIPP(*/inW|ϊL/b\04]O__@@e,l,} v)@eiyz ) v?} ? 4or^{g=Zi| *>薚=v*0} 9  3os^{f=Z@i| E(J-I4i^xz xY~**)(!= xetpq@tJ͉yiiylHXzdipsl_~UGJhsxyW9Yӿwyk]]s}zw~{mh7k>Yi{ ztdYgrn|oM򹓝gptx*kSk*kl1wGb_]aTfvst+*r\zheN;h_hg__hh_ilu~~$rfP|KEUfav,ɼuaaP@YT@A :~@7뀙v~6{ T4` * ** >TQ4* **) 4* T$drrZ\Jxk^kwwkkw^~|}T|zxk*kw U|zwk-jx T}һxjҺ\DE[[DS^mxH||T}.һһ\D.####k'V''8Ltt22T22 22T22O )$ xrOrmcqly|~"|yy|~ |ylqrkew}xt[pwtoptbptUkr#$Ua m}||}#V䕌OVP[d\R\D?G!cLm?J9_ lq1:KI>?DB(DD(BzD)ANZȼxȼXN=k:jTRR;;PPQ2<;5 ,$()MU]()++\TMqqz΂34ypm1 .oQke^ 'uv& ^ekex#B9o=9B]:#/ݠ"\&"iRex hB RXD@ _* pX@RchE:dM+A * [ $qf]]]U9pttp.ptqtoq$ #$ A#A$ #lL6HpAOYKI++srs I0"/rIHqqIHrﷰg(7]F$ gVc p'7)28]8 j @ j j j @o]" -]" -]" .\#<]i|i|i|j| 66 66Fٯ6Vg <- gwr r r r r ;A A@ !A@!!@A! @9ŵwvmQuLflD^A94wHMZXaǂݏ,|) *) )* )* ** )* *) *) )[OCPZ[P55ZPCO[[PP[(ǻ@:M`edeSO[/:~~|yw{ >g7.iczdfptð+&4R l^vQBR{xxgd~y</Rc4jc'^dcvYXwrlO[MOO[Olr}twXPYv@c>kPS/k_`bjpN1kI7+447o uU)4S'-{:d@G{ &zzEwvlmulchr]tbFs^[XVvN;mЋD1 %/O,jF?j}yykDvDK'wsxx l DvD)l _>hjthhjbgSgT.  T譁bjh>n_KD;Ds ^ ,~ 2+ \ suS&yprxo@nrR/Eoqwn썍c@ ";;dxpXBB}tq۽F Tdmlsur|jt[ttstt/t G ]]  43) \<B4i , {uNvQ*33Q~Fu{uv+NR-Xv T  vXRX,  *6xllsvr}jR_  )[=)R~[~w~5-!/4 B"~v_V=)[ R5 uqu f!D! }qquur|jt[ttsttBtt/tì|rPZ<:`jvg$gJAv<ֽYi}=af44 )5Mk4444_  E E TTE Tl TWTTH 3  TjTtTsR@6{@),\,)əEQTW IIs~xxx{?+)])+8s~T @`c Ti mGTu kc TTTTT//TTTlT T!5 1  4 a4 a4\ }}{ptrmg}e}Mpvwyۏ c ״( ¯#wmݿbt@r|kj>Slst=Sls_tiqnv„Ņ3I`QnN^DyagTQ3I`nȜn;((5;!!6ryPqhn}.d9=k%)}|||{zvvuyyvvx}̖ҹ֐acrppxswzn}{wvvDӍ⟳͂pTlZxeyR{o|WbeVHquOz|n*)j4_SnNe]_\]“†gwkrmn nny{ʼnZlvTdp@JI4X@^xԉjwvw@~ny yorpmue{`nYnpr@^rss~~xvvyv}yuwz{{|z|{}{x}~yz~~} ; `ˉˬ7y88Siˎ; Lp` d|jK='t< $k:tt $K^ \buBs <<[=:0  Yvk2  OTV0OUƀGԫafob~hGSwk9&&  gY8>%˻XM,ɾYMr}QQ|Q'%`em_Jppuiuzzwɺ˿gYv*ʹ%q-u*+?q8$@q+ )5x}2#xww;Q" 7=YjyJLkttTtTg[ MCΫ MC1XNgZ´[VmJJ{K/oqwnbI ѵvj+^ ` d^]  Ub[Քm)xyx^HCii}l\NJp" #kkgko t c7/{{{ ` zf+!` lln%( 0 ǓEt^+jffllɽYM{{}.}PHT/7qͻ]H{4cycq_MYɛǦsjZ\ !}Zcdznp% 0DRɹXNMTYNdkdEXÿ!0WV~Y6R}XcP^Zt|z* z_ q  }z!~q{yzp~"{}~{=UP? Q={~ 4Z]41YW36ЧubQEd]"* T$>/V,'t> 44'%YT8?9|2'8 (%XU7?9|3'94> tt++UUttttC<<4444 TT UUttttC++<<44\ aJZZZZ44cTSc++TS33ZZ> DORKPKaXWaaXWaaWWabWWa 45! 54! 54!-..-......-..-..Xcccccccc0ɂь8`a@aNdC9sbccc@ccbcX9XE-JF,bH5@Y&nË49HbFs̷N{R{ `_`_`_`_9''''pqD-A&aa-D`qX_1`AMtCC%&*)GGbbIc~c͋%)Gc͋cBս_k3PD33DD33DjKgl:VF_-zMWSRn\nnnn\nZECSSnn\nnӾN+F:g˝VC&&ӋlgZG%%GG%%GG%%GG%%GP8 X@ 6DD6srpsG4Tmmv)t~̩vVJk}ltu(vumm $O?$d`zw~y8Mva\tiN߶܎`4s~nkA["gwdLaG$lΥэv~{ҊꅮK-5%L .U \  @j<Z\ fzd?* 1"0-)/!U=ITAIzWdd],O+2=q4{E)|肙i54_:vxH|Q̋yPBCĻ*O8Qz }y2!v\ 2!dx%%uouyf"2E"ciP8+ H>VV> 8PicE0}D8F?:/5mV?_@)*_AUm֡F8~_ :hI K6AOR||| 7::-R=6jsnVK {Qr2w..4$<1Unk;HKTC$[EEq;rI/(6F+G-7+`=(c2F]U=PO>Ul gT|z TeT t3/t  KWWKKW#1bnZyOL/õB+ h'X=-k7yS[rWmK|CO]ew,i@RF˿WK)}xyk~JJ?X7gf3.x,+.46?JGXjkځLJvl~doJLN*4A@Pbaul~xyJJJww}IIJÐN~LkR{mmaUULEC><;;{mDRs*MSPwms}wy<u|ƌ  Y10 Y 1122X48C1£dzʧr]^NJqZoe~|Z~W43XV32X+1fIHJLh67:gfs˂uncor~EMUUaml|ؚѩʵɩӛlG@/' "vg9~{~iyenaMxxw^Fyl}l 66xtm|cw&LL+dtjiJ4qq˚|O)xOpYpZ,,pWwT,JyIE7wt4vQ^6_ c wo K KW l j d ( d (  @l TtP K(t[ttstt/ 4Q3>t# +PPPP]w~PPPP QPQP]PQPQk# ]w~PPpp iP#\ TO ,-] ] i 4tT_`b#w #b`_ yyL Mt33V22VN (!!yrr. K0 , !! e+w TTTrryy!! !!+ @  yuw{{{s{sqvwl zz zm m`mm\ H @= = = = %%WBS qg@\LP{|@)҅%_ ``@@@%% \h<;v-;ݯ].Sg9GFXVi_d:ftl\mM>U:\!-B o-Bvˌ{bє~8w F2SXtegJ]lA9HH8QXi[syxy\HN-fXR22"E`B5 3352E%%%%W*~wwwwA.#C'K]fT O'R/+,{{a{L{{44   km +{t ?0 sw{    oT~ƣ@V 5!7EV@p -F1M \ZG#n' - ! ϼ 1-+q >P * ++EZ[spkT\ ~O@GA BHEB Bc> ----mJ#66"-!!!p[mmVJE46H``Z[|]~c`}pG;-7-m{<8Yn,=auKKvQ.-QjKs[hshs\hF:87s;\Fsh[t3]-3s\hsht[h"eE!sh\s-3~ + ** * }Mz]c.p%$fM55277<&UA++Kq5PPm;XY ;v2 ,TTT ttttk< .O8T tԁtN P * $ Fh͉yy}~a pjM M jprk5jThh i itt R*N^Ȗ* RDejok4ph4hplh/nh4nh9joqjhp4lh\ƙ;/ ;ǾbP0&M q$ ;. O ; $9 q&MsT |~}StK|}Sth =h u=h ttt*w)))((.ddZNNZZNNZQ+A@AA@![  [c `@ W0+. 4wx{0~}94l 4Wp@   &.1<@EIMWktx|#'v ")-;?DTY%=BFNRW[_~,GNY] BGKchrx%.5:]ej,27>Ft{ $*5fl   ) U l u   = H L ] d k | ) 7 I i s w * 2 C N S f n q w & , 7 = F L S Y ] b g l w -:BIPW\q ,38AHMR[bt!&4DTZbhr| #27<@EN\iw $)5AIQW_ejpv{<<T'T& "  t% M   33 0 y}}y : ( 33 ]]]]B TS  ? :  hnnh 9T KTFTKB KH K\ H T\ @  @@? ? % y}}yKy}}yTJ < K. r O8 4 , d N  (  ]]G }t ""  %%%%%% L 0 X N   +  z||z  ff m Tm Tm TT T|zf '& & t R }y J r )  1 V` +[+s/+ " @h `w _OG`E}n\>l9 , EQ |z@z||zTz||zz||zTz| @3 E  - y G~ - YQ ffD ffN~ DRRD } -! O  Z 4 ,  T tzuxu[Brlmyz~5qsU RD^ .    y}}yKy}7 1  TTM8_^X*D4 4D*Y_`t, _@ TTTT < . Bi  ^ D lnl||}_zob^^bzM zz zr^``^?a  }D}}k K$  _hnnhW   0  ~ < T. .O   yy ! ` +t!t      |z@* Tz| }t.+ݭB @3 j l  1 F 4m  6g _ c   Y nh z{ 8T(A(A(A ̍t|~}: @C ~ ~~w~ B T3 Tj fz\J$9:lA . O  ~w]]w~ z  R !!PTj ; %0  ZZ @ ~ o E l  ,, , ,   +S S T?   \xcikvss]tRatyxx h@@hh@ { HM tk G MY } ~w~~  V @ nh ttC xyots{ pttp&pt . 4 QK* _ !- ! < ) y   ` n +<< B !55! QDnty y  @$$@!  QE rrcr  r  p] w__c $  y'& OG  qt ]]Ch   !$DD$ `F B && cesz 0 hn + yy  > 4 z |z a `=db97 haahi`ah <<<< '0cGv=< !  `V  Tt y6%6- _$cX ?}|A ɽ  z P@zyz Nba] ;   @    f    c    ' f RD 3 h@  DR  60 ++P, -  EGxZny /  , _hmx     }y XtxmihbW_)   z} t $4 z T_  5!  `  qt{tsoy 333vK _gg_ &  }jii V @hh   ] ?  wkz||   g }y +: s}  ^   f    %t~  nh &m/ ofZedZd rsyy'& 4X *   ]] @   _33spyrs@  "" n@. !"""`>N^fin~'(.>N^n~>N^n~ !"""`!@P`gjp ()0@P`p!@P`p\QA0ޕR     lT  7A[_<Pt@  npv_]yn2@zZ@55 ZZ@,_@f@ @(@@@- MM- MM@@@ -b   5-8@ D@,*@  m)@@   ' D9>dU*q    R     @ e  %RE    $ k(Pv/ /: /Q /Qc    ^ [ q . [ $ [  s  * <Copyright Dave Gandy 2015. All rights reserved.FontAwesomepyrs: FontAwesome: 2012Version 4.4.1 2015Please refer to the Copyright section for the font trademark attribution notices.Fort AwesomeDave Gandyhttp://fontawesome.iohttp://fontawesome.io/license/Copyright Dave Gandy 2015. All rights reserved.FontAwesomeRegularpyrs: FontAwesome: 2012Version 4.4.1 2015Please refer to the Copyright section for the font trademark attribution notices.Fort AwesomeDave Gandyhttp://fontawesome.iohttp://fontawesome.io/license/hugo-0.92.2/examples/blog/static/fonts/fontawesome-webfont.eot000066400000000000000000002122271420147000300244260ustar00rootroot00000000000000LPj^FontAwesomeRegular$Version 4.4.1 2015&FontAwesome RegularBSGP݈YD MFx>ޝƏ)[1ɵH-A)Fٜ1fi)׺U'&a n;c)2nb$'3JV䂡@ꯔy|[\AXFCp-B̄ VܭU_^dV/Hvsrx9*cN%]72Fb-$}3*>q5N6d狲{*q%}BH$Mx{2ꎟ } d! C_ ugƒK.~Ey:G*# Ot5apOҌ) Щ?HVCi`@'@8(P@EefԌ6aGu?e$k DYyC6$FLfV2v㵦UklI&\β[/*d! l 1 D X̨ CH?d. }XBsH'_5 D3˼Pȏjmx׉ @ v{KIJVЕ4p%QH, ¾L|ݍ9@_NS%3hԳ̫G|EH oǙFzk_vȍ2&䅐ZۚII;2H!#nR5Q>YT!~JZf~ #Kiw躛jzd%>aĸ:)ˏՠפS`@`'`/>í#npib?X`_Uʃ(7W,G  H݂A vqߥKEeYbf[<',y j}G c-\\w.<=K+z>jܠ"B'kD e( DbI:Jj)ƴ=+canL/6bVHN}t/ӠvPC2!G \"" L⿅e(nWI+;\M $܎~УGu"0 X]-[Og73gfPE_4\e[m]S:ŘeћG;8Y ,3`2'5Y71ߘLL>54V9 P.VI-Ux9~Ht=%'ng < *3F'y?#[/Jsc $OeHH#F'Lq'kos!hG<Ƚ|4t1BZapq WӞ|:櫌SmGhN 糃D 1HVƵw  W鈢2?J ă0(8 ZJ!Vb;^*IQiuY`sjF T* i1@qJly$q؉Ű qX0@]0& Rw3l]yT8tyJFtiYSNmU&S2nRRUҊ[ #-?Ӹ}yw :h: HG 0 _c`pLJB"j$2c: G2ƏWobh`/%6)ύ!lܢX/ I8]^o { ]dr^O1u,4,R[T??*?Kĉլf;fާ451ЭN3V)'`P61wT,cr-MSPTX Ͳ`,Bt,9uBN0/g [\y0tSx\h)_B.F7o[~7\m𲇂;X}6ĄQ"y"A`=ZI6T'lO!k\W#{z͉%'R։ ۈ]򗌆 CѩM:>_.(4_ƃ|#*+k[2L2u$B9-4.(e5,=@B!{ZED-(%2gsLih[#ϟ>-@;:cEakJ=F2υ'D tGuMޫBz( Ca("% s2K$ﻺ^oO V{Yᵖ: 4Iя5%onm] \:DP;/ /ȸeE-w^&9:~gC 7Bnl,wkf'>>I If3^5_jB@5.@5GqH! R= O[aDgA@Tɧ7.JVxB FuHG1"* hBON8U) Em* ȩ0l lF k,!!I 3 Hn<6@Yqzk 3Ģ3)Q5H[ B hB, Zı,4Z_+C df)]F"k=Zǹi4@ᯘV`T*d7i.Ge]OZv{TmFc&pUq_ 8(z駪jD9XQѤ7, CKMo9CH2g:d]QSnj31jnHxY!l, Y`O<@Gh0 )KAʘa$̑p2HCݸzE3gs7hc<8P)1" x-%/ Ϝb|v~6^AdǑNS'>=Ba' ^ً[.kܲ[bG:ëGEKm&!<7>$CSA uvJT-=c*dX7yҵ7؟ɵJ*6Fvg=璚)N t|:'LQ\6Չ֯&lņ(nHe(3g Q` 8!,,5ށٳ81 szW/si !1;4$g3^w"JtB06pM+2xINP=&*T뽒sZ/Z-0jgYSU_s`Uc`aD>WЦv`w,A .j׍*BǐAKXml{C@LF啴5<<%v*upKI&}*lR{_ ~ʟ0ï hA/>t'u]Mڭh*x !%MVJ]e l .`4\/g߂:FM"Gqiw2'C(e3P{0R$<# -M8@"tÎRjuGk_-`,tIԺQg4c(cl̠hL8E)iݩfmm3 ʻc (\ѓ@4YM'Du` ,e|KEL~%6DUf&m@xT&wV, /' BJ"YC:-!cvkb>ۂb>{d-@WU8AڼRXXbmF2!Xt6Mۑ~B J6\] ~`x^ta4 \N,7' \7A;ҁH "fp#夶`:IDfT6p#MH4^=[!q(Surm?WQ[Э1\`Xg 13>ŲJJT *]U#թ^\ d 4eKo]D,3sb=O62QnD(5)kp_hsCⅧ‰[ԥR8 1d9)$FXˁPx!]NQSw4,IpG#(4GaQ$b86Gь8 ũc`te[9O# $2L)Nn4ګdBY.һޒG=hBxAlaRUܶ.98ЀqL<&܁jԔL.ǃ9i2 yRkҳT/131'@hc hy-)ܘЬK;(MU}NL@OHOB$gKӸMQ4T;`K7JZ(~Kkk(N0Ma%ehl$Y3H]SuO+' V{;I,SC+J("ORIV4[F> !ΛQ3a$4da?(aٺN!EgsWmo>F!Jђ4{T4A (^+42/h5"m/)E掚 c U!`S-ꄳ @Nѓe'G돂n)4VUNy(@HUJDB@NPvEW|4b!8hU}(t0CL/-7΍rwQaeª#mᥳg$:sC+Q_yGnLF@/@psXtPC;v#;?4x&q4߳ѻ2? m #QGHyM > /9j:ݼBuTkMNmWse md#3ƨSTAhqS4wCŔ ̅ P]#C, *@B(볂ܡ}=>yQ1`_g%|&,x#ΘsQZbCLS=p s<7Yv4nզIa2:;t! H/C |9iB/Jgu y`fp2ل7Iu΂s`M\s݀0˳+8 Eg;]cGؾPL%|/ȉa }T9hi Rfݻm#Jզh(7)0Oy}1v*z@(]U%6_q a(AjgE  'fN#~QlG)/-pS5}M*A,]SMCkv8O{M%7˝8,Q@8hG/Yt",Y `4D -V~p՚cA2ߝǡ4?aL ;šRkYz5=ho<8kɑS1 #(%A%(V^<#Kq?Z<8:sF<<:9iiG@GOI "%P͜#HB)2K´%T F:?ʼ?뇶II]1 P1FMHN=4QXc'ZE.eetE62 y`"CFQ#kqx9r>d=@L\H,eBE oj_U@eɏ).qe|)ϵ-Wًp-P.\D#芳w$N@ΌFBQ<8FuYV ;,ӄ!LGg+-Ohű AE<`((u *zN3b %u"nrBu Ńd |̙4\U}HYEPQ$F)ؤSCeCCmPㄊWt$A\W3R(<2s̋ST#F9ncI4URK3$M"Q- .j 5L>?-"ZG= .q `0N7 p'Š;C_s0 ѐe]Wvp"ʛFl+ ,ƏBhHnwg4>\ATRYEJ$m`"#&G2|b$Nx k8?v_oWf3 &#ӤdiHaZLr~f(:'҇wp4of`0Y'[ЄX]4V/VƲRo3Jȓz1wOfވǠbDI 3 ,sC!)}dtz)`t.=!݀O,ʞ0Պ[WOY%1tlsPN|%6;"Ry6Aaĩe cuPS,%|~ $y =[49ees*ZI&#̚]ll!E ղKqNn㈳4'IhN-Ģ z䍣K$Q^spUIN-6DlRg!@h@;%Gf 0(qL'3Z;{]gC¦?I7EiT.L_$JI}TXc~v<%RPb2O"6}uT;aGu( 3Fy =b΂UΒ(]$f*PN'@?IrS8}JPlsKuSNӐ[lPٺgf&[EkeO9KWa҈;1@Is'̊((iI>? ##o4F&Q.:.P?ۋ ʾ4}R8Kk4P)B1z;᧑Lުr_yPZRdƯ7fHºw@z`Xwe0#QhR9?MɷeoiH1*LI?/A9ݒioO;Nܹ si$(˷1"e g | V`o>7#P_W(? $p +XKz(GkGig0!R8*_*$Ƅ1{:~Ip(pوj_ҧM!!˵m:kyi㯗zѢ \T㩥VBpNfB5w\erP6ȥ?9U7k6qB~`l c+xn ^\,/f)SD=ô꒰_ݲaFp q L$1Ur8&,^he?Y_^lK{]b>(Q[>kA/*ʄ9(xKU,td !i2R= ,C&$mEBJLBy|H/%*s{zw@ tXՓ,.MtdP|_BO|mr&T~հī-`ZJId+(&ߴ*4,=gз@fFc ! =eFy3rXy?*X}X*JFݩ1z;X.,>kGX'DZG.PYYq /g,$ 0,(urSKiƔ%9PQh+/xI )ǟKfx0yM/#+s1d (bfđQuJ 6-jfƼ^R[^;tL 9d ¶ sah5,hB ;E ͢Bf<^f u#}$3 l5Xm1! /l NАj9m GAPE-d ,~pJ` w8qZaL WTTԖ ǘȘ"2YcwO벞!uπX#0C~_1VSv,u (`$cMO>$%ͰbGMP&sp0dCNVqm'Ő!72RA$˞1;lp$(0@O?FcԐɹgv3mOEe|o~X6ms'SO%vjwb`)&9H;cr(x:r:{[f(d<'ܧ ƕS+%UU|(1i9S|C PtP "Bu!3栾l뎊a >1'((ăw:@fA hW7Z`,/T# 8aeT J_1̍-ŋxH [Sy۴\TTLG:LLh,MG֧G H[c]> Olu4"8ԭ=U* <`Yf$µ.@9"}D9тq"t8k'4{F҄V_@bhCс(qlu>啢N6/YqUsi~8(By=ApYz,´\tV52y+}aB=1.XCX} 2 `V_4("4ݕJPBZ0"_O&de6@M0C1๢$ՎGMif{?^d1"lsś]R6`@[$ zQ{9Ev[: e'KJhd ƌ ٝ:,`İ$'ъ,g")~f\9\?50NT lӫ^H-(2!)}oG _}y"osZ#L(@܀fCy$~IόL e8ڞ8_[ȅ7[Y $V E[sڱE3ʌ}J'-,8X̸ 'X(d7RЧdJW)t\ޠc87ya#B^_bG[f +c+G:!C*Z:HCP [.GH4C#T _݆J cAcj4e8Z &iQQ*̀&}|UD\X儴J_NK%@6#[xsK,^ `B)8Q}fBoA6GUGFVB jQ!x3vӺk3нE 3`,tH+Y?]Sar"sĈnhEnˆ"aG!G͢%9TĢ2=H!òtVD+o~l;(O p8UbTT;Q9&˔܁*6B7o40ۙٚ Ro/?XH&J=d> YtSH.BW+FܨRR됕DRY~vms$^j¶F݇G(Xk]6X*T hslq=06\Ѳ0gk! HARL)\dD""K^5wQ1P$d_ݹa8TDl0 D+&F2%h6g Ґa`;K #ss~|KVqjTuC-fr`CX5F ?l% Q8 ;)cNH{@rt=K^)]X0Yq? wxXdLJ"\8f5_\c1H#| 7$`/ZИ ni6}$k7*ܩJphnբH5O;$m9wAN#XW9#vĨeoۮ`{p)s~mp_[d`Dw ؤ /$6?#b&eg ޒn̥PW665mfĀ.Gͬa|EHM^Pjp/$@2bk=vspt5p|Vf1 e~\DtKdPV6Ӂn:*RVR*|`82:ip7:ټx)Ѕ'%/OztB$ӅbZ=xOG1g}eQ3sp/PL',v8~ͼیp#Qla20c 2dT!'u%\;$FL :15)Ȁ"i"_:$+Yޚz?<F c+)QiY~U<@:_1#m05 bpx1C!sVrvв)& ؅(i-M,s5EiQZy L9_ɐ,mnA);~fb)@q}C^p;/AS&9:8$ Gs. K[JCoOlXro-S0CRi Y`(e{=*`@R- t:"N~0_kxcT6u%d7&C!׋Y92_9M]< -y=('ua2 Z0aW?#fhXYG7Z k1`DkAݠHJXPH"7-V+s5y]|g  xpcFL~&(/)Em0R4}t@aWSqzi~tOv&j>'Ʌt" S 5ý;tū4R,l%v=x+~ybDKo4L LB$jG*qR t$WY."ΫYxH8#C9pm9H=Snrrz>*2zS~dC3Zb=oQXj,YEHGNyc\~T6Ďj[݃/*'[QT`!@/ (,ˑ}DlH"W6̉`[ #y=6|2lM\kpkewւlS8Bp Oդ!0#F{@ciqP)2(hɑ-Gb Qh?y7EZ~ˑeGx.B6)'ajKʀ߂}R. CXc]C S)ƌM'#,S=:'`HS?u321D S hn@Gev&hU[d0֦֗9 P %@a0= 7Ơ*lLzd(!B5ϒ%-:ug|6OHQT O/= aA˔r }M<:T mN' D+alJ̋.Tl0n2M l'[̀T0XD_k▵v 8Q/sRN @("(OZjo YgjRѰ%RJz*[{dZzC"#QV@0dR!\-3H2U| /QbD:tÒJRŏG糊箊N"s9Ìp#(0?)pN%dX P[3P/[-Gr~,Q]̷5t Jnʗ ғ6jρ`L+nE{!YL_q-q;#gAYX˅X63hDNOUا`59J#&6~XM1P&`pI"3&CoAf^:ZYJƗ8ZD[ D BB lư ިB+͠V[vL dUdt mīD 1*u 3mIk[xJS"nUm/wHzzm/R. B5~v:D(*\V$8_m$0WCd(:k3=w\*싕m /{}Chb Ɣ-(<)~ 8NwV >.%pD~Aێ,<4-wPB- ~-WuBXK`( $4-~nB&Oa*8Q2z g 12Q_Dvl-DrTքᕟ~'q:5j&="%&|Y&~[,aI28DPORsFX;Da1dzf!Wi4iց,MV^#!NjʕogT8Pm'M7@vt DMbLM]QB|1 "Esl̼= r`d NJ[}𢐴&Rrx_ OIϓ%^EϾNq0DU̺= ؙ2+xxɓtO6g>t5 t&NiM!:VaA F9Ddԑ,ţiht=zD:GNr0<ņ-F5 j!ms(T W+02Ѵhd) UA~ov r\x 8nb%>/ Z]ˡ)acpRSc@>--+$c੦r%P llӺ6CCPI̿1jIxyrrabBiaOqX?C^wwC=XL Z1V!b*1 /)JPjM̘=t@rХ&[c+g NͽZšR1"6]"g#(͞ц l+hRϾ+eC!$KHuY O)nյl h<",bL՗جOuYX7˦'W\`0#ů;3`#QdSx5)"wx2>H`g><`R fَp،j.Tɯ|k^LZ]V%u;В'.ZEN`aCpq | `פLqrevuRNj-+`Z6+G D_9G'*;t8&%G=ݙȺMBL~vd+.GYT*; w+idf~{}l?6J/S9y=f4):' .Tb/6IpAa5Q8?&Ց+hyhO9D@s +W%d K9&{F#3EhT2|/גETt~aذxWi㴻e⼍*'2mۨ|Ks`4y9|T$\ Fҟ.hJMOlL7*jPwrKM%GM]\/6:}Ċ|\M"fKMdP6}ӰOD5 yհC'z`pOڀWal@=O %-EOEܘANt}MI]%7+<փ pF#hBd}M7*[ #f#56piΆqj1\:1ڂMV"'Hkr7wחnnMX! DZXrAw| _>RGܠ%К Gm1 {>%:_JeL@bԯa*)_2DǛ+R@5GRD<9,a[Cn q+1uWpS0s =x㎊B狮o+CGa'{ W+xg5t̙=8c[#֓ɸ:Ƨ YB6p,4g̓^?2 z@ FAr.fw ).*.kܘu y{oP=p֒e4I7t,## lޗe:I/4 [jDZjw"8 &?+Nͪxd%R#%Bo§Aݒ٘ ?<&,"[qR@e3L5Q|[||l44HEQ.l u`aPOlS1BX VJ 9 fJԙgFKJL䁭&߈D_0D=roܽ< MGyPKF`8ӕI ZO _ ab9j7|J~h=ů%LY-/Af b0xz.cI `7Yp,4&{M,;e tF%q"&_Y_rA m,jS{.y@ҷ:ofsp)wB_w ;@0 Rl0#/C@,Y9,]蒅l ] ٹ]Okޤ Knլ4a>Oc;oTň^Kqq8FĭEva=E`3{篅=kmgqhRI,QI[ʳլԇðC a2]jj<+,n21#"F 4/# &A _l5޳&8Xΐf3Gp]F̥J6@`1qŅ'&v*0$:WήmTs ?$SliF*-Tp9S P "ۿsiZײz`NE;d'̮.zq|/8\Cr/i =4`Yݒe0lN>z`ҕװk9V㟽ey0+~HPSMIݴ(`f}B蕬5l<]  !K 4\.`dFk!nj~ `P)TDœ&I(X(8|&V+["O+9a\~ %lz\s.GWQG3%Tno(ʑ!_`GH7UVh(cP,x m7"@:TŲ8кGGݑc+Hقs1fբTȼ5m_`R_ܗ{hP\~c7l:M"X{_=s: 8΀N]>әwtvG~7T@yWJ1P# $?7`zx`z?rL2XejiA&Т:Cd4v^.4x'J)XlId:$-cLb8:d$@?50p,Gf⛋*Fajf<@5b($W5 lsGcR]c"K<O^C&!\@b8 F|5-*5a3 ( *l(>V1UO XּC\3DŲlڐ"qfK)WDB -:DOoڝ[ ( !92vOݮU^$+ H桄mt'ACHU6=];{!I0o?V(BFb ^H2 jqF5c|r07WB}֤$6B䥌(m 0t 8,4bUm9@CpTdҝOAB+ZlȨk|*ǻsow;5,NOR ւx6q_SEiTS#"o0+h>9k;!7@Ĉ-S1rjL1k=,=N'V e 4PbRmM6Nz$2p~ֻ(:$?EHZ8yYe0恀͈e};݊J w#GќWG94˜d&ʞ.c#c~o2:b@8y&Zhs|g[Qd`yլ[̔d `[߮6,>F {L͌mZQb:qjUNL2rSAƨJȍ34`5ܯ,UrXJEethfgah%}"K- T;*"Bysݬ#@xEJAAck@L|' '۟ &~8?3e,2݇+ A:ukX2FK_!qKL~fd!ۦ65g Ub O>#CxzP(ٯ0dЕa5.x ^pjwU=1]m[zֵPq^~'@5'jNӽ`qWŦ/٪{E}:? :l|&1 >x/EX$lϤ>?aݣmec0DSpT"CYMЄ:Ѕ샂ԫEٻNM` IrI:2h]-5n԰u+ ƃCٖvҖt5 A 1ֺulAwyA6 Ty>,WŖƐ)K گYմHEc &jP`n?~  @^~Y*G ͋Cͣ!q )UX:1h$.{9&-Y`A`C8 mf/1 \r.U8Y/x / mʁ X\:* R=ˑT0ژ)Ӓ_&txU &`|-uoN3KLRtH9Z7Eaa*/'-RkO<>g8 jW@*F\! H7ҚƄd2M%2@ƖPj`P_/_MQ3phk; 5 ˚ 1 S ieՆ`YX9"basfd9]-$}(,ôE.Qbx)ǢȂ灒a-y<0[$,2%QM@ Á){!ߥR?D'`1$: H>vCʼn6,H:1Gz&+h`+ { <1z -2){-}!#]P(<>w-xبJ?0jF#DVM  3) aݨ?XO4FV}:@4GflS]{ brxĊ4ce9+W(\YiUeKu*sNx&ʱN8z IaD#U#e;MU{\h]vTa`!(mDӽH"Al= 7O&hI[Cԓ|x UV„pr?e (&Lv6 m?ۄ,)XYjռ oquupw {6d=S#;iY ~¹E0\OeTB*yZqTrP0pHP_Dg9+cuۉUeEm;a^c"8}A97D7l .e|<е"L܀JA-jCqH B`M)sg?g;`bheNWJQ_[avwtF߉pO]w{~^W ߣɋ|_] un!!im;0$Y(Ţ$`I 5rZӊb6C+f ֤ Cccx |N8:i*I3'JJg;w3S[Pq#Or!DF+Hm1,CNh<<xs"+5HH/et qr~+d8Cw(2"an1>$p K.ǘD?Tc"F8#! 6+eVp@4 XgMk)h詵2Ǥ4<2zQ9Cv?<({W'o<%'0ܮ.%_J _ś~Z([ ;M@T܏fe_ț<17XD$o"cI Q'U3%TTT^0Q))lÓ. L+A#o"!3]-R( d3fPHត̡{3!6^R WW qm~H?~י7?P"rh/8qЇ"eP<@V)F^|D0G]CqNFȪ=.}U^mX^9=b5esZCS5qtk1fh}ꤋ+k]G\g8 =u&a`%w2cK,mCvՄ )@``Td<1sw d7zz1)ȡxNpA^<-xrCJrE= 79L $Doމ?W_⽫h!'7Lq_(f9!Z*Lbmw|R[- ]Ұ* \m^@U*q2⎏g5@t`dM[l3OħCl6O[BQk";":gѨjf-.J^$rJxP52-c IoFm@,vn@ $V%{.p( ҥ:Ink[Dq.@>\v$5ͬ }pOũ~{ -ɨAt&uWUM_d +_UInjM^pSK m EA5/a/9COVcR?=R$3HA/P$f`967 & [+<.܂jFu:gWTNzZVPܕ+ͅP7V֬ Όbp~o3ӗjŒl*zAJU0U)d`DZ(a `?jKjn u!+@:3ŸG 1# s0 IO>fNMHj!6&. LyG1D`&Y3s."ɔ 6"x1I!uxE^_s74uaO#&Iyo!+ H@G@xr7ի&j`*Q٤ ({BhX*u1V<"$nN\- &b6f89w6>np鰠p>3b+*< NA7ZAhzWqЂ[dsT&ggG A8KCu 蹲"W<ܿ7R95$ $S AY[x:6C$T! ѷ9\9F4YyY50tQޓߌ1`mG7+ 5֑̠uѐr@F1lHY^4lcNwkeR'-Tk\ժ/3Ҟ<"h! ļ%=PQnnO@aN@j')ֹCCt%!ȯΫ @J9 v` l Au7ƉR^3i", RN&g2S,`Bj͚&vbKSp¬=R,f2GRd&N}@?ÆEE)!$ua F>brI&sтZ1a#3EJU,ī*PߒJ,vJ˷6-=ydJqM3 eG+Q%YwȲ$.7 VHi/}Nt&5۬ƓBҔ䩸+V4M@fk~o 5#_!I i~4>C-\ec>pnCqvvBwn HXKfwTŏSw%uc؊[OɠHf$ `!q48Vl\uUnii H3q\V ;Iqp-x"XÂ=\?$|}dz˦<*@P1=㐶hY6^qDՎ\7d)/L膄,DnV2iwJ-g@KYAl?* /=.|9ՙ  q0tu<\rdp8?]%Xe-!g zx6?庍ϧt4 ((̍_D0ۖ|Sɰ֙|܂bpGK_|ɇHmk#KG*:z5]k31O,16frt,ll*rv["~U=xUz3WNL`zAUvy5V'q|L La|:)k ,36&K)Bz׋KM1ŻSC|M2jɚ$ͤ@D[kH aVBBT4r$Mt 1e7;vSZg@tȨEG8P2f;1fq W wCl-xv\ .H$0 !XB5.^7+y1iF)V^AM=\300_~/Gŀ`7<U&m ǛI[dt[ӿx!`p 0r˹<̣[̈Rx4c[?ƹ?S%DPIR2b;"ih;F |Y4,R8YD"M5V=Ed=na:%qV0*2#>o3 r6rCڮSLJjf'܂fZ#7Q|+hYn%6 z=eXDb؈M_8 JzY 5gGN6ޯ96$;Y+MF87٩SQ70Ie$6_984z(Jd$h?!M#A f3 taos<ˤfx1+lp[ Sbӡ딀 tW""#RUr 'V=kcL2YSęNd L,U3"k<::?PҙX,l/nHa8&c}!u>!M-f=;J@7!m~3`)V.wܰx8f HgDc.".i  @ GD;)gn]g y r; ^tA uWG$zEdȷ2/6k}R*PQCT;wPđd֦b|A>?n]y@Ff "AoWZ КoNO& 6W ``zR 5ԁBWIEaU»=I1jc2ȆoKC#]?'D\dMB^|ӿ8u>;YmǀPʈuu'X<%EcV73пwAAQK Fhqm3dk'ɥa,0blMhgٻYwQ2"--zlhr y v@  z0#} X1I6 :HL D0WWYQG#1 -.1)QSE4 $-ďNFz$24ϞzNXWpDET{Y0dQ# MI,fU?O/O>pn;t{KF4A3 l ^  [ʍ[ rDZԔԮa`4_P÷&A,eW⅌Kn8605 B9w|j{d*Vj(yzQ]:u+pp*-s(x08x)o@\0vH1^Mc?>r%'3 wI" o2d2Xp 2j[NBIAm`$%pVÀ\8CD(=(σ( neF6n¡9lvё|xObH09su9mR]L˗(sxll25r <eѪbbpJ%mj>3  .»mg)FH80b9(Q}f7|%6t#]CK0̠cV@ !-rRk1rgC%&a(2r^ft3k o!Y$p۪ E#ȡo;fǰ1a e a@6+vZM 1V]H;} DO*h~ @E$w;1{r~ J6kyG9,WHvazFe%f5T%u ]'tVPth7K)%NEXR; I_ۑ V백f;FL" @ZHT-+NopŹ#I&AȓMy w'3[h"xXae:hCWW"`3T1-M܉!Y_6/l-9`C?CT{d`?IE5V"FygDRQۃ n+kz`aw-劔.Uei0 OsV0JSPޕ7 Uxz+QԬߍ`:#!5chH:F h3rsm.0-J(0RF8v~:6F:е9%@,,uH\ Z NZ.'LoZi-JF&h B\šwӝ;%'%Sښg=qGQ,N"gU>÷M1‚Ke]5l(a@`ZaX5ӄtkV od* a48dV4z1c9)À@@bZ#Xȧ+kj qaWCιzt 9TI?a GA|BwKqT%BZ~ټ;,hjWHi>DM~Vմ?ޱb'e!.#nVe|<#p#b%'=GӎŃn\ (*H.8:Eι9;LF?+Ig/y]Dz%rAZÔf\}!C*W@uղ*ɱv)Zΐ8Vn;ֆ| PT춮 oڊ^<WY%A,@DןT I`yjBW%8ՉOVG5k7n"ĐDƂFt$ M}6@3\ ˸mF3M1>|HgM6P{,ԲU%3 `{plPD$?2ɇ%@ԓ6J"$a3/|ZQ9WM ;n)# Ők)Ґ9F7I5Fql5jJJ%9BmJ89c# B6r@'37DOǢIyr6V2e>7rX9BΧ*6yFҮ,Q$_OaFwv6b=xJH:ESz܎H}41zg\D1>5{T bL^;v86Eq&zz=IΙX ta`|b#6#eUW4'2*Һ`b{S&@qJzY#g@R"SZ%f'f( DI$"@&Bc[J\UB<ekv#}=AyKK:lxځFCRsw\$ミFTٰ /Ic(4\|$^Ol~hԣcL[4ߥ i:_ $ pm5ڸxSN@P=#7jB>N|G| _o#*jcd@DŖ:K[BCSʢB@e8 +U"O`k86nKK&Wim;\ґ޷"U"rs“s5(NN3W.Ȏ @C(zQGd@̰ɖ2p$0}nwbµRr C6>]j ŏ)GJSȐD֒-nC]Ax3 cL hq'o,܊?y9]yZj\`ot$/#w a RŁdo`ɃXœ( (nBɋN+n*n mjZ X00m:: o}¤$rv7BĒB = )L1@Jj 1BV2Gjl`tlɻW {DpO쀁2]D@^/pa˓c~cH QpdiTxRWHM7꠰]"ΐUͣIcdX #v7 q:"С  U-RdB0 ?@vh#_@%ǿM0zdٍ:0.!,0Un!{HB3r5j]NףdLYQlwl|S 6N""oJ ;]x<-p%D^̦*$znF3Wz4 v۶4FOR$xIP\ÊVeeb;*IHDv_#r`!g*#"mi^i?1шs1M0&Ɏht872&eGjqi % hTE^$.CTU@(åxcw~ڨ\App6FVp5Ŷ C)BOv|gebNvdW8B+udȫ,JYQnߋU _2u?gyZ) _BشOe !J q=] ˏWP4F!R"b ҭLOL %>& pi0ѳݢvtm Mꦲb/PC@o  "`CX^MJԲIԁtPqx,pFDJ J"_3VU' qNeƳDN(L`$אq*Vo"Y_ىc *ʾ9)'j/PPkkfEedrhM)לjX('SYj<*} kiL|^laq+ tфlnq@eh^ ޾tɶǨAdfd.S8&?vhLUSsVB3G~MM-hC Qo' FY|D dl2|,S{sg0![(ؒ ;њ 7JV ϒ0+){;S݃ LcȌOMYh= #Ga$@QҌ^'@o=!ma=Ҿ7/^ WҐ;a-iĢ@GD%']K/W>CFԮd2ǩ]rW35XRX M۬&A,* a)_}t'"k :da}1?D45Ӊ` a׹ۙF =ZWY,=PKOH>5 COݻG0;)A@c!Y ގ7 Rjљ}1z>VPa 0,+=oޣQ> F 賱]M\ y腽Q;r:z7%zia&MߩR e9Ä[n9 ϕ#*{X晴ڃՆ9N`YYz%3fm$0F77`/B!V*G@Žjoc0ߘH֛C!>8 2Ơ H{rg*# ⠻Cvɘ5([ 'Pr%ii‚'F4ٽR=!9!SO$l/,Ǘ61fx7,obO!c$}K.A:e<Ot (BS;F &5G y'!Jۿ>ky3L&^-c[WG`i)nW;/aOGT^QؿU\)B ~(j)0qI nRN (vK,(+ ΕHtҞ&m,1H4D2O<1)JS@~ $L|݈*G4l!5ydoa([bT%wJ3- avN$y<khIebI4Zx.)Ù=B*=AbߏбwN q1V#_x?ip`Afw@*E|gdagC1z(ؕ̾* [4~  ~"X;phjP@-(kFFa  aGY4iDj2x4By(4gshi0ͺc މǐ1sSgߥ0 %[hp}񽄲I9VF x90_D.ut*;;zOxC}F|{BTWUMpȹ`LY ܢo_f*Mi{j-pH 1mOfV1&oK,9]ntv&0iلrC~E"OڦE88ףT< 8 ,@9jͫȴ$z=M&ŋYB|R2cs4T`b;i! 3l6$K\W7/ e Q6YaUE{KU_m'=FuBܾ6W["GRkfP&fκt/GT y ʾ)l筮!A y%ʇa e$3uQ1b |ܰN4@S۽ !iz >4AYqbZezHh/Рa FV)aFRnL'%]Q=ny0֤K4b%xс)!e%9>-;b[XV Ƌrʱ<h6$%!Ed$KT[4.DFDG9r.֌b#H+,,:q3P0[q8uQ'|(/$_YW*UyS [ K*+HCbmqSb>%51^? ˠqx% A_&ZEuBn`JFgR~/lOoAR>pvQ.? Fi⍌#?ŕ×bM҇pblU쁽YR(M? N(E4⌓뽥m[}Zmn[7Q{tA__g/rHIIG0 BQ:g[j=FAsG@G޷ᛴ=.(7foUuiƃ5qO88 Y(Y!"WlR,@+3E) `PH՗\UQFi5)/5hȄAd:奺nhw6;ʟЎZN2?o2<1Ll¾R҃aV3ԻDP:c P%`}V[O5_ uTvJFa) d gO $c9.>]?mfс;@}tC>FKό.w[3 Ǐ@dD-'hrSmx8D["15Z=6^4asM&z %lKyH5hW]q ,]G&_$=mAA3!$tc煄7Pnst 4Z\"x,oM/9WH0$pMRؙSep3ˮgZ^nB4o X*E"l }R;pEmȟ{'is<-6MrɷZk"vFxM/dPҘ.B~ /ӁD[3yf;-Wh̹.VZ9Kf QїѢY`u> ]bwC:۱^l9tŢ֬_"V7c+bjsZɐ%Xz45G/azQJ2fCWWN Ue 0<ס/2%J!4Vb t&ǚeʂϽ(vNBroG7^\J@$9!wTХ:@H\[ ͺJ*xOp5a`6rڋN9,/Lzk  a).^iKd`p4ZsC{1b}(k(_p(_*D܇>{@ B ֹX}T cU:Pc?aZ* 1P!|yc%CU|.l i*YKK{N@o^>j=ȼYW,Ӱ8g T=dg(;ϲk|1 |@ͳCkjʹ`)m}ZZB4K!-k:THtFgp.xō4[ƇQUIζ[?w2'f^Ճ괜ԆWZ1eq.@"'tAWN Ԙ?QpIBdy.;.I'0udQx8WЄJs> `nQ΂ttזQ²~Eƍ>]d&5ȳ4_Um2LϚ`2g>q\(e7&DG|}~]t84 e A[YITxo -;b]| 8`utu8WabOخf(qII>o'RM Kp>8G롖EűX1*f]IhX40.({7~d( eّпXy?AR-E{T Q׻HmFz);O<u@l?_qK f2( H> 0@G#fѱjmZ9 # \scHw&GZ%[4Mf A+mUTe:UsO& _l.OLWQJ B$t}厇TX5J2dkzŒwUSk? ǕiKm{s뷃 uqʞ,t7m5ʏj -*\\ٕE*1b%NDN" \ٲC8" FxD` NbE#PTG7vv! 5Ophqmf7W"%ccMo3p,Od8 I{֭,8?w%r6xy7֫ i2JZE@ XFaD/yF\a5̔ۏ oՠI6O~ʘBDS'ao1xuda_2^""' kI9Bm,{ҭyCRߤpX47JW] 8 B3"rtKڝ| ͸E ;l2eE- ᖌ͹G!Ki KT|mo }g$\&b\eܗ0  @~h{@(.: !dz"5w#I/J$ZA'`UT]we}Eb6b!2TcYM+;Tk˳ًT{2{F3LsWod8} U&D$t\hyJsǣ+jF< 8;FCl: 3\ǎEwS:Мj6ZJ$(' 玊Á;57y8oj?W)s:0Լ^TzŸ·HX>l sRc}?^7a#uhOhI4v}LXVZAE'`q)9GEa(_UR H움Q',xdN1lg|:h%)a^); AA-_ P9*:\c۟Qo' -F) (+ ,ɂA0xY557X#@\p|ͱ)o&^_>OFPj=S Z?ҜCYZTռLe]ʼn?SxM- K<[)x&Xj45,%ZN?ɵjSufKM.`"&Vs4(AJ3w&Ab"Xd])B۳JIv=) Isx6nVULO"0;crPP{ڠV"iRjfF3>56.qQd&qisF%^plrF2]V P/ ِdB1H`@"Mơ1~1& LG|V| b(4  P3*eB) ߾Gg?#u; |iS*WrlPhu"՚:4&r 8M%EUXCK&fA&xRV;f4K*@eDC<Z楴% ]J]v^> D1SƓ'9‹/f"cU6j"g}Ƞw~O L+.8XY ~*}Q ђq`"(P+Yt 6d4p0%#\ƒ,n _E(o9uA .ұL{|ڱBzt)PY8~t@jiKiEh*D]A%;8cTdSp+;3oa5!ZCBV,BgL \n z6k4|b3Pc4ߥz9L0xs :dc.QY`YR|QcjAgU2yA/B!B7quyXu o@ [4 XEG,PIfxuS*ƪ25YiVՎ7DS-z}'ԡh.}xS[tLRBg&=7b*:D%@-@xarPؔG,,Ȟ?OuHijdJEBKY0|`L$M䔇ڮce QR>^#٭l:A vNg2h%ӽf\;ͼ/ + dÝ~$z`_.(@IQJ6}t7Ö)=d)1#]=Ɩn)aq8P -v2 B-u!Au^@8tUӕ0 ?Na:8t\12^4k  ;}\a?>CB|%!H'Dq<+CKXD('`tdbQR# B Tb9+}/`^`G QZ fS?&tV^e2|feuI߻,GM2T j(Y."P+ FRLrE#Hp[WKw1뒷|aR\02ڈIẇB6I8o(x L)u+L"TԐtY:ҊVs0g]?NA`Ț%I8qJaGlhL~9aFz]EqJz i, #1fB7 i Kgau Zȁ^J2URp?lKH9gbltp8<&7BO?]9j)$¹^Ő<ER 1_=uJ$H.`GjMo>켗d [bX^!s=H:A ؝n5қ \ۢZY Bkg~m2u\97 xڢ@R˛!S O88L(ָE$Xy)qT^& &V4?bTewfQlŵuI4rTDʿ$Q l %J20lr`gIITl<%l.97֎zyB'qYq'i4ԊS{@d֌7NRkdT/ߍ`#Qt64?m׀uHؚ6Yԇj|3ٗ=bl&ɶhƖ94AW(>}i"y nY|53X1\cVki(KlGMa@]A7T nц/_{Gg _7g2M`+zƑض H~*~(+Jή:Ax ^?F[GdJP<ߪ=)|+#Ц9'_[z9 &$T|S_;Qy&X |H1%%:N8sQ\[fȭ(Qh]HIŃ(Y1WՂ3id[Es=e0_ĀL[{, 8%GnqI)!cL@+IImY"|v.'=b3Yᮄ1++a@,1j…Cwء=#\8-R'@,\Sǝu7ƛ ^_*q)ƧM8<=B蟝:JV^d.HV Iۮ2[mA!,QV=-[33irtDaa!ƽR#,fD'eF kӹƦ6P2DmQP킶>vrE-`%vY2Gv# ֜f <h}'mDaOC+YyEa۳(#AhU Jz$37-J&p$ӛ@`XQLSYMzLjx6.={ 5V;l{ UjA`q [ cކ[ 8"lG!ՅKOY*Ph\m܏ITR&݉;{N[d=>>Yv'^0@"nag7*"LQYGg!驨.$0PȉJբH4ӷ5oTʅ 7iArw-+r4HLEݭy|wJe-=| ߴE#SS G(fhû.-k0Y \ݝƘ)D<,~vl8:Da0k5;|]?:؍fӧZn y'ƌU0i:.Xᖪoz+U49 YF2X̌ ;I\7$BآnۅkqHݑ2wW`t2UIT m9`M'Ljk^b< JԽ u8|"G5_qG \A|Gmk1W<\*>>` `"эK8( qܢrU'p ZhO%T|o0Va17*[%ABC¤ X8YJP!f @_ndi;g=@HN_PUc]d0N\E#MB'*9X=z"P=K-K KXs܎/4~]BKqܞࢠ\ӟxsZF5QD:i䈦:-1P %8R>KT` "9a8SfH6eKg?AAJX[P7R'{頝$ǐ?n%׍cDяE!~Z!IVw/}0*`y3̰s|߾b@j"hL)ϙBWݱWMpל8Vomks VpŹ{$p#i {HAB%0%P׾2ZJkX|7)!IN[4#KjneUZ2=i ,,e`y9,-R\"e];XYgL0+Dn;lg6E{ Ф{;\av'mQT{}QAԾqIQ}A'qq&ݔF;F{#2aPOE!;n4t UvBP9G] 1fnH9h&IX :c@wr"IQF@-{\ $yB7fk/O`Kd%Gi>Z]QT,"%llC YFF\-M_nK۴^yB? Yl<|`oK$󱝎v+C$̘zgCe疤T$(sYӫ̌ :|v?~Kʏ}ȸJF^","ǏJʰzh5EU{V#ibxGTؐINؕmy9]qEwI 55^BzJRfHZY;, gqDޙX mCn5f|3.xFs֖Z$mOgwƠr(4ba_Z{Apl eZܥ gUHF.%tT[D8~*PO9i aWCo,16ԗӾAx2{>ͩ_f\HkEo7;8L`ZASe1bՐ%`;$D#4>\aL G)FzAy'4.2ST 5Yn̚US-;qysn2aSTƓeȄ6;+jx`Z%k.*vܣqكP6Uϫθi<)^n%;&ʠ;k^`.(w:Dk|D̬q9NXnOjAH1 S黸r56]9ҽ/+3b(bypfz,vA}x.ŸF[)E7]+?MȮl6iCDHǒ@kR 9k4MJt'ƐS80kdQ Oܩ&ZO íFax{+HZ+@8=|OvxF?tށx?.~fA>E?9Uݱm'?2҂UNZ ]%dR/@ټ:腾) A9/gun} {%9Jˡ SIK: H@)t=*9II:G&KfGnqHǃ{s]bl^|^݊Z%6̙Ovq9 xJЕ ,n-\0`'$CCSfK+@&L㞇*Ax%$Cbx0nAp/oaIJt"7P%̓k90rۉcśÔͬ#`CVUaIf Eaf шXU]/L20"RAr1#-nW5sdۭHU"W:2yD'4䉈IUȦ$E$b5!P.[nGx*O 8ْ_/Q_,iV ƺn6AW)ǯ%D|Lk&mb…e8 r$8*Sx0ak!IF qi عUHP-08J42%E0U%eht/{Ij|'iP#+y .&o=HLgJlr M^ON WY*}叼񜶉^\2 \C?[u111&Gރ? "44DC ˚͸ؒRl|й{*8GMN/@4fJҊx$f_JǓIJ A n,΁AIOtP#8w0cıYŧsyoSe@P1q 63 w?NP L%^% *ר|$]àČy%6#w)#¹dP~&"cL9* -vt%Wa8zQ o8qܬykɇl V?bтSK4Ga'Rj:_\;h? }·Q2GgZ pf~wװ AmKz xN( uHmI+b0L>M:IR]_нRj xFkѫACmA&EpkVHOdq˙~oZiG;*ؕ(yXQ0Bo:j{Aҟg/ZA3bjȴ:@؏SKKkrܖ*&dm-#QI7FSr{.;x Dnt44NP:Xx` foYPV!(1Hyg55ՠQB+9MHa @zr&j:ɓ;š]F`B_I IsoVE"9ǂaW}0ua;/_n_HI䜾QAI"# hKcn|Sƿ$)O}Pcgjfhɒ~''QeS^>Ha}@Zѭ ג ??( UԆPNg|G{!%gD`6<'B1>5e1 u*)l_ᲔYlz(E42:iQb܍" "BO(<& !vL8E䉩6ψ+'+"_o]yisٺ7l=B?}P `}pm-cnKBMQpȂrEGUk MaoK>LH 2(0NZɐ Tg74;9]Mdz03v̭я/LA5 )}+0k Y/Q#ءZڵxydDG61l4^%yo qS٪"Hc\Oâl랦GS[.6f^kMz${z7} F]8 dXC׏"(# N S qh6ih@-94P[/ޜO{կMqְ}{2V.|*w9f}9v+g ec:wIiˬd J4yaB1Bo9ftE<%ngܝJ`q/,;O39&T8c=L)OMw AQ6U6 SH *:q0ڃ_ Bk١س_P Mk.msx`r,M p1lc;$: o7 PUq*x^cp֨.-<N:OzP3,Ԑٙ8Răl4!h^,&]hLlܷaͬL¨%c* : 2PPY 8IkGRKPE AgB&6 J )mxC"p%-4b*X8auWjPQf!V⬔Ç֡5ČEɔ7XyqjRNHw݄!64#p㴆t)(,nm>86$6PH8{ 1:9V9+\Rcbt '-! BGNLTȝ K̪f[s2L=A!0HZ m:\P;ۑZ zW=r&yjtEuB/R~8iaᖺ..wK" "Qr(D]g&4# U>V›&)j7lqF%|Gd'rP8VĩYawIȀ|G-~fHJ6-*%J@ K`H ] qׯC|q d[)ى%&?L`/+ QQ6Ics[:Uv&{ɯ@ 81&$mKg ^얨2D \KfnO?~݈NeJmZўL5E@ϺfK2 ꚳ^hl94 CoG=%mzfYA{ ٵ)n=n׷ۜo"gƪb\KٌlNXd\p"0앶x-pDaݷ,$Fȴ#H̷͢ėEE0̯mړ,غLE^d.戇|YD"BAZXFǚEYg1%-T,4no 4aTT(?%Dl<0 iֳC`~Hsr*7\*Tɘ4TT;pA0/XjQDNa.bE# T& l)veS.[$:ב@|=QdkToNh7r0>%m2cܛĖ)u‚aio"Sx[qw-}i`$rspl:  0NoDeHwIANS.:<֖j7WN yd b7ߋQ Q0|yuO;3]9@+mj$m~Lۄ4C0D;ugzZT߫UqF*AD%q!) )6.KjTusm*S7r:;'~ >;Ʈ7s*Ի+h0h~ DT-cU'Hl5<MG)LjiAAT%ȫX3f2&-<eGjEʇ5L^^XwY>):(kw&`mEMgH`N"$_m5;N(Zgh#SgS:3iAs4 V;QP"2Ǘ%cCw5M1/.xJspJ.(?@af6J"P1)+a뗶uEf>PZ1URJ"xp@~-Ѯ޻gb>d1<Jg+ƣM/Ƅ(Iy'ZtY*`XK h ٠ .\5wΈ:' Jt6-VI#1uZ_f7<-v||$Qi5#2: Zl-­JDM/ ;ń tn6N?>r΃N,=A?}i;a!?;^TF$ VXA;1M7olj#}74m})gM HԹճrE})K%iWH_nQsz%7gr[N z3²{S)Z_+%ܚRDWfXJKQca(t h~%?"o#ɻFaR\wN؏Zh $U\Tw=.D $$j]#[KW;L3Iq( <_ Uuw,^p>fNB'd7wx:#zYautxP22w iwgܾE^oHfC|Wڸ|vm> p‰$uf nkI&qrrdlѽ>n]w{2'6ɰ<< iALdC9+*o|}A5 a y?Y>ߐ ,>_^*xBm557 j6)yDxi`~= >}"/i%}d{'yLdQ$c[ f 6jT-!.'V5& K }&3OGm 2 =L!s,D=l$$72wI0sr;u/, 6!%9%rC~e†b SU!Y`2G-CE5d=kCkOc F'mZMW>g;ídD3×M8&7/!$FYf{H2tTk2R4[4%x0q~I+zYSab4e a8p![€]3Ƞj tTuRdVv=\5KWΰC-UҾe<[m#{&䪧6("J4W0}lYZShݳI]ڎWZSчC74xFUzq5$NUT ZDADBM閍U@s&1[7PCH<xkM i|85GhFW\那= ߀Q 9Pל8u'r4eqjwˊbD%$ k9lݯ1t0xj4Nr]V( q-e%qV *i@Ơ׺? F1HţE]ZbY}դ,0y3|L NXW>EKHFJ޷"^DB3pV|pjHA`~crip&69]'?H|)*sjbPO֑9F ;</w|s[v3=U!֗f8[߿)]uִʼnz GZ&;Z,Ұlyy!W4,.j6[dgc_{aX{>8wf]k0@ؗg˴@D}"rvwqTSHie`+c;i7qg( "u1\* A>]إUڂbRRkJՋ] -vTQ.>WPPE hT[rF3k2W lƹEC 2T&`~7V , Ki )˵Żs°KD8;oaN1 _@JW_pVԝkHHP,>q4&"1\-ftq4ìyq1hk[j܃ZN\! b}33-OOYBfZ6߲B cۅ&c0ό+`p_1n6QEZp9Ŵ&^%YYl!g|bIܱ$;'R yAL&/{֮`&(=׸Vxu8n0~EҦo7"]U6O"vk$%%-~{}`+Ml3ڟa%!b`q<-//BhIဝK&6l$זZ\ P:?fWr1ާMh2P@[Ԧ08_P D@jl'o5LD"Aj53~"ښ*+R]M@eDlK@!b8q`ty!:Ir@*zS: (U6BZsM魼t*s kcKQt\%9qSbwFf3K8 }Eٍ`.OPJKPWhz0]Dj0XAdwѫwf9!IȲ6'VVppI7U?JH-- ßw2g,a 5L`epVBr[%zUu .n(=&[X?}߯$8ѻB2LI6{G) luэúLc/H0A'ɹ L|DH-8:d(|fk#BJ![;>{k]~Cy+z>c'kT֔`d@0`Y0vJ:7^'؉G,05?иJ Xz%:|'O[*t>fX$ ~YP(pgN3_.P!`T"Hhɼ쏒D")5 Gi湁/IX>y8pAփGGp郆 6f(#A J3iHQ#,F#0+݊.*TAo )LP@"! *8Uqa♅{ )@ThBE' y^$B@Gb%tI(a=fD&HHA="AD*K 懿 M:h?a [  z6 z M T ~ ol `2т HUhrpt (IA  $4x ` qp@NGp .dPGu_bo>O ?|_cۿZ*w?ɟ7]gVx_3zYꯣ>>}b/k=C޾aҮü&vWKɯf9S&yqhok56x&][<'mտKt&- ;&v mlm~Ǜo`k#UB9 EgP^e{u[nyn+Lf:+a.. G!\e󌋍ƍ@wQvY"uTQ+dPv@!c&w`fuO(Fjh0 9aU&Yb$je}AcLWt; ]g2I<ㅀ?#fQ+H<^2l:.BacӈB,Q^G靲`aϱƣ9ˊQcPveK?pN%00,2ȟ}M}KB )MGtigPvab/ *Z H5RE0uG[89p/f]҅-: d)#l'~'U(6-(j0`TtӤpƣǗ^X* 8rbkL!n3χ~F30Ne/~D)x5P@o30|GymB¡(@k~.aFnP! _{+f@'}}b 2ÕtdFDKg8m6E鎕yWZ" EaLk(zCq0vu&OPŖ!uƶK5ƐMٳ&F{I=X;+ʂ_3M:#㑎\=ߘ4h"_?HVÚ7xxi" (mŢsN Jz7W$[~-yHNq@"uStav½ MiYb,z1hb-"I~%xK6%F=~dPMKC|^HDjM>XihH]r%f-%lYVW|vEby[I[_TxVXMLTau<0K!'[¬ -I(u먶t-E"iMK{BNx-"s)gzP5Ea9)*OZxp;LvHcxk.T >ZR1ǐ) tM,7zW4RSCeT`6SŲlFdN2,ob'z\&* D騊MCe|=<9r(RUV:J֗8J$fЗV8һ$wثu@[JxыJ~Q9;a``)wF3I4元_ q1Q2?뛉9'b|:P6A@Y8iǚxQZgaMW4x(]W'鉐11PCF([*.EA^S+ _x:b`T@ـ`$SE:".'W#+I;<6d-O3Bseٸ\%8t< .?^pz4Nhdlxr\nF=/^Fhݺy~66įMtܝ8Ŵs`lH&jׂgŘQ 4#ɫۈ9aElGh B3* N|4 roHY࿂BJjJŭGW*QCUy$&mZ`- Pi9m+Wð$(@X ǒ~$#yMEHvMp'a8 O'gk\J[4faI \Dž'T`0;K`?PQU$ Y,:aCˍi6c 2Ev٩gpb"ΞX-2]B՝ATYi^U` ^)Bbzm| & )jJlOQq$SΡe=E=Q#> baJw]v8g{`QOQBK /I[+&̓"R|x» _S}x آ|RD|f1 1{?S@0A?TӕrxDgNo|錼8NnF A 8V c#t} N%-_ "гhϼݿ_dG<3|{ y 0.< `i^ @JtR{,ݯ|lס WHahcY{r՜V#!IaqZ7וU00DlBݢȬ[l٬[E`V*_rU8!^QPXVXR|*e%f ZJxPr,|-|p@^y>4,ʅ MTAG =鱃0rPj `:D''\ !4߅'g|櫪X@.ʋZ~qAbӑ'T0'=Cy!uDݸ|s2ف|5~UmLQ% j4ǁt5 ([L=ަZisTG/`#Zhrr>$'[@pq-3cVEĝdgwe7p԰p[ hugo-0.92.2/examples/blog/static/fonts/fontawesome-webfont.ttf000066400000000000000000004253701420147000300244410ustar00rootroot00000000000000`FFTMjo)GDEF OS/2Yz(`cmapmgasp|glyf,q,head U6hhea [$hmtx)* locaiV maxp( name3FHpost7cA webf*VO*=Pu>G33spyrs@ # p@0 / _!"""`%>N^n~.>N^n~>N^n~ / _!"""`%!@P`p 0@P`p!@P`pd]YTC2 ߸ݺ  p7!!!@pp p1]!2#!"&463!&54>3!2+@&&&&@+$(($F#+&4&&4&x+#+".4>32".4>32467632DhgZghDDhg-iWDhgZghDDhg-iW&@ (8 2N++NdN+';2N++NdN+'3 8!  #"'#"$&6$ rL46$܏ooo|W%r4L&V|oooܳ%=M%+".'&%&'3!26<.#!";2>767>7#!"&5463!2 %3@m00m@3%    @ :"7..7":6]^B@B^^BB^ $΄+0110+$ (   t1%%1+`B^^B@B^^"'.54632>324 #LoP$$Po>Z$_dC+I@$$@I+"#"'%#"&547&547%62V??V8<8y   b% I))9I  + % %#"'%#"&547&547%62q2ZZ2IzyV)??V8<8)>~>[   2 b% I))9I '%#!"&54>322>32 &6 yy 6Fe= BSSB =eF6 >xx5eud_C(+5++5+(C_due> /?O_o54&+";2654&+";2654&+";264&#!"3!2654&+";2654&+";264&#!"3!2654&+";2654&+";2654&+";267#!"&5463!2&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&^BB^^B@B^@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&B^^B@B^^/?#!"&5463!2#!"&5463!2#!"&5463!2#!"&5463!2L44LL44LL44LL44LL44LL44LL44LL44L4LL44LL4LL44LL4LL44LL4LL44LL /?O_o#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!28((88(@(88((88(@(88((88(@(88((88(@(88((88(@(88((88(@(88((88(@(88((88(@(88((88(@(8 (88((88(88((88(88((88(88((88(88((88(88((88(88((88(88((88(88((88/?O_#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!28((88(@(88((88(@(88(@(88((88((88(@(88(@(88((88(@(88((8 (88((88(88((88(88((88(88((88(88((88(88((88y"/&4?62 62,PP&PP,jPn#$"' "/&47 &4?62 62 PP&P&&P&P&P&&P&P#+D++"&=#"&=46;546;232  #"'#"$&6$   @    @  rK56$܏ooo|W@    @   rjK&V|oooܳ0#!"&=463!2  #"'#"$&6$   @ rK56$܏ooo|W@  @ rjK&V|oooܳ)5 $&54762>54&'.7>"&5462zz+i *bkQнQkb* j*LhLLhLzzBm +*i JyhQQhyJ i*+ mJ4LL44LL/?O%+"&=46;2%+"&546;2%+"&546;2+"&546;2+"&546;2`r@@r@@n4&"2#"/+"&/&'#"'&'&547>7&/.=46?67&'&547>3267676;27632Ԗ #H  ,/ 1)  ~'H  (C  ,/ 1)  $H ԖԖm 6%2X  % l2 k r6 [21 ..9Q $ k2 k w3 [20/;Cg+"&546;2+"&546;2+"&546;2!3!2>!'&'!+#!"&5#"&=463!7>3!2!2@@@@@@@`0 o`^BB^`5FN(@(NF5 @@@L%%Ju  @LSyuS@%44%f5#!!!"&5465 7#"' '&/&6762546;2&&??>  LL >  X   &&&AJ A J Wh##!"&5463!2!&'&!"&5!(8((88((`x c`(8`((88(@(8(D 9 8( ,#!"&=46;46;2.  6 $$ @(r^aa@@`(_^aa2NC5.+";26#!26'.#!"3!"547>3!";26/.#!2W  .@   @.$S   S$@   9I   I6>  >%=$4&"2$4&"2#!"&5463!2?!2"'&763!463!2!2&4&&4&&4&&48(@(88(ч::(8@6@*&&*4&&4&&4&&4& (88(@(8888)@)'&&@$0"'&76;46;232  >& $$ `  (r^aa` @`2(^aa$0++"&5#"&54762  >& $$ ^ ?  @(r^aa` ? (^aa #!.'!!!%#!"&547>3!2<<<_@`&& 5@5 @  &&>=(""='#"'&5476.  6 $$   ! (r^aaJ %%(_^aa3#!"'&?&#"3267672#"$&6$3276&@*hQQhwI mʬzzk)'@&('QнQh_   z8zoe$G!"$'"&5463!23267676;2#!"&4?&#"+"&=!2762@hk4&&&GaF * &@&ɆF * Ak4&nf&&&4BHrd@&&4rd  Moe&/?O_o+"&=46;25+"&=46;25+"&=46;2#!"&=463!25#!"&=463!25#!"&=463!24&#!"3!26#!"&5463!2 @  @  @  @  @  @  @    @    @    @   ^B@B^^BB^`@  @ @  @ @  @ @  @ @  @ @  @ 3@  MB^^B@B^^!54&"#!"&546;54 32@Ԗ@8(@(88( p (8jj(88(@(88@7+"&5&5462#".#"#"&5476763232>32@@ @ @KjKך=}\I&:k~&26]S &H&  &H5KKut,4, & x:;*4*&K#+"&546;227654$ >3546;2+"&="&/&546$ <X@@Gv"DװD"vG@@X<4L41!Sk @ G< _bb_ 4.54632&4&&M4&UF &""""& F&M&&M&%.D.%G-Ik"'!"&5463!62#"&54>4.54632#"&54767>4&'&'&54632#"&547>7676'&'.'&54632&4&&M4&UF &""""& FU &'8JSSJ8'&  &'.${{$.'& &M&&M&%.D.%7;&'66'&;4[&$ [2[ $&[  #/37#5#5!#5!!!!!!!#5!#5!5##!35!!! #'+/37;?3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3???? ^>>~??????~??~??^??^^? ^??4&"2#"'.5463!2KjKKjv%'45%5&5L45&% jKKjK@5%%%%54L5&6'k54&"2#"'.5463!2#"&'654'.#32KjKKjv%'45%5&5L45&%%'4$.%%5&55&% jKKjK@5%%%%54L5&6'45%%%54'&55&6' yTdt#!"&'&74676&7>7>76&7>7>76&7>7>76&7>7>63!2#!"3!2676'3!26?6&#!"3!26?6&#!"g(sAeM ,*$/ !'& JP$G] x6,& `   h `   "9Hv@WkNC<.  &k& ( "$p" . #u&#  %!' pJvwEF#  @   @  2#"' #"'.546763!''!0#GG$/!''! 8""8  X! 8" "8  <)!!#"&=!4&"27+#!"&=#"&546;463!232(8&4&&4 8(@(8 qO@8((`(@Oq8(&4&&4&@` (88( Oq (8(`(q!)2"&42#!"&546;7>3!2  Ijjjj3e55e3gr`Ijjjj1GG1rP2327&7>7;"&#"4?2>54.'%3"&#"#ժ!9&WB03& K5!)V?@L' >R>e;&L::%P>vO 'h N_":- &+# : ' +a%3 4'.#"32>54.#"7>7><5'./6$3232#"&#"+JBx)EB_I:I*CRzb3:dtB2P$ $5.3b[F|\8!-T>5Fu\,,jn OrB,7676'5.'732>7"#"&#&#"$ zj=N!}:0e%  y + tD3~U'#B4 # g  '2 %/!: T bRU,7}%2"/&6;#"&?62+326323!2>?23&'.'.#"&"$#"#&=>764=464.'&#"&'!~:~!PP!~:~!P6 ,,$$% *'  c2N  ($"LA23Yl !x!*%%%% pP,T NE Q7^oH!+( 3  *Ueeu  wga32632$?23&'.5&'&#"&"5$#"#&=>7>4&54&54>.'&#"&'2#".465!#".'&47>32!4&4>Q6 ,,Faw!*' =~Pl*  ($"LA23Yl  )!* <7@@7<  <7@@7<  pP,T MF Q747ƢHoH!+( 3  tJHQ6  wh',686,'$##$',686,'$##$/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&&&&&&&&&&&&&&&&&&&&f&&&&f&&&&f&&&&/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&&&&&&&&&&&&&&&&&&&&f&&&&f&&&&f&&&&/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&&&&&&&&&&&&&&&&&&&&f&&&&f&&&&f&&&&/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&&&&&&&&&&&&&&&&&&&&f&&&&f&&&&f&&&&/?O_o%+"&=46;2+"&=46;2+"&=46;2#!"&=463!2+"&=46;2#!"&=463!2#!"&=463!2#!"&=463!2        @     @   @   @   s  s    s    s  s  /?O#"'&47632#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2     @     @   @  @          s  s  s  /?O#"&54632 #!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2`      @     @   @  @     @   s  s  s  #"'#!"&5463!2632' mw@www '*wwww."&462!5 !"3!2654&#!"&5463!2pppp@  @ ^BB^^B@B^ppp@@  @    @B^^BB^^k%!7'34#"3276' !7632k[[v  6`%`$65&%[[k `5%&&'4&"2"&'&54 Ԗ!?H?!,,ԖԖmF!&&!Fm,%" $$ ^aa`@^aa-4'.'&"26% 547>7>2"KjKXQqYn 243nYqQ$!+!77!+!$5KK,ԑ ]""]ً 9>H7'3&7#!"&5463!2'&#!"3!26=4?6 !762xtt`  ^Qwww@?6 1B^^B@B^ @(` `\\\P`tt8`  ^Ͼww@w 1^BB^^B~ @` \ \P+Z#!"&5463!12+"3!26=47676#"'&=# #"'.54>;547632www M8 pB^^B@B^ 'sw- 9*##;Noj' #ww@w "^BB^^B  *  "g`81T`PSA:'*4/D#!"&5463!2#"'&#!"3!26=4?632"'&4?62 62www@?6 1 B^^B@B^ @ BRnBBn^ww@w 1 ^BB^^B @ BnnBC"&=!32"'&46;!"'&4762!#"&4762+!54624&&4&&44&&4&&44&&44&&4&&44&&6'&'+"&546;267: &&&& s @  Z&&&&Z +6'&''&'+"&546;267667: : &&&&  s @  :  Z&&&&Z  : z6'&''&47667S::s @  : 4 : | &546h!!0a   $#!"&5463!2#!"&5463!2&&&&&&&&@&&&&&&&&#!"&5463!2&&&&@&&&&&54646&5-:s  :  :4:  +&5464646;2+"&5&5-&&&&:s  :  : &&&& :  &54646;2+"&5-&&&&s  : &&&&  62#!"&!"&5463!24 @ &&&&-:&&&& "'&476244444Zf "/&47 &4?62S44444#/54&#!4&+"!"3!;265!26 $$ &&&&&&&&@^aa@&&&&&&&&+^aa54&#!"3!26 $$ &&&&@^aa@&&&&+^aa+74/7654/&#"'&#"32?32?6 $$ }ZZZZ^aaZZZZ^aa#4/&"'&"327> $$ [4h4[j^aa"ZiZJ^aa:F%54&+";264.#"32767632;265467>$ $$ oW  5!"40K(0?i+! ":^aaXRd D4!&.uC$=1/J=^aa.:%54&+4&#!";#"3!2654&+";26 $$ ```^aa^aa/_#"&=46;.'+"&=32+546;2>++"&=.'#"&=46;>7546;232m&&m l&&l m&&m l&&ls&%&&%&&%&&%&&&l m&&m l&&l m&&m ,&%&&%&&%&&%&#/;"/"/&4?'&4?627626.  6 $$ I     ͒(r^aaɒ    (_^aa , "'&4?6262.  6 $$ Z4f44fz(r^aaZ&4ff4(_^aa "4'32>&#" $&6$  WoɒV󇥔 zzz8YW˼[?zz:zz@5K #!#"'&547632!2A4@%&&K%54'u%%&54&K&&4A5K$l$L%%%54'&&J&j&K5K #"/&47!"&=463!&4?632%u'43'K&&%@4AA4&&K&45&%@6%u%%K&j&%K55K&$l$K&&u#5K@!#"'+"&5"/&547632K%K&56$K55K$l$K&&#76%%53'K&&%@4AA4&&K&45&%%u'5K"#"'&54?63246;2632K%u'45%u&&J'45%&L44L&%54'K%5%t%%$65&K%%4LL4@&%%K',"&5#"#"'.'547!34624&bqb>#  5&44& 6Uue7D#  "dž&/#!"&546262"/"/&47'&463!2 &@&&4L  r&4  r L&& 4&&&L rI@& r  L4&& s/"/"/&47'&463!2#!"&546262&4  r L&& &@&&4L  r@@& r  L4&& 4&&&L r##!+"&5!"&=463!46;2!28(`8((8`(88(8((8(8 (8`(88(8((8(88(`8#!"&=463!28(@(88((8 (88((88z5'%+"&5&/&67-.?>46;2%6.@g.L44L.g@. .@g. L44L .g@.g.n.4LL43.n.gg.n.34LL4͙.n.g -  $54&+";264'&+";26/a^    ^aa fm  @ J%55!;263'&#"$4&#"32+#!"&5#"&5463!"&46327632#!2$$8~+(888(+}(`8((8`]]k==k]]8,8e8P88P8`(88(@MMO4&#"327>76$32#"'.#"#".'.54>54&'&54>7>7>32&z&^&./+>*>J> Wm7' '"''? &4&c&^|h_bml/J@L@ #M6:D 35sҟw$ '% ' \t3#!"&=463!2'.54>54''  @ 1O``O1CZZ71O``O1BZZ7@  @ N]SHH[3`)TtbN]SHH[3^)Tt!1&' 547 $4&#"2654632 '&476 ==嘅}(zVl''ٌ@uhyyhu9(}VzD##D# =CU%7.5474&#"2654632%#"'&547.'&476!27632#76$7&'7+NWb=嘧}(zVi\j1  z,X Y[6 $!%'FuJiys?_9ɍ?kyhun(}Vz YF  KA؉La  02-F"@Qsp@_!3%54&+";264'&+";26#!"&'&7>2    #%;"";%#`,@L 5 `   `  L`4LH` `   a 5 L@ #37;?Os!!!!%!!!!%!!!!!!!!%!!4&+";26!!%!!!!74&+";26%#!"&546;546;2!546;232 `@ `@ @@ @ @  @  @  @  @ L44LL4^B@B^^B@B^4L  @@@@    @@   @@    M4LL44L`B^^B``B^^B`L7q.+"&=46;2#"&=".'673!54632#"&=!"+"&=46;2>767>3!546327>7&54>$32dFK1A  0) L.٫C58.H(Ye#3C $=463!22>=463!2#!"&5463!2#!"&5463!2H&&/7#"&463!2!2LhLLhLhLLh! &&&&& &4hLLhLLhLLhL%z< 0&4&& )17&4& &&#!"&5463!2!2\@\\@\\@\\\\ W*#!"&547>3!2!"4&5463!2!2W+B"5P+B@"5^=\@\ \H#t3G#3G:_Ht\\ @+32"'&46;#"&4762&&4&&44&&44&&4@"&=!"'&4762!54624&&44&&44&&4&& !!!3!!0@67&#".'&'#"'#"'32>54'6#!"&5463!28ADAE=\W{O[/5dI kDtpČe1?*w@www (M& B{Wta28r=Ku?RZ^GwT -@www$2+37#546375&#"#3!"&5463ww/Dz?swww@wS88 ww#'.>4&#"26546326"&462!5!&  !5!!=!!%#!"&5463!2B^8(Ԗ>@|K55KK55K^B(8ԖԖ€>v5KK55KKHG4&"&#"2654'32#".'#"'#"&54$327.54632@pp)*Pppp)*Pb '"+`N*(a;2̓c`." b PTY9ppP*)pppP*)b ".`(*Nͣ2ͣ`+"' b MRZB4&"24&"264&"26#"/+"&/&'#"'&547>7&/.=46?67&'&547>3267676;27632#"&'"'#"'&547&'&=4767&547>32626?2#"&'"'#"'&547&'&=4767&547>32626?2ԖLhLKjKLhLKjK "8w s%(  ")v  >  "8x s"+  ")v  <  3zLLz3 3>8L3)x3 3zLLz3 3>8L3)x3 ԖԖ4LL45KK54LL45KK #)0C wZ l/ Y N,& #)0C vZl. Y L0"qG^^Gqq$ ]G)FqqG^^Gqq$ ]G)Fq%O#"'#"&'&4>7>7.546$ '&'&'# '32$7>54'VZ|$2 $ |E~E<| $ 2$|ZV:(t}X(  &%(Hw쉉xH(%& (XZT\MKG<m$4&"24&#!4654&#+32;254'>4'654&'>7+"&'&#!"&5463!6767>763232&4&&4N2`@`%)7&,$)' %/0Ӄy#5 +1 &<$]`{t5KK5$e:1&+'3TF0h4&&4&3M:;b^v+D2 5#$IIJ 2E=\$YJ!$MCeM-+(K55KK5y*%Au]c=p4&"24&'>54'64&'654&+"+322654&5!267+#"'.'&'&'!"&5463!27>;2&4&&4+ 5#bW0/% ')$,&7)%`@``2Nh0##T3'"( 0;e$5KK5 tip<& 1&4&&4&#\=E2 JIURI$#5 2D+v^b;:M2gc]vDEA%!bSV2MK55K(,,MeCM$!J@#"&547&547%6@?V8 b% I)94.""'." 67"'.54632>32+C`\hxeH>Hexh\`C+ED4 #LoP$$Po>Q|I.3MCCM3.I|Q/Z$_dC+I@$$@I+ (@%#!"&5463!2#!"3!:"&5!"&5463!462 ww@  B^^B  4&@&&&4 `  ww   ^B@B^ 24& && &%573#7.";2634&#"35#347>32#!"&5463!2FtIG9;HIxI<,tԩw@wwwz4DD43EEueB&#1s@www .4&"26#!+"'!"&5463"&463!2#2&S3 Ll&c4LL44LL4c@& &{LhLLhL'?#!"&5463!2#!"3!26546;2"/"/&47'&463!2www@B^^B@B^@&4t  r &&`ww@w@^BB^^B@R&t r  4&&@"&5!"&5463!462 #!"&54&>3!2654&#!*.54&>3!24&@&&&4 sw  @B^^B  @w4& && &3@w   ^BB^    I&5!%5!>732#!"&=4632654&'&'.=463!5463!2!2JJSq*5&=CKuuKC=&5*q͍S8( ^B@B^ (8`N`Ѣ΀GtO6)"M36J[E@@E[J63M")6OtG(8`B^^B`8%-3%'&76'&76''&76'&76'&6#5436&76+".=4'>54'6'&&"."&'./"?+"&5463!2  2  5    z<: Ʃw 49[aA)O%-j'&]]5r,%O)@a[9( 0BA; + >HCwww  5 /)  u    @wa-6OUyU[q ( - q[UyUP6$C +) (  8&/ &ww'?$4&"2$4&"2#!"&5463!3!267!2#!#!"&5!"'&762&4&&4&&4&&48(@(88(c==c(8*&&*6&4&&4&&4&&4& (88(@(88HH88`(@&&('@1d4&'.54654'&#"#"&#"32632327>7#"&#"#"&54654&54>76763232632   N<;+gC8A`1a99gw|98aIe$IVNz<:LQJ  ,-[% 061I()W,$-7,oIX()oζA;=N0 eTZ  (O#".'&'&'&'.54767>3232>32 e^\3@P bMO0# 382W# & 9C9 Lĉ" 82<*9FF(W283 #0OMb P@3\^e FF9*<28 "L 9C9 & #!"3!2654&#!"&5463!2`B^^B@B^^ީwww@w^BB^^B@B^ww@w#!72#"' #"'.546763YY !''!0#GG$/!''!&UUjZ 8""8  X! 8" "8 EU4'./.#"#".'.'.54>54.'.#"32676#!"&5463!2G55 :8 c7 )1)  05.D <90)$9w@wwwW + AB 7c  )$+ -.1 9$)0< D.59@www,T1# '327.'327.=.547&54632676TC_LҬ#+i!+*pDNBN,y[`m`%i]hbEm}a u&,SXK &$f9s? _#"!#!#!54632V<%'ЭHH (ںR&=4'>54'6'&&"."&'./"?'&54$ 49[aA)O%-j'&]]5r,%O)@a[9( 0BA; + >HCaaoMa-6OUyU[q ( - q[UyUP6$C +) (  8&/ &fMa%+"&54&"32#!"&5463!54 &@&Ԗ`(88(@(88(r&&jj8((88(@(8#'+2#!"&5463"!54&#265!375!35!B^^BB^^B   `^B@B^^BB^  ` !="&462+"&'&'.=476;+"&'&$'.=476; pppp$!$qr % }#ߺppp!E$ rqܢ# % ֻ!)?"&462"&4624&#!"3!26!.#!"#!"&547>3!2/B//B//B//B @   2^B@B^\77\aB//B//B//B/@    ~B^^B@2^5BB52.42##%&'.67#"&=463! 25KK5L4_u:B&1/&.- zB^^B4LvyKjK4L[!^k'!A3;):2*547&5462;U gIv0ZZ0L4@Ԗ@4L2RX='8P8'=XR U;Ig0,3lb??bl34LjjL4*\(88(\}I/#"/'&/'&?'&'&?'&76?'&7676767676` (5 )0 ) *) 0) 5(  (5 )0 )))) 0) 5( *) 0) 5(  )5 )0 )**) 0) 5)  )5 )0 )*5h$4&"24&#!4>54&#"+323254'>4'654&'!267+#"'&#!"&5463!2>767>32!2&4&&4N2$YGB (HGEG HQ#5K4Li!<;5KK5 A# ("/?&}vh4&&4&3M95S+C=,@QQ9@@IJ 2E=L5i>9eME;K55K J7R>@#zD<7?s%3#".'.'&'&'.#"!"3!32>$4&"2#!"#"&?&547&'#"&5463!&546323!2` #A<(H(GY$2NL4K5#aWTƾh&4&&4K5;=!ihv}&?/"( #A  5K2*!Q@.'!&=C+S59M34L=E2 JI UR@@&4&&4&5K;ELf9>igR7J K5h4&"24#"."&#"4&#"".#"!54>7#!"&54.'&'.5463246326326&4&&4IJ 2E=L43M95S+C=,@QQ9@@E;K55K J7R>@#zD9eMZ4&&4&<#5K4LN2$YGB (HGEG HV;5KK5 A# ("/?&}vhi!<4<p4.=!32>332653272673264&"2/#"'#"&5#"&54>767>5463!2@@2*! Q@.'!&=C+S59M34L.9E2 JI UR&4&&4&Lf6Aig6Jy#@>R7J K55K;E@TƾH #A<(H(GY$2NL4K#5#a=4&&4&D=ihv}&?/"( #A  5KK5;+54&#!764/&"2?64/!26 $$ & [6[[j6[&^aa@&4[[6[[6&+^aa+4/&"!"3!277$ $$ [6[ &&[6j[ ^aae6[j[6&&4[j[^aa+4''&"2?;2652?$ $$ [6[[6&&4[^aaf6j[[6[ &&[^aa+4/&"4&+"'&"2? $$ [6&&4[j[6[j^aad6[&& [6[[j^aa   $2>767676&67>?&'4&'.'.'."#&6'&6&'3.'.&'&'&&'&6'&>567>#7>7636''&'&&'.'"6&'6'..'/"&'&76.'7>767&.'"76.7"7"#76'&'.'2#22676767765'4.6326&'.'&'"'>7>&&'.54>'>7>67&'&#674&7767>&/45'.67>76'27".#6'>776'>7647>?6#76'6&'676'&67.'&'6.'.#&'.&6'&.5/a^D&"      4   $!   #          .0"Y +  !       $     "  +       Α      ^aa                        P   ' -( # * $  "  !     * !   (         $      2 ~/$4&"2 #"/&547#"32>32&4&&4V%54'j&&'/덹:,{ &4&&4&V%%l$65&b'Cr! " k[G +;%!5!!5!!5!#!"&5463!2#!"&5463!2#!"&5463!2&&&&&&&&&&&&@&&&&&&&&&&&&{#"'&5&763!2{' **)*)'/!5!#!"&5!3!26=#!5!463!5463!2!2^B@B^&@&`^B`8(@(8`B^ B^^B&&B^(88(^G 76#!"'&? #!"&5476 #"'&5463!2 '&763!2#"'c)'&@**@&('c (&*cc*&' *@&('c'(&*cc*&('c'(&@*19AS[#"&532327#!"&54>322>32"&462 &6 +&'654'32>32"&462QgRp|Kx;CByy 6Fe= BPPB =eF6 ԖV>!pRgQBC;xK|Ԗ{QNa*+%xx5eud_C(+5++5+(C_due2ԖԖ>NQ{u%+*jԖԖp!Ci4/&#"#".'32?64/&#"327.546326#"/&547'#"/&4?632632(* 8( !)(A(')* 8( !USxySSXXVzxTTUSxySSXXVzxT@(  (8 *(('( (8 SSUSx{VXXTTSSUSx{VXXT#!"5467&5432632t,Ԟ;F`j)6,>jK?s !%#!"&7#"&463!2+!'5#8EjjE8@&&&&@XYY&4&&4&qDS%q%N\jx2"&4#"'#"'&7>76326?'&'#"'.'&676326326&'&#"32>'&#"3254?''74&&4&l NnbSVZ bRSD zz DSRb)+USbn \.2Q\dJ'.2Q\dJ.Q2.'Jd\Q2.'Jd`!O` ` &4&&4r$#@B10M5TNT{L5T II T5L;l'OT4M01B@#$*3;$*3;;3*$;3*$: $/ @@Qq`@"%3<2#!"&5!"&5467>3!263! !!#!!46!#!(88(@(8(8(`((8D<++<8(`(8(`8(@(88( 8((`(8((<`(8(``(8||?%#"'&54632#"'&#"32654'&#"#"'&54632|udqܟs] = OfjL?R@T?"& > f?rRX=Edudsq = _MjiL?T@R?E& f > =XRr?b!1E)!34&'.##!"&5#3463!24&+";26#!"&5463!2 08((88(@(8  8((88((`(1  `(88((88(@  `(88(@(8(`#!"&5463!2w@www`@www/%#!"&=463!2#!"&=463!2#!"&=463!2&&&&&&&&&&&&&&&&&&&&&&&&@'7G$"&462"&462#!"&=463!2"&462#!"&=463!2#!"&=463!2ppppppp @   ppp @    @   Рpppppp  ppp    <L\l|#"'732654'>75"##5!!&54>54&#"'>3235#!"&=463!2!5346=#'73#!"&=463!2#!"&=463!2}mQjB919+i1$AjM_3</BB/.#U_:IdDRE @  k*Gj @   @   TP\BX-@8 C)5Xs J@$3T4+,:;39SG2S.7<  vcc)( %Ll}    5e2#!"&=463%&'&5476!2/&'&#"!#"/&'&=4'&?5732767654'&@02uBo  T25XzrDCBBEh:%)0%HPIP{rQ9f#-+>;I@KM-/Q"@@@#-a[ $&P{<8[;:XICC>.'5oe71#.0(  l0&%,"J&9%$<=DTIcs&/6323276727#"327676767654./&'&'737#"'&'&'&54'&54&#!"3!260% <4"VRt8<@< -#=XYhW8+0$"+dTLx-'I&JKkmuw<=V@!X@ v '|N;!/!$8:IObV;C#V  &   ( mL.A:9 !./KLwPM$@@ /?O_o%54&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!26#!"&5463!2@@@@@@@@@^BB^^B@B^NB^^B@B^^#+3 '$"/&4762%/?/?/?/?%k*66bbbb|<<<bbbbbbbb%k66Ƒbbb<<<<^bbbbbb@M$4&"2!#"4&"2&#"&5!"&5#".54634&>?>;5463!2LhLLh LhLLhL! 'ԖԖ@' !&  ?&&LhLLhL hLLhL jjjj &@6/" &&J#"'676732>54.#"7>76'&54632#"&7>54&#"&54$ ok; -j=yhwi[+PM 3ѩk=J%62>VcaaQ^ ]G"'9r~:`}Ch 0=Z٤W=#uY2BrUI1^Fk[|aL2#!67673254.#"67676'&54632#"&7>54&#"#"&5463ww+U ,iXբW<"uW1AqSH1bdww'74'!3#"&46327&#"326%35#5##33#!"&5463!20U6cc\=hlࠥYmmnnnnw@wwww&46#Ȏ;edwnnnnn@www ]#/#"$&6$3 &#"32>7!5!%##5#5353Еttu{zz{SZC` cot*tq||.EXN#?? ,<!5##673#$".4>2"&5!#2!46#!"&5463!2rM* *M~~M**M~~M*jjj&&&&`P%挐|NN||NN|*jjjj@&&&&@ "'&463!2@4@&Z4@4&@ #!"&4762&&4Z4&&4@@ "'&4762&4@4&@&4&@ "&5462@@4&&44@&&@ 3!!%!!26#!"&5463!2`m` ^BB^^B@B^  `@B^^BB^^@ "'&463!2#!"&4762@4@&&&&44@4&Z4&&4@ "'&463!2@4@&4@4&@ #!"&4762&&4Z4&&4@:#!"&5;2>76%6+".'&$'.5463!2^B@B^,9j9Gv33vG9H9+bI\ A+=66=+A [">nSMA_:B^^B1&c*/11/*{'VO3@/$$/@*?Nh^l+!+"&5462!4&#"!/!#>32]_gTRdgdQV?U I*Gg?!2IbbIJaaiwE3300 084#"$'&6?6332>4.#"#!"&54766$32z䜬m IwhQQhbF*@&('kz   _hQнQGB'(&*eoz(q!#"'&547"'#"'&54>7632&4762.547>32#".'632%k'45%&+~(  (h  &  \(  (  &  ~+54'k%5%l%%l$65+~  &  (  (\  &  h(  (~+%'!)19K4&"24&"26.676&$4&"24&"24&"2#!"'&46$ KjKKj KjKKje2.e<^P,bKjKKjKjKKj KjKKj##LlLKjKKjK jKKjK~-M7>7&54$ LhяW.{+9E=cQdFK1A  0) pJ2`[Q?l&٫C58.H(Y':d 6?32$64&$ #"'#"&'&4>7>7.546'&'&'# '32$7>54'Yj`a#",5NK ~EVZ|$2 $ |: $ 2$|ZV:(t}hfR88T h̲X(  &%(Hw(%& (XZT\MKG{x|!#"'.7#"'&7>3!2%632u  j H{(e 9 1bU#!"&546;5!32#!"&546;5!32#!"&546;5463!5#"&5463!2+!2328((88(``(88((88(``(88((88(`L4`(88(@(88(`4L`(8 (88(@(88((88(@(88((88(@(84L8(@(88((8L48OY"&546226562#"'.#"#"'.'."#"'.'.#"#"&5476$32&"5462И&4&NdN!>! 1X:Dx+  +ww+  +xD:X1 -U !*,*&4&hh&&2NN2D &  ..J< $$ 767#"&'"&547&547&547.'&54>2l4  2cKEooED ) ) Dg-;</- ?.P^P.? -/<;-gYY  .2 L4H|O--O|HeO , , Oeq1Ls26%%4.2,44,2.4%%62sL1qcqAAq4#!#"'&547632!2#"&=!"&=463!54632  @  `     ` ?`   @  @  !    54&+4&+"#"276#!"5467&5432632   `  _ v,Ԝ;G_j)``    _ ԟ7 ,>jL>54'&";;265326#!"5467&5432632    v,Ԝ;G_j) `   `7 ,>jL>X`$"&462#!"&54>72654&'547 7"2654'54622654'54&'46.' &6 &4&&4&yy %:hD:FppG9Fj 8P8 LhL 8P8 E; Dh:% >4&&4&}yyD~s[4Dd=PppP=d>hh>@jY*(88(*Y4LL4Y*(88(*YDw" A4*[s~>M4&"27 $=.54632>32#"' 65#"&4632632 65.5462&4&&4G9& <#5KK5!!5KK5#< &ܤ9Gpp&4&&4&@>buោؐ&$KjKnjjKjK$&jjb>Ppp %!5!#"&5463!!35463!2+32@\\8(@(8\@@\\@\(88(\@ 34#"&54"3#!"&5!"&5>547&5462;U gI@L4@Ԗ@4L2RX='8P8'=XR U;Ig04LjjL4*\(88(\@"4&+32!#!"&+#!"&5463!2pP@@Pjj@@\@\&0pj \\&-B+"&5.5462265462265462+"&5#"&5463!2G9L44L9G&4&&4&&4&&4&&4&L44L &=d4LL4 d=&&`&&&&`&&&&4LL4  &#3CS#!"&5463!2!&'&!"&5!463!2#!"&52#!"&=4632#!"&=463(8((88((`x c`(8@@@`((88(@(8(D 9 8(`@@@@@/?O_o-=%+"&=46;25+"&=46;2+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2+"&=46;2!!!5463!2#!"&5463!2 @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @ &&&&@  @ @  @  @  @ @  @ @  @ @  @ @  @ @  @ @  @ @  @ @  @ @  @ @  @ @  @ @  @ @  @ @  @  @  @   `&&&& /?O_o%+"&=46;25+"&=46;2+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2+"&=46;2!!#!"&=!!5463!24&+"#54&+";26=3;26%#!"&5463!463!2!2 @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @ 8(@(8 @  @  @  @  @ &&&@8((8@&@  @ @  @  @  @ @  @ @  @ @  @ @  @ @  @ @  @  @  @  (88(  @  ``   `` -&&& (88(&@<c$4&"2!#4&"254&+54&+"#";;26=326+"&5!"&5#"&46346?>;463!2KjKKjKjKKj&ԖԖ&&@&&KjKKjK jKKjK .&jjjj&4&@@&&#'1?I54&+54&+"#";;26=326!5!#"&5463!!35463!2+32 \\8(@(8\ \\@\(88(\: #32+53##'53535'575#5#5733#5;2+3@E&&`@@` `@@`&&E%@`@ @ @      @ :#@!3!57#"&5'7!7!K5@   @5K@@@ #3%4&+"!4&+";265!;26#!"&5463!2&&&&&&&&w@www&&@&&&&@&&@www#354&#!4&+"!"3!;265!26#!"&5463!2&&&&&@&&@&w@www@&@&&&&&&@&:@www-M3)$"'&4762 "'&4762 s 2  .   2 w 2  .   2 w 2    2  ww  2    2  ww M3)"/&47 &4?62"/&47 &4?62S .  2 w 2   .  2 w 2  M . 2    2 .  . 2    2 .M3S)$"' "/&4762"' "/&47623 2  ww  2    2  ww  2    2 w 2   .v 2 w 2   .M3s)"'&4?62 62"'&4?62 623 .  . 2    2 .  . 2    2 .   2 w 2v .   2 w 2-Ms3 "'&4762s w 2  .   2 ww  2    2 MS3"/&47 &4?62S .  2 w 2  M . 2    2 .M 3S"' "/&47623 2  ww  2   m 2 w 2   .M-3s"'&4?62 623 .  . 2    2- .   2 w 2/4&#!"3!26#!#!"&54>5!"&5463!2  @ ^B && B^^B@B^ @  MB^%Q= &&& $$ (r^aa(^aa!C#!"&54>;2+";2#!"&54>;2+";2pPPpQh@&&@j8(PppPPpQh@&&@j8(Pp@PppPhQ&&j (8pPPppPhQ&&j (8p!C+"&=46;26=4&+"&5463!2+"&=46;26=4&+"&5463!2Qh@&&@j8(PppPPpQh@&&@j8(PppPPp@hQ&&j (8pPPppP@hQ&&j (8pPPpp@@ #+3;G$#"&5462"&462"&462#"&462"&462"&462"&462#"&54632K54LKj=KjKKjKjKKjL45KKjK<^^^KjKKjppp\]]\jKL45KjKKjKujKKjK4LKjKK^^^jKKjKpppr]]\  $$ ^aaQ^aa,#"&5465654.+"'&47623   #>bqb&44&ɢ5"  #D7euU6 &4&m 1X".4>2".4>24&#""'&#";2>#".'&547&5472632>3=T==T==T==T=v)GG+v@bRRb@=&\Nj!>3lkik3hPTDDTPTDDTPTDDTPTDD|x xXK--K|Mp<# )>dA{RXtfOT# RNftWQ,%4&#!"&=4&#!"3!26#!"&5463!2!28(@(88((88((8\@\\@\\(88(@(88(@(88@\\\\ u'E4#!"3!2676%!54&#!"&=4&#!">#!"&5463!2!2325([5@(\&8((88((8,9.+C\\@\ \6Z]#+#,k(88(@(88(;5E>:5E\\\ \1. $4@"&'&676267>"&462"&462.  > $$ n%%/02 KjKKjKKjKKjKfff^aayy/PccP/jKKjKKjKKjKffff@^aa$4@&'."'.7>2"&462"&462.  > $$ n20/%7KjKKjKKjKKjKfff^aa3/PccP/y jKKjKKjKKjKffff@^aa +7#!"&463!2"&462"&462.  > $$ &&&&KjKKjKKjKKjKfff^aa4&&4&jKKjKKjKKjKffff@^aa#+3C54&+54&+"#";;26=3264&"24&"2$#"'##"3!2@@KjKKjKKjKKjKܒ,gjKKjKKjKKjKXԀ,, #/;GS_kw+"=4;27+"=4;2'+"=4;2#!"=43!2%+"=4;2'+"=4;2+"=4;2'+"=4;2+"=4;2+"=4;2+"=4;2+"=4;2+"=4;54;2!#!"&5463!2`````````````````````p`K55KK55Kp`````````````````````````5KK55KK@*V#"'.#"63232+"&5.5462#"/.#"#"'&547>32327676R?d^7ac77,9xm#@#KjK# ڗXF@Fp:f_ #WIpp&3z h[ 17q%q#::#5KKu't#!X: %#+=&>7p @ *2Fr56565'5&'. #"32325#"'+"&5.5462#"/.#"#"'&547>32327676@ͳ8 2.,#,fk*1x-!#@#KjK# ڗXF@Fp:f_ #WIpp&3z e`vo8t-  :5 [*#::#5KKu't#!X: %#+=&>7p  3$ "/&47 &4?62#!"&=463!2I.  2 w 2   -@). 2    2 . -@@-S$9%"'&4762  /.7> "/&47 &4?62i2  .   2 w E > u > .  2 w 2   2    2  ww !   h. 2    2 . ;#"'&476#"'&7'.'#"'&476' )'s "+5+@ա' )'F*4*Er4M:}}8 GO *4*~ (-/' #"'%#"&7&67%632B;>< V??V --C4 <B=cB5 !% %!b 7I))9I7 #"'.5!".67632y( #  ##@,( )8! !++"&=!"&5#"&=46;546;2!76232-SSS  SS``  K$4&"24&"24&"27"&5467.546267>5.5462 8P88P88P88P8P88P4,DS,4pp4,,4pp4,6d7AL*',4ppP88P8P88P8HP88P8`4Y&+(>EY4PppP4Y4Y4PppP4Y%*54&#"#"/.7!2<'G,')7N;2]=A+#H  0PRH6^;<T%-S#:/*@Z}   >h.%#!"&=46;#"&=463!232#!"&=463!2&&&@@&&&@&&&&&&&&&&&&f&&&&b#!"&=463!2#!"&'&63!2&&&&''%@% &&&&&&&&k"G%#/&'#!53#5!36?!#!'&54>54&#"'6763235 Ź}4NZN4;)3.i%Sin1KXL7觧* #& *@jC?.>!&1' \%Awc8^;:+54&#"'6763235 Ź}4NZN4;)3.i%PlnEcdJ觧* #& *-@jC?.>!&1' \%AwcBiC:D'P%! #!"&'&6763!2P &:&? &:&?5"K,)""K,)h#".#""#"&54>54&#"#"'./"'"5327654.54632326732>32YO)I-D%n  "h.=T#)#lQTv%.%P_ % %_P%.%vUPl#)#T=@/#,-91P+R[Ql#)#|'' 59%D-I)OY[R+P19-,##,-91P+R[YO)I-D%95%_P%.%v'3!2#!"&463!5&=462 =462 &546 &&&&&4&r&4&@&4&&4&G݀&&&&f s CK&=462 #"'32=462!2#!"&463!5&'"/&4762%4632e*&4&i76`al&4&&&&&}n  R   R zfOego&&5`3&&&4&&4& D R   R zv"!676"'.5463!2@@w^Cct~5  5~tcC&&@?JV|RIIR|V&&#G!!%4&+";26%4&+";26%#!"&546;546;2!546;232@@@@L44LL4^B@B^^B@B^4L  N4LL44L`B^^B``B^^B`LL4&"2%#"'%.5!#!"&54675#"#"'.7>7&5462!467%632&4&&4  @ o&&}c ;pG=(  8Ai8^^.   &4&&4&` ` fs&& jo/;J!# 2 KAE*,B^^B! ` $ -4&"2#"/&7#"/&767%676$!28P88PQr @ U @ {`PTP88P8P`  @U @rQ!6'&+!!!!2Ѥ 8̙e;<*@8 !GGGQII %764' 64/&"2 $$ f3f4:4^aaf4334f:4:^aa %64'&" 2 $$ :4f3f4F^aa4f44f^aa 764'&"27 2 $$ f:4:f4334^aaf4:4f3^aa %64/&" &"2 $$ -f44f4^aa4f3f4:w^aa@7!!/#35%!'!%j/d jg2|855dc b @! !%!!7!FG)DH:&H dS)U4&"2#"/ $'#"'&5463!2#"&=46;5.546232+>7'&763!2&4&&4f ]wq4qw] `dC&&:FԖF:&&Cd`4&&4& ]] `d[}&&"uFjjFu"&&y}[d#2#!"&546;4 +"&54&" (88(@(88( r&@&Ԗ8((88(@(8@&&jj'3"&462&    .  > $$ Ԗ>aX,fff^aaԖԖa>TX,,~ffff@^aa/+"&=46;2+"&=46;2+"&=46;28((88((88((88((88((88((8 (88((88((88((88((88((88/+"&=46;2+"&=46;2+"&=46;28((88((88((88((88((88((8 (88((88(88((88(88((885E$4&"2%&'&;26%&.$'&;276#!"&5463!2KjKKj   f  \ w@wwwjKKjK"H   ܚ  f   @www   $64'&327/a^ ! ^aaJ@%% 65/ 64'&"2 "/64&"'&476227<ij6j6u%k%~8p8}%%%k%}8p8~%<@% %% !232"'&76;!"/&76  ($>( J &% $%64/&"'&"2#!"&5463!2ff4-4ff4fw@wwwf4f-f4@www/#5#5'&76 764/&"%#!"&5463!248` # \P\w@www4`8  #@  `\P\`@www)4&#!"273276#!"&5463!2& *f4 'w@www`&')4f*@www%5 64'&"3276'7>332#!"&5463!2`'(wƒa8! ,j.( &w@www`4`*'?_`ze<  bw4/*@www-.  6 $$  (r^aaO(_^aa -"'&763!24&#!"3!26#!"&5463!2yB(( @   w@www]#@##   @ @www -#!"'&7624&#!"3!26#!"&5463!2y((@B@u @   w@www###@  @ @www -'&54764&#!"3!26#!"&5463!2@@####@w@wwwB((@@www`%#"'#"&=46;&7#"&=46;632/.#"!2#!!2#!32>?6#  !"'?_  BCbCaf\ + ~2   }0$  q 90r p r%D p u?#!"&=46;#"&=46;54632'.#"!2#!!546;2D a__ g *`-Uh1    ߫}   $^L  4b+"&=.'&?676032654.'.5467546;2'.#"ǟ B{PDg q%%Q{%P46'-N/B).ĝ 9kC< Q 7>W*_x*%K./58`7E%_ ,-3  cVO2")#,)9;J) "!* #VD,'#/&>AX>++"''&=46;267!"&=463!&+"&=463!2+32Ԫ$   pU9ӑ @/*f o  VRfq f=SE!#"&5!"&=463!5!"&=46;&76;2>76;232#!!2#![       % )   "  Jg Uh BW&WX hU g 84&#!!2#!!2#!+"&=#"&=46;5#"&=46;463!2j@jo g|@~vv u n#467!!3'##467!++"'#+"&'#"&=46;'#"&=46;&76;2!6;2!6;232+32QKt# #FNQo!"դѧ !mY Zga~bm] [o"U+, @h h@@X hh @83H\#5"'#"&+73273&#&+5275363534."#22>4.#2>ut 3NtRP*Ho2 Lo@!R(Ozh=,GID2F 8PuE>.'%&TeQ,jm{+>R{?jJrL6V @`7>wmR1q uWei/rr :Vr" $7V4&#"326#"'&76;46;232!5346=#'73#"'&'73267##"&54632BX;4>ID2F +>R{8PuE>.'%&TeQ,jm{?jJrL6 @`rr :Vr3>wmR1q uWei@ \%4&#"326#!"&5463!2+".'&'.5467>767>7>7632!2&%%&&&& &7.' :@$LBWM{#&$h1D!  .I/! Nr&&%%&&&&V?, L=8=9%pEL+%%r@W!<%*',<2(<&L,"r@ \#"&546324&#!"3!26%#!#"'.'.'&'.'.546767>;&%%&&&& &i7qN !/I.  !D1h$&#{MWBL$@: '.&&%%&&&&=XNr%(M&<(2<,'*%<!W@r%%+LEp%9=8=L  +=\d%54#"327354"%###5#5#"'&53327#"'#3632#"'&=4762#3274645"=424'.'&!  7>76#'#3%54'&#"32763##"'&5#327#!"&5463!2BBPJNC'%! B? )#!CC $)  54f"@@ B+,A  A+&+A  ZK35N # J!1331CCC $)w@www2"33FYF~(-&"o4*)$(* (&;;&&:LA3  8334S,;;,WT+<<+T;(\g7x:&&::&&<r%-@www  +=[c}#"'632#542%35!33!3##"'&5#327%54'&#"5#353276%5##"=354'&#"32767654"2 '.'&547>76 3#&'&'3#"'&=47632%#5#"'&53327''RZZ:kid YYY .06 62+YY-06 R[!.'CD''EH$VVX::Y X;:Y fyd/%jG%EC&&CE%O[52. [$C-D..D^^* ly1%=^I86i077S 3 $EWgO%33%OO%35 EEFWt;PP;pt;PP;pqJgTFQ%33&PP%33%R 7>%3!+}{'+"&72'&76;2+"'66;2U &  ( P *'eJ."-dZ-n -'74'&+";27&+";276'56#!"&5463!2~} 7e  ۩w@www"  $Q #'!# @www/4'&327$ '.'.4>7>76 "!!jG~GkjGGk[J@&& @lAIddIAllAIddIA@ '5557 ,VWQV.RW=?l%l`~0  !#!#%777 5! R!!XCCfff݀# `,{{{`/?%##"547#3!264&#"3254&+";267#!"&5463!2R܂#-$䵀((((tQQttQvQtn?D~|D?x##))((QttQvQtt2#!"&54634&"2$4&"2ww@ww||||||w@www||||||| !3 37! $$ n6^55^h ^aaM1^aaP *Cg'.676.7>.'$7>&'.'&'? 7%&'.'.'>767$/u5'&$I7ob?K\[zH,1+.@\7':Yi4&67&'&676'.'>7646&' '7>6'&'&7>7#!"&5463!2PR$++'TJXj7-FC',,&C ."!$28 h /" +p^&+3$ i0(w@www+.i6=Bn \C1XR:#"'jj 8Q.cAj57!? "0D$4" P[ & 2@wwwD"%.5#5>7>;!!76PYhpN!HrD0M C0N#>8\xx: W]oW-X45/%'#.5!5!#"37>#!"&5463!2p>,;$4 5eD+WcEw@wwwK()F ,VhV^9tjA0/@www@#"'&76;46;23   &  ++"&5#"&7632  ^  c  & @#!'&5476!2 &  ^  b '&=!"&=463!546  &    q&8#"'&#"#"5476323276326767q'T1[VA=QQ3qpHih"-bfGw^44O#A?66%CKJA}} !"䒐""A$@C3^q|z=KK?6 lk)  %!%!VVuuu^-m5w}n~7M[264&"264&"2"&546+"&=##"&5'#"&5!467'&766276#"&54632    *<;V<<O@-K<&4'>&4.'.'.'.'.'&6&'.'.6767645.'#.'6&'&7676"&'&627>76'&7>'&'&'&'&766'.7>7676>76&6763>6&'&232.'.6'4.?4.'&#>7626'.'&#"'.'.'&676.67>7>5'&7>.'&'&'&7>7>767&'&67636'.'&67>7>.'.67 \ U7  J#!W! '  " ';%  k )"    '   /7*   I ,6 *&"!   O6* O $.( *.'  .x,  $CN      * 8   7%&&_f& ",VL,G$3@@$+ "  V5 3"  ""#dA++ y0D- %&n 4P'A5j$9E#"c7Y 6" & 8Z(;=I50 ' !!e  R   "+0n?t(-z.'< >R$A"24B@( ~ 9B9, *$        < > ?0D9f?Ae  .(;1.D 4H&.Ct iY% *  7      J  <    W 0%$  ""I! *  D  ,4A'4J" .0f6D4pZ{+*D_wqi;W1G("% %T7F}AG!1#%  JG 3  '.2>Vb%&#'32&'!>?>'&' &>"6&#">&'>26 $$ *b6~#= XP2{&%gx| .W)oOLOsEzG< CK}E $MFD<5+ z^aa$MWM 1>]|YY^D եA<KmE6<" @9I5*^aa>^4./.543232654.#"#".#"32>#"'#"$&547&54632632':XM1h*+D($,/9p`DoC&JV;267676&#!"&=463!267 #!"'&5463!26%8#! &&Z"M>2! ^I 7LRx_@>MN""`=&&*%I},  L7_jj9/%4&#!"3!264&#!"3!26#!"&5463!2  &&&&&&&&19#"'#++"&5#"&5475##"&54763!2"&4628(3- &B..B& -3(8IggI`(8+Ue&.BB.&+8(kk`%-"&5#"&5#"&5#"&5463!2"&4628P8@B\B@B\B@8P8pPPp@`(88(`p.BB.0.BB.(88(Pppͺ!%>&'&#"'.$ $$ ^/(V=$<;$=V).X^aaJ`"(("`J^aa,I4."2>%'%"/'&5%&'&?'&767%476762%6[՛[[՛o ܴ   $ $ " $ $  ՛[[՛[[5` ^ ^ 2` `2 ^ ^ ` 1%#"$54732$%#"$&546$76327668ʴhf킐&^zs,!V[vn) 6<ׂf{z}))Ns3(@ +4&#!"3!2#!"&5463!2#!"&5463!2@&&&f&&&&@&&&&4&&4&@&&&&&&&& `BH+"/##"./#"'.?&5#"&46;'&462!76232!46 `&C6@Bb03eI;:&&&4L4&F Z4&w4) '' 5r&4&&4&&4}G3#&/.#./.'&4?63%27>'./&'&7676>767>?>%6})N @2*&@P9A #sGq] #lh<* 46+(  < 5R5"*>%"/ +[>hy  K !/Ui%6&'&676&'&6'.7>%.$76$% $.5476$6?62'.76&&'&676%.76&'..676#"NDQt -okQ//jo_  %&JՂYJA-.-- 9\DtT+X?*<UW3' 26$>>W0 {"F!"E    ^f`$"_]\<`F`FDh>CwlsJ@ ;=?s  :i_^{8+?` ) O`s2RDE58/Kr #"'>7&4$&5mī"#̵$5$"^^W=acE*czk./"&4636$7.'>67.'>65.67>&/>z X^hc^O<q+f$H^XbVS!rȇr?5GD_RV@-FbV=3! G84&3Im<$/6X_D'=NUTL;2KPwtPt=  &ռ ,J~S/#NL,8JsF);??1zIEJpqDIPZXSF6[?5:NR=;.&1 +!"&=!!%!5463!2sQ9Qs***sQNQsBUw wUBFHCCTww%1#"&=!"&=463!54632.  6 $$     ` ?(r^aa    (_^aa%1#!#"'&47632!2.  6 $$   @  ` (r^aa  ?  @  (_^aa/#"'&476324&#!"3!26#!"&5463!2&@& @   w@www& @B@ &  @ @www"&462  >& $$ Ԗ*(r^aaԖԖ (^aa]6#"$54732>%#"'!"&'&7>32'!!!2f:лѪz~u: ((%`V6B^hD%i(]̳ޛ *>6߅r#! 3?^BEa߀#9#36'&632#"'&'&63232#!"&5463!2 Q,&U #+' ;il4L 92<D`w@www`9ܩ6ɽ ]`C477&@wwwD+"&5#"'&=4?5#"'&=4?546;2%6%66546;2  wwwwcB G]B Gty]ty #3C#!+"&5!"&=463!46;2!24&#!"3!26#!"&5463!2@`@`^BB^^B@B^www@w@`@`2@B^^BB^^ww@w'/?P+5#"&547.467&546;532!764'!"+32#323!&ln@ :MM: @nY*Yz--zY*55QDDU9pY-`]]`.X /2I$ t@@/!!/@@3,$,3$p$00&*0&& !P@RV2#"&/#"&/#"&546?#"&546?'&54632%'&54632763276%>S]8T;/M77T7%>ww@ww!"5bBBb./ * 8(@(87)(8=%/' #?w@www#~$EE y &L(88e):8(%O r    O?GQaq47&67>&&'&67>&"$32#"#"'654  $&6 $6&$ CoL.*K  Px.* iSƓ i 7J ?~pi{_Я;lLUZ=刈刈_t'<Z :!   @! j`Q7  $ky, Rfk*4LlL=Z=刈&$&546$7%7&'5>]5%w&P?zrSF!| &0 ##!"&5#5!3!3!3!32!546;2!5463) );));;))&&&@@&&&  6 $&727"'%+"'&7&54767%&4762֬>4P t+8?::  ::A W` `EvEEvE<."e$IE&O &EI&{h.`m"&#"&'327>73271[ >+)@ (]:2+D?*%Zx/658:@#N C= E(oE=W'c:#!#"$&6$3 &#"32>7! ڝyy,{ۀہW^F!LC=y:yw߂0H\R%"N^ '&76232762$"&5462"&46274&"&'264&#"'&&#"32$54'>$ $&6$ G>>0yx14J55J5J44J5Fd$?4J55%6E#42F%$fLlLq>>11J44%&4Z%44J54R1F$Z-%45J521Z%F1#:ʎ 9LlL#Qa"'&7622762%"&5462"&546274&#"&'73264&#"'&&#"32654'>#!"&5463!2 55 **.>.-@-R.>.-@-<+*q6- -- 0OpoOxzRrqP6z~{{Prr^aa]054&"#"&5!2654632!#"&57265&'&#".'&'#"&5467%&4>7>3263232654.547'654'63277.'.*#">7?67>?>32#"'7'>3'>3235?KcgA+![,7*  2(-#=  /~[(D?G  |,)"# +)O8,+'6 y{=@0mI#938OAE` -  )y_/FwaH8j7=7?%a % %!?)L J 9=5]~pj  %(1$",I  $@((  +!.S -L__$'-9L 5V+ 6 T+6.8- $ 0 + t |S 16]&#"'&#"67>76'&'&#"67>32764.#"#.32>67>7 $&54>7>7>7rJ@ "kb2)W+ ,5/1   #   Z -!$IOXp7sLCF9vz NAG#/ 5|Հ';RKR/J#=$,9,+$UCS7'2"1  ! / ,   /--ST(::(ep4AM@=I>".)xΤlsY|qK@ %(YQ&N EHv~<Zx'#"&5467&6?2?'&"/.7.546326#"&'&/7264/7'764&"'?>>32.AUpIUxYE.A %%%h% %hJ%D,FZxULs TgxUJrVD %hJ%@/LefL.C %Jh%CV sNUxϠ@.FZyUHpVA %h&%% %Ji%CWpIUybJ/Uy^G,D %Jh%@U sMt UC %hJ%C-KfyEX[_gj&/&'.''67>7>7&'&'&'>76763>7>#&'&'767672'%'7'+"&'&546323267>7%#"'4'6767672,32,+DCCQLDf' % :/d B 4@ }  &!0$?Jfdf-.=6(:!TO? !IG_U% . j+.=; 5gN_X "  ##  292Q41   *6nA;| BS N.  %1$ 6 #nk^ '7GWgw2+"&5463#!"&5463!254&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";26#"&=! B^^BB^^B:FjB^8((`( `(8^BB^^B@B^"vEj^B(8(`(8(/?O_o/?2#!"&5463;26=4&+";26=4&+";26=4&+";26=4&+"54&+";2654&+";2654&+";2654&+";2654&+";2654&#!"3!2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";26@&&&&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&&&&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`% "&5#"&5&462!762$"&462B\B@B\B8PpP8.BB..BB.8$P88P広3CQ#".54>32#".546322#"&#"#"54>%".54>32%2#"&54> &X=L|<&X=M{2r_-$$-_rUU%&&5%ő'- "'.546762@FF$@B@$.&,&.]]|q#<<#(BB B%'-%'-'%'-"'%&'"'%.5467%467%62@ll@ll,@GG&!@@@@@@!&+#+#6#+$*`:p:px p=`$>>$&@&@ @&p@ &.A!!"!&2673!"5432!%!254#!5!2654#!%!2#!8Zp?vdΊens6(N[RWu?rt1SrF|iZ@7މoy2IMC~[R yK{T:%,AGK2#!"&5463!!2654'654.#532#532"&5!654&#"327#2#>!!ww@ww~uk'JTMwa| DH> I1q Fj?w@wwwsq*4p9O*¸Z^qh LE "(nz8B M'?"&4624&#"'.'324&#"3267##"&/632632.ʏhhMALR vGhг~~K „yO^   ʏʏВ*LM@!שwwȍde)qrOPqȦs:03=7'.?67'67%'>&%'7%7./6D\$>  "N,?a0#O 1G9'/P(1#00  ($=!F "9|]"RE<6 'o9%8J$\ :\HiTe<?}V#oj? d,6%N#" HlSVY]C =@C4&"2!.#!"4&"2+"&=!"&=#"&546;>3!232^^^Y ^^^`pppp`]ibbi]~^^^e^^^PppPPppP]^^]3;EM2+"&=!"&=#"&546;>;5463!232264&"!.#!"264&" ]`pppp`]ibbi^^^dY !^^^]@PppP@@PppP@]^^] ^^^e^^^ 3$#!#!"&5467!"&47#"&47#"&4762++&2 $$ 2&&&4&&Z4&&##&&4&4&44&m4&m+DP4'&#"32763232674'&!"32763 3264'&$#"32763232> $$ g* o`#ə0#z#l(~̠) -g+^aaF s" +g (* 3#!| #/IK/%*%D= )[^aa !!!'!!77!,/,-a/G t%/;<HTbcq%7.#"32%74'&"32765"/7627#"5'7432#"/7632#"5'7432#"&5'74632 #"/6327#"/6327#"/46321"&/462"&/>21"&/567632#!.547632632  *     X    ^  `    ^  b  c   fu U`59u  4J   l~ ~ F 2    m | O,           ru| u  " )9 $7 $&= $7 $&= $7 $&=  $&=46w`ww`ww`wb`VTEvEEvETVTEvEEvET*VTEvEEvET*EvEEvEEvEEv#^cu#!"&5463!2!&'&!"&5!632#"&'#"/&'&7>766767.76;267674767&54&5&'67.'&'&#3274(8((88((`x c`(8!3;:A0?ݫY   ^U 47D$    74U3I  |L38wtL0`((88(@(8(D 9 8(Q1&(!;  (g- Up~R2(/{E(Xz*Z%(i6CmVo8 #Q#!"&5463!2!&'&!"&5!3367653335!3#'.'##'&'35(8((88((`x c`(8iFFZcrcZ`((88(@(8(D 9 8(kk" kkJ ! k#S#!"&5463!2!&'&!"&5!%!5#7>;#!5#35!3#&'&/35!3(8((88((`x c`(8-Kg kL#DCJg  jLD`((88(@(8(D 9 8(jj jjkk kk#8C#!"&5463!2!&'&!"&5!%!5#5327>54&'&#!3#32(8((88((`x c`(8 G]L*COJ?0R\wx48>`((88(@(8(D 9 8(jjRQxk !RY#*2#!"&5463!2!&'&!"&5!!57"&462(8((88((`x c`(8Pppp`((88(@(8(D 9 8(ppp  #*7JR5#5#5#5##!"&5463!2!&'&!"&5##5!"&54765332264&"<(8((88((`x c`(8kޑcO"jKKjK`((88(@(8(D 9 8(SmmS?M&4&&4#9L^#!"&5463!2!&'&!"&5!#"/#"&=46;76276'.'2764'.(8((88((`x c`(8 6ddWW6&44`((88(@(8(D 9 8(. G5{{5]]$5995#3C#!"&5463!2!&'&!"&5!2#!"&5463#"'5632(8((88((`x c`(84LL44LL4l  `((88(@(8(D 9 8(L44LL44L  Z #7K[#!"&5463!2!&'&!"&5!>&'&7!/.?'&6?6.7>'(8((88((`x c`(8` 3  3  3  3 v  ?  `((88(@(8(D 9 8( & & - & &  ?   '6#'. '!67&54632".'654&#"32eaAɢ/PRAids`WXyzOvд:C;A:25@Ң>-05rn`H( ' gQWZc[ -%7' %'-'% %"'&54762[3[MN 3",""3,3"ong$߆]gn$+) ")")" x#Z#"&#!+.5467&546326$32327.'#"&5463232654&#"632#".#"oGn\ u_MK'̨|g? CM7MM5,QAAIQqAy{b& BL4PJ9+OABIRo?z.z n6'+s:zcIAC65D*DRRD*wya$, @B39E*DRRD*'/7  $&6$ 6277&47' 7'"' 6& 6'lLRRZB|RR>dZZLlLZRR«Z&>«|R ! $&54$7 >54'5PffP牉@s-ff`-c6721>?>././76&/7>?>?>./&31#"$&(@8!IH2hM>'  )-* h'N'!'Og,R"/!YQG54'63&547#5#"=3235#47##6323#324&"26%#!"&5463!2F]kbf$JMM$&N92Z2&`9UW=N9:PO;:dhe\=R +)&')-S99kJ<)UmQ/-Ya^"![Y'(<`X;_L6#)|tWW:;X  #'#3#!"&5463!2) p*xeשw@www0,\8@www9I#"'#"&'&>767&5462#"'.7>32>4."&'&54>32JrO<3>5-&FD(=Gq@C$39aLL²L4 &) @]v q#CO!~󿵂72765'./"#"&'&5 }1R<2" 7MW'$  ;IS7@5sQ@@)R#DvTA ; 0x I)!:> +)C 6.> !-I[4&#"324&#"3264&#"324&#"326&#"#".'7$4$32'#"$&6$32D2)+BB+)3(--(31)+BB+)4'--'4'#!0>R HMŰ9ou7ǖD䣣 R23('3_,--,R23('3_,--,NJ ?uWm%#"'%#"'.5 %&'&7632! ; `u%"(!]#c)(  #"'%#"'.5%&'&76 !  (%##fP_"(!)'+ʼn4I#"$'&6?6332>4.#"#!"&54766$32#!"&=46;46;2z䜬m IwhQQhbF*@&('k@z   _hQнQGB'(&*eozΘ@@`  >. $$ ffff^aafff^aa>"&#"#"&54>7654'&#!"#"&#"#"&54>765'46.'."&54632326323!27654'.5463232632,-,,",:! %]& %@2(/.+*)6! <.$..**"+8#  #Q3,,++#-:#"$$ /:yuxv)%$ /?CG%!5%2#!"&5463!5#5!52#!"&54632#!"&5463#5!5`&&&& &&&&&&&&@&&&&&&&&&&&&%2 &547%#"&632%&546 #"'6\~~\h ~\h\ V V VV%5$4&#"'64'73264&"&#"3272#!"&5463!2}XT==TX}}~>SX}}XS>~}w@www~:xx:~}}Xx9}}9xX}@www/>LXds.327>76 $&6$32762#"/&4762"/&47626+"&46;2'"&=462#"'&4?62E0l,  *"T.D@Yooo@5D [  Z  Z  [ ``[ Z  2 ,l0 (T" .D5@oooY@D, Z  [  [  Z ``EZ  [ 5%!  $&66='&'%77'727'%amlLmf?55>fFtuutFLlLHYC L||L Y˄(E''E*( /?IYiy%+"&=46;2+"&=46;2+"&=46;2+"&=46;2%"&=!#+"&=46;2+"&=46;2+"&=46;2+"&=46;2!54!54>$ +"&=46;2#!"&=@&&@3P > P3&&rrr&&rrr he 4LKM:%%:MKL4WT&&%/9##!"&563!!#!"&5"&5!2!5463!2!5463!2&&&&&&  &&&i@&&@&7'#5&?626J%o;j|/&jJ%p&`Jj&p/|jţ%Jk%o%  :g"&5462#"&546324&#!"263662>7'&75.''&'&&'&6463!276i~ZYYZ~@OS;+[G[3YUD#o?D&G3I=JyTkBuhNV!WOhuAiSy*'^CC^'*SwwSTvvTSwwSTvvWID\_"[ gq# /3qFr2/ $rg%4 HffHJ4d#!#7!!7!#5!VFNrmNNN N!Y+?Ne%&'&'&7>727>'#&'&'&>2'&'&676'&76$7&'&767>76 '6# <;11x# *# F-T93%/#0vNZ;:8)M:( &C.J}2 %0  ^*  JF &7'X"2LDM" +6 M2+'BQfXV#+] #' L/(eB9  #,8!!!5!!5!5!5!5#26%!!26#!"&5!5&4& &pPPp@@&&@!&@PppP@*  9Q$"&54627"."#"&547>2"'.#"#"&5476$ "'&$ #"&5476$ (}R}hLK NN Ud: xx 8    ,, |2222 MXXM ic,>>,   ̺  '/7?KSck{4&"2$4&"24&"24&"24&"24&"24&"24&"24&"264&"24&#!"3!264&"2#!"&5463!2KjKKjKjKKjKjKKjKKjKKjKjKKjKjKKjKKjKKjKjKKjKLhLLhLKjKKj&&&&KjKKjL44LL44L5jKKjKKjKKjKjKKjKjKKjKjKKjKjKKjKjKKjKjKKjK4LL44LLjKKjK&&&&jKKjK4LL44LL 'E!#"+"&7>76;7676767>'#'"#!"&7>3!2W",&7' #$ &gpf5 O.PqZZdS -V"0kqzTxD!!8p8%'i_F?;kR(` !&)w.<\.'.>%#"'.7>.'&67632&'6'&' #"'.766.'&67632Z &+\cc:>'D> 6KD3W6,9(<*0-?")/SW7.Crb  :+OIX3'#C3:@ #*"-A%,1U=}AQfO$"|'"S*`H(:UܳJ?27sZy%+A07C~Ӗ5A"3 >IY#6?>7&#!%'.'33#&#"#"/3674'.54636%#"3733#!"&5463!24  : @7vH%hEP{0&<'VFJo1,1.F6A#L44LL44L"% 7x'6 O\JYFw~v^fH$ ! "xdjD"!6`J4LL44LL $1Ol-#"326%356.#"#"326%4#"326%3#7#'#3%#7#"&546324>54#"47632&#"'"'473254&'&54323#327#"'47673#327#"546327&#7673>7&#"327#"&54632#7#"&54632654#"47632&#7673>73#7#"&54632.#"#&'#67&#"327&'3673326#!"&5463!2 />  0@[W,8 G'"5,Q4/&4/ $&J (W" +Tl +7o _7*#) 83 ( -5G8 .'3/$&I8 48+5%7%{,2,rr,2,x-2.jj.2-xL44LL44L[ < J 2)(*(8$e  '+ , 1)H/ 'H4/// ,~i6_7G*''4fE!%97+" ;=4FYqO" '+ , &2hh_ ,0(5N(ntggtnno__on4LL44LL  BWbjq}+532%+5324&+32763#4&'.546327&#"#"'3265#"&546325&#"32 !264&"2%#'#735#535#535#3'654&+353#!"&5463!29$<=$@?SdO__J-<AA@)7")9,<$.%0*,G3@%)1??.+&((JgfJ*A!&jjjGZYGиwsswPiL>8aA !M77MM77M3! 4erJ]&3YM(, ,%7(#)  ,(@=)M%A20C&Mee(X0&ĖjjjV 8Z8J9N/4$ 8NN88NN  #&:O[ $?b3'7'#3#%54+32%4+324+323'%#5#'#'##337"&##'!!732%#3#3##!"&53733537!572!56373353#'#'#"5#&#!'#'#463!2#"5#"5!&+&+'!!7353273532!2732%#54&+#32#46.+#2#3#3##+53254&".546;#"67+53254&.546;#"#'#'##"54;"&;7335wY-AJF=c(TS)!*RQ+*RQ+Y,B^9^Ft`njUM ') ~PSPRm٘M77Mo7q @)U 8"E(1++NM77Mx378D62W74;9<-A"EA0:A F@1:ؗBf~~""12"4(w$#11#@}}!%+%5(v$:O\zK?* $\amcrVlOO176Nn23266&+"&#"3267;24&+"'&+";27%4&+";2?>23266&+"&#"3267;254+";27#76;2#!"&5463!23%#2%%,,  _3$$2%%M>AL Vb5)LDHeE:< EM j,K'-R M ~M>AR  Vb5)LEHeE:< E J ABI*'! ($rL44LL44Lv%1 %3!x*k $2 %3!;5h n a !(lI;F   rp p8;5h t a !(lI;F ` #k 4LL44LL  2HW[lt#"'5632#6324&'.54327&#"#"&'32767#533275#"=5&#"'#36323#4'&#"'#7532764&"24'&#"327'#"'&'36#!"&5463!2=!9n23BD$ &:BCRM.0AC'0RH`Q03'`.>,&I / * / 8/n-(G@5$ S3=,.B..B02^`o?7je;9G+L44LL44LyE%# Vb;A !p &'F:Aq)%)#orgT$ v2 8)2z948/{ 8AB..B/q?@r<7(g/4LL44LL ?#!"&'24#"&54"&/&6?&5>547&54626=L4@ԕ;U g3 T 2RX='8P8|5 4Ljj U;Ig@   `  "*\(88(]k  &N4#"&54"3 .#"#!"&'7!&7&/&6?&5>547&54626;U gIm*]Z0L4@ԕ=o=CT T 2RX='8P8|5  U;IgXu?bl3@4Ljja`   `  "*\(88(]k/7[%4&+";26%4&+";26%4&+";26!'&'!+#!"&5#"&=463!7>3!2!2@@@@@@0 o`^BB^`5FN(@(NF5@@@u  @LSyuS@%44%,<H#"5432+"=4&#"326=46;2  >. $$ ~Isy9"SgR8vHD w ffff^aam2N+ )H-mF+10*F +fff^aab4&#"32>"#"'&'#"&54632?>;23>5!"3276#"$&6$3 k^?zb=ka`U4J{K_/4^W&  vx :XB0܂ff ) fzzXlz=lapzob35!2BX G@8  ' '=vN$\ff  1 SZz8zX#("/+'547'&4?6276 'D^h  i%5@%[i  h]@]h  i%@5%[i  h^@@)2#"&5476#".5327>OFi-ay~\~;'S{s:D8>)AJfh]F?X{[TC6LlG]v2'"%B];$+l|%!2>7>232>7>322>7>32"&'.#"#"&'.#"#"&'.#"#546;!!!!!32#"&54>52#"&54>52#"&54>52-P&+F) $P.-P$'#+&PZP&+#"+&P-#) $P-.P$(#+$P.-P$'#+&P-.P$+#pP@@PpH85K"&ZH85K"&ZH85K"&Z@Pp@@@pMSK5, :&LMSK5, :&LMSK5, :& !!3 ! @@@  #"$$3!!2"jaѻxlalxaaj!!3/"/'62'&63!2'y  `I  yMy `I y'W`#".'.#"32767!"&54>3232654.'&546#&'5&#" 4$%Eӕ;iNL291 ;XxR`f՝Q8TWiWgW:;*:`Qs&?RWXJ8 oNU0 J1F@#) [%6_POQiX(o`_?5"$iʗ\&>bds6aP*< -;iFn* -c1BWg4'.'4.54632#7&'.#"#"'.#"32767'#"&54632326#!"&5463!2#$( 1$6]' !E3P|ad(2S;aF9'EOSej]m] <*rYshpt.#)$78L*khw@wwwB % $/$G6 sP`X):F/fwH1pdlqnmPHuikw_:[9D'@www34."2>$4.#!!2>#!".>3!2QнQQнQQh~wwhfffнQQнQQнQZZQffff#>3!2#!".2>4."fffнQQнQQffffQнQQн ,\!"&?&#"326'3&'!&#"#"'  5467'+#"327#"&463!!'#"&463!2632(#AHs9q ci<= #]$ KjKKjKKjKKjH#j#H&&&KjKKjKg V i jKKjKKjKKjK ..n(([5KK55KK5[poNv<+#"'#"&546;&546$32322$B$22$$*$22$Xڭӯ$22$tX'hs2$ϧkc$22$1c$2F33F3VVT2#$2ԱVT2#$2g#2UU݃ 2$#2UU1݃2 ,u54#"67.632&#"32654'.#"32764.'&$#"7232&'##"&54732654&#"467&5463254632>32#"'&ru&9%" *#͟O%GR=O&^opC8pP*bY _#$N Pb@6)?+0L15 "4$.Es  5IQ"!@ h "Y7e|J>ziPeneHbIlF>^]@n*9 6[_3#"&54632#.#"32%3#"&54632#.#"326%4&'.'&! ! 7>7>! =39? 6'_ >29? 5'17m-VU--,bW.뮠@Fyu0HC$뮠@Fyu0HC$L= ?? <=! A <`;+"&54&#!+"&5463!2#!"&546;2!26546;2pЇ0pp@Ipp>Sc+"&=46;254&+"&+";2=46;2;2=46;2;2%54&#!";2=;26#!"&5463!2A5DD5A7^6a7MB55B7?5B~```0`rr5A44A5v5AA5f*A``0` !!!! #!"&5463!2ړ7H7jv@vvv':@vvvMUdkpu{#"'!"'!#"&547.547.54674&547&54632!62!632!#!6227'!%!"67'#77!63!!7357/7'%# %'3/&=&' 5#?&547 6!p4q"""6" 'h*[ |*,@?wAUMpV@˝)Ϳw7({*U%K6=0(M "! O dX$k !! ! b [TDOi @6bxBAݽ5  ɝ:J +3,p x1Fi (R 463!#!"&5%'4&#!"3`а@..@A-XfB$.BB..C} )&54$32&'%&&'67"w`Rd]G{o]>p6sc(@wgmJPAjyYWa͊AZq{HZ:<dv\gx>2ATKn+;"'&#"&#"+6!263 2&#"&#">3267&#">326e~└Ȁ|隚Ν|ū|iyZʬ7Ӕްr|uѥx9[[9jj9ANN+,#ll"BS32fk[/?\%4&+";26%4&+";26%4&+";26%4&+";26%#!"&5467&546326$32]]eeeeee$~i qfN-*#Sjt2"'qCB8!'> !%)-159=AEIMQUY]agkosw{! %! 5!#5#5#5#5#57777????#5!#5!#5!#5!#5!#5!#5!#5#537#5!#5!#5!#5!#5!#55#535353535353%"&546326#"'#32>54.&54>3237.#"Q%%%%%%%%%?iiihOiixiiyiixiiArssrrssr%sssrrssNs%%%%%%%%%%'32#".543232654&#"#"&54654&#"#"&547>326ڞUzrhgrxSПdU 7#"&463!2!2&&4&&&&4&KjKKjKjKKj &&&%&& &&4&&&&4&&&5jKKjKKjKKjK%z 0&4&&3D7&4& %&'S4&"4&"'&"27"&462"&462!2#!"&54>7#"&463!2!2&4&4&4&4KjKKjKjKKj &&&%&& &&4&%&&ے&4"jKKjKKjKKjK%z 0&4&&3D7&4& %& & !'! !%!!!!%"'.763!2o]FooZY@:@!!gf//I62'"/"/"/"/"/"/"/7762762762762762762%"/77627&6?35!5!!3762762'"/"/"/"/"/"/%5#5!4ZSS6SS4SS4SS4SS4SS4SS4ZSS4SS4SS4SS4SS4SS4S-4ZSS4S@4SS4ZSS6SS4SS4SS4SS4SS4S@ZSSSSSSSSSSSSSSZSSSSSSSSSSSSSyZRRR@%:= :+: =RRZSSSSSSSSSSSSSCv!/&'&#""'&#" 32>;232>7>76#!"&54>7'3&547&547>763226323@``` VFaaFV      $. .$     yy .Q5ZE$ ,l*%>>%*>*98(QO!L\p'.'&67'#!##"327&+"&46;2!3'#"&7>;276;2+6267!"'&7&#"(6&#"#"' Dg OOG`n%ELL{@&&Nc,sU&&!Fre&&ss#/,<= #]gL oGkP'r-n&4&2-ir&&?o  4 _5OW! .54>762>7.'.7>+#!"&5#"&5463!2"&462{{BtxG,:`9(0bԿb0(9`:,GxtB&@&&@&K55K`?e==e?1O6# ,  #$  , #6OO&&&&5KK?!"'&'!2673267!'. ."!&54632>321 4q#F""8'go#- #,"tYg>oP$$Po> Zep#)R0+I@$$@I++332++"&=#"&=46;.7>76$  @ ᅪ*r@@r'/2+"&5".4>32!"&=463  &@~[՛[[u˜~gr&`u՛[[՛[~~@r=E32++"&=#"&=46;5&547&'&6;22676;2  >``@``ٱ?E,,=?rH@``@GݧH`jjrBJ463!2+"&=32++"&=#"&=46;5.7676%#"&5   &@~``@``  vXr&@``@+BF`rks463!2+"&=32++"&=#"&=46;5&547'/.?'+"&5463!2+7>6 %#"&5   &@~``@``~4e  0  io@& jV  0  Z9r&@``@Gɞ5o , sp &@k^ , c8~~`r8>KR_32++"&=!+"&=#"&=46;.767666'27&547&#"&'2#" @@ 'Ϋ'sggsww@sgg@@-ssʃl99OOr99FP^l463!2+"&=$'.7>76%#"&=463!2+"&=%#"&54'>%&547.#"254&' &@L?CuГP vY &@;"ޥ5݇ޥ5`&_ڿgwBF@&J_ s&&?%x%xJP\h463!2+"&='32++"&=#"&=46;5.7676632%#"&56'327&7&#"2#" &@L? ߺu``@``} ຒɞueeu9uee&_"|N@``@""|a~lo99r9@9;C2+"&5"/".4>327'&4?627!"&=463  &@Ռ .  N~[՛[[u˜N .  gr&`֌  . Ou՛[[՛[~N  . @r9A'.'&675#"&=46;5"/&4?62"/32+  '֪ \  . 4 .  \r|ݧ憛@\ .    . \@r~9A"/&4?!+"&=##"$7>763546;2!'&4?62  m  - @ݧ憛@& -  @rm4 -  ٮ*   - r+"&5&54>2  @[՛[rdGu՛[[r  ".4>2r[՛[[՛r5՛[[՛[[$2#!37#546375&#"#3!"&5463#22#y/Dz?s!#22#2##2S88 2#V#2L4>32#"&''&5467&5463232>54&#"#"'.Kg&RvgD $ *2% +Z hP=DXZ@7^?1 ۰3O+lh4`M@8'+c+RI2 \ZAhSQ>B>?S2Vhui/,R0+ ZRkmz+>Q2#"'.'&756763232322>4."7 #"'&546n/9bLHG2E"D8_ pdddxO"2xxê_lx2X  !+'5>-pkW[C I I@50Oddd˥Mhfxx^ә #'+/7!5!!5!4&"2!5!4&"24&"2!!! 8P88P 8P88P88P88PP88P8 P88P88P88P8 +N &6 !2#!+"&5!"&=463!46;23!#!"&54>32267632#"_>@`     `  L4Dgy 6Fe=OOU4L>   ` `  4L2y5eud_C(====`L43V &6 #"/#"/&54?'&54?6327632#!"&54>32 7632_>     %%Sy 6Fe=J%>     %65%Sy5eud_C(zz.!6%$!2!!!46;24&"2!54&#!"&&&@ԖV@&&@&&ԖԖ@&3!!! !5!'!53!! #7IeeI7CzCl@@@#2#!"&?.54$3264&"!@մppp((ppp#+/2#!"&?.54$3264&"!264&"!@մ^^^@^^^@((^^^^^^v(#"'%.54632 "'% 632U/@k0G,zD# [k# /tg F Gz  #'#3!) p*xe0,\8T #/DM%2<GQ^lw &'&676676&'&7654&'&&546763"#"'3264&7.>&'%'.767&7667&766747665"'.'&767>3>7&'&'47.'.7676767&76767.'$73>?>67673>#6766666&'&6767.'"'276&67&54&&671&'6757>7&"2654&57>&>&'5#%67>76$7&?5.''&'&'#'""#''&'&'&'65.'&6767.'#%&''&'#2%676765&'&'&7&5&'6.7>&5R4&5S9 W"-J0(/r V"-J0(.)#"6&4pOPppc|o}vQ[60XQW1V  # 5X N"& . ) D>q J:102(z/=f*4!> S5b!%  (!$p8~5..:5I  ~T 4~9p# ! ) & ?()5F 1   d%{v*: @e s|D1d {:*dAA|oYk'&<tuut&v HCXXTR;w 71™  Z*&' 1  9? . $Gv 5k65P.$.`aasa``Z9k'9؋ӗa-*Gl|Me_]`F& OܽsDD!/+``aa``a154&'"&#!!26#!"&5463!2    iLCly5)*Hcelzzlec0hb,,beIVB9@RB9J_L44LL44L44%2"4:I;p!q4bb3p (P`t`P(6EC.7BI64LL44LL  .>$4&'6#".54$ 4.#!"3!2>#!"&5463!2Zjbjj[wٝ]>oӰٯ*-oXL44LL44L')꽽)J)]wL`ֺ۪e4LL44LL;4&#!"3!26#!"&5463!2#54&#!";#"&5463!2  @ ^BB^^B@B^  B^^B@B^`@  MB^^B@B^^>  ^B@B^^5=Um ! !!2#!"&=463!.'!"&=463!>2!2#264&"".54>762".54>762?(``(?b|b?B//B/]]FrdhLhdrF]]FrdhLhdrF@@@(?@@ ?(@9GG9@/B//BaItB!!BtI Ѷ!!ь ItB!!BtI Ѷ!!ь-M32#!"&=46;7&#"&=463!2#>5!!4.'.46ՠ`@`ՠ`MsFFsMMsFFsMojjo@@jj@@<!(!!(!-3?32#!"&=46;7&#"&=463!2+!!64.'#ՠ`@`ՠ`  DqLLqDojjo@@jj@@B>=C-3;32#!"&=46;7&#"&=463!2+!!6.'#ՠ`@`ՠ`UVU96gg6ojjo@@jj@@β**ɍ-G32#!"&=46;7&#"&=463!2#>5!!&'.46ՠ`@`ՠ`MsFFsMkkojjo@@jj@@<!(!33!(!9I2#!"&=4637>7.'!2#!"&=463@b":1P4Y,++,Y4P1:"":1P4Y,++,Y4P1:"b@@@7hVX@K-AA-K@XVh77hVX@K-AA-K@XVh7Aj"#54&#"'54&#"3!26=476=4&#"#54&'&#"#54&'&'2632632#!"&5&=4632>3265K @0.B @0.B#6'&& l @0.B 2' .B A2TA9B;h" d mpPTlLc _4.HK5]0CB.S0CB./#'?&&)$$)0CB. }(AB.z3M2"61d39L/PpuT(Ifc_E`1X"#4&"'&#"3!267654&"#4&"#4&26326#!"&'&5463246326\B B\B&@5K&@"6LB\B B\B sciL}QP%&#"!"3!754?27%>54&#!26=31?>Ijjq,J[j.-tjlV\$B.R1?@B.+?2`$v5K-%5KK5.olRIS+6K5̈$B\B 94E.&ʀ15uE& ԖPjjdXUGJ7!.B P2.B %2@ 7K5(B@KjKj?+fU E,5K~!1.>F.F,Q5*H$b2#!"&=%!"&=463!7!"&'&=4634'&#!">3!!"3!32#!"3!23!26=n$7654&#"#654&#"#.!"'.54632&5467>32>3200?t ='/@H@"+4K8"*!4dtB/&> c@0&=  =_JUD29i1"07 {x\YSgSSW]|t eyD0&0D/  I4C+) t .B3%h#/B0&&03|&p>i +#] WsgQT\QglU ]#-39oK_3[_cg"'&#"3!2676=4&"#54&#"#54&#"#4&'2632632632#!"&'&5463246#!#!#5K)B4J&@#\8P8 @0.B J65K J6k cJ/4qG^\hB2.1!~K5y?^\Vljt-.j[J,qjjI7$?1R.B+.B$`2?gvEo.5KK5%-K6+SIR[&.E49 B\B$5KG#!+"&5!"&=463!2+"&' +"' +"'&5>;2>76;2Y    M .x - N     u  , u ?  LW   #  *:J4'&+326+"'#+"&5463!2  $6& $&6$ UbUI-uu,uuڎLlLAX!Jmf\$ 6uuu,KLlL-[k{276/&'&#"&5463276?6'.#"!276/&'&#"&5463276?6'.#"  $6&  $&6]h - %Lb`J%E 5 ,5R- h - %Lb`J%E 5 ,5R-'uu,uulL/hR    dMLc  NhR   dMLc  N1uuu,LlL@  ' 7 '7 ``H ``H !``H ```H` '%  7' 7'7 ' $&6$ X`(W:,:X`(WLLlLX`(W:BX`(XLlL $ %/9ES[#"&54632$"&4624&"26$4&#"2%#"&462$#"&4632#"32&! 24>  !#"&'.'#"$547.'!6$327&'77'&77N77N'qqqqqPOrqEsttsst}||}uԙ[WQ~,> nP/R U P酛n >,m'77'&77N77N6^Orqqqqqqt棣棣(~|| on[usј^~33pc8{y%cq33dqpf L 54 "2654"'&'"/&477&'.67>326?>< x ,  (-'sI  VCV  Hr'-(  $0@!BHp9[%&!@0$u  ]\\]-$)!IHV D V HI!)$-#36>N"&462."&/.2?2?64/67>&  #!"&5463!2]]]3 $; &|v;$ (CS31 =rM= 4TC(G zw@www]]]($-;,540= sL =45,; @www(2#"$&546327654&#" &#"AZ\@/#%E1/##.1E$![A懇@@\!#21E!6!E13"|! gL&5&'.#4&5!67&'&'5676&'6452>3.'5A5RV[t,G'Q4}-&r! G;>!g12sV&2:#;d=*'5E2/..FD֕71$1>2F!&12,@K r#"&5462>%.#"'&#"#"'>54#".'7654&&5473254&/>7326/632327?&$  $6 $&6$ !&"2&^ u_x^h ;J݃HJǭ qE Dm! M G?̯' %o8 9U(F(ߎLlL&!&!SEm|[n{[<ɪ "p C Di% (K HCέ  pC B m8 @Kނ  HF(LlL "*6%&6$ 7&$5%%6'$2"&4}x3nQH:dΏX e8z' li=! 7So?vM '&7>>7'7>''>76.'6'El:Fg r *t6K3U Z83P)3^I%=9 )<}Jk+C-Wd &U-TE+]Qr-< Q#0 C+M8 3':$ _Q =+If5[ˮ&&SGZoMkܬc#7&#"327#"'&$&546$;#"'654'632ե›fKYYKf¥yͩ䆎L1hvvƚwwkn]*]nlxDLw~?T8bb9SA}+5?F!3267!#"'#"4767%!2$324&#"6327.'!.#"۔c28Ψ-\?@hU0KeFjTlyE3aVsz.b؏W80]TSts<hO_u7bBtSbF/o|V]SHކJ34&#!"3!26#!!2#!"&=463!5!"&5463!2  @ ^B `` B^^B@B^   @ @B^@@^BB^^>3!"&546)2+6'.'.67>76%&F8$.39_0DD40DD0+*M7{L *="# U<-M93#D@U8vk_Y [hD00DD00Dce-JF1 BDN&)@ /1 dy%F#"'&'&'&'&763276?6#"/#"/&54?'&763276"&'&'&5#&763567632#"'&7632654'&#"32>54'&#"'.5463!2#!3>7632#"'&'&#"'&767632yqoq>* 432fba  $B? >B BB AA.-QPPR+ 42 %<ciђ:6% hHGhkG@n`IȌ5 !m(|.mzyPQ-.  je  r=@@?ppgVZE|fb6887a %RB? =B ABBAJvniQP\\PRh cDS`gΒ 23geFGPHXcCI_ƍ5" n*T.\PQip [*81 / 9@:>t%6#".'.>%6%&7>'.#*.'&676./&'.54>754'&#"%4>327676= >vwd" l "3 /!,+ j2.|%& (N &wh>8X}xc2"W<4<,Z~fdaA`FBIT;hmA<7QC1>[u])  u1V(k1S) - 0 B2* %M ;W(0S[T]I) A 5%R7&&=,Xq&&@X,LΒw%%;#!"&5463!546;2!2!+"&52#!"/&4?63!5! (&&@&&(&&@&&( (  &&@&&@&&&&  #''%#"'&54676%6%% hh @` !   !    #52#"&5476!2#"&5476!2#"'&546        @  @  @    84&"2$4&"2$4&"2#"'&'&7>7.54$ KjKKjKjKKjKjKKjdne4" %!KjKKjKKjKKjKKjKKjK.٫8  !%00C'Z'.W"&462"&462"&462 6?32$6&#"'#"&'5&6&>7>7&54>$ KjKKjKjKKjKjKKjhяW.{+9E=cQdFK1A  0) LlLjKKjKKjKKjKKjKKjKpJ2`[Q?l&٫C58.H(Yee    Y'w(O'R@$#"&#"'>7676327676#" b,XHUmM.U_t,7A3ge z9@xSaQBLb( VU  !!!==w)@T!!77'7'#'#274.#"#32!5'.>537#"6=4>5'.465! KkkK _5 5 #BH1`L I& v6S F!Sr99rS!`` /7K%s}H XV  P V  e  Vd/9Q[ $547.546326%>>32"&5%632264&#"64'&""&'&"2>&2654&#";2 P 3>tSU<)tqH+>XX|Wh,:UStW|XX>=X*  ))  +^X^|WX=>X:_.2//a:Ru?  Q%-W|XW>J( =u>XX|WX`  *((*  +2 2X>=XW|E03>$32!>7 '&'&7!6./EUnohiI\0<{ >ORDƚ~˕VƻoR C37J6I`Tb<^M~M8O  5!#!"&!5!!52!5463 ^B@B^`B^^B `B^^"^BB^ #D2+#!"$&6$3227%#"$$ %&$#" 7=D9KqMLw9'qnH.Ktfw㿢p??pY9n6 LlLkT ၌.?p㿢p?   7!' !\W\ d;tZ`_O; k54+";2%54+";2!4&"!4;234;2354;2354;&5462!2#!32354;2354;2354;2````pp``` &4& ```@PppPpppppp$&&$ ppppp j#"'&=!;5463!2#!"&=#".'.#!#"&463232>7>;>32#"&'#"!546 %. `@` :,.',-XjjXh-,'.,: kb>PppP>bk .%Z & :k%$> $``6&L')59I"TlԖlT"I95)'L&69GppG9$ >$%k: !+32&#!332 $&6$ ~O88OLlL>pN  iLlL '':Ma4&'#"'.7654.#""'&#"3!267#!"&54676$32#"'.76'&>$#"'.7654'&676mD5)  z{6lP,@KijjOoɎȕ>>[ta) GG 4?a) ll >;_-/ 9GH{zyN@,KԕoN繁y! ?hh>$ D" >â? $ n"&5462'#".54>22654.'&'.54>32#"#*.5./"~~s!m{b6# -SjR,l'(s-6^]Itg))[zxȁZ&+6,4$.X%%Dc* &D~WL}]I0"  YYZvJ@N*CVTR3/A3$#/;'"/fR-,&2-" 7Zr^Na94Rji3.I+ &6W6>N%&60;96@7F6I3+4&#!"3!26%4&#!"3!26 $$ ^aa`@@^aa '7  $ >. %"&546;2#!"&546;2#/a^(^aa(N@@4&#!"3!26 $$ @@^aa`@^aa '  $ >. 7"&5463!2#/a^(n@^aa(N@ %=%#!"'&7!>3!26=!26=!2%"&54&""&546 ##]VTV$KjKKjK$&4&Ԗ&4&>9G!5KK55KK5!&&jj&&#/;Im2+#!"&'#"&463>'.3%4&"26%4&"26%6.326#>;463!232#.+#!"&5#"5KK5sH..Hs5KK5e# )4# %&4&&4&&4&&4&` #4) #%~]eZ&&Ze] E-&&-EKjKj.<<.KjK)#)`"@&&`&&&&`&&)#`)"dXo&&oXG,8&&8!O##!!2#!+"'&7#+"'&7!"'&?63!!"'&?63!6;236;2!2@@8@7 8Q NQ N 8G@ 8GQ NQ N7   8 8  H H  k%  ".>2I20]@]@oo@@oo㔕a22]]p^|11|99|11|(%7'7' ' 7T dltl)qnluul)1$4&"24&"2 &6 +"&5476;2 &6 LhLLhLLhLLhL>  &   &`>hLLhLLhLLhL>&&>jP_< u>u>  ~pU3U3]yn2@ zZ@55 zZZ@,_@s@ @(@@@- MM- MM@@@ -`b $ 648""""""@ D@ ,,@  m)@@   ' D9>dY* w    T     @ f %RE    $!k(PBp<$H<TfT H R , D x 6 \ DLX*(2^n0|bX*Z >n@jDH. 4 n !>:>>?|@@>@xAVABBBBCRCDE:FFxFGVGHH\HHHII0IbIIIJ*JrJK`KL@LMM~NN\NO.OOPZPQQNQQR`SU6UV(VzVVW>WWX"XnXXXYY^YYZ2ZdZ[[[[\l\]]]]]^R^_```a`abb:bbcd$dfdeelef&fvfg gghBhphhi2iriijBjzjk kbkll\llmm8mvmnnbnno8op pbpql Ǣ"ɚʔ| ͜VΤ zвTXҾ&`ӎӎӎ,Ԩn(\֚8\tۆ`ܨRݼ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq rstuvwxyz{|}~     " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuuni00A0uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni202Funi205Funi25FCglassmusicsearchenvelopeheartstar star_emptyuserfilmth_largethth_listokremovezoom_inzoom_outoffsignalcogtrashhomefile_alttimeroad download_altdownloaduploadinbox play_circlerepeatrefreshlist_altlockflag headphones volume_off volume_down volume_upqrcodebarcodetagtagsbookbookmarkprintcamerafontbolditalic text_height text_width align_left align_center align_right align_justifylist indent_left indent_rightfacetime_videopicturepencil map_markeradjusttinteditsharecheckmove step_backward fast_backwardbackwardplaypausestopforward fast_forward step_forwardeject chevron_left chevron_right plus_sign minus_sign remove_signok_sign question_sign info_sign screenshot remove_circle ok_circle ban_circle arrow_left arrow_rightarrow_up arrow_down share_alt resize_full resize_smallexclamation_signgiftleaffireeye_open eye_close warning_signplanecalendarrandomcommentmagnet chevron_up chevron_downretweet shopping_cart folder_close folder_openresize_verticalresize_horizontal bar_chart twitter_sign facebook_sign camera_retrokeycogscomments thumbs_up_altthumbs_down_alt star_half heart_emptysignout linkedin_signpushpin external_linksignintrophy github_sign upload_altlemonphone check_emptybookmark_empty phone_signtwitterfacebookgithubunlock credit_cardrsshddbullhornbell certificate hand_right hand_lefthand_up hand_downcircle_arrow_leftcircle_arrow_rightcircle_arrow_upcircle_arrow_downglobewrenchtasksfilter briefcase fullscreengrouplinkcloudbeakercutcopy paper_clipsave sign_blankreorderulol strikethrough underlinetablemagictruck pinterestpinterest_signgoogle_plus_sign google_plusmoney caret_downcaret_up caret_left caret_rightcolumnssort sort_downsort_up envelope_altlinkedinundolegal dashboard comment_alt comments_altboltsitemapumbrellapaste light_bulbexchangecloud_download cloud_uploaduser_md stethoscopesuitcasebell_altcoffeefood file_text_altbuildinghospital ambulancemedkit fighter_jetbeerh_signf0fedouble_angle_leftdouble_angle_rightdouble_angle_updouble_angle_down angle_left angle_rightangle_up angle_downdesktoplaptoptablet mobile_phone circle_blank quote_left quote_rightspinnercirclereply github_altfolder_close_altfolder_open_alt expand_alt collapse_altsmilefrownmehgamepadkeyboardflag_altflag_checkeredterminalcode reply_allstar_half_emptylocation_arrowcrop code_forkunlink_279 exclamation superscript subscript_283 puzzle_piece microphonemicrophone_offshieldcalendar_emptyfire_extinguisherrocketmaxcdnchevron_sign_leftchevron_sign_rightchevron_sign_upchevron_sign_downhtml5css3anchor unlock_altbullseyeellipsis_horizontalellipsis_vertical_303 play_signticketminus_sign_alt check_minuslevel_up level_down check_sign edit_sign_312 share_signcompasscollapse collapse_top_317eurgbpusdinrjpyrubkrwbtcfile file_textsort_by_alphabet_329sort_by_attributessort_by_attributes_alt sort_by_ordersort_by_order_alt_334_335 youtube_signyoutubexing xing_sign youtube_playdropbox stackexchange instagramflickradnf171bitbucket_signtumblr tumblr_signlong_arrow_down long_arrow_uplong_arrow_leftlong_arrow_rightwindowsandroidlinuxdribbleskype foursquaretrellofemalemalegittipsun_366archivebugvkweiborenren_372stack_exchange_374arrow_circle_alt_left_376dot_circle_alt_378 vimeo_square_380 plus_square_o_382_383_384_385_386_387_388_389uniF1A0f1a1_392_393f1a4_395_396_397_398_399_400f1ab_402_403_404uniF1B1_406_407_408_409_410_411_412_413_414_415_416_417_418_419uniF1C0uniF1C1_422_423_424_425_426_427_428_429_430_431_432_433_434uniF1D0uniF1D1uniF1D2_438_439uniF1D5uniF1D6uniF1D7_443_444_445_446_447_448_449uniF1E0_451_452_453_454_455_456_457_458_459_460_461_462_463_464uniF1F0_466_467f1f3_469_470_471_472_473_474_475_476f1fc_478_479_480_481_482_483_484_485_486_487_488_489_490_491_492_493_494f210_496f212_498_499_500_501_502_503_504_505_506_507_508_509venus_511_512_513_514_515_516_517_518_519_520_521_522_523_524_525_526_527_528_529_530_531_532_533_534_535_536_537_538_539_540_541_542_543_544_545_546_547_548_549_550_551_552_553_554_555_556_557_558_559_560_561_562_563_564_565_566_567_568_569f260f261_572f263_574_575_576_577_578_579_580_581_582_583_584_585_586_587_588_589_590_591_592_593_594_595_596_597_598f27euniF280uniF281_602_603_604uniF285uniF286_607_608_609_610_611_612_613_614_615_616_617_618_619_620_621_622_623_624_625_626_627_628_629VO)hugo-0.92.2/examples/blog/static/fonts/fontawesome-webfont.woff000066400000000000000000002432041420147000300245770ustar00rootroot00000000000000wOFFF*FFTMDjo)GDEF` OS/2?`Yzcmapwmgasp8glyf@*,,qhead.<16 Uhhea.p$ [hmtx. )*loca1LiVmaxp6D name6d3Fpost8r 7cAwebfF|*VO=Pu>xc`d``b `b`d`dj,` $xc`fsgbʢb l |6Fe ňDfsx͒?kqgI]5 5C W NW "R: %SX!c{M6o~hK҃{{@^;%$ȧ&=d2,<jT֬浨ej]N:Bq!,(*hF-ky+Z٪V$=~!&49-hI+ZӆtWSA# r( jh]уX2b;;r 6݆[WSY'YG$ 2'axBx?x7W+/ʟ|Ƨ|z|[^^(+5Y|`&DTxڼ |T0~9w}Ν-d&&$a'Ĉ. P VZQv_;ݴԶn~b[۾U[߶?[!s?ܙ$$}{Ͼ>y<#6q٠$rPF5m'IC\տiiN|RsuqHH&\1l2ɠTJ~$>\Ѩw$O(W9w yw<, AtG89jYPu4GvXpC Nd- cLe xK7΂Vz~3BPbQټbxpͻJ}Ҁ8ì yh6.@CG͞ x HBi G=cW]u ȏcW݈VF0$@Xͧhō):/G#tvy8us 9."/Yp3E#јpXg.B`DrN!Leemr2| d6ڮ%U (f`V t'sf7^;--نodϯ;[O( .?mڴ="gV>zYg3[?%LFwOhn1[qC§ ?vP:䡔x!4ժrpxU oj]ƿ*>yaAQ U(f#J&V t(NW u57.M~;UUMYgzSSΈ~>zQ>_OԭЫG#L-vL jPW;Fh'8y5[{ԟk^yL|H+ia@U BR=]Y~-9tЭ[>O߽aN&›7|q;]|xs3/xG-M35%zPs+˝]]t*ڌ:pu"2/-4>c?[}GlgsQon4FʩSLX$BUC9^ V ?5$IԇR'Y[<xz>n=fjи;K<R*Haud1@ 'ag䇓plLXSkU7Z%a=qQ7W>zj7 0'}_TQ'0 p.>Č0aX 8,8̐ĆV^HWroG(~,wD>K|x+OEDžV$6Mecw9$=dW꯴P\PT Cc}R4|F/Bp6fY{i is 2<:*a^d)a h0 1Xz2| :P=$OV͵>^Y{?rKKH[#&g3.K,zkA?]vgk;4ųwW~Wh>`mZyɾc۷d&k~SӁNj)wGO}]47]X!9x 55[W/EAcA?# \.DdO7-=P5*sӠ2&[o5n ^+$.Z!toL.DL^Cnn l͹Yo&c055iifi[Z/1 =Չ ۓ:͇(tr3K57?"q,:n:ilGCA*k{QVwJ`ZPl~p6 )l$aX'_Q4yYpGDWw|U֯aؾbvq8Ih!,U~]h!P4s)<+kĥqDRf6Iv?wz<Z s&X":gMˬxFZ}l.k|niPvO6#h%+)>rйo6Fc˖-pǢ^y?S3iLZ7wC,}q)D1G5מX1ί)u y3_]l(lk5u!Ĉ| ;¹ĭ9V U }/R8ndiId$%;py+|Fy.~4p4BP)yS>3bgÙqͥtRx2$'{#w3[{l:WȟEohglQ0" *rl"3JGhz (A7~5H0O@:ZʸR]&h@HBɏ g?z=Bо C& ?֚M8jS%v ڢ*N>AtWn `zXyw;XPi sչVt y?ͺzF]~A~}y/ϋ^d̈́}eP%s , o޵yU2lV><s\8LJSf:j̊þilF3F< "PvUm#r_a2pRِ\z,^:O&GiR<ЦisNTUFy.f$qFv>ND 4;O@):%@=B:[DOKI#Ő+ѕ#d.uF:UgQPw#Ω7 =K;C!ɏG;G2X=ވOX$5H cZ'F,9 6tǿIpnZLow,%:]N/丈+S$C#pGa{.AVDI4H'NH< Ў}CĦKwOv\/Xa( Ň-I_~۽57mN]ޓ~9{fglR9M ʼ!}"۾|ݺ|e>sMޖ-xZ ެ3- v,?rzGzdOti)OtsP/[p,KISw PiQjwγ,>MӽHQ_m]>'3z\{]v B3ll6m훕='6jF\DZ!bUZo.ׯ_zNa$ f.j7atCz[0At]B=`SñB@a[n(/Lv3r Sb8#r-kAfGŋ=8cz,|OEDi5 :b3#ѤHuX((G τ0~"ϻܣ`pCM|".sxsYĘd/?1o!m?G:`ޒ`5odc~tlJ8۝$3% ׇ0Շru ?ݬO%.I%SLD`ը$\)Y4,GInʒ:̇/[GIm>c,w)fN!$&=\) ];s'?a=cGJECȠ\L^Q@o1+?`=YSN'MCx9T:AA@K.j :IbfS]bnѣqaQt^k2(ItH9E+ϵБI&$U@V{K m2o9G! "&R,K0xlx8|$8fN p\0I'J=nh@ ڼ5y| + )ۑ#p&};6ɐ2h遲#4ӑ#hhϱkr\ (czM@ zZՃA4=\wŜh4H9W@ScdJ*1\Ns{&rA>>>PsB{JĢ wB3zON pœչ|t ѿs uzbxyWTR%(`mf ;BNw;y/|RK[⿠"tf\H TJ/S`i"l%p&Fvl=usY}BhݒG\oJiv00$b5>Au_V^[ :bqRNG/il?Z#d(F5!u}7~U.BQطŕgwr:MQ:Rn HbJHvIA|i]n{gym]5VzS[  u.js`*Z,S1 cjn#6[.>me3:b.@T`[Ԡ<Ѵ.9t'Sݭ̨Lısj0#?yԥϕF^Wz:cҀ+ST~Yi!%ӰDa>gfc+|͙WL>)HiNI s F28vI@> h>^zelmU<a<(hvlSdOW)v*IypbyM ~Yo(.܀q6EǗ?I5,Q&+Vj;N=IMbkf*5/j (6A7am0ų(P =Yx5w0¢  07FZ:xU $4F>!7JTS@29q 4Ѽ6vJܥJ4~ >::raS#~9`a Je89|yW7kvV#e*|vYP![0 ղ^댥Z"PɒS?+UGV=ouL6}:ؐj돷^"`9ªCK_,fy<`63Lnֺ{<0^>ɣ $W<<q¾htAt$P(էы*<*mE("mT2H11# ꯡh*wFp. P? (ΥaՠGU/u".Px+uw.!mmp|Ys YbHouz/uG^ ƜZKܮQ켼Z+*]t{јn7_Wi{,kկP-IϢw,}E .,C*Z3Kp־1Y 87aC ]u!hX  ݤ%TyyP& eKuah48>1-q I4ӇyDMmg*pJ{# &JZo{i>tK_ۂ ԢA[R>_ џT_ejOBCdٯVbJLe?^( UBpe|%`v8av`[a<r/Y%CA+LN' Vkn ڕ̜ KA,}IvpS yN&4j}0bOL$\dH-}_Xmf9xoѳGtj߽|fB_ؿҎN ZWE0i~~§Z/'c^І"J2Ie91QTMޮc*Sc 9SNX^g:^$}Ջ_>|>䐱=>_KWd/=3 1O7`#T;=<7"7UXȹuE4KeHcv+"֯ݳU"P>jBoXlӍS.i47s{Wg5_|Cu^YeIj\ϭ/R%T<ȌDckpQrLtBn1nMß@s>M_};W8j75؏~-qm:U}_9VT2+mz+4+r~IT[pL\l bMog]T삶8`ǯ-\]Z y㖿1C'/yjA7G+('tZ'ϾvKfգ7ifpݾ| 'yAF-?if6`fi$wIulYϓܖ-Jc-7zYkh&o5} =/ГF zl/?o:yvh˖Mʖ[8 si?'PW< iCN^o.]ݧV)/3$üq亴A䊫ƏC||?U~ bATK6Z@Tip'>Q7XD=H6V&:iry˘W[6km5<Ήs\ƒj:75ϡq:+yUapl"Æ) `=ʶ_|{-zfzs]fMe|#zJILW`E:`?AO颤9T4Z3GYPs^Oѕ5S1[ `Եۄ ChOG;]_aK'7tLͱ=f ;~й~O4g @:dx^m@bvMֆ[ /tmXxSiO{vko*,i7]\g&EL*~Mh1Qj^rLrVF2\#m+*["@k OYWcDEm n[5čsCX kk˶<"Q4^ӯTZ$wN̷.eUy{8$YO\] f͞ _™XۣZ|ʔG 73 4$qΰKr- 'suI^¨t: G&C9~o9v <gކl~Ƴ^̿U>me%7o%\ 7.ykgeDGeT).q,pJ2O*edc$X*ФJ^@ ,x2"1 ,0^&g]_1׷'R4 $l-5<ڠ1C[ R2rpC9}|:t9w$䏒kVt܉zj֬Tr쑧=mC_q?=4ߛJ1Ryz2%hFdrԞ ;0`wT%lB€z7ECu0{d3ɵ譨`NT;ڋiv}+'Ŭ\EEBjWx&BY%, 2Cd)hd G"GmK)NJRQrJ `'AtT,b=QK0[ ,A%* ruXWh}*nӻ4P~H:dr: Kl]5h<'2շ)=mkDi]fz\lV:M4l0{ͤ,\d/mD J Dh FAD 6#611</2RzTѓ9gןj}z@31 Xksc "v;jF<ܤBm# ift;t-Z,+&YE݈ȉ>ˌ5QK*]yPB}t#}海xy9-(WS44bz2c^v*v2 GYb)k|,GӤL` ]ɠ3xKg1kZ\X3]z϶<|opՄW,z;ء 8,0`c^9Us)S)uuWrogǿ:{QarjA .1X`4( K^ 1]1b`'y,TC; &sտ"~]J'jVZ${ XIeɉ7XjDRL ׮I'%OBm 9p~q}.YvADH7o8v}rJ(RG1dUN,w64~pTdoFUECF#3ZS"j6 eu#C G8y硧MZ.NEѡsU7 ?܆(/m6ե:ZQ%]~a~;tZ v\{,J BA2-56+].aVKLgrA8 X` 5Wknr;n.Т|ƌ|h՟|N7Co>{ّiYMyYwW F.;߸~wZ>~B6>JܽlU_6D÷9^k?Gb|n )#kwj?Yх"1U=~; P5o1E='WK<Ƨټ.k?(-ENjks['eJ?^P:GX;cMg]AdU(X[7:ЉCejH,OUNTk{EMɆ7ήNf dO@7l :a?hJfE+f<GPQT6+8ŌCfk2%BCU.IHg@j]`.<gb65Z+kإVM){!۱;{d;ׄv/A"?Ͽ:Ҵl`[h knۯZ}Z#Ts}Ɍ"5a~`IO+Ms{O%X6]&ZZ[P+{=V{*c_FymXkЅ}Z66E5˲xs$t__D-¥4P ~\{gAd+h 2/)/b ^n>5ZZJ-1;Y@^N݇'y7M 5AeXpFߑmru3}@j$LWҨmr9E~gbJ PS-pb̸?bسELʇ̈́k<7puC}m'6SsUݱ?k_ܮ{ϱUK iͿ)ؑ|}o˓wRMk~owFOqP|w3ײ5OS}'̲̓g/cAg6=!t' }~)bT_|$;nhh{ޔ~1n2KXwuclEG5h0yh/H&GOW͏,C [>{ڭI,J >9>o@`KYrąD^v2N'}Ć gŃgMOuHwNq,^rLȁe{kٝ+M>,:Bu,U5\3F"EO=d_?b4n^2Q ߋ O5ʳ"C{Ќx&xbw9usσ+R_N\KhFOg&Aeވs=yS!nK6@?DS/ɹF3;&S'p\.Z" V {_vY;o z:  `/5wЂ=$k23}AgcvU'_P 2fU;2fSg@hi/N<헎j]09Zgz|R\oS]/vx(׀'eF eO`QXnIdw&쮒t 2 *MLJ!rE6zaIo>:\ :י>n霍sJ'ې mq~Acz1l'z~2NǑc?n_6Tr"cMIC >\Kя'Q}BhTE5ѕȢl֞ ƨ%_j*ڴ7mChC!:c]1MiMETqX3z^ YƷZ$})]l*2ÍXFv]<:wtɌ3Nwfj(eQ"1sH+j@)Ih,ɢ$.zB(v; _?U^dueb.BtG-@DDNJ|EHZ!@Ny*Ya m+ [䆷Xb Pcǒh~ņ.lQjque3i1(etDg!Qr>A,AʦYWUmg+ Mg,m|=CBmI Ʉh# !eJ% qS&%~Q7^ V mh݄x6`AD؊!p%FbD=du] 2x%$a$ <1*wB&(`G&B&@LV6 :ZV` P 0YyDx iiEtECM ,m 9̎+JL-s|$*~\|4 jl<4طNEN h,!ڵ![^W-96u*32TF*H;e64#^t;K1{ExM8biE}2+ZwFh.RкEM䘝pMfp˸5SN MRġ+ _`2?LR Ko[FG>hCmqͶYQ0%-Ko%B⍚!(\]YLi!җ-Zrκ mbe]{-{\]V8gdbQ2l<-wӴٵ}&Vң/)`Q>g}M~0*R{Z5ՓxmcwW;|6OEv{pَ_jՊ;|Pzԛ5x{__ ֏MT|ee;nXj<[g9 .8j䄚%Ү9%?o>v[1rQ: n:x3(؛ug=<{wϡMq-93QR 겚t|IbAK!)}SM?seTQoN}G}W}ϑ_uޮ]tOIY2G:m;$(q&nwfq 9:ٓL96o^mSAҤScfD2Az((YAG!Č;Kk% ]NϛmJ8e{cj~f;wسt$46=KRw%E~NmI,Y{jYh-xB/'|Î9{`/b#Iz#ǣim J/_:/Onnde{I1fS^m_<ϫxknP|K6 ޥ uf2^tU7}cd6 t?{ٞh]Vz UK֏zγod08Qx9YfyXGyAͪa ҮWɆ㋳- (+ǟ4k QFX7xv[vWثg펎mi6?u챶&sWYDNv$j@cqYєqsij{շm'V_cнޡ1b!UZ~?9?ص/n퀭:XΦG3ȘڝI]Sfn2}1`:ئ(ŲIpK6M62nZXͰmB /HvaZW:sAg-v nJfuMs$SS=Z[5Ηӵf6N^ui='kj;:ӗM,ktbWu]D$Gv7U"ƍ+!Js^:FH0)d4êGB ;*$X8[ӔB(ޜj@4*]%2e4 v'whL-̚;"Fw[dofV/BhjsO\©Kp~u <ߥ7tk|}MgǪ3g8Z|\,}ՆPKL:6427,GNW{uU|ы譓mՌɲ>%)jrj=nц̊ܮ2X4Kq\L 46`[DG̵]= +nu)f,P6lonòSͭ44_l_|JtiFo۶wulrn x%4%X3ķ?ݸ3þ:g3! 1YQzQQo-3:-?X>ykyngqfu8?_ol|W}=6F&)ݔe7DwWꨓX& =kТ/t}% 9lV2Ea&7ZqӝI٬7Og/H'~?t㷿?RHђ,CB k>_|].+`x o<ª[vjOxa!M(=?@dz5LL$Gf&"t%hJRJ6GbExb~Yzyd4z "7|a-z?R 4%QfAŖ݈(iOtBuhKW$5~.]uMm͝~cS/mۻ/5͋u؄E9ݻ{Eqg=+j.jƧ ?ዱ{;tw?>ޙm5I+;Փݩ,ElM! Øfӱh'&$P!$BK![3{E6y`Wݍ.ӣ8匛޻X߶}iK=*[ruΓ3dr-rd=e#bpJ2y3}O:b Ѱof\9[ecl~EB ywл{Xl[| lao⚉NV5̛m5ֈA ɯqMX D(qkdJIߣ]V]y媥-}nA!_۝}ꗯnZk_ڎ/!5.St-0Tc牫0:zm+H4bexT7J_ut#pm fμZy#C _ _: * ZPL @`(QJ`˄H3HZ).e'z 1LS8n?(;&$Q,3W1>$L0ye&Hg0LsGƨQTK#Oq:{I=;2tvc=nا?J͏A4H>5FϞOM9+̉0sʑ&^3 IXV|sՆ5M[[Lp%9~lDKU l_] șP>v; .埝G*yQ4>}üV6@EV6N(h8dM/b4f3ϨqT> T1"k5@kt H5+a>PAhrqí$Ez$>/Cz%hd뮃> +>?/g;MuץsI fgQ(g̱ZYˈM\]21 $AOnG'o~`]pV+굺EUVFk~v+yjtZ` MWcGn03gNmP/ji͚lJ4FԳY`?B)Њ؅W Wx(KX薑"D{O#ݥ$f8Lm&L:PBzR9cK})RV# X'>域&|PVcӊވެ\ITLT)&IxfBͯD6XdHL&#`,^)2؟Z("fj9 #>Qc[elYd=]&tń+40cm\lmMSV,{?5y [6|փݭGǖ1DenDAV8icP+ܥ+)8h5Au: 6I Is"7gat}$_8 p4b?>n&!z춡 4u' Li(&+?tu&1R {߹%ƺW,[zzZV[^i-+nM_\T?w"׹ݧX\W.l9БݖbFNҋxJ0BI>@}NH~{8*!Dm6laJ |A'17ۻP)ⴿ٬Ň֡eDJЇg]8A:hh 1ֵ#lEMevU ȾQlb"YW(< 2"38L%e(H[@$^۷FHޒ=SK>Ԧ8Ȩ(F'g0 eÄ"ț&^ӣ[1K$=}SSćbH9DOz>F}ʃ ax.K|6TRd i6ӟ]:7Lɇ)Q,9#J'g15h-P KG#޴g+ǯh6qdVh#;ob^Qf0%eGYG[#A'K{ 4::7P7bP&T00 {K']8b.+ҁ18p{3F#`κwʥq4u~-1'/eŠ ~gGz>Ϯ?]Ũ挷L#͜rT.}"/MI,3 u#ST>P[cs3JqSrrmoQ< xQNZqc_.ʁ 6a<K)QGRr77P߀sޝdos3z|ON===:Is*vhYnqGzd[ŝ]׵hUK~z㑉=4Ip0&20 ][x 14shy> FǶ?ue""3F:4Z"`0~|P3SX:(C7 &Ӡ(SF{s nqx.QVY*ȲY9'0n d(-̭% !Y)$H+~^ʍF%Q|:X`1يWVs#qm:̲֕nm%&~(!uw @3su n+] `TKXjEx&0_]FdH7)h/̄21YoD -Z %|~eNydOpޢW U/7.1WsbY;МE[Κ̙vك#+;~ ʸS2Z93&^CB4ɹDV~2Hb.u2ja bott•ͱ嗋X6T;!$Jp BZ!,Wqx*[nKΰ2Et,mO 0hNQ1:)W5aOH.J:CLA7FcRh`?4!|s~P9ժK@5!id_/. Z^לw˫7VБ2y<6Jmt!EN0j/,QX5$-!JdFQet)Oa01x*_"UE>\uz~.9y~9Rfьp =px6 $]uz= xո||M=5VNƯ\7GckWV:V@7*=FBQh!pt1]#ێ<~1(7v$mƑ3oڵ^g*')G哎,JQPf;K@$b8I"H5fZqkRԆ66vtGRThJ4͠}D;%73]9TÀo@ƾ`O'ͥJl~`a)%y~L*K50ɋ &!M :xe `U|)n9z*87DdT1<8rA7/j7İY7< 7j5p]02/fYӣ|Ʊ̵R,qΊ>$Q~S9u^[YVu&:>OP/a0/\@VprG++*҂sd%*x<&e6eo<gw̧ .xkʁ$š)83Zl]2?U/Y s9Ɩ75lyX5zg1Q+P |!_Ԍq1p3AʄjXkȄ:hQxVYWUgi}{-e Á@=0:~ (׼'Հe_Yek驘<3 tsE&*xɜ[U`Q*%iG=MŘ$။YqtHGIYCfIJGޓ*'#ҷG-H~ =';Ts)CHqJԾ#GA=j,v0[5=yySs` |kpXNȾx ϓϮs$4hVڑȾYk(W M}GވR爪;% ҉of}e!ۀKl1,2?$Ku|IW3Ewo|U0yiя^t.'qk=@bBxhQcGE )]6ZM&s?11T\ގ :$ "g'f)G9M!$u| c ÛF:ƣm@q,Z)ڋND T:Z judki`J1v'/Xo Zt+^)eR ڵǷ ?X4ͫZ3}$[`/ոn%'G5b,: z%{'|UzUOfx4K'=)L/xXZUe9oޡZ+k "k*Q/:x(MU,|u"Q =)|BoW+χɷC5RzR| W DȰQgʫ$@nхn H3 1TF?'0AċIah"Doxi6m/pVmT&F?Xӏ+OWU4xʻ&Ww"KYt_PS@YFhx{Eh e?Q<UyjY7-HƲmn @-G,.mMۗ ʂF^Je\p8'7;7~ݱڨR@A`>&c4hSAkej(KvYDZǷm2w9>߲kjh 1Z؇uenOˣH W Fy\rt)5҆%뉴C z8C(dvؔx'pDDi !SL!^Z}Zkѡ =Ig0ƬO'KI;iړIs9,10f?\oK5󔋊bKkWED0( 不c& K}b>=UVZ#_KF !(~'`Xyh߿UooZh4(TUQӯ\X/PNyZb 3حLfM4$DA QF2v"ʽr]liY Cmˇ20~mPhN(~4 cA4n 1m 0ҋiùUuzxhp[EhgW`vÔ_dJa*='zi|Rrhyh-ĕCYTKhF|JQ4N=T!9rQDŽTA $R B+z.֒ cJ @1HlRC2$gP}>)^"!<+UZRRiFR^f)0|4 LjS8R(ɓ@(' õ^ߊ8eosVP9"}I̍٭;@*Sfps]}/x`>0 f7KǡGJɥ7.#XN_bK ۔`RtͅK{O`Zג3,Aq +HrC@۵K-"BeE8i9OdͰ|4׼\Vg"3" AL ,A%2nEg{5k3d2FKiN&=ov8`5h`e2Xd͠!F%^֟OP;FgȆN oG}!CQIAHoNx4baS7MׅmN+\#ܸmܺgέ= Sŗ7֪LF߽9r]9yQ,1Y31\4vUL&_{eSDtbʆ6q0LF;`0_tfGLN_|x54= ⰌA$Il׷r`ޔP6`H?P_ =YXZ` 6Oi ʃᑽo)n6{H~d\&{>{=f/JON3%.r\i1NUړ]xI,PvqټjE0G2'y!*[-/ Ê3FEJ#"s0J#{GH)Kҙ~lҩ1QN<Z[VO>3}61wgL%pz4 j5 -YB%h! L˶zzrfOZo0f){O jiZKù1{4_Q)Xix]@uaܸ)^Háx5 x$9Iv$\!EvNPdW<&)Ows])^( i<Uk'O*k @<;p}>`pޡ`(.ˡq?"T"A .0 ۾vrΓT g}϶Ia2ykL:ky[@^%Ic[ݱ9޺95&g Y zf8`M:иfjL:WSs'9G̯ORWd#G+2af޺1ZbdAo#a%fcC!Xk`"0ct38tJ < 37aR7&..6߾pN3XR NZDgkTQh֙AwA[!00‚ BsP;RՂZc5z2XKpj$0,SxE}of!X`daЀH_jAbufԂ:BEDRC`Z#ܔj!qIVa RR1 &K=fv^5bmֹuEVKZb҅ˤϤ/X4+.+P:?cz$:Sik-VWtG|_5 E"L'+*4Oc:kyY r3"M( .lr#Nj#V6F#T*qbJsRY_(,j$W3,$> j}h %*ju9uYcdBY$"CZ2//zG@O:L yqjC<`p+<#b 8=~%d!03K/[ <] t 1pXmV,^\5!fV9Kа~ &ME \4,j|.|qމMIzعՆ@aLa`RG01)Pf-ֆ%\nP6Pe ;._%BJ{GeK]{uq\}DS2iYH`a\jgoMO6pV+4N ҌA$?kf=̑ր#Ky}(1W)GN^APf֌R>kqZ4ii/KWGؾ,wH BkiZ؇ +4ju b6VsZbs%ޗO,WLUA=O?' =ZTJ~:[fΝxY[w.Tg[<Ǿ} ^_aYY}sٷ}F1$Dwj [/x MGcʿof^6w+[.E>G# ^Og y{ {,; Ḝ [ADD$mHNHIh4$*'r 3 昈oVm %]_lN3/]#pBp/7~[tQ_Y Ox80>dLO;糕aozjթ|%]GNPv[ ں=9ŝɼ~se$U_5>g_Ta26,E8_=]Wht \uڗw>2Yva!0mi%Rg tP$}w$͊u` FF@8p0r[itr0FSR*Baj5X:B=X>/kY]R:i'}njso[0*[ T_$v3@Kحae`[QR<4Zkp|EtH(g4͇ ~NwklWx82j{\:2yK:Oc)\@ jG1SY}ؖ0(Ok-nԂ=}` ̿ c7>X]eVh8}]uo#WC èV,w('PͥI4Oir j|3.M.BXi 5Ph.SD,4)\QӠʯj/&ԞA%,0HX%%SdHeb8n ͻ0YdĖٳ#7xGU\;eYmX>q@Yx]/z<^aсknobI#|`vL܍֗&e} v<+S0#e J/\rxvBzrX'}6 H31-Vv7S,DR ~eʳܹeG؂da"5=ӱh1v<2>8ci_zc9ٴNY8*&?S;L"|6ing쬰"W7kzsa͔R}*QW wMzkZZ)ۥ5fbɱfGt,ꩽ~`:)˅eo;uіI;4?cI"T%3&w6G+ܚ`%J:c35x.^|Ny羉/?lW|mXU}$ u/ Xx؅JR#LW3uӲf8voJgP&+Ԇ%&/0Nscqь>wa`Y0HogrcGpڂg<=#kkj#z뒍`F:FSXޫth6he8J׫Ur[.=>oEv':3g9$z@XdbEז\_tI_mJE\ E#py`i@=`HtfcĔC!J젴!) d)vp%֛63Ȥ..FlFbaHџQ`= sQ@.@ދ뢋 W5F )}E\^J:^|ErY\`U]IręDv=03 I %yS=\92://[oj D"^artAѲ,\d61F 0lzHZ)--gq4hm6{.%fh@m4P&ĝ6ĮXƌo-'%vZr;sy62&} ƣyJz`KVSj1t<%$(QNBm6h5&[^rN1^h}ބ΂ZN'^GgMo){(P*5x )x8*Xj\u${i>ypҲbO\u)fe&V&lW1}:328_\=M\\uچZc?l[N%Smxد^'㿏? ,o^[ #/Ų9m ΄0!ѥ~50($|A:A.iz_3[F]ڮlHG^ pU;4]5eY6u ,Z2 @,?^ilUBtdU{RK2 4HrFi#'w:U¸!#[ߢB8 d`쟎zH0{JMnv%xPT:RKE i LsLOo10/4-QUcr.y|>{_6 !eEwQ7 << jfXV'6F*K*#F '0AM|Á=*`+ړP1e+ZXB6@!2sI5Ͳ_]H=?z1.:\mRdm}N[xQD b8sny~su :-gz:Īalj{tm4T]u8K87^WIց5em0+ @~)=6Ӂ ZA =T]޾2j]NˆS-CtPtX-VR4FO-%&y*)k/ *lvBQmF+V6"|>>zj6u&D4!A'hx$f&HgÉB^E(jjhQb o6b*-}. =:3Gu== }=u`/u4qm9`v_8޹4|7ꯤp mU{{>Ld&3 B-fǂRT+nIJuq - |7 ٿ>¼w+r=N+>A/Eɻv@jU8;Tg'ȁ (5K~v^爄jph\J??XjzwlX|ލÜzO@;i1O$YtHC1UOk0q}>H}w; 3iܗ~OO\S߆ڥ#3Ϧ~L)$V&_ b}($ά$kR3(8 aPRD8ˤD(O.[9) `0ӎ0H"*@,VMF֏Ĺd'}~$s?}pzXe.6sm3ݜK-)TALӣaYYb,zl:q6 'jGD O  |9|)u_x6(R $2 f-Ul;AUU L*4To{!;pCxYkoJ8 Wk4OVٍoUC.!LPx(G3-~ Ja:MxXI$zɣk@_޹䩍LƱ'7z$8eytjG6y،zV*0 U@'{lx$(L0dSDHIXFb xv0s**VY]$ѣcMX]4ozU?0H=Wi %+*`E#XTUiIQ]|1ܗ:E pcMHoB "_Ƒqk]iӔ>{q| ) ~DSNt;f 5%hC vDK/U1Gy-BUy5y]<"'۽ Md/t\-]9v|-A<]Ivd;?LgW[B9ټ}/iɬvET6\kɋ%.<D_-rXZQ!@INX޽tZ>bhp+wSG;/UûGK: ֮7:KKږ.^Ր9.!OM1ćӇxO_%!fqQ<@Gz_ׁ!g>ڻE–$1=| 99p~ew9PVo˳++ ܢ;ы|OeN {Ik~npl2S5g2ܧG}tR<@1g5Ec:60<`%7|RC$h9!0,x-A2!z KFqE /^b@Ht bi'F~c9gv \j4Xc]zϣ6?s,Qy)k9O!١&@Ω"|m-"Im:jsq4o_9uV&Ma5(>wg̗ \X:XP}D%GEq 遰Tm$yrԖ> JDX"/$Ԭ%/a6qUR& &բQX\K.Rv D8PI2 Q3i@5^vٵ9  V8BӇ%L+y=+Rے@'H華rJLZujTa28x"؅d:N$w /HrD$*#l8*y'h pCu`23Ӭ4Ιe}>.ձ9?e *\8J%`^D:%<[ŮMa WMR2/QJTk{!׺̪J&ٻZ6*S04f6?]FVojԲj]㴅P3oj$,r\{cLx2Ytf,6WrX\f Qw+l;Wʹ6 2uoѧJۇMJ?W4tD(bPE03,yrKZ#WZRUP$#GpYY[gvu-5T7?k}[=uKdȥc?`FCe4dϳpUY TP-l"j 1bre-PJnV( /bo 0Cd;=a!Xp F`VD[TÆaQ]Gk^=~9VK\x^[ݽ]\Gc˔ggݴT=.ZƵegYz%hC3؝QŲѫ[ݻ]5Ǝ5ti>lQ7IěČc&0SDo7m/MT.n胃\?ZTBf^̇-5Vʌ| nYt/THN'A c(M0RGF8%Ed-;Z =;u?9gNӽ-;Su׍)[:0PtNÏTrq5ʢ&4{XV13{~gp߄~ L2~%wyсL$DYyuK°; 2)H<.I%sވb\'a%a3j@} R_ kSF ~Mt%LZvS sbf0;-#L";~Nvq\S3J9 3oN&h?E$~ktu?/_ݍO֜r=|'مv`Onz?]w9Oζ-*ؽ}%Q֕?w5|^A&H$zgq* t`TKFzWu9 _Uץm0r\r\fjL\b~=CԱ4Z|[e{hM.ǡ{Yִgʶ۫ $~M"V6?;Y:%=v?̛t;G_ru  |CnG͑7&<"PD Mcl TL$a2ϤSi;Usj 1aO0}!SBZ-H*|,SF*=˨Dsm|%29x>xۋU1~=৤ />@|܄"bTcB>s| Xٝ=l_׃>Z}7zR_=V9k;X}\=ry&ֈ$ex[=3da "h]za)x'+yb§< lC7@)1 _}PӨGZ5s렼aؘweoV]ZDyp %gw֡#OwLF_2'yܸ6]w0X[,>DO,Dr0'ad|!x\QH{^Km>Rvn63Wþ =ac;0-k} 2~ųsםyl#~1\ ϡ ^>~cB7=7IȠ|cB "_zW0JOPѤ]A:+!]o`K&DA ։Cn;d3:}cR3|,'b0AF<3N͹8z^Yg/~9]m3I*`MGjb'{|<#F>>Hpbɓlb#BIHeS<9r4vesf NRAQar=IT&#咸]7l&mmjd2嘇o/,{Ҟ,>Yp)B}&$/p37i0yy5KUP&m&Ilgi?9Aߏ#@XYQK#"hG P/(bOerL8!hlOn[قtA{c!i0 \!yX9LՃI |;4ՀSt/4Gځji]/d;|ߠ68;}_?ܼg\k7;Vͷ |n;˭^7dyBL2,ǘ!uV8e6ԳNaBΖ*Y.+&B f+`:C C1+ >Z: 3pAN7B_@{]@cOn9+,^ aF1Ә̍nm=FT^%6dQ܌mhݏAoMXN,(Ƴ=k> wZiGp #(D Ĉh^Ē\ 4i;| {L:PJ.S@%3lR%JU@ F#TCP*XdR`?l)drd*U&JىjhI`#d ZY% l0(8R4f4J*S+_h4#P5FtZkh͚?v=HP.SH5f_o9EJW TjyocI+yVz LP2eޒT(A~R}߫rV&Dp!QR{A$ߚL߂2*#\V|Bv! VB"?Tzj ^OݴnW-r/:cO*L3N'TCv+qYǡ:nG_`ѾQ3ꀨq`T= eSRӀ\cg|dk)Yܩ8b^3# >7 $ 7}cu{q{|>Ӌ%T$E?֘ H##;glήT]؎U%Uh,?+P=ݚS63KX'Hd/C6=ں0-R%Eɾgۏ!ϛ`(*ygc#`:@-s0M>$Q $?}d1p|  5MO7{Sh\r?koLt6r‘6G5hI&NVL3`M냩bD#jC"YKVBE3#MΉ)TLqaFmhu3fx9qX}< h0)_jN {hR{&N3]\bi57'N2@XzS1]OG8pOk5 H"zdfQO@&M !@.O0foz*b1 ;+&+R??ELb %_R"`O>)eq.Z J^ͪ7B_J πc$,z_"Z,@s;f;~x5|SkpgA[vecafV^{ۏ|L՗eXfl/b}{=P[z@zB_yߗC@Pzn29{؎KZ/󚄑c.J9R0]Od зьy6ΘvExu+'^xw` Akn@z{4zz(-?o>G=䓓>"FԇYԇ*Z7ҏo*eո_v}<9J6;g4 >|mM+.{8 {f0/MT[1e=X߸wݕDKK,wDmKjs%MSⶦҜuCW={vg@=,w/Xkn[کZ.Z:HLv큈I,jԗyLBP@"XIL&>zC>3N}< f#|jmH#g9tu`Z*;HGTUIі4?+K/^dJN!(r(3 lbfN/9q?PF=h; vL>B2yO`yMMμ6nڿqN=>ODh" 5_ȝlj&Fj‘dҀċz"ԢO}pM:$2J 95ZV  d2 y9;`p{#MC\fvQZE 9N`?DBk+y#Ej#![n^:Õa+%eFpq'x=:2[乍6nպ#+u:ᭋ5͚i0J3hה 3m$f3u> D *ĂQxgb%!j;&ݒc__Ob⣨w+$HZtf! 'Ɯ{>,#u4;JM+u}lZ7LPiGaŽC՟y+][8Pʮ-!ŃyN+uG}W$7)}t'Kh?z嗟T|"dVE{s(YQy򸧤9k!$u@9&Ж=&mb˝oowLIl-obL}%%Jݏf=)p^5YR zp}c.p46ZL b2ˈfcH>1ODPɁLǔ QzD94O&ɇ+Tx$ bOojiF*Ƭ, f- 74lutJv^e*b.N. ֠W E"u5`QKDhX]CfkԼۚ+,nuTGlηX lchu`<="#/w0 x:Lqtsxy_L$@F@NYxj1Dr|KF}(J&jEc^tO`qND\lioq#]֭*vp(o1ЎAk>Y_=dtOO~qrpU )SSwR豕[Kچg̙NlrkJyNֆ,`ȝe1FmF/trF\}pdgB Wt+S8(y9ZeɃ]Y@u՘}j ̄9O!]!w"(At|geP LDF"n#1G!bN]Xl2ScXihU<0xMƆp`n=kMS&S\̒Lוg^!M|mK~;stu|t1lT.v_L܃A}z$(i%!V7X' ["5]P%[D,d?QH1-PK*SC[WDn$,26䗙t&`R|qdB 9߱e#j4Ru4v_QF!,\9~h83xeZsjSQ0Z#J`,3Mn[ٜU2Uo6 /j@8B*bY 󁡏P{x(O8ȑ@gHH A#+tNK)V3lddhؑG(S!*F?CwY|{a]>|(=_" ]yy?'oDá(s8rW&nA6 ][>KU'} \n]"9ƕKy+B$0@(GrjBʿջU20ܸ8N) hJn"IA9*rDx8sڣQ&_g9+PKpm>8ϒl)kJϺpgpB_{mdZΒx!b: Fhbv#à]a#&y\d(Ëוl}4/\ݛ[ &U5Zp(?@Ίk<NJe|՚(?l͛Sv WGDm6|ɜrl6_^j+ ֤ d.N.7'7mך BrR6wD!D9i^jcRjK0rUU&3\\/d=n4v5=9{F8E.Po[`_/nfܸ5A|dC3jĦI~wL9ekV\ʬO1|}zf0vLXZž䋑3{aޅ{fq:Q7nҸnݽ'NHTsl\֜8MvJC&? OwMd6$8{x&htLg'sB|g!=q=n]?́n!Eݪ4?>dyܬ'7V?yh,9*n)Fsư_tܨo rԸK/}d=j$Y \t zd}jZl#]]z# .eO ~Qǔcf`aE3WWBp4#%70M`190.?Ci*Vq]EX4#d,-؟+7Tlw(t CxF`Y)wb3rJ>A&VE\.s&2j zҩ~H&r\.D lr>i|x%2u t;wE hr3a7@2&)tѶmǷEu(8WNbۃQ\ρ`\+nR k.Fcϕ///Kc"Ni^24#"K"ú!Oȧ+'x&*'0G Oѥ2\K&QzQc眅t.}f'Ebx ꫁@Β'hP! 0o]];y8spClD]H:Zx!4W\`;31e@t񘲉SqKx<]O:]pKz7q3;w ?q} wf{GL9d֬!&̄3Z'-%8WQ]:Cޛ@< } 3c@qL0gGKr$38~;Ы@|wYS 3V+3R45%Dw$Q{ ㅈYBAr=< OQOgb,xe(~֧U"ձ-Z J^ke}р]}@|`Rg//+AIY,,cV6C^KMFd@N }UT69[cRM52ydBH %C?&90"931˨94r>«!Y#)I :Ԯ_$ϳ{p0>L_5Q OGcJ7=:p'1HSJg&0,J:N%ۺC*ŔzLLzkD9qP=U&f3*g&KZ1ŌJڂ&A(Žy_Jzu0is c3w[Ft#;l`좉9?g#Mz4'&^hb* IY1BRi#wῒ2s633>%eɞjS8Pt?Dgpzx>Wv`ie\UᲪ} Cm4kZBΫfcu ]_:M&de96qѐ>*Q}ΛW->Qyݵ#v-Bޑ/ز^{ǝCFؓMn]$޵yCױ&|AW{{„}Uz 1I61g#&bMVLT~/N$ q!pl㩅 0ɂ9j&j :Dl^8RUTAC;uC.s݃.`EhLҴxmܢƸ$k?>{ܒl.ve)>BoZ//4%_H^5k:'ke2oFS9##EVf/F]'PNAVB@b8M`]ϸCkuPO1#~b C{LOhY4VJTv+gI{[ H%FJ̎bY$E:TsApDʷ(yn/ v2gFzv%ˋ\U3SCl<@! e:QlL#4~mỳHER9 '`hyըiI.٩pKt_VZL= y|f|; 輥& +L.gfnaƈb/NWa]!M鲛/ai3GQኧ 0|uQh+8B l!IQJ( LI3EHu `Y%>.hwt(bs>_WYWjTrmΝpQ^xpMLe?sdױF&w.N̛Y-c?5> טiTfӕ 5Zۦ_ŗJg(KRlt,q_>\[Z\RĶKQR ^"w.@ZR]ei"6 >˨2·sz"{!>RL2Ye8U}DxxbT0Zm\T ??"wHG3HKKJ랏;q|yy]-;dH#ӛ=^N |\@k<fLG@u]dz/Ɖ240n(z^taJP?W_ˁǭ F|Tx?0C%f-HPkqC#>gH{-n2PN=(zu\ AQ5VM#ݐZR^!P{GY1}@qq\Ht$#BrVf{#­lMK};rv{vvk}چkdUy鐀 #9xܼ:YCj9EOmrav 9e2PN&~T;D+lY=E=eZx$eq2/}W2G u8Jaߘ?zS;GK&1S |w~BO|$ M*kΓWxs GDP|Ky 4 4"afB"@.!l Q쌨 ~SL^[i]&Kq9m4祑<-0ä/k\\x+jں0CJb N1$"063f3hfwqL]̼0uTb-#2rM1"u*K 1 ]?)3JXӛϥzOW@́͢;g蝇>qyY_`_y7ԇ V>)69R*Rd[Ь?(M،coܱ[V]frIJ`uqM% ŭ 6ڝFFrB >m˜# />Քns_51X5me˶_ږ]mXK‘O/2SykX*O':m+!'Hhg$~8a:Ewe,uh{EA,h) 9y,7顅L2**_{ߜR9˟(iΞ{yN>X'WP?8.0.k2g/k`ǬUC![޲쑻ї% eNk[**OФ@ *)t-:5{^{¡3* 1ń@10 _ $^KZ)JSrX S`͝+wݳ@{Nc.@X .ĝ$1d(W,,>~tqAWNc*it:0i)ٲGGes-@1@6 iȰ+?. ;agjBdlذXR< ]+++*VYt]Olqoyg_*!LT#ZzQ!qG9`ไ*O#?|lf{Qta gл|=ۇef[OnqPt`{c43fT\wG³lEFf ?(`3x;(2of-z"sƑ@IX4XuEBi]1..F"L8'& I|iwh3MqΐWT6-UrWʤ8"~XRx8#'tdʌ[7@I~V}Ãzw/wz^/jf۠ [rLy5v5mZMݖU}þSج/)xi8h0v5Ae.ʏBAgSSz?ZGL=h7,aiCFMI5;QK>ٙ8ng@tbK~d ǜxl:PГI$>7̜'W&_Y[6yknW:_-)GUEHz,T yIݖn4oI\<"6|W ?_=򯇺k׬(R„'zRjNV_)UyOf-V*^a_?Mui/tS/jзy[Ecw0'֓B'>"]4^]g(6'q-wm3UTPk>i֗uX ֯DCP4n5Ӊdmmp:6jM LO:Mq: lcu8]ngN Rrr@cŵf$[b14dz<v B4 ?xȟ~7n $a4 ;f+ٞ݅`IlaF33L.a61c&ff/ a02g"1K-5ٴ#!?q^c!,+I!=y'B(->h*sЅ$XS%X` (fr,f֓ fԳ: (.|$b( Xj@)%.eOs_EU==}$d2I$CGHpDpSnPR@AW]pAQBgI@d^zϰS#!QtE:PgqYcb .fm@ nѓ؅ =t+zg%TZZ2B_isc lvt,E#i{F+CN}҇m@'pgNJȞ OfDVo_f6,KQ57 p)CwdF|zL*F#AøTLF4k4a %:fȥa-< 0)ͧOkFHa ] 48 VT} )hU'J޼ c)2Ml4Nf' 0+ sOЗ7/@ҟ<̒s[gDcEy 't 8eg6/A3 w%{C}sن'֊M/)I GFo?lFFNny ǰ _|@ϸ hD0WQrxL?`|Y LP(|Sn=4 ~TۗS7>&Sh1`Lef@eCP=MEiEs E7xI600ى䆍ųdq@=7YaڡkOlN_]k~e^3kc:~Gywǎŭhݻwl weme#Cwf8McshNË14d}zc#f8IBh ȷ!GTOóix?>w7ܷ4{{U;>dF#Q&m[Dj&EA2)aJL Bg&UfY):f3sه1DGD,=A#wʏpBYLu~EAjl0`&[x@m}E,~JZ´_H;[O}hؿr,M*yf,ͬ2znb`\Dg]ŝ"? <.yT4M&a SZs2jV Ӻ = '7D/^7ִ<:͛F~*7-țM4/nzcK's>A,-1=SW%7z0$fK/a-1xx Y=ֲ3x% Ļ[naᖻn-W.斗rBPx,l#M sŭ/攗c>\#>J$tSQ3D/Lu g1c㏏Z,cA@AcZObQFC,rc!"DPUl, 567BdaҀQr#*U ޢJ*R*^PJVAS{vl߿r,;?}3|=]t{mn{z{Iוߐ1c a! Re pUjLKLLs&rR0H'ʛo^YC!1$lW̕,8cO?`ZV9&bM7L('wwl۠# k'=*9a6ݗS{\#kF^oa6w%u0;55 &[[@fȏmns'D IYq׭o]9q zilzE> /vgV#(>?sj?ߐIȓrcRTb,Y V$Hm RxEG/GaL0 E 3QQs#^ʩM 53dEUI^^tëZ:bɊOj,6OnMFIc/k*XXRnkH4C­Wau#EU>45tZySʓ,ZNT%N$qN8?30/A~j vIS'bMz'׊bx#Agb9BKK (M_`xYf6IvguiUę/A7@-eԦ.X_ւ #\$HL3ZFEG:#3Q|hM2C]]JOUe_!<`0ߎ 1՝N\\@ӧ=#ҥ.P1땊n~d=Έ=p_K*qGЖ/wk _y*~?uH=4/ec|M_6{_/OK߾EmTh9#V4t_jKηCkZMk.(ͥ}ބ+Mw3T Sc#TRA+4[v ܨ"}.XĠo4Ӝ#M)${*~7=JA'I66&iO]t`{7GH!DEwRClc_cZ`{cZmpg_v-߼~q'zd[^`ԍ|G6u&`'p޽nMYr DNnn=*zcLaJyؿ@9$-5gBƔkiE"D߉0LS3\t8~gM3'IDRM'^#29(ab F R8F3Ӿ.͋g<8c1Y՛/ #x`~}) &c䭍`ƍh/g-MrN3l(m(c%oL-3{>g #H=^6(NN=P2*22-՘ t!|ۀ[O)7yܞZ϶.N{z7D w=17$یGp&~~[S>8)q[O#P|eq:bt'O[Rlr׊j 11 % 13 qu"6%{ u9-rMhGznfz%oy~oFG%&:K<8msleqIԞf{ФDG_, ݯ~|I{gCKsЩ,)t=]8^!y11|:¯ϫ[qBaס~agKE3c2BnAGD%zvu  _GmtP zdXZ->WjîI@}t?nf[Z'>ѸcF[$@m Y` "- ~AG֥ bN>T^y;1 s~GQ;m/]#vV|qs&w S W_`aga|E^ێ>q8>\l}Y[\ ;"L]<-36#>~Hس'{Jv]U!/+u`*Z G\:+S(FN]~,y 3/&^n ^OTFD!ձ/Ll<4c0a@wPWyA,I ?VY4SF>LbrzV$I^G+J0J~ƺS0܌ *4  0X!fE Bf@sW OW]~\$#4Sn}O\omO^jm-f“m/:[9cZg4g7/6SJ`J|w(a,gOPEBnDWRHElfLQ?)>:m!"ĿEj#R t!hoAab#:Z S8nlۜDky[bLt0@}~WAMkz;t=1[HC\3C")1H$}@0Lsr8.@*#xW}Fk! Hn y9O:B r (DE@0mT\bWlE)uNAI"IrIiמRW0Į<Ĝ_bd#۠7n/1n<~St3P8D, ~}-NG i4z[ ,סz9#)"QT"~юxhY(|,u%: nC$D5:-wEQb Τ(oV2kܸl8Ajp et RI:I)Sl*KӪ7*B& id^UP)h,la$bY |RA~aƪd*r)a=O32!`{YxH^g`ZȒNipZ&U60daMRȥ* IVg㒒DU?g}6udڮl9 I)DK rս ^k"{IcY.#$gA>U)Hi[e|WX&`80rBc- jnv i!$@^RJY]'seRYW_|lSe@04hMT7t.AmFBy6 +u|/a% I}e*;GŅ 47Ym1 5kS%ɘzYj/a^Vbbf>d՛ ̜"23M:T- "#cQYA<0ݽnʆB̆`>.NQQvNw6D};s+]Dw>ٴP@ E]¼Hk`jg ]ާ8V13h7Yt,趶c`|O;=`6GjyW6Tw-"E^N?[(}'o8^ >{HQ )n̦L&b[(OGa>GS)'eVUhW^W"@*4WLP!*&9fW!XH5ӣLIe"z)*fyRR(".=i^F`(?bn<<p5㳶 hC|5#--ݻ-GhPlΘmCC6EM*!Hg7QG~irPmV\J6jN|$#DІy,]"N_xF8bāiaJ8B@B0$<uJ%FwU霱Z:M>ïp?;Yᕸ_FJjĢDlDp#LG׆o*>#HD ϒguKmѦt#"}'iuBbq^+pL{#?Cԍ0QSlaF18xP06!A|M!vZq%Emc&7f3W3#^#N-DR ;+Ӿf*# t>3O1i"vqѵ"qEAjb_:ǵNݩԢYXXf}^oJ,05eUN?39y3sr&?n[5$TWyT6xbwx"w@4\ (BݤXX$H'??Y*%Kk3$-<+ V*6 {l'w`eLjJ Jn5JUږk,޴ N4{6{e@ <ύ菏K= zvh%2_K/328^A?.- l{?>|hڃ߰Xl7^ |~ ef}]TaH6PFI= =N\߬VK;#cU.Qe͎~M*J[muN}Cw0){,N<dG, <3}v7ٽ? 'pw997:|bx{`4zj`Z =-]%ZzݐsCQmA4+˵_/vrS!Z'C(8sTC:-97:0jfzqDO&PgНިsG R[AC 6&=[7=)@8)څфŋ#{([AN/s4УSB^:oIEiI;T$M蝚Sd" .\WEܒD=dٛLDo+* ­Sڦ#@F); ]<04SI1F@[7?j!;wE,Vd< j'nQ**CjB?mq2eۥ5GjKGaC wNRp744}sWNC/' 'p):ɎYH̃LSvr{t׍gdc'+Qt(|TUI%,?E#CS|^UXW 7EqGdkwE;![Y$\喲*޿œc%x; =2CGm^ ZmyQm_E%չ.)|]0 gmK{?o[-~.ycڰ48Xtx+嵅 lRI&0$;+jFtzv˳39NZG-=wn@t?knggߣt{tW \ 1 tEkQ`C#sP誀 ko-$/LE+&\U҄PnuK}E<־)fk6)wcUEn5nk:WqFӜPa*okT%ޮ/,\=aDBc )θ ~ 8YX-$#F痳Kd 3iEŠ-- >(Nr"]&bĆݥ++#GV"dĂ|sPZX1N  7Ưi|2_+z~_6lʹlKJB3SΫwG}`l^¦ L|0n#ےӜ)ꉱ=_Ҷ>D2"r]ڕN@ $GgZgz"?"=hHϚbq}fyE &Lؐ&th sBdYޯH]խ d-Q ҷw՝x0“$Rt}͝B3o0 4֣ ^iDx~j WmUПTMT8 (Դ({1[UrP|(,*#qJ϶,UӇsjA^RuJXF J\fO)uȕ$)R. eLKCnh]<;䍨L&a&nlp>TtF*0J_9Wzp#$/?A8y5kx})hqr`]NlAtj#_o>/+;?k7$AH@޹p!eh/> ˣ(5Z/ =x~wH4 [;ѕMSWW,<w>;  wE`2v) KT@AueE=$i)Q,چ~rg7n|v#Qq\U@a)SG;~J@1E DrƊAM%cst_x/CǏ۸qI陎* f<~(*ёdVN}V#&0jv@"a;摅h 13*@Q$+Ժ~Ə|ީr ˒R{oR`6̥擋l>YsD/_~(xSG~6&҄t>O0nɏfF"?7$7UwSQ,E$Մ \<DSNVTw̶/ЩG6.O9^W O|xlQ[~ BC!4-w@ѿ8:w`09SL"aRC%u{7\T.P/+%f31>~ u(%9 /Z 笠BЧ1>S 8*\ytbK#נ[Oh=!a-yduT ]~t}߬ 6e!2 _tGx lSb', 5A  / Xp9`j[^wP(]($VFJ5D2X]of&TJKdxdδy'웓-;zj涛&)yEurl#@=E/#Ō;K~C^PЫԪo?v|Y0A`.?[Og|Ʒ:~sW@剧IOۯ4ז(?3\RFt<>=rfwWm!ƅ$AK:!@fRMr? tQbNy_: ~~߷qo,ρDx"4sd~GݽOUx'+"]w6~?n_G<f< }'`58bCO'{pֶ5x8_‚g\wgt͞?~s1]KN7#@cN6-% ҄dO=.Q\f&*Aѷgv;Xyv*{lAd"> S(WسJӜ&8OSWe5컱Ϭȃ_WL<@iH|Cݙ!Ra+O}w K03YU!BD]h@NfQtGx`^ FMW,fHh&~'E-DUv bǢ/&]MkHZh$oQRl,*IM5@5Zcw],KxO.>9i׭Ó$rҔLdF.+-K+*6J"%7kںl ]};e=+՞K9sנ3 Ė;8ßrٔjұl cwު J&̞޻y}>Ն&dQi(TԴ{ƨd4c>9P\%X K+x-Ԩy m諳% ^6qjfڥI:mJP58{9'eYɭ3 X;MWܱß2h|5W;|V8'5jUValVqzAΘ'OgRH《6uHR ~ecϔid<<>*=휂Lܐ{,XH?A L(R(Z\CF I~cG_, &Y6jQy9ɹ@cD&^thi͉ +wv\QLKq-zXю:ƄK).̅[,s u4=Va\UOLagN4ح}4ہjB3ѹm,hPV" WDUu6?UcX}=ibx{`΅ WęRNCQ;t/6/$ZǮ_|QngyZwe `DФh+E Fn藁XY`d.6΍f_4yStЩ9vNf&,zK}3xD"&(WHJ~=)'7\tSfLE, <ryԀCTgY}AЬ,$/jxjͳIwwQ.CEP]▮EbꢦQF$;3Z) VLFr@4Qe)NZksFNdIPreoeE0inRod,3~$Ӛ1Ż׹f}$#r\mK/L8ޖCmεDZְ.t0 ? '^ɿ~V/q?F/e:\*lDq\'&N)6dT R|-U˶ *3!wۍR@=cFnhL: p<{l.aNll,LUbgQ#%3X&>3Qvh=ZҔFK]jƪ w8XOxѽG,P+4fޡvYyDn}x~Yn/Eta;<\R  _кBDNwĵsn;F3]޺atR%KS} 'P:j-k8rB)3.Q|zsSۃ /HߠƐ>O-trJbdoOv[e @ #gTJHLx'r]dGN 0 arúf#|! `i{kYU/o͒Ge?_29aH! x9q%1MZUZo$4G@L6ݞqT~;tnv+I!ed/ZJ?(壏@)p .O9 8D*ಀCޢT KJ;LjzRAB(5'ưMJJQ: XJ#E-QS)!{=ÉQgH7c (7?9z//|lC+p,]e%җY}{:2  Ҿm3"#x"8#*"kmuM=['o[1>Aԇr1 2P#f 0N5EsDxpn|d uJƏ:bH"&1mēHddN%]# *OudD*b[b:Qx^ \Q6N +!^N T_fP },1Ar Y3ѕGEnY9|mM ;/?faڦ/۟%- `{ ̴#V'iEi!& y&"qๆ4ܙSLŸ;pXNlv9XGLI,Ľ"ʍB\,Ɂ$B,*s!\1oE Zr;ЧzpJ00D4%8\HlDSFC$?u0JKBT[гxzӂZx "qtT9xQ+{ձD7O-, l}nYP;ƃjt?f>xc`d```ado󕁛.ڭgddq9@5 xc`d``cw?p22ESsxڍTjAytƋ!!J(Yĥ1 %B̪3%.Lꩮ>*Cw5 yT@(&YB p?H߽|ڣ5.{W?M3nj+6ss#ǻ'?;照,0MRsݑ~(].߁bA~_4Hy_zS ;TC.;iL%~W%&cZ W? 'O}w99nojdmp2 6ѲϚkY&ו7Ն+ܥ홨WtN4W]9.@ m厚%Ӧ_l^.-|Cy' O+ȭzs^싮HYVK~ r9r{zπ A+6w/ oqE| 댁ǤŨc&[ J'\]ZZڧ u&i= II99;Pb8me 4R"I*ksTٖ4xZyk+mLfV'=8=>ޔOedmcosddZmQǎ5;,Tu EgfLiaiB6KJrsY <#aCI"v7+n+ cwg9PNW-ګbe\>}<O& %Ba}?z?gPZ )&P>``@IáCCaÈ2xYrQQ@&l+emʚ*lJ]5T孎T?"EctǼZ1D gNW7v2CINNI:x}BtrFـk7ςffm\$$yy}NS(l)%Ui oBkh.b/.Zy_y**Gy I~ɢ 4]6y{F{pUMʯɮ(]nweCx=z7t2 Fwno{X=^-譌[fӠ5. w(wl}}~bQ.n^= |qTy}_iifՃ¡9'ý0؏Z4ǀkeZV Vj3=?#lz|Ǒ9/^q_B^r_Fp#WWQߍcה׃.63>V;һf7tt}ɞIكSSiŴ#c aSxMAɟվLҗ/^xc`d``jgdPg& fB0xڍQ=KA}w( buXX$`pI.$w1bkiim/BXvo\Yv̛7xw5y  ǐqICY~+]c`16@¸zTS6E-b>`×2ʳ)=Qs9UQ:ʩc_Roo_>&,U`dVkM\T^FVd 8,xVBݙQ!j·&vynrMM \'c\r&-zďt~W;x}WGݪ03ӮNQI-if]@Et1]Bet9]AWUt5]Cut=@7Mt3B-ljSdG}C[iH.hLmjnꡩY (bZeZUN#(z4=Kt=Lt'Ew=t/GSz*=NϠgҳz.=O/ҋz)^NWҫz-^Oo7қz+Nwһz/O҇(}>NOҧ,}>O_/҃%2}J_7-6}Kߣ#1~J?/+5~K#L'M3+q \Os+<ó B/KR/+JkZFo[ŷ]6>iͤo⁧f5'9,e[gAFFbkIDDyeh,% s%.nM2LLZD*mF/R;+ATXБDedO22eNpvr~I>δ=qF;tJ[Uٺ<0HTog6t )DۥKK*WKDybׄCIQ%BfF^JnLDomeSfʳv<äcr 1׆$ h͊[+|8{rjdž:$%(-sQs$>e9 0wݎx &iHo#Ql!2ת65r#::n [c:F(&v5p۝$t7Z&Ph tlN-w.$@ s0D2iTD,InwpMBڰor|m:yat~vtaj$M'ψ$'WU[ӔdrRTHā}]_UAV`Yfzǝ]ġ6Vܸ7pڎ#pIw7JbSV3Mvv[W&OcbW"j қ/ycIأBO޴@]  c>A"T*Zz,5kBW״+,\o9,5 <66rK8\%yqn1yTBO²kr(#Wa j-7ΒQKqڞp˟ hT璳&G_}tK9ř%y˫4ٓ,Ϧ-hy誢WbEm¦y =M54j Pf3ת'6*z:Y hX((Q0_ZhBb =UW \*pUXj@ԀQ˶9pBV'#eKnYme5&c:Vc:V'gsj4@ HU    +@VCK@ 2 ,Ӱ0 4Xb]ԡ:tQ.E/ DQoѬzՄFX -bEE EFahXD/ bBsiHBCА$4$HT4Ġ! 1hAC b4Ġ! 1h/]D h@׀Qנ^z 5נ^ׁ@w 5x]w 5x]w 5x]wmaҵޫ B t @kAkAkAk@ hDH^aVZp@Ńj (d= Z-o [-o [jZ<VO)hugo-0.92.2/examples/blog/static/fonts/fontawesome-webfont.woff2000066400000000000000000002021001420147000300246470ustar00rootroot00000000000000wOF2@*?FFTM `r 56$   ?webf[@֌nC˜tTLɡftȰq5?=ilґ\vl Tb 1fú7TQ D;:Ю1l׾jvenEߠk5>d7QlBa ux].WC$8v#y`F1aM8諠w=|'є0T|2/M%b tY$!ʐ5cb̚( &-A/mY /yo\Z= 5ck_n3㌾(WɃNag+O樴R'5=?mΩL :ދ*_Vz+zc1`Q#j/Z0-FibF"2ipÀF(2b~H]J]jݹFf-~ @ggB-Tx%pUume ';@7 t=pN/_U8 rsX=gׯHjcَܟdד_1l:1iITr>v{GbضT1*f-x-i{1h>(33!$:j~:ugv%ѽꄻ? d5+fUzҍXXOo | s&$y'x[`2(E_kbbp716;~vo[byݷKrfMB*Mۧm @ 3`,OmrFa0-P6Kt}>O`jT(aP GװSz=naY-fѠTWUV?](k=GƦW_e[K?j@eUw uNS3@}3AX?dz8iC/ɛJKE'&]=z_z;&K R∏Wk49 eb,g8{o>db7l1j|ʘUo#[U {37**Ef[D4GjAѢ ':ԅ8`WFckO.:q PiO,Vӫݽx3Kn5JjL {{^fy]O^AFі C0}XHny4tJc&&{ZsF|rXF5˺Pf5_jZkn( Qs<E':"`LG9kjSC6Aݢ1 &/ &c|n<؈>o^ ޮ)t8%iꪮ6̕4h\T˒)`$w_QK{x 0#́,]֭en%3jF* _|q2a#b{9vz2?.EX5x]U =ьnqlԔP!8` Z<. r+&ۇ:dOx1;! 0E[r'b>M1A;E5N6T!dHj9Mo2;Lڰ_"D<k<*-k"Z }m9(.{y̎2΂- R%hM%K3 hC>iV' ƫb':U됏T$aՠtZ,XW%7m]<t18fGHmeYI So[rYڌ\Ad)1ېOJoͺcQh!Si= -(LzKDC:Mc$“q־hW>KA@QEDtuqW|0QT"W|(aWm j 1!2H':I_f,CbjA\ΈLᔯ1 )Ha =N(U;qlqђd;h3`gkz"%(8XXЌJk_wo]Ӟ J8a46&033=9)v̞&JPVˢ0\q$HY1i9/i}4,rpջrWubiܝF# ]ڱ)b/5LN#'Ognx(aӑ%ct{&\`NQmЮTɽ}Hyɑ\._-kst*5$x)M/熡T=bq{:YDbBNfJ*9VDl0K LtNDy)M|nK<,*7+Iۚ٫ xA'zңc4EsRakszb)=m՜Ħ2ԃ~An4X;-Fpjd0M"M;p 0p/9iĠ|N:Ĺ EH=H}Ll@cOF =wAHKXE> b4a گs+BoӢwN޲ZCu^9|Bf6yN%.=3K$@媶$THMċ-EonW$F=fKQW(_|bA-qZ&猐[@EjC &>`Y:3JD8+g*ٕޤh2IY߽ ,&ʕ/xӫu b? F_)fGB ) i[yT6nbUO7l?bx5Rk/`C*g_N9 j=4ACCcs4No G2*8rJiOV?uVNoPCߗlIDֳt׹YZS5(F]y\._<.`9sJ]JOyQ WV2yy K}C^u0> E/{>W60@[`^ل S^G-u樱ycsiKnfl-4>wlKx-y f5,fTFd.fIjveY6J.is oUɾb)DO,|\)] xv:wƟaw cŢ0Bf}vp-Y"#1 2mU@Ε;T.yo]۔' mDZyaN;5H@VE>kv=nݠՅR~. .{>,G&^!>ӮK)\'K54-F{g:ABP*)Inj )H!E .#CncV>AU]=ZE߃aہf͓qzblj5;{|:͏|5mF% r HzX0Qh#πj5TxDDp^FOvRֆǟi!4&[~{"2+>U] ZuI4 qKt1rYxiMWt9ZVNo_~wР}^Pr:c^JqoKf=Y sr8(k'>Ձ :1ڠD:&vbyG(\컖Y8 &O裨4>;O]"x 6.B2FM8` ,lT!T9MUh!FAGuBc^/Ӧ*ijSN* @8\svq*1,9jD!nO_s=9w9&a>;g4)GRjM)V>5j wvz J*N=M)RQN2Dy}[ ՎN0A{cU@ˆULU$ȼ[+[ӤmՓ4:u2{wM${-Fzj&Mpםg q#"Z,ѣ2,CG]۫pkߩ< Wc~0VZRJ\W -JnC$ ~[\ˬɬrgz Stq|_ĨzR0gPzV-bU%;Lr@MuKR;2lFo׈^U7ϝ:5rJ|!!Mf0Ce7 {U!s ݩB  ~"B1q*Nj+7^7^&DCϞ>pB[i[IJ{pU[/T%po6Z#j'l2F ;xE}owsH%mOM%xB WbҸj0L@:I9pt ]xUT*g -r1[P|:$Go<65!#@` 'RîFӗm mӀߓ\ :Ȣxap(3ک4j(n{uY|bt)&8sU-?*l[G/Uqa ]A{ ,%7yz'Eo] 3El *k/^D/kuC *`NǓfvL퍝#_fFƳ.Fs]59V64601npX^ 2cDf g7øtp`HAkSb:T>3'յDsY]KIZ9vqKO+Iܿ\c1;i}ѥ!{lZ VZc *p22y@ %}_Z:oo&8CWFcqll1Pb6Kʷ#J`s$`.0(`nAi`>bC4d9AnCZFBW+vݻI* ܶ~O3>g.IT4 3*9K`"I};Ѹ0:qAmj U+OU:d3v-Ggšv&G7E,t'KJ(@[.1jh.'TjJh clt\[-le3`-cQŭ&QG' ,xjw1xo{2|I+ O~'3꽙G<]B65@Bz]2"_1*?91Rʄ"|rrIO5B/b}A ~S<}6/~Rdf6LIk)6gGӋ:\6u!=/02J"GxZ:Smy3R2ˑYdf_j7*i!E4ǥ?ԍD<! ]IZ&mO%v~\Mћg/SC(JLYŃoC:VǓA1yхgӮHx𢺥Z{ 6N\_V}y*]m/[h{EhwapЊW]7 2WxL"'jU$U~q9_.j dp ?T8 u*-/)HlYsluƱOZQ,p*e̙EZx,&8%Kcnjdwes?vs{-.A.w<!!X:U9~*x *TpO\G?^`<'߿*T!D{@اs$K(U,1jPL!- Ho%5çanоWwpحkd _yxhAMb M] ;Tn|D}Kqb:'A QrC&?ݬLC$|ƊLNieqƆpLQg;Nf^RUbz^>ždr,/vKO#V^bGqM^;v +5^5 S++f\߸ 7(x=ȵ!i*Tl +(@ӄX*2Bh*& ,vH/ P UQ pyn&VE=_Ya^Yj+J5u@>37W3%u9_3e<)0x6Fz UEXucxMi bo `لp UGj K嘢_-; Eb 8[t?lϙ;JRP ,z - 43œ=}l,u&P;,ɶG42h9ri l#36վ"K !N#gmRyw3wU v#B\^  ω`BU"^&f[qn4xso/FR^9P͐ 2A|mݥ|UϠi͏X^ʹq֓J˲~n&ki `;c@bJb2! ͅ M vQEs$9dzr{U942Iע 4( NDE"ԭl|-klWJ2C~it"#juGo跠|D<<?`FړU1CHY1F:S҉gȂ. 0؊|:DaN nLy⿛ޗNlڔ,KA0c)[RTIF|*$ '[IODf\~!"qݧ3k/JX0_!v |eZطe̕(2[yQh䀟NsLn+E.|,l##‚?cW)@) 9u{D_pnZzF7:`={u'uoZ?iЛy1cE6=(All{9}Nq jԉetJ3%N'+@wos-aeEn1B B'#<|W-6!~yx{iWiYNvM`/ =wrʢW~+cHžYM0w8)>{^?2hV0 =h w\y+r(je+Ȉ? 1@.\Q:"s?mCTaDUC KNjzOtq{Fa&)e07Rq&z]Rowht-u.ڷÔԴc$'$AQ7r7&gqcg/Z~o`6|.;mAr4T%5ڈ!h( ˤJL{5On#j4P nL|*IJ7ntH¸0`63QM`xb"NdqF?z4ҠcIu/dj!#`Ѕ=tßƵ8o<!TkWL$̇獐ίp5, wsi^qKPষɴ`hH si%}@NWtrƁCޏڨPP.A҇9;piZ]˨˛)뮜yFJJ-/)`/L~-Bt'Zgf:JMc{fș=T8=un'wنRix+hT6!eIa6Np? һK |NiͶ>A\}*n̨7,M%j\cǨ~U;<*+3:r Rz0; I`k~p!;^C*{LuG0zy K9bLXwm %V vB$yu|v$djgħ3gu 32rc[H 9A`po6%oZwCA߯Ib4gh7bo̧H7aI(E>742hRkyB Wi& Gx"a&NTPy@}j&Qt&SWQrI<9v1lY`)lĻ,,p7oc WWXg.05s5OӔ|JJYz'PE3Ut iuW569^#dZ&c/81>yaO虎kQeR`ӡ3QE,H=hGzX43UC|zRCth#l0Ra&b[{NItzvmˈ Pj1s &y~iwń59OjtDo;;j^mB75૴tsE9_ާXJCpM‡@eU7uyQ9@lOZEL|+,b&Ѣ vDy8܋;JБHA=^PO&@6,6s<. ߙ3F[P,B!G5R^5-ҾswR24!g֦vkіs{)whT0;j,RA}Srg,&Ζ(Z< #+ff52<|yuV+(KG@Ap!DgهI 'Zݦ+<i iyMUpbA:j`3vq?Ӆ"3 {4! D#qZ]Goy j)՘$li_>WGVa7<" ˲w|R o})h2۰JX-7GImJ;_۸h/$-{7mYufލ:HIbItxg/;%mpj%9b; xR 6GͶ! Đ~ΈHHcp~6rc=ԛlM jjS+-<#vf=**Nf["$a`K2RM{7܁4asp✅0n0FxLw[ 7&ߧ]|k NPx^,z,&XH8⎮#rj5?s)jiԑ$JP(uE0;9t-Y\nE4gGaxJ ]$9}#-U(.:➱:rrҠ!ItDWW*վZ /Q%&"4Α[e1uzo *$jB3sA0̔sƠ}& KI `Uzg"M=cT|-11k3Go冫*r{;CPhjNq=5Jhku1ٻr|vRqPƳ"|$Bt9nl{B_c;K _c&.t㛼xZiD*?rqy}WE.]1Ή^jh#1v30jHU nL V/ -r>eFHSRR}h'#lI\2W½_3W;F| m%vb\OqPoJ@h+%:#O;TTa*1761Ƅ,3v"Pǥ J!CC{5>cJFQ`@j8ۂd0m̟SRl(F \XO#cM֣Oc07Fʹ '=N IN;Tvx=|%A|NMHCQjR5n)StJpY:0>ϲEOnn|ȆƓo$ #!%.1D_YjXݷB=NsI+Q#Xtݰ BPv+3 & }Y6euzc?ejjb9ZsTb] bMI!1|M.Zdah2rG oJjzQ5=b%d4I<:SN#ǫ @4'0K"Ƹmt&dO9mΌ&u437;]?-H"*O1%43& Rr#]ddY/C/#o=EO|Crxצ +ZxXM bɅW9GݙPw ,Ox pcm.dH,T$Sa-t>K ~LiLvسx&&uYTyJ0R!0j{:$k(x{И48F#{qZYc0XCC:T`J EI#*Zl3ߟ$ɻO4Vq`AG7kuDWFnUuU"9S0&e#672OvZKF4Pmh^g];q߇:O7mYW\b1XH_ҭ7|&Fn.a,_6(j=p-jE ȸ^#qs<40."jǓ*g֣B+x޼?w&Z<=w5B9MOghׅ6_'^l _5mJ讼wP4 .]5BX jGvgѝed:O]Q`S9uNg>hb (ZVRjۡF[Z&H01`빬oE4OeE W#hE5NwCxwX^Z@z] Ͱ MvN?ӻ6!z0R:`݇p0v)VwdKxN:T4c~-٤ZJCyoT p: A]D$x"lŜ I_v&# Ֆo-'fG'*EvKܣو!ל{E G2ÊUtb-ܖ:6ӧN;bٟLm϶NV LZOGSy, ,b!Rkؗ_vD C+Kͨ(2a^/odnzN{L@ s-8?[hmIUC8V7CT gnRqjB ?iZb(؜D>c .mrk#hxASt;vs N<)ʁtb>ImNKTTŞ^V?_-Nw6ϔh㦤X,`$$n)]kpkR玟-ϒC:( 3mmhGڱA K۔6:GܖL m#Mi9r/E8Y3H?"sSGuTs=i*uۏmվQ̡7Sfpf#3CG_3&?aZF sⅰ^;ڒ\5Wj,pG :_^lsKgΎcqfc;Qc|3cWqh`Ǣ; *LETpwxXItZTp*PcЗs-uݥzjAՁm{P/sܸ?2L>2M&Q՘-Csh%%[od{+Z͠n8k'T;)v?.AC~.hu͜@X0  1;XY7Дhӎ%WF] D?=(;^F^ɡ)#j˯ "h &e>^E^^Ʋc(@<^4瞁$h">s\:$j+e1 ~< Z+';q҆tIn7ed ׇ ++bMMKe_ 7AJԨX>/?KZBH2kI$7wqoȭzn,N;L>euzJKۨ|77 ;I9۟${k:ٍsKZ6"O|ۄ- 8wr!0XŮh7t64vW u߼L;M)U~ZjDsYs!cw_};Q2뫮Bp bBQ*rEB!P`t>ߣ{`MW|&'f_W  .̭lT6͐jTK.#n2!+yww 眰eĩ׍Wa;Cp9TF 6 j*3ks[O|ixn|k* k/PU mȘqGs^g0L<Җ|42:c;}8RDKl+.G#񭬇O\ق`䝙<3NHM! z؍||Sh١ =P g&[+n- bmк@njư }RS5baA^ӐKFq?" q^7NXfRY[9m|Kso%R?8PZ)L&?Mu*k\F )Ļ>5 `{q4&dp ʆX&Sϩ{)_/r Z?O@C}Xx6dN6h޽m++P;[Q~$xiER!TB2j.rMVm,e]2X^[skp^75A&"LwMI1ǻCpAح%Ʃa]S&0s9Bs2f_t٩vEY{DY[Pe:Yr'~7躺S%xrɍıZG!1K.QsmtmskuӍ0At?~ߡBۙ,EqS5\=$dj ;ʒj[ Qg- {ʗ<2fDTpVǨk?t53\^6k=(`z*WY@e[q‡%΀HHuGwJ([_;@A]{/kI_KmsAk+bM{;ηla -||lhNeNL^tGTu|7B"*<Ũ2"6@spsS| 5R%J[{  [ݫ"էZB»?G_mU< s (K&ޡ юD vީU{ nZfLbAm&t E[W~bRQM˳I1[W)`->[DJŵ)9Mea]ݙzv\JVuȐppع\Rו@콅 9~?@Ν ?h&žy|,\Q”;VIY;yj<>el!Nv‡tj3 +(ךR(TIuG(@H#J/K!? V,Sh8*M&mҤEL9d>z`'O!.B!]SHp<)؍?,jӯ'wT_]Wh,Cl@7l OD&'H>*e) 3OK0Ty4 U@xSd0=B@YXe^>qg|]<6#,4-L6 5͵*C.T|/A_!sϒxgYNcx'7\.͠/p8NhcWG/O |% Bpg^`SE?e\`܅8cz? )Y\Hf"o@OjWgݧz#܌xMe i /YseU{`V\Ju=xz%67|ˆ 3{uCaf$X{a~ KU️Q _=cOb.=Opw2eFmhPwF!lmn ȱ}}T-텆1?Yٞ: 4QPst>I46g4SL{qe خUPUbL.:6G0mz+cFz{4f$vB!G>G囪sk eҦ@4#"?X,PeN }ROj·.ar%/:"Q:U35Pvët#>y{(ad)p"#IM .i\JrwVY*Y0ǃhj!ADm. _搻";ד(ˌQ"-nAgQ0w&Y:GMȲjpxUC A?OMyi8H1, *\mMaD|VcuSCWv1BV.: N3=16bRs[綬;i*1VQ pVнCJ>CnJ;ه҄~^TXP2R&{*U0T0?嫑#T ޲8y>,!p"wFflFf=jų֘DwFKCNt\[hKaؽ0FUxDGaAs.O<^9Iį6 \4;daH.dt%D86,S7_EdžHҾ7N7QKoBJFflJr vh4g(ƚYWG-&x vLOJ*!MӃ0Q8ZD'gVxx@GxBCU, +rKD)޹ퟩl:dWymκ;t`[!8AoY Z%92q x洇VS, ~Q &J uwN f!7R ngRjl+/^o_|[*M-K+r~|w:QˋJgn"$S鸛!TͰ;F`vݤm.!E&;Q4r *k!&D(?'jd <َW~ჺYņ,{OX7:*~URpNB̉>1ښE3rKߟyqpbtag=),o85ftzeVAB-05m38yC^`:ЕcCm)et5 5)xѤq ăi}7tBt97~>T-ϽXQJ܎7MZL5i5ŨrMgvxUVr|frh*ݖ'T":i#_dynjH O7yK aLqb^˲#L6Wɠ/o dzm凵TFV?L^(OD;WR^i|ʼj|xJL>zI¸xnkIgCe1S)ޫq &340Lh2A_o39b$~rQ*)(wkAS]@YJ :y[Wk{q:`9e Fj>;:Q_p_4B@\ K @P`hJmVPV2ghde[4 hW] KQ2&#ηV\ uh\Kͳ'ML/s)XyEUdv[Ѱe%.*]? 3x-|2SGp)*$+-NBs'-}~c4XK$I z>J@7qߒ<C1pmɳU1<P2$zkD-Nݭ3QS [7ӑ+=uH4'ߢqbצu ;)G)@}t= O,ox7!LtX ?sjp2o*VpڀtM6 ހUET-^ǁ^ U۰J7ꊼaǕB}J]p墀!e%;CDP>;g/goJ FF W5/탳g/;=APD!O]tTn7ODgy(&:POil8owLWXA?nNe{m4C\^Xb6T˓b4&tx8Ș=ҭҚ!lby,81Objw s _ yP8F(K>D`6f &v6: W!-+zlSbu3m;?E1cĖ}T&}&O0MgX6?:BY ΞE!o1.%RIoBu$[ZƳ- 0 UTi}1ݯO4sJ&/U/&jgZVh.#.H&kJ%e\){}d4kb\C(lzb_q?X;UY*,q+6~!.b"B][2u]2Op-sW83#2,>cƂL-=r-?gٕ9poX1sqfΧR*+?%4>VP$?{RlQPF",`?9 "oODJ` BO${QK~J%YVrTdL 4d,}\şP{ O$d,~־eXz!;cm顢`0 -$XKK1sиx<"5fRY $STcJÔ+uM1ś:o?۠REH3V=L(שX-8tϢ S%e72up(֚V2>uwO9}CyE핻!LJT6v&rAJ Lv4{zǰ޸O99n&<~ϑ'NB%摂kUק̤mu֘/BcTSjA!B-Ot&ՅTAkr,Qcyd!:p@xf8?WpsN66g`x [za{kz⪔ZVSz֮)*O 2+ W0hzH}X߉}#yx#SN -)Pm+7S_[}NFdòP]Ḱ^vu$ejz ۩.M>vz7`]Mݖ)-:~n?øl/yWUӒ }܍Οc]w%Qr)u vܫXq_vַ(+WڛUG]EJlʩk+'Ό3|,'f/^\̽Ŕ)j19k`Pid=~+ p[dQu!:}FGk`;>=vJmDvT~Z7\Jk+pf;ZAxYF\B VԲf`לtІQ>迃k5XV<\{ApWwrx#9Τ ;%)`ߨmO'^`fc,:@UJd VxV(V54$ X.㞚49Q#{-Ck, LRRѹ9d!Yo2xk݇&'q"}H#XJ  r=J2 -2/?d̙b]A۱5{p8>~golu`ӹuoMF073G J mqY0V@ܳv<9u@Xii,,bB54\IҸcdzXw?ɷV"4łXGrVW O#L-Υ =[o ?+(tJ~ޏ=LmKKVU0J'M6@/ _iee2ݥ6ax+nA^Yvj z H&#.Y*d :KuSuh5?,F0Ftֲ Ia>1[*F #S=q xΝ9B.@/#~G@ MF, *#ԯo _(mpxS":lei`^0 4> ܁ys>I-dCD.] 6aG1Jf55#լeg6.g#0ŕ=0p70FO_[^DT マL"DdNr.bxY˜z8JyJk{ǼۼtX^͝\Az̮Nր}ot7d5knh qcG aWdk4d&pi._[6YMȰas+`>d<e>d9rP{w;lȢLmW/B*+Z2:ЁkWK`;]/㤖$}~u1{T jM7{U%Ġ l|[v*kѽCRkÖ[Hr :,PqEC Mғvj[n˨p/SIlfGb!_tHbNQb$dӌ }R1K8pK.i zj#'Y$W{rzW'[$_§uciWF! wsxJY{QS]ˆc\x 3UlH9.g3Թ+{洐k-8x6іdZE<"J(r[rfѩ47r+; Hy0Jy G[b!98V8i6nM3;/,kG?Q[r\N(xWc)0%ِkjsrÌ4p ,:B/cMF :[Z z6>~oAa]B\x 4bG"tIФ7F4Kve"$\ I|'+S[^ 1?*N{xr]sH` ,cPJ_`dl2 Mօ- Q0zP0HZE\>5.r;4=P) }cL( &z;'{ BNg|X(iw`8}393:'5E^=:̵:ؙ<~DPqh8fMA7h֘;@: 0qY nnPᛢ`7ʝNfH!i F%dp82Ad4jLD(`5h5̻Ҥ].)NsyZtr@ [F0 DH" 0=q ѐb8H(R+W˿xn Π^1,b"U7l`dfLʌlȥԴWߏ ^"&6^5 iv:]A'-wtӢXO(>s~VߧMd2_ϭ韬P3= NdCN`2{PTjMjl_{(P{^`|A[ǝ([1f,B e E}-ɉh^vK#z+Qk)E5Ff[~PjcW@2H$FϷ%}G 1#LU yP롢.oW̕!p֬ތ 26.kNNƼWK_WwV&n1ZzpG^؅{H-'C|is\|:uG]P-nN,ݚسMj?HHH7feE V*u :.BS{vg%A਌7>9"EiIބV,?MJ"qXbo?Pz$$"G7n~lFˆJA{guՇinݵ#.X2$v&Ip'+ȱh8Evj5#Bh[RZO] f~q::4yP:&'jf|tAO|+d-i≮75 !bg אidrA5 ~JEF'ːWV)R;"S3g?QjDkF|v\ɖOf."h:yo.>sbqM$t\J6jg 7Go1d 9)lekVq6y.9L#=>{n .?Ɨeg/P00r^/ţ% ߪZ3M4%WJӿ>'+N(A\h*r6@ljD}t"$Hr|뜦ei^'P4 888IlkX$䲸wN3Y\m:m,`RԺ%˯]%WW#J|&)ZgxaU]0UD>o5HD2eE2Q$'+5z寁\$ȝΐ"(ӓE8{zX ko?o=g"H'SW ,7 =8mB-DDn ;7?~*__?`p[[󠼭nƴBqWrmN8YiL_W 8mÜT?wE"tFqv:ǹ$9}HUփ:GCBݖfTT6~3> Exc1v x}F0Y2ic5C,2i-6ؒ5T=rrpƵe$׫id_HkhQlnôdk( i 6FғɊLIA"&bcZt$3xL#Y+}mvϺMݡF3]F8se&6pW ,f$g \R֦9 єFD$nlT`01!1x(vHrtEj\,xZHGϊń>XPo::䂂-ckffjJ;SXmgN0I;p >j]TŊfqFC+|ǝ%}{9@GF!9 h+`:6>w4z1W?~a`5T™B8G-2w:v18ܙux@G o3˛ T>5vFPVOꭋgsz߄;;ɹxVo0>﷪ӉMq+~mP0vTwW!xA c%0iR%Йq)% cR;ɤL; @QP!2eq 7Z<s2fQ6x_iU>>SZ"e3.05e/$yS NJ}ۄ):c`01$N8f[>鬳:aٸq@xl6(3eAڙVL2ȼsqSr%l5`a`$+S* y:O$&H`4QQ V*U13SlYE1sxdf})AAbpځ >X Fne۷Gߊw][^ywE ëps (5tpL'9~*A:Cݖ Y4/'v \ѩ ^Ǐ(͛,.LO%[fd(G??<6J&IL fiw _SF5- XF&9͍ʓX Fgs-O&۪sl 7GQxlr`sTp5j:-E.2N\RaG0Hjn[N3"VG0XU:ߝ^CsRy]d WGW$$ӆI`g\l#~^@7V]ۿ_= Sx(}c<ڐdozqnkRlMJhH tϗE(2Tq5,rjd$R[UX^+󶠵N,3O)j$_)ڙD={Ҕ=+\ ՈYPVKYKunݝq|2fiG_W\,xM$ 毹.qѽ;VJ=NB d8YVM*iaJjt/w|dR^ۃ]])`yX4vM]Jx[8^Ebֳrӝ+ٔDJ} f#|5x- /dJ0Pce\Vif `G0DDutd]}-gvFnUO/]WSHVE҅dn1}R$. _%"C*$ɤ(Q->Q;wsi|oGu[G rihddO|25 Xk__?3mDVDz{2b✒=KO&Z_¯1y^a:%)͌Xe@e{K rO;v>++iş&, qx)ae\hJ{p0-xH~ETb?>.y{oXC4L&8Go&7dX[s>43\ :+7ehV:\@]%K\@ N] qsOߧjB1ޕ:dd1.R2׮ 0B994]2l]f`ق+*{0B_ 2Ď"B.w<*^ _q}+]wvS"Wy/! V!pGt,CT;|aSǙ3}""ة]ëu<ˮh"kdvc$Ïd*yhWi?nq&I԰H%0|J|˳UA^ULvaqqaX}$0&&"Nפ֒!n/?#m. ۫;E$ԜOFEݽ7:zaD\CζRv"oiy`>o<わd>oץ反7̄Őf@2+` ].XHl??qi^I q{ڎ:w.X9πHg{JiP K@5~qkY)̈́skHzd |w4S8[]^|u\pf ?H?2˿dp/?*z5:zbPD_➫?ws&tf;\?pBQ[}kñjswѰQa=`z/HDPcXv%d3nJOʀɳ DԖ?+*op_oE$Di߅ϭ]@nɗ墺g5*C9xaMBg8 8=p@BBp ž8%)m^Vo9fAv/fR\i=]i|.rY  b&nN(X[3c̝E: R+nOՆ %%A/w-)(H;I!lՒΘ6'QN?tYi_vmUG}U4 S^.֎p?c;a L(*g@\>w?\*zeJC#V(f-Q^> w*H =GM@H \37d0L\<? "p{i^d' x4eTp Yd !6թ㻨I`y*Ҁ(9!ylL%M*dxؠzVJKm$N%FD54\gJAMP~ǢZ,pV! gZuF NKuPNc2]*I GMu|uSn:?ix͈GcM.uҔU_}=ހ|SO:lY%!89ifͽ <ʡԃ??KިJBrO]K)JfEIug|,]Q?tW-Poje!2!@;2bDd  !#bϫ~>To-=?)22'dN}DZ'rqc3 ^k!QP,ݽ}rn<Eͽ P=kbJҎ-Hqe-I`ո֨ɫ)Dys}*t Lʹcg2Ɲ2w7ʩoΞ^e]2ObWʯҡANwmH'LE2͛#q3P+hVVSGPp[ $~nڢrZ%$%r 4++AyHC٦04 ͩ;ud=S3.!qwfV.EV`<:IfT!ۮJ+}ԪZe_/RD)=*qcɡb5P}Ry*f2)0Sl`~E!N!ޓgB\{fM):qlg@fv̀ISg&рtU ׹| Ev={ĞaaUJyևh%`WmTՙ;lPZqө奩i&E$z2-=&*`p ?2ҷ 'gl+%LN O&rҲ2i 'S4G0Lӿ wj7ӳl@:z4:2Dߺ2RR&wJXUvƛ|OZRƝxi76T\")`2LBl|Y0,O@DtbzGƘ*{˘LFWnqL)ʖJ8jz.8cՙni tT0~'vK&[]Z|(SۚJ3qQ,n&:,Cr'$חCY!B&>1Pr~eb}X|C} ]dF=a|ʅۅe}'N,XD % Ē-IN^Жhw;)/ަl7 C`c 3"YNfә yܢa$'G]K?]ѵEMΐ0D\`_DYU&GZTn>c*nԝAk}rp&]YoH\Y]qzMD5sNNCgf_&T:Uq1g xdJHQpP _]?Ѕå/,jY%"h!ralBE8,KxZ[.J"[%ffc՗7?ҤH^΋e`L_z{|L랮'ND{j!/ 5[\Do ?g*D[=^n=&(;FTʉe!0|Mstǖ] eN~4/ hZQݓݱo(SIiWRm1a8z=;sd3w4=KK^m^E4mfŗ*(\6ʴҷbAjP4\ "F#'"xB1{_jwe 29]5p-ri0QF| ̮MC˰ pύ^Un2Y%.aHp `ʋ{Yr"X4m| ʩgL̦{]պUf9rBЧd4 y;6lI쳡m/H0]8cs0uVFn3eݐn]$ S]*x#zhB?DͰEN 8 1=Bb&ipI!TVŹǙx]X1aya塑ڜ {JCgt2]h 24a܄6Pظ4lL.kUWzdֳ> Eupfyb4 gc6sEݕ a)S'1jt )MfcdkJ8q8/Z\k# /\I%,\p?Y&;5 vFO;R[n1|kDAnjt󞂹QYW0a9x=G-1oSE_r c@ ųN )f;bی0U!hgf)za@d 8d[Clil!(ߢc6Km6PnOv7ȡ`'c!^NUBeհ^Zr&iv87 ؆5tG,]ۀ kOjVKBdust--Tr;+!d8`u R-qO5NNEԒhX0N(@$nT͵{nL #ԭscfqɰ0D!^mSuAԎHc d& `I q Z + /^MrLxq .otI%WРRNH|-E$A{ ՛wf[I~N[ݶi䧊6] O 6擺Z[RkKR[Zn-rM9RazG*yؚ0dCSᕪҀ ah~2Dkb+A2![ƞlY638ޣk-*Ѡg;ZK80oz68Gu i1jnJgx~& _ع(IfȆ[GZ$3хkeQ99IsT-)Is ( Q)k˂/> SP߇У89l3(Nk|>ާםj imUlG./?nha{|Fe{؇>m㞷M?\i^I`ndNܠcя`17omm6ӟgƒ# A6|}X_ Ƌ{Gj7 SE3}wݔ{ %&)`XHпM%~Z70b? hp+ՔS/տS28b_*FOT,6aHlN&!3fFT[NWOղ;ծp."-0IE/IvJ*iq@Z)RP%iRj}HEbbtmY!c8O8,n)/3}brbce4dD8Ljy^u+pl d++,d?.v:#Pfk{ɚ{}S}~M3˛fW%9W2b G@8u0@TNYY@0앎0ug*K\ݹ?j=moߩ@>iڽ Ҝ( ݟ[O]y= Ϗf%ED{;L߻2%;3}D !wRuo>B=aJ8y!;O%q DH2 {yqIba|EHv.^j?"L5as eg2,p-LU%K=lcbԲ|;BzExV%ŅndA"Coma1B4EGzH@4O]x,@ M,]xOYtِ &&+-,87dAo$U(ԢSMEnjoIDtG;ݞw7ꔳ pіUG 9aY2Z*$L)\Pn֮4t$CQr&Z7$TɆ*d r,!  ޯR]%o^(]`/eN}D)dEO iR}$KV7cg,aql¼aݳLC]s8s++8Kf7}7WŊNQ*X1Ǝ&c| ٳPA,^ZU0vhQ~/Ӷgl->qA('/N]z50RfgȲxyv٤E~&g߆9zyyVc4X`@e6 ;I^۪ӯғ!SgO:͟r`RI*C'RS׮ݱ d. ,::sf&+5#Pz6r+y04g[Ff%gfKY"d~ TFyq5@ Vi]Jٮ#1˽VGs P+ Mjw;5Yb5hv{F&U7 'f߽˞D.MRRAq܅BL|S_9Kw$ycdQ-|x]>N!&*Ԭi Gz5k5H!ܢnܬz!3UU*N-`!Gnf-",8 hdBKqDQj ̞-`߇dۼA#A>q`2@&sKZ7-)E& ʖ+zVvdGHYunvf WROלsiP)HuYc;~`/MtPW7^zԄGQAct:;*̱ kY1cn[lh(me"N?'m7 nw *poHo3ytSS T^XsyG͊haT7H'~1‹B8 SWt_ ~SGM1'MM#;bzH>g[NOD_}O>VQ_σht#7G>8_BHm_:2(ZϰUcŷa4L#aՎ C{`h& ;į=y´/N^%+F4#vUTO7U*BMc-]HoۑV.m 9[-fW{&M@](@gI2dFDXXo*b* : LV_Œf>.Cv8> s%$iDMQk2a)DҠhބuu裘fL倥*Ba|7-Nt9Dxp>]_[4z%{.B倞PK+Kr\n ,bH_4McRF;X7Ē6IAZgEE0LPU0v$uUȉPlXl#G D'QKP'sb6 !Q/OCݬ# .6.ꇶ9eI|jq2Mu?̯9 8o5yKc!zjτINfUN1 =^3|dx?yb3O ݯ&H{:0ʾRkT!C-T01.өGI񭒧D-hi1`\֓!խv+F*Օk~: k3fjFT4/C33v⅂3)~7| 1W,䊖9W|fO3Y@¶y^zY!b/ Di4gf*0od~Pq*X,r$*V{.RPY2ybb'5lLXݝSٮF]HxV5L~x=1g*{Yod@9 ]"cRpB b|[*8ɫ, v$:{tZ[z@? ꝉ.j$7&OH//T>< DF][tO<4ⷫ&OhmF7 M'x8,Z1-1S~3$ۚ8 zH!nH!7 l{3k|=cK k> ]uܗ!5Vad!Eى<dŹeP#?D1F3ԢDz9;m'u]cw"#N:Kh61f竚UnIBO8 搣}}_|C,ߋ}aG%}?j| Lx;)X]38,OgwlN+Ʌה 2<n pvgGcϯ0gGG ); д]C ӹ3p/+o'F.R"Yj)}m!Ϊ܃Mܮ{%UW}kA%P!| H}``@.3deQ@tz0y-?b )'^a ^?K"&Zds}񖄸M21O.=ٕxfXo}M]|㧨À綶xj߫j9a_Dj%ID'hb*i.wMeo@w"M7G쪪ҰcQ?8Tk*M0ˤHXmP-Xꩋ֍ҭxZO_Х{|&ދ&?5g_*0)P+hwg.}s"S[=u}+X@)92 \m;JP&~ [I:O[UɴTE|̖H:-W4fDH1_Nwg1unfG) _?ABrrCt$cp4cO0qK;3Ih2dx 7jKl+u0΄!Pgcg0`QO;X7c?$rmAyђ2juuRcQҴ튎!izC=\ANQ;LP8SBX&w"e:^Ht#1}=o.V_QwKrIgKJ2Ii߮E!xyuX1T)=A~y?z[@:YM&Rie6</Z?r4`#w~;>%xaqe]fo&Lxj941g][l0VMQ\w3e+ܓsEٲq aȺB@DO[uȸ , s6zG-d.WFjÔ(IKh︗d5/b6ATg- 2 *دP'>[Jn';lclf3W~iP:8qCF]=>!#Qy8slM'GI/7ExՎ>,dgP-AZ#"%7<84 XT"~2B`(V,k(Wy0Tf2EujP׋DRۿ҂\MP:$BUu%4IxKkRtҩy{?9>hBkVQOL⑁p5q\*2|n_uƈwBy};҆3bo>tbu\9;+CW`rNs7d` \iv4jוg0MiBsABuh$S#9N= f5Q`N 5 Z^)]'~RM4& UHͷm;+鴊U2iw}oy׵IDkpd <} ^xveԾ2:\dH8E~~J>/FPֲ"kzx6/Mл'19/T RkSwpsq8A2OMq-2xO㼤^.; =eRϯʌ<?;BD%VIJ_0[Jp:^u]4ヒdڳG \UdHУXV?U\8h>½W[Z]")c9ny5JxՐugOݍ.xקU,hsӕ{=zU}o4U> q)>͵ 0PPS$!MaGi{O٘D^K}fuVGtvud~4:s8NjC}@衁ED!~(E闆-k!?z-u &C+-0õ\#~kFMmZIT\vzzM y1Z7Rjg[>P)/, 41.+j[^U$q`Satu|Y5n[ߡ?~6 aʞϯwŇ~?k@?pk@*LVRќ"a,ǟX5MHO-.^XZHTI<~/:Y-GrX;p9RMpTЃ5X:^Үjy.O!$` `Rxc8:>VK׍ʘy.\3]Of߶/)!;̹5|.]e6=lGmR-)Af&ZVkb)5ya%Hm-|lİrSՎBh?9frozؑ8%-DOBeoϤ¡#pϻ"b21i^e;M|OZxV,7!nnv ˖kӱ-?OZ_-?G߮k(ږ`bN'ܦ3{6~kcQtLNc])5  @ U`{!m6iF*[r9 $ޅ=lj:xo&y6]sPKeNטWe9Y˂D`y!PUT. }4]`u׺|f:eGhT$0>Xtr|+#Q_Y~fo8/ ltXޜ 1yM%IByM\X1{퇠=<.pOO(1r|Mvv6$1I**U2xV‡yrlޱ_;v6< pl #r^ 05縺nK:; i\SZX_.JOdBPp[Z)Hr7 L& mLpIf=[6a#{=it:݊נR;Td[F{MU-빷q#3ewC?E,5[gu(`ns_mx,%k\{.Z P`jL-&D"qLooX6AWㅚ4׺U@GN,56)-a Ӑ S-$i}){ %|}(>%4*΍/-4,sf.Xze$^BNRyu iXDܐ>HVʼ7ٕٙ8"_=ʼ/z$fAu]_UJ|7E[٠ x"> s_ rHKTinM=`.M]~(=mULÁcak!+aL[UNh, ^BzQ2=UwyԨqgbS³~?1q8\4iϡSa!?0_=>]ØKPI*d*/#n/vf=FMS)'^>k,8ߓ'tT"S핔WlBּvqySTyn!.1B76*|LMr25ey~$w!mdY3sL=[ˌqhjک:Wkip0f{[4fi5ΰc%JpijÇ£f{ic͹Cmuƭ*^o㓎،Nϝ12ϺMN ӥ\j_沄2~Yj&rSjy9]=ȭ% ScL^& Swo?IY)YE}m#luH!D{J+|dN,Cew̚^y0sN6 #g^۷9k+6e󸓉7/ mu) CqV1Cd21/( I, a|t (5M@4@e(VYĬJHҔ2#f #4i!P) hSV2:A:Q \֐@ ܨfp"IR/v1x umMֿ_Aj\Z)?b}Ѣ)WvƗLys涻3wn]emo~75-8]'EC઱y[| /ţlvlL'`kuʗxxoQPx}7;Cca?W( s*BMP:?05?SUt#qPU(d*1@!6 z* ;3">ch`xpg7'O5}@3d {u_ʢx?#ņUӉz)P~I%c[JGPFpZ1r׽dl @>( {D%nEǔFY[qkd͈Cݱ2-mԎDlشp۝(0;%O¨1Aם@Fg8XVi(rkxE| M ! 3`z>R* 8eJʊ dm{FӲ-S>,=B"V'GlB3k-L?gZg_:#sDEG,!#wtƐ8%:8B\F%h~fDxH|fŰjΏ?xT ,A@{7G|κf%ʘM!<|13֕Aaʐ$4OxeSg$B34剴+qZPle̯- 2XJ;M5b8 j݊rY[Z3a6aUnsqOcW mߏ<70;Z]@Z)D^iؖס2]= %N_A-iA ,,ہE³b4o@_^'+}58kO}3͙gm-5?;n4 YG7XUݖ5"ࠀ'q \8b!Fjd20ߊ_1YV1jub£>bP>=P !?$e\+ʩ KsV5VMa,۪׈S盤1rYHRTlϋ> n)x}z)zPe]@0&DrqR87¨@l^b<S(?to2Ik&c:"𻾛ƌ|zFN޳B**y emE)wEQ\grT -ˇSI£$LFbn,)P:yA"N $fk!҃x l +G \mNꮛs䏝i%rJWg q%=/sa2si' U+el(=ud6Ջ+VwTA_N랩—ZPNXF[Aqej ,9oFq +dvIɂqS#cvsQ{GZ몸`-PE4b!D#FӨi%JwP7DCX/]V\[AU~ pX:9E4A7⿚e77ГxZ>z7l М,;:VG@HOU;|Y?Ĩ_[zÆ)՛M6B|MB]\dEG 4 "1& & $.P0/`@Bt[̩$|/ |zXBp *|- ^ 2=Cºf+?HEx|??\M|wcauğ4ΆwnAWXSsx9Z9+! v HCz;[:y!3_#GJIR7w*[1C 43ȕv@n<k:gx>hzgpR H!hB KZ\t%J eH¡!AU.l {SY^cp woU¡lVhBp'~ռj<|5 GAF}KJMVމ8Տq@HҪ%@d+0=lFW AəBx $~}x'=/&ph7"1:!W< fOcQ\oDK\ިkbu0SF6DIXn񿨯X@N9ⰴeM:lC{%=\ЂN;ZQ|9עWhUSx*FUk@i$@z~)q=ngO4=|8>Ϛn~r Hu טR(m^/t<hjtdamG0+U d-Zlyf!)%e#{zrjXN4 hE=9{~t|7 :ٶeto.em%ow?g/-;1m8rqͼ%푸;d gYJDV<'oK!) JKIM - D,Tnm> k22]-|̿_qIdpYT[QP 4#b-Qo֧:~sK\4+ݴY')#mx!!;];]<%I9wpiaVT K}5 g"YY#;WO`#! Hy$`C#dr?  : 쟻CB񼕮+xۓ J#8O=s66Y߹UmbI)Lwr nT'|Mul*Z]ځd== 0yQYD+·}uA4.xAv x 'Ŀit"1--˘D%:,WQC#:-AML"7D 8{ifnʓE &|IX|*g mfsD[$ qL샞B;{`м 1]4C ǖZSwR"_>95(זfdgؼ̦"Ӄƾ?%5PO\#}C{! doApX! i0AP\hήy+ӌL(r؉\>OHNtSQy\r_PO`Iq Q os::7EEByסI~)ĝzժyx1`xlUi >ojk%\Н󬧓b,ʾۧ+[5s w{P3bUϮEU>z˝kdN؁PD^:"i2kkh[ 2f3n G+^ ;6ML<. d"Eu:]Uz]Tj-WRE0=,ӟ9!}Z kO)vzQըz&oMHpa}bRRZBmjvݮzMlIow;w<07gSnnyyɜkxNi3L`,,; d$N7oznj`̲;83o+* rK_H;Pf۴kaG߬Je{8a7/6$xƢSB G=LOWߍRx'{ ;sW.< ߵIR5{PĹkH=6OS$r\|N`k $`#5s@r4,a?P$ӯ8͢YQ*s_qx $'$:)wʼnKq<ȯÍ>ҒT{]"jr[*=U hP|2E$u3?w!$K$A [^Oq*ĴG+|HU~"r ^fEj,tG D{S ˑOF>rBSVmmC93S\OCWҒPXYJiUU˨!mܮ}23s6(֗'v͞Y#׉4`1IP %40•چ[S[@,~TqFVk#D-/\70=( $n<~"ζo5ۢ#LWibyڧ/#%ifw*Kj+ (nK'4X,/ĚgTskU;bzBѢPtm5~<:j Z|9܋a{qnנgM滚ߣo#2׸1yW}q@TF iv︿Xuk[63hl,V"e1ŸnH&Dh߾/δx_EHAD`3o`Ϟ[+w.Z*jC?Isffͱ<~#Έ݊̊;{/zB$]1.I~,dbEL`j1gՇ28!̢^waw641<=Ḧ́%c #9r{H#݌snW`lL<1^+nnБBnV#`uaP}˾4w/Sƹ!'Cx~9Onr`RuewxH3) "y1Xo7n<;Tp|oK:ZoPa]J.F}"wS=!kf1c*j<㑳!Ó bggDrYe}TYe {aq "c"< ?+vm8?3h~RFppˬ ֲWA%f.{s֗?)ut0~͓ȩ3gҸVJGPk~ xQ{6n30XMSjwikljp Oյ ݂wո0,~gpuU;gmY;kQᑿ@m8(e;$o>{}bF6]WE7eݯЏ :#Ӟ҈u97Ѳ7+/.鰊=@f-J8`|xu{a^c=ױ{&lvQÊm/V&wgo5 S=]$C}V8wF,>.yEG|ĩ펡ǭo>dDLTڠ#*#~vdPC1ru$$sF wO̪rvUXUsp RE@aӇ;8eV2G|H[*au}PGv98H.nU)Kٽ @ļ#_Fj}JX) 9I$xr~R[CATEg=n/?7h?j|=ȉΜ;Ӄrc#LWCU?t 'kftn{z 4`1J b GpYXŜ/`<5\,))%1ˆ4qs{<2@ P]i,3ػ(Pi zѴllD3-V}Nal%'EYcE&PxanP-P}\cjR14~ݥ] < K&xu&.;vq8&UXѿiM^63(pDP±E 0} y^%H~@HkeB^}oRregΔ cS#-}Y]2ALI(U 5QWW>( u/m> ݧ$1J:?oe!8x)<f K ?A8g+$J+ 8ݣO&ρX$$i귭u oʠ[ i&ޥdx, fdUZ+̅XmĬ;Kɩmr$NH]/F8(jN[~'C;oC)xkZ&=iO]85-oIpy`Tg|nEJeYXWMd=ab̐;奇J݇O) M prܜBu$'(d4~Ti~Q>cdpwI4JTEv)4Y}( q3 S_B {ܳz ;D],.`䃎ۆc 7>O\PܘCzEj"+vN}CwM7S˅PL[ X۵R֟~j 2jyH{١g͙KUk#̦{&D"rmaTdzF#i?wnNjM-JbX!7a &km6OLhd͝&" z /1|`AAepal:onRW.zޞ0f G&H9!ڜ)P mwk0hIS K|{#W`<M:v27OImNh$ejx !ξ2V&>I}"ܡ_1ї7v6]s\% cr&1鱥eMYIF`aK[f[V ̛o6A@ʊcJ*A-xa_۸z[7C9Uע&F]+P^+ $T7Uېf߆_&Տ[ux߾^wpRw5 ^39},??3Ь\ƺ3 eE Μ0*C,h={݈jo:LIZCVA8lyQ .wf܃#Z"@&[Pi9=9S%-;GnCkhaɓ-,C *acD*LRsJEo`LP!6g(ڇEDMZ¢JMbXhT20wJ-ƱŢv v>4? &!0NAϰok>v20A4ߩ޼zyX<_k1<;/5=1.BFP&m˨gwMTeg_!-83jd ((9!J_[x9I>u3=,">5AI \[a.b:w Sv#mW/;gJ<b(D()N Vj6f7RA7 'J ?\bm!fه:: |lڸ܈*dХW//&5Pǚ1(E %GF2vm~_ۮ]җ;>WxN캔kސfv+*Cq>*VhwS~UqEZ䀘bjG涶xej|ŘWj/duA@|lB+e'yП-횋\FP\W ^`nH~$'Iپ@ia2XjF5n(zHnlVVeh8ƙkQF$; al>g GÂ\#dkVAڂԁJ|aD<|S'L&ToѯcBL 1!t%aj<86nWDk)# ׇn*N?zmI޺|.Wȋe7f) z{/_3' 8oLwp<^d|o3ϫf IaN~r:h]ۮ|}m㌮B}qF<ɷcmV#ZBeoI_)m= f`R JA>v̤GW_Wx3^Si ʥ0{? \rsg*De3SbBHo_9G~xEKU^`m)7J.Lb0CO6uz),|ׯN87&9Wފ@qO,KChs2g4vSGh@~U~Ѭ_@ibfmo*J[7(@Y_#9 TOjkV۷b6QŁ"~avFߩ?3tr@.:WFb6 et?37w4H1.Ү iAkӭ7q|Ws< cu5|;ޕg k4b^-|6@/bI90}: ^ʈXOCHҰ[J̈́z:[2+wo >;,߶UzSzZm=|IeSQA=΢Kk?({}(ot4 HGQE~y„DRtU{;$W]ɰH&_D}au2cmAO@н9\Lh I&P{cLY`!ڲ"8舄Z9pb7sc_/5+3b;S>YO>B~ ҠϽC$na߂AzZ'wkmH;'<Ɖ3?/lTU\RѰq7<8Ted]~Z{ikcoEVLX`E:DS[] dMbDz/vu#i&,v62EP!|݁ DwVD'.c3eC[K}YT9"1&vEQȴָQ '*O5 t9`k" !;؃Q|Tx$/+_!Pb8>|7&aQdZv[X? g%v 9B؅ eʉS_XfLr:lX%nj́M;+)d)Kb DHƀ1%EGUFs{DҸQGy>sdF e͖5I_ V@ XMgjJ5ʭ:T^"4~/DL}y_d/7FUчdtvP#QN8=?Y܊3&/q+#MP}Zb:[6q(pN l{a;ı [˃~WoQ<7Q\Cmȅ bD:BR^BZZwHwh5RI͸oJ(lb)pS_JbKQސ9)aaHƖ*$>i|$AP`#}RT葌<"K´ue nZm6Q]z?7Ip~)~6eI4_nuHgHsH&)= ڧ4HLt+K HG&MV_~cbKhKbo6yOQAPW8~v]V}qVa߃S8ěV^4K!`cJWViD.3։xLMy^#P^46̩N&xZn<##AVUPۼ_3U$"zV@}Z2e"4ġXnjN]T43Ij Vj6rĮUIjk~#HiRFj*{8q(2/`1y5?\H}NP[N9Me~:-K8*+s)ZmRƘ]9m@Q18(NZ$Q{x^'\l5vs</3.TCe m$ko`$FcgY(cc6AzZJӷ$lN9}W!sߟ;ͳDKds,I24/GohT2,Q宋P8Aj&*pQƔ&rׄuzzhN(L˳2(78&{y}WzP1S(_HL5^k1(3$'(oٟt3z$ɲ_ϖr4(WX^VmP.__2,.mg6Ӗ<֒{곣('b?ۀ]l[W({ s@_ ?'q:-<3K8{+phiy_\j3Bs{Le9Zۍ\MVD=C˨{2/.GEΪht2 -dX>,&ɐɰi zbCû,̂IDP3|  3z5UC*jZ+Qт]XO5K؉OTZ10n!d|6Yz~Ո+rHq)K^| QmjL ,q+=(B@Qr802YJ=Ma,iуaŀeYJְ85d&6{VL „2.z~(N,/ʪnڮi^m?~!PD1X@$)+_`./LPNoر3-Vt=^!A1 )a9^%YQ50-q=?8I(i~yY8y?B0b8AR4r JjaZz~FqfyQVuv0Nnq^r +e; #($E3,/"D*+*F&Eu?( @,O *`./K2BRk:h2[6r{>?B0b8AR4r JjaZz~FqfyQVuv0Nnq^~`phxAdEtôl $jn>~0Nnq^~p I &'ʸJ 8I3yQVuv0Nnq^~  $ "L &H, JlTgƴ?_fv~JöP]Uo@~!v^5 u{_SbXs:'gwXJ/[\|jc!;5hMri HMʅ Ҹ |PZdRX 6&ZX;٭7HXBMgԂ&2MW~ HmYd^JX4g8ZkcS"^^Ec&[Z_.PI 6u؁gepI< [ߤk"@gcSmh֯^. z|=V7lj`3,?t)#Tp yMGG :pHWv].uNoD]b[˃F%%mz;_(=u$y$VC~POTJMh:A5h{ݰ,9W;N T|mcwI.*|bոT9rEa ЏtI1`UdKbj4ĭG1>)IMTDikS焎!j~BQ9BߋH¦ф$AqɭLi7MlPx7ߜW^Vl?PҲ #n XKIk/O5z͢Np4Xjrq.f±nVu+S@??KTcSd +]Goӫ?#(Xv%U~ǏБ.cZJkLthT/.&Lt]Gj(2=HS;$ ʱ&05e w^fiv!*H@Q빵o՛pK)n@qW"QT|GE}[O;af[mC4l),BD?+TVae]Ψ6j:Fuoz~Z] ~$lyy7FO}`/TNMU'H\:/[FQqUI7Df6XuANq]=ғÛ%$gcŤn=Ytt\!7}qԳ¾ +7O+2A 8 sѝI'9!]AOy_r[|ȧi?5BSTF)^b!j-4rMrDذ }pRa3"9[~4^c9PZ7"Le6:5m4 h;|/`I22TY ~/K,(´_܇I4^M== uBbxdگ#Pm Xbk u%sSo6޴@(XQMż!J\bgEJ,NB-/eMUk!#ܡxcEO7<5}H'mW) 6]ڥW0d:ͅw5Oqd>avUAшXlߌ#[6XȽ2sŦf^#o։ N(fhOYܪE/̇_9G1}[]l3mBQW,NHB*}d緰35@"@22W,~㖢ix߻_yV&x!TJy6yCK=cvu/$䡡>w}8 HB*͖yE:cNJ)u_bEKvP[$ZkKhc)pÖ!H5l [ְ%,@s_U{wT ,"""""BړIF!RJ)K jRv-:$Zk1c|3ɿ+]r؊lnT:hugo-0.92.2/examples/blog/static/fonts/glyphicons-halflings-regular.eot000066400000000000000000000472371420147000300262270ustar00rootroot00000000000000NAMLP',(GLYPHICONS HalflingsRegularxVersion 1.009;PS 001.009;hotconv 1.0.70;makeotf.lib2.5.583298GLYPHICONS Halflings RegularBSGPMMF٣(uʌ<0DB/X N CC^ rmR2skPJ"5+glW*iW/E4#ԣU~fUDĹJ1/!/s7k(hN8od$yq19@-HGS"Fjؠ6C3&W51BaQaRU/{*=@dh$1Tۗnc+cA Zɀ@Qcal2>Km' CHMĬfBX,Ype U*Ҕz miO1nE. hx!aC XTV‹ R%|IHP5"bN=r/_R_ %҄uzҘ52ġP)F7SqF{nia@Ds;}9⬥?ź R{Tk;޵ǜU\NZQ-^s7f 0S3A _n`W7Ppi!g/_pZ-=ץ~WZ#/4 KF` z0| Dѵ&däIÏ;M{'omm I !wi9|H:ۧ{~qO, L]&J09/9&Y 蓰{;'3`e@vHyDZ$3Dx28 W Cx5xwB`$C$'ElyhԀ DJ $(pQAA܉A@'$ hp0V0 `se$4$"t2=f4A{Tk0|rH`L&sh]A<`R'!1N;_t3# V *veF`E O${)W=p:F`22ړC^.ćG<.pNe2ִ+Ysl:˼ ܫu5tu^86ȄTmyQ%u~%~1rҘawߚ^_ZZa0!N`. uqYB\ᨀ[e:@J'Eہ,3ubj@pfeW9( ޅ=lG7gj SM609OˑlBa݁ <Bՙ(VRApf^+g9qMt]تpEr@]@VkV ud^X R@?EY2]#Ǽ4JK'dPC|mmn#$+48u'e&[n[L%{BCDL:^!bƙ:&g3-3ub iLZڂWFSId6.k5Pl77UzT:NN.")['|U"AIvwptdk9嫫9nDmq7I|6Kbc]MBABȪ_JT q  6@Fhd`GT:M7'L,IhFP ~j $¡„ 3hA-S^چ-%qe~Qqln"i&Qe?FlK"As(3Y;"Let'RzM1 0{=) K%$C 9M4c EotjVGD)l8,\w !%$3t TBzҴ iUJ[xgdBr$!eq"J> )\~3(^ R€8#>bHG'7_ fӫcκtDoAA߃(qB<``VΫ֘*buP4v@+.Qԥ$V@C0 RܐP[z:XH#e s>?EWO>@I$|si ES)0A?9ab,@K̩o&Q% ϞLu+ +H|Ɛ?NK4CnPt 'OT.j5Ĵ8vw֜I&+`yScaO[#gQd[KI矗`ČLP # )27aTi@c\ސ 0nCpߖ運4͵x*RzYbT[\kUvHʈqp঄IIŗ) bB XPNtz 2 I== ;}bqjiކa#" >11Ap1POOuxQ Fϲ(h݄O'MDxLK$ȵh& 14SirHJPtDM;rM+ *ؗ5u2$f3K %ѳb (@,2f,~"7R;E;HX(42Z'Tۿ2J+^!#oY~4-׃GW*!A0&8f{`W=DP8'= R g}iP>#4EBRY^4eN8V,[BĨD#X],LBsNC> +o^x jC.4Ya_{eA2=r+9POA!! }YPJeGn%x1/}RgHa ^3- 5 |qSaWK{ 1al`I1 Qf_yyCZ)L3X] W6@DMT<.uGK8DsбWr\7Z\V"ISd>CUjeD 3MtWcPӉ6#3QnቩJ\7#磱`؀K lV6 &T ~l. @61`! ` wYk/a0A¹ԁYhdxk:fEao̟^<IwYgq7s[ -y1ع5aMKאRBYFq}8*Nt'.YbZvK (]&ɜ(ՙ2:0 oΏхPKiBH4UX,[$ 0mXش f50VR 8%ާDtUs`-BPzPsvI8z-t1DiB "˶YTJ .?07jLN[2tĮ̎ #6?E׻:ɞY;A&qSIR)ss 9*x0Bj)mHAhyЏhMm&4Ŋ4 gV&tYOCS0Yd7MvNj)wA(o "͢[ E`7ezď-Q]6+Bca@^I:һ=sSnc 6 OB4LGpBq/>O pwj A*@JC[h&3B Qbϩ8 :%f~v/lS00a"B8(f uGoǚgyt_y~͔ %mL !I$Xt0~ePz]Ug Н=_?.j#+`li BM5 őGp7a ֒%Y[UG9@\bDY{{ED0 $Q+FvC`ݨ3Q E\uC9![$l 6DoDgG*+X!%#Cq ?8ZUB)U@opgީZq89|uccAќW;@">Ph_9}.6V/O:3}ZS {:~ykcO6;OB=bV. Rk o ^GV= }oI"+ ]wFzϷ`<30h3]Rf859s`KM8 XUq<\ZOssM&j&  .%PBL~^Gˈ3pD:Z<\ǠiW̆"(:zX~0PG]8RQMNTqfW~!0R%Ց0xvGFy/F-wu/*+ \8@6c<L;c[º nr QS'oQuT{qҐ_ͿSdA*ð:m8Yuz2PB Hh`lkpLLh cEb6eۏҋ ?!>| *=VK@rx0G`%ryr[6Y37 f**n%9df11ޢځ^'] Rq.,^%l e#wWs56!=!q[ %Ԯ]5^:m5)?V b|u7fw,:Ye R% [ o gFAzFPx{dxíw8ٔ{{L> d2CLL,L,(mS$=|%֝lu& ą83 N Xx \VnJ[)Iw/鹻 |GźYDH*Sp60cJ2@W%Ѧc_^$#*:G6n>D;~`9hXB UJB_вˈ%w'$v|#T<68KMϑ-5U+'B ĪNbJOv'|+*Mk(d }C˱@q&aR%} !VЃs3w2a2awHz/Q0F ]~;ä NDP mK3xke_ S!V&=v_PL9؃Yi NU_)J69f*S  17F|BR$y,Ʊ.&=uqsODBR=ɳeؽɇBH 2lu'h7^#S)Xi2..Pe/@FK$](%|2Y1pC8tI11N//+\pjdWmI=߽YZxMЉP81/ JG^U ,Pd1O^ypql2h$jvI%]V .'[+WU8[D,߻-=[ O wE)3J&dقݶR¡S\. 5J$I&oHȳ~ lz> Ux/Hu;?Gt{?;TH L|F8}{p:2t͆aѧp65Y"LD.rVS_ k]n&Hz~9æ p $4ق'{&M\ΰч!qi (.h' B T|{I6cL.빍iI꫿\!;g`1 j%C o3*60E؎]t.-%0 YK_nft] *VFCtJT+\WZ8gF^ ޞf 5I=#6.@2z;W`B/ęQghjyJNAX3, K66ڲM0T@O{4kj|"ftџۄU<-a5b)^R8:ilKa6@!]buvΏ$ oUœ~:.Lte JξP l$S[z~Rq39钺9Q/m"%ʤ7 5MKL鑧"IߏG XTގXLFݧV jp^/Mgۻ{w *9Oʈ<"aAq.M2@mp^'wߕmkxO8 $[&|YZy`2_|%r/J?QṈl3ÞKE$wvCh a@U1M%0?1* $GZ{!|ʿ$ە-٪Ev;͓:`Bl˸쌧ɬoQ0&,F?^s,ch˕$Ecl0w`⏺ň@/r^l8cT3k@JݔuP&ʪNdJjTKi *uX{tj~ɡ}i\BKenȵ|N u#]@lCZ$iPa㸩t04y20 s֪,Au!QBϖ^@Vsɑ\Za7쾉ш6-TrU u~1HJ(<αbRԖqi J?eG *jVħ ":Y);-Fd!HG~ux cb6m)&;0dU?8X~12ۼtIx5{(z '[ŃkZЅi,b1̇`(mHNeK/ [(#QGduT^m%!(7KgP=hϕkɐU+.[eC"GDΨ<*Ř 9&܂?)\<&Ŏ5 LJu@Y,냲ھ_w0^17p޻*>D8_)$UźR!jOF>{ t,-bP,m`D"/zA ͔إQZG&U]xejxLwv~=)@B6?!;53/ps@tOZS7ؙnlxZ?Zj a{6L41 2Qi&֥l]o=7ļ ofЖr MEV@H/aD٦HlK5)ŒZ OE3IG'г;D'zl(E$.ٜ-W R'\w+)w3꺾 @%R).~9;].šg+)%ȝk҉^NW>b1z:soD K2w[|>9vWMFu`axchիU`*ʆe]OV'6xd?H]_rA+zdFH ʋ<ǴkUsFzaH9-gvb=L/E).x9j%B)$AB t b.bAEZRbH(Jya9Wj0fF'Xz $DQ6q` o i={#4FYH@J3 3i~tYТhkHP17YD"pĦ;'16fpu>FoDQin̒- @P# hj ނŀfC 7°T5HVXpklĭ]yXr)?ͺBNJ B#9e&&_0=pZ6h) ̗a b=(p);.N,W^ *hԺCm}E7i6aIvͲxp*Ac#4N&`)ĉHWey7jloEh_n3 jp?4p2WE'kT_ &!ȖjVlHӻ_kɚʳaY s@[G"bYLܫXi Cq8&zVaY{#I@2m!d[1 AƢnKeם/>dmuX:xʷ\pNl+H+ctSǶC[~3e}6 \,Ʉ|Yݧv]'|&M2 ddsx-((76aXm=ӊQ<$Q†\ qiH阇i'i$"{S*VwF/tfQCWUZ{S;Nx}H&* 9׸qU1 a`(M-aG}n̽0 pmcn ɘ_\l} 9FvHþkJZNO mZQҤ aSf )QC+2 d[ H"t* c*bڢq,#S#u'Ҭ:4asCDMF|ɸm_1L]Y\*X>tgDd@&[)8;<{8<+VG\H^aae-4sJA \ hM[\`#pD5Z97g;BWmqTXX%0v&]E 4]FIJ&S_4R0D+meY gO+M{03v'ͅft:;ر Nn\ǔ^,)1laBZZ[  ZSUYh߆wS\/*?zQЋ`X4gr[CWG.Y0Q|RԃE[wy),ш$NK@c/b -#ZI G$ƗtmH#)XwPZAD|S ofTH)>M1b 7ɆSuq jK4[s xL Ǣ]5 !M!AdƧN><:ǻZ(8)e /W| bDDŃtT7rur0Ң`ܴh5 5S}4hrvalc!ZjB]xDbTxzYS6_)op>#@PS*bS\q ƋxYfQ><" Y6IEr_7Ұ VH!IrEL6!Nq"'daqMvA% v n.;A/2ʲa8D$GWv#̏ 9k'o؟o@ (]gk+}/ (nqK(f Ɵиp23YwpDdGq2$}KӯA"E&Ntg'Nes!Ю4qo}쿝S,ojr/s TMT&Qf\12h'&ctN'Tx7]2 ;G ʅ|T++:%/ 1T  ˀ<4͔˗ ,0~!WO' :suҦن(^ﮎ )7fmlҹ1ūtZh L0 6X"J҂ 49 ֩B}ԭ``Ӓ #Jn_F H|$OK=œi17o-Hqp[ɫ%%:Ɉi3۠G CLL4S:dBj|pYSDP>pv5KLe{t0yEND$*;z5NBIgn.N|׶nRaSZJcH mXek;_ 6,yb0#ZA e|wG U1lLD7ÄVqt[xuEQULPBlZSh.1Q0Uٱ8Rip;{H#GON!?t>Q |pkq!gT,j2sǍ4툊tjnƛ/IOE!ˋnF4M&1x$ew+vS  bm]e%8 P !s_06)Q2JB [t9'Ԝ,[fÆג]BB@r&Bs|Q gOC1J D&LJiC`A^#X8tH?daĖTSTaH0@U)^e}Jb7%ܔ%:ƿ@M+ysqL Y00ÔGD >ĩAW 2I:F 32ʠq:6S]K"g[ ϑHB5VEqLJX{CB!PIq9Llxʪ7>֤]@!@9H!pə$ ?)܎l/"́+@`}}:\ 8zQgS+򒤿C}R:HUF\Xg/AZ%c1wlETwX ZNhyf2D ø&vLq47z\iJyJ-kN3 -sJ5)V0N0d\ӛd0d-E[mf\UmxCR<(`ѕp4^!hQ `!l ~ƙ:JɠlW9˸ZXB=l)`jeVJUG!s1?Ƽ3Ê.}bIa6ʕ t?SxZJ'p i,.R2T`5-R BxrWH JPe#Bb|-[PEh‹(5Sfr/]IƊ dE#OS39ӻ]eۮɹ.9_beM9b#e(- 0Ra9"U,%~X܀z۽{'6[@t[W%* .d'vR {h!AedCE}x=E[|B$7J* B- ,=k7[_-I J5e̶{ ( ;WMw`~pAz 8f))(@ Īم<.a%N n@bz>%T*?lgbd<ĵw9Na8;<^*%y:tDҕZ<@0q4l\ 1`/$IJ ғsN);:A;)$ו Wwy%KrIv\bV\nd{6tv/~*O 7U>8rAC<jE-j牷xs)D1Ì/qp**̸$ّ,  Bȼpk MhpK7U]h&-$鎻Y;q6wzW˄֭AhD^R"s5fw +Q&/9ȂwNbz{Y> ]NEc,ߞ# BF:0/-EȾŒ׃F\I{tAZCORuk i)ytkdN&vA P{P'>xƆ`.%,;:Կ:aFoTQ}v#ףQk's~z5hMQʒY>CʍiUNF#J0uC8k! fv {E/IKIE> pyde ʾ=z:@7J|5g8x 3O 3H1؄F.yfzWIM j[.w%i?҆Uf|}@+[8k7CxSEOޯp$Q+:<]K3T-y[Nz;y-HZY^.M*'h8A.N2rLB 7:Or}CS˚S9Jq#WI}*8D!# g#Y>8` В ?a2H,^'?^nhOƒi<Ya2+6aFaMG-Gkè1TbL `*ـVX *xe§֊Z*c`VSbJU*6TK@zqPhg*ߔU(QU49L cM*TR!R,BȅE*C|TzpF@4*텰جXbL.T2y`Upb T,%@` #?@tGLŞS)ÿztϲFy׎ 14Lhfe(.)pK@\ Xe@TbvhD&0-IbD d@ZD1@ DyѧCN| 94Ӛ#Nc l;, `cX@(2$0 "@- $B@<$А8p7C b(@ PA@F 0tGORIJITySMW52\ToRKV0Ȏ( -$ !6wHGO r~e~/]V~/P~7SzKFv`;`9v# JBN,ӭ'`'`\LTApBs)r! ( i`hugo-0.92.2/examples/blog/static/fonts/glyphicons-halflings-regular.svg000066400000000000000000003243021420147000300262260ustar00rootroot00000000000000 hugo-0.92.2/examples/blog/static/fonts/glyphicons-halflings-regular.ttf000066400000000000000000001305341420147000300262260ustar00rootroot00000000000000pFFTMm*GDEFD OS/2gk8`cmapڭrcvt ( gaspglyf}]oheadM/6hhea D$hmtx `tlocao0maxpj name,post5 webfTPT=vuvs Z 2UKWN@ { , h, h@( + / _ "#%&&' ' )9IY`iy )9FIYiy !'9IY` * / _ "#%&&' ' 0@P`bp 0@HP`p !#0@P`fbߵiY!     |vpjdc]WQKED 5 *+  / / _ _  ""##%%&&&&' ' '' !& )009:@IDPYN``XbiYpyaku } )09@FHIPY`ipy !!#'09@IPY `` ((h ./<2<2/<2<23!%3#(@ (ddLL[27>32+&/#"&/.=/&6?#"&'&546?>;'.?654676X& j  j )"& j  j )L j )"& j  j )"& j LL#32!2#!+"&5!"&=463!46^^L^^p@LE32!2+!2++"&=!"&?>;5!"&?>;&'&6;22?69  x } x }  x } x v L   d    d  l d;2#4.#"!!!!32>53#"'.'#7367#73>76p<#4@9+820{dd 09B49@4#bkv$B dpd>uhi-K0! .O2d22dJtB+"0J+ku0wd/5dW%{L>G!2+!2++"&=!"&?>;5!"&?>;4632654&#^CjB0  0BjC x  x u x u@--@$?2O*$ $*P2@%d    d   BVT@L!2#!"&=46 %A+32!546;5467.=#"&=!54&'.467>=2cQQc22cQQc2A7 7AA7 7Ad[##[[##[dd76!' Pԇ $ op zy#%**%$ pdL #7!2"'&6&546 6'&4#!"&7622?62~   \l lL 7  &   l 2'7' & c_"fn &\`tfjpO32!546;! 22&&L%6.676.67646p'0SFO$WOHBXAO$WOHB"7Q)mr *`)nq&* )2"'#'".4>"2>4&ȶNN;)wdNNrVVVVNdy%:MNȶ[VVVdXD>.54>0{xuX6Cy>>xC8ZvxyDH-Sv@9yUUy9@vS-H^{62!2'%&7%&63 a o  ^{"62!2'%&7%&63#7'7#'JJN a o  d⋌&2##!"&=467%>="&=46X|>& f   f &>|.hK  ]  ]  Kh.| L#'+/37GKOSW!2#!"&54635)"3!2654&33535!3535!35!"3!2654&35!3535!35~  Ud  & sdd dd d  & d dd dL   ddd  ^ ddddddddddd  ^ dddddddddLL/?!2#!"&546)2#!"&546!2#!"&546)2#!"&5462pmppmpLpppp LL/?O_o32+"&=46!32+"&=46!32+"&=4632+"&=46!32+"&=46!32+"&=4632+"&=46!32+"&=46!32+"&=462LppL/?O_32+"&=46)2#!"&=4632+"&=46)2#!"&=4632+"&=46)2#!"&=462DDDLpp&,  62"'&4?622;;nnBB# "' "/&47 &4?62 62    ;    %I2"'#".4>"2>4&3232++"&=#"&=46;546ijMN,mwbMMoXXXX K  K K  KMbyl+MMijMXXX# K K  K K %52"'#".4>"2>4&!2#!"&=46ijMN,mwbMMoXXXXX^  Mbyl+MMijMXXX  -32+"&5465".5472>54&&dd[֛[ҧg|rr|p>ٸu֛[[u'>7xtrrtxd/?32+"&54632+"&54632+"&54632+"&=46  ޖ  ޖ  ޖ    ~ p     >     GO27'#"/&/&'7'&/&54?6?'6776?6"264X!)&1-=+PP08,2&+!)&1-<,P  P/:-1&+x~~~P09,1&+"(&1,=,QQ09-0&* !(&0-=,P~~~d!%)-1!2!2!5463!546!5#!"&53333333,);  ;),,;)D);dddddddd;)d KK d);ddd);;) dDDDD 62++"&5!+"&5#"&l`    j`  w  ? d3!#!"&5463#"&=X;),Rp);vLp02".4>"2>4&3232+"&546֛[[֛[[rrrr|2   [֛[[֛;rrr   2  ^  )#!3333))p,p,d/3232"'&6;4632#!"&546;2!546& & T2   2 >p  ^  12".4>"2>4&3232"'&6;46֛[[֛[[rrrr|  & [֛[[֛;rrr   12".4>"2>4&%++"&5#"&762֛[[֛[[rrrr   &[֛[[֛;rrr  9!2#!"&'&547>!";2;26?>;26'.    W & & W tW    >     '2".4>"2>4&&546֛[[֛[[rrrr[֛[[֛;rrr] $  (76#!"&?&#"2>53".4>32  mtrrr[֛[[u$  Lrrrtu֛[[֛[576#!"&?&#"#4>323#"'&5463!232>  ntr[u[u  h ntr$  Krtu֛[u֛[v h  Lr d/?O_o!2#!"&546!"3!2654&32+"&=463!2#!"&=4632+"&=463!2#!"&=4632+"&=463!2#!"&=4632+"&=463!2#!"&=46}    R 2  2   > 2  2   > 2  2   > 2  2   >   ~   R d 2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2 L#54&#!"#"3!2654&#!546;2uSRvd);;));;) SuvR;));;)X);dLL 732#462#".'.#"#"'&5>763276}2 d!C@1?*'),GUKx;(.9)-EgPL 3 0[;P$ 97W W!1A2+"&54. +"&54>32+"&546!32+"&546ޣc 2  2 c*  `  ct  ,rr  ,tޣ 4  4  G9%6'%&+"&546;2762"/"/&4?'&4?62A   Xx"xx"xx"ww".   ^ x"xx"ww"xx"r/%6'%&+"&546;2%3"/.7654'&6?6A    `Z  HN.   ^ d  g~jb1K3#"/.7654&'&6?6%6'%&+"&546;2%3"/.7654'&6?6 D@  *o;7 *    `Z  HN iT "ZG !   ^ d  g~j  !%-;?CGKO3#!#!#3!##5!!!!#53#533!3533##5#535#5!!#53#53#53!5!ddpddX,,ddddD dddd,D,ddddd dd,dddX d,,d,,ddd dddddd,dddddd  #7#3#3#3#3#3!5!#53#53#53ddddddd,,dddd,Pdd[[[[[   "'463&"260V C;S;;S;V0 ;;T;;  ! "'463!"/ &"260V 08D;S;;S;V0 V08;;T;;d&!2&54&#!"3!2#!"&54?6,9K@  D@   K|@  @  J  L !2 46 >>CEU!"3!26?6'.#"#!"&/.+";26=463!2;2654&!"3!26/.6D N9  >SV N N      & X & l l- p  v       dL!)13232#!"&546;>35"264$2"&48]4$);;));;) '3]dϾV<?!(% _5,Ry:" *28 T2*BBW-ޑY". BB % Zd'2;#!5>54.'52%32654.+32654&+50;*7Xml0 ); !9uc>--Ni*S>vPR}^3:R.CuN7Y3(;  G)IsC3[:+ 1aJ);4ePZo!56764.'&'5mSB ,J   95(1(aaR@ 9%/#4.+!52>5#"#!#3'3#72 &2p"& 2KK}}KK} dd R ,১ !%/#4.+!52>5#"#!5!'7!5L2 &2p"& 2C১  vdd  ,}KK}}KKL/?!2#!"&=46!2#!"&=46!2#!"&=46!2#!"&=462X LLddddddddL/?!2#!"&=46!2#!"&=46!2#!"&=46!2#!"&=46DLDLLddddddddL/?5463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&Xp LddddddddL/?!2#!"&=46!2#!"&=46!2#!"&=46!2#!"&=462LLLLLddddddddL/?O_o32+"&=46)2#!"&=4632+"&=46)2#!"&=4632+"&=46)2#!"&=4632+"&=46)2#!"&=462ddA ddA ddA ddA LddddddddddddddddL#*:J!#;2+"&=46!2#!"&=465#535!2#!"&=46!2#!"&=46dddd ,XLdddd}KdKddddL#*:J32+"&=46#3!2#!"&=463#'7!2#!"&=46!2#!"&=462ddgdd /ȧ,XLddLdddK}}dddd!2#!"&546 K,,,,,,v,,,D,,L!2#!"&5467'2"&4,XJ*J%pNNpNL d>tNoOOo62.'&54>"264usFE66 !^Xm)!fhHuXyHÂ2".4>"֛[[֛[[Ktrr[֛[[֛oVrru5.54>6?6&'.'&76#&*IOWN>%3Vp}?T|J$?LWPI)(!1 )  HuwsuEG^F&:cYEvsxv!K:%A'# " A)Y l */7>%!2!"3!26=7#!"&546 7l l27);;));Ȼp87cs* s ;) );;)2cL6!#"3!2657#!"&546&'5&>75>^i4);;));ȹpS 9dTX .9I@F* L6;) );;)g  0!;bA4 L5!2!"3!26=7#!"&546 62"/&4?622^^  Ȫ   ȯ  ȭ   ȭ   L326'+"&546d0dLJJL#3266''+"&5462d00dLJJJJ3''&47660J*J36 &546.2   d32+"&546!32+"&546  dL#!"&5463!2L  346&5&5460d * ;O#72#"&5&5&5464646dd12N: 9  > =,L32+"&5&54646Rdd0L;;dH  #!"&762!2#!"&=46  *9HdduJ  u`((&;(J ' 7(a#aa32".4>#"#";;26=326=4&+54&֛[[֛[[}dd[֛[[֛dd2".4>!"3!26=4&֛[[֛[[E [֛[[֛~dd32".4>"'&"2?2?64/764/֛[[֛[[ xx  xx  xx  xx [֛[[֛ xx  xx  xx  xx  $2".4>'&"2764/&"֛[[֛[[Tw[֛[[֛1Uw;K2".4>";7>32";2>54.#";26=4&֛[[֛[[?2".4>#";26=4&#";#"3!26=4&+4&֛[[֛[[    KK  ^  K[֛[[֛V   2  2  2  /_3232++"&=.'#"&=46;>7546+"&=32+546;2>7#"&=46;. g  g g  g Df  fD Df  f g g  g g ͨ  fD Df  fD Df?2".4>"2>4&"/"/&4?'&4?62762֛[[֛[[rrrr@||@||@||@||[֛[[֛;rrrZ@||@||@||@||02".4>"2>4&"/&4?62762֛[[֛[[rrrrjjO[֛[[֛;rrr}jjO!2".4>"&32>54֛[[֛[[KtrAKihstr[֛[[֛;rtxiKA>rtsS6!2#!'&4' &F   &S &5!"&=463!46 &U & U ## ] #!+"&5!"&762   && ]32!2"'&63!46&# U & U # &] &5>746 ^$,[~UU & U #$DuMiqF +!2/"/&4?'&6!"&546762R,^j^!^j^^j^P,^j^IIgg+#!"&546762!2/"/&4?'&6j^^ ,^j^`j^,^^j^/2".4>#";2676&#";26=4&֛[[֛[[:#6#:1  [֛[[֛.   IUaho276?67632;2+"!#!54&+"&=46;2654?67>;26/.'&;26!"&5)#!  &0  =  2 pp 2  =   353  X  v  v !{,  2  ,ԯ  2 0y    r w  +I6.'&&&547>7>'.>7>&67>7>7>-BlabD8=3*U  :1'Ra\{%&=>8\tYR-!q[Fak[)ȕX1 "@&J<7_?3J5%#/D &/q!!6ROg58<'([@1%@_U2]rO.>7'&767>.'&'.'&>77>.'&>' '8GB    `H  >JS>H7 '+" NA 5M[`/Pg!;('2"&"IbYCe\D9$ 886#1%)*J7gG:    8G\au9hoK$]54<&"&5476&2>76&'&6?6&'&'.{nO9:On{{nO:9On{FZ  2Z__Z2  Z# %8-#,- "F-I\b\I*I\b\I--I\b\I*I\b\I9>||;7Es1$F^D10E^E$1u$/D0 "%,I';L!#7.54>327377>76&'&%7.5476&6?'&'.P[vY,9On{R=A &/l'PjR.Mv&  6QFZ  *HLh5)k|# %8- ,- "xatzbI\b\I-yRU4Zrnc1?1FrEs11) ]@ @] )1ES>L'+/37;?CGKOSW[_c3232!546;546;2!546#!"&5353353353353353533533533533535335335335335Rd22ddddddddddd|ddddddddd|ddddddddd2222pddddddddddddddddddddddddddddddw%7&=#!"&=46;3546'#"&=463!&=#'73546oXz#z*dXzdM*zL!2#!#"&546d);;)d);;L;));,;)X);dL ?32!546!32!546".5!2>&54=(LffL(, '6B6'p)IjV\>((>\VjI), +'%! !%'*L 'L'a'M 7 Maa'aQd_)!232"/&6;!%+!!"&5#"&?62**p&032!2#!!2+"&=!"&=#"&/#"&468^&d,!02**6%%+*2222 *L !53463!2!!P;),);DPdd);;)L 3463!2!!;),*:,P, pX);;)dDEk+32"/&6;#"&?62{**YDk&=!/&4?6!546X`)  )   !.#!"!"3!26=4&53353$`$-);;));;ddd-(d;)d);;)d);dddddL #12"&54%##"+"&'=454>;%".=4>7i**d]&/T7 " LRQ  )2( Jf,53232#"./.46;7>7'&6327"&)^Sz?vdjO9t\U>/ v?zS$2451 7F8%M)(  ()GM~ 1==7'''7'7'7'77 N괴N--N괴N-N--N괴N--N괴d!-=32!2+"&/#"&54?>335!7532+"&5462(<H(<,F=-7` 1dd>2vddQ,}Q,d-!2$'$(ddw} L 0<32#!+"&/&546;632+"&546!#35'!5X,<(<(21 `7-=|dd_dd22L!-d,Qv,Q($'$dd dԯ}wdO7G%6!2+#!"&5467!>;26&#!*.'&?'32+"&546dkn  T.TlnTj:d%8   VOddip &yLN(  % H YS(22S dO6F#!"&'#"&463!'&6?6*#!32!7%32+"&546n jUmlT.U  nJ   %&jPddO (SNLy& pd(Y aL7G2#!"&/&?>454&/!7%.!2#!"&=46ސNS( % p &y22SY( nTjkn  T.T8   Vd% dd-I!26=4&#!""&5&/&7>3!2766=467%'^ NLy& p  (S22(SYLddjTnlT.T  nk V   8%d%2".4>%&!"3!7%64֛[[֛[[  [֛[[֛9   &%2".4> 6=!26=4&#!54&֛[[֛[[%  [֛[[֛ &   %2".4>&";;265326֛[[֛[[K &   [֛[[֛@  %2".4>#"#"276&+4&֛[[֛[[  & [֛[[֛  2".4>%&277>7.'.'"'&65.'6.'&767>'&>7>7&72267.'4>&'?6.'.'>72>՛\\՛\\d+: =?1 " "/ ?9 #hu!$ 0 E.(,3)  (     *!A 7 ,8 !?*  \՛\\՛  ' "r"v G  .&* r$>   #1    %  *  '"  $  g2( % 67'"/&47&6PM<;+oX"O\e~Y+" n+We`#'7;!2#!"&=46#3!2#!"&=46!!!2#!"&=46!!d);;));;);;));; );;));;,;)d);;)d);dd;)d);;)d);dd;)d);;)d);dddL !2#!"&46!|;**Dd%32!2!5#!463!54635#!"&=);,); ;),;);));;)d;)pdd);d);dddD);;)+AW!2"/&546)2/"/&4?'&6#!"&54676276#!"&?'&4?622,^j^5,^j^/j^^^^j^j^,^j^&j^,^^^j#;CK2".4>"2>4&$2"&4$2#"'"&546?&542"&4$2"&4ݟ__ݠ^^oooo-- - L- 73H3)z - - - - _ݠ^^ݟWooo -!!- -! $33$ 1~ - - - -Z[%676&'&#"3276'.#"&477>32#"&'&6767632'."[v_"A0?! -  Y7J3$$ )G"#A.,= # (wnkV8@Fv"0DG([kPHNg8B*[eb2!5(7>B3$$' )M"#!7)/c# *xnfL@9NDH7!$W]B$&dXDD>.54>"".#"2>767>54&0{xuX6Cy>>xC8Zvxy#!?2-*!')-?"CoA23:+1! "3)@ +)?jDH-Sv@9yUUy9@vS-H-&65&&56&oM8J41<*.0(@  )*D*2Om9w.2&/7'/&477"/&4?BB8"._{iBBi BBBBBB7._BB^*k"5._{jBBFi BBBBBB77/_2#!"&54>!"264d:;));XV==V=.2G);;)3-D=V==V "/''!'&462*$3, #**#4$*' 2@K#.'#5&'.'3'.54>75>4.&ER<, 3'@" MOW(kVMbO/9X6FpH*M6&+  4C4%dfJ2#4.#"3#>36327#".'>7>'#53&'.>761T^'<;%T)-6"b "S5268 jt&'V7  0 $ݦ -$aPN(?",9J0* d2>2 ""   7Gd/9+DAL!X32"/&6;3+##"&?62*Ȗ*,|%#5##!32"/&6;3353!57#5!ddd,*dc,dd|ddd!%32"/&6;33!57#5!#5##!35*X,ddd,d,ddPdddL32"/&6;3##53#5#!35*Xdddd,d, dPddL32"/&6;3#5#!35##53*d,ddd, ddd32"/&6;3#53!5!!5!!5!*d,dpd , 32"/&6;3!5!!5!!5!#53* dpd,d, LL!2#!"&546!"3!2654&^pg );;));;Lp;) );;));LL+!2#!"&546!"3!2654&&546^pd );;));;oLp;) );;)); $  LL+!2#!"&546!"3!2654&!2"/&6^pg );;));; $ Lp;) );;));LL+!2#!"&546!"3!2654&#!"&?62^pg );;));; p $Lp;) );;));L5!2#!"&=463!2654&#!"&=46&=#"&=46;546&p);;)>DLpd;));d&  #%2"+'&7>?!"'&766763 ,  P'' K    S#  nnV/L5!2#!"3!2#!"&546&=#"&=46;546^>);;)pDLd;) );d&  1!2/"/&47'&6#"3!26=7#!"&5463!m)8m);;));Ȼp,pm)8m;) );;)֥#2".4>"2>4&2"&4ٝ]]ٝ]]qqqq{rrr]ٝ]]ٝGqqqsrrrL#3232"'&6;46!2!54635 ' gdV^|d22L# ++"&=#"&7>!2!54635Gz " 'gdM !d22LK" 62"'&4?62!2!54635qgdq#d22L #'762'&476#"&?'7!2!54635*MMК=gdML*Л:d22L#'/'7'&6"/&4?!2!54635^WЛԛL*MgdКԚPM*MXd22% ! q3gqdL+!#"&546;!3#53LDdddp,E/'&"!#"&546;!3#53"/&4?6262L_  Ȗdddj\jO)_ p,j[jO) >'.!#"&546;!3#53"/"/&4?'&4?62762Lg%dddFF))FF))gp,F))FF))F/!"!#"&546;!3#533232"/&6;546L dddd*p,/'&"!#"&546;!3#53++"&=#"&?62L*ndddd*pp,L !2!546#!"&5!52LPdL&}-1;&=!5!546#"&=46;#5376!!/&4#5;2+p/22ddpddd33*ȖdȖ*yddQ%6+"&5.546%2+"&5.54>323<>3234>^%"% "  d d 1t5gD >?1) A..@  ^  ^ dL3"!5265!3!52>54&/5!"!4"2pK Kp"2KKL8 88 %v% 88 x88 %v% 8LL  $(4!2#5'!7!!2#!"&546!55%!5#!!'!73wipdw%,);;));;),p,ddibbd;) );;));dfdd&767>".'.7.wfw3 .1LOefx;JwF2 1vev/ 5Cc;J|sU@L#A2/.=& &=>2#!"&=46754>ud?,  1;ftpR&mm&L!((" """" '$+  222/2 ! '!'3353353!2+!7#"&46!2!546L J LP*dd*22dL #"!4&#"!4&!46;2d);,;gd);,;;)d);L;));;)D););;)L%)!2#!"&546!#3!535#!#33||D| ,dddL| |||Dddd,ddd,L%)!2#!"&546!#5##3353#33||D| dddddddddL| |||Dddd,L#!2#!"&546!#3!!#3!!||D| ,,L| |||DdddL!2#!"&546!- ||D| ,L| |||D ,L )!2#!"&546!!!#";32654&#||D|dDd&96) )69&L| |||DdVAAT,TAAVL%)!2#!"&546!#3!535#!##53#53||D| ,ddddL| |||Dddd, d dL#'!2#!"&546!3!3##5335#53||D|DdXddd,ddL| |||Dp ddL"&!2#!"&546!#575#5!##53#53||D| d,ddddL| |||Dp2Ȗd d d %2".4>"2>4&!!!'57!۞^^۞^^qqqql,dd,^۞^^۞Lqqqddd '+2".4>"2>4&#'##!35۞^^۞^^qqqql2dddd,^۞^^۞Lqqqd2d2dddddA 62632+54&#!"#"&5467&54>3232"/&6;46n,,.xxPpVAbz  & AwasOEkdb  A32632&"#"&5467&54>++"&5#"&76762n,+.yxZ % OqVAb   AwaxchsOEkdc  dLm%5!33 33!#"!54&#Ԫ2dd,,Md22y7/2#"'2!54635#"&547.546324&546X^Y{;2 iJ7--7Ji/9iJqYZ=gJi22iJX5Jit'*BJb{"&'&7>2"3276767>/&'&"327>7>/&'&&"267"327>76&/&"327>76&/&oOOoSSoOOoS=y" $GF`   Pu "Q9   ccccVQ:   Pu "GF`   y" $ooSWWSo++oSWW"y  `FG # uP  :Q # cccc:Q # uP  $`FG # "y  d "!#5!!463!#53'353!"&5+, ?,dԢdu       d !! 463!#5##5#7!"&=)+5, ?,>dԪ |  ^G |d 77 P#3!#732!!34>3!!ddԢ!,d!s, d,+$d$+ppLL293232#!"&=46;54652#!"'74633!265#535d22s);;);)X>,>XL2dd2;));FD);>XXԢddL6=3232#!"&=46;54652#3#!"&54633!265#535d22s);!);;)X>,>XL2dd2;) $+;) );>XXԢd  #!"&762#";2676&35} ,, }@D:#6#:&77&P'L. dd LL/?O_o32+"&=4632+"&=46!32+"&=4632+"&=46!32+"&=46!32+"&=4632+"&=46!32+"&=46!32+"&=46                  L                  )33#!2!&/&63!5#5353!2+!7#"&46!2!546dd^>1B)(()B1>^dd> J LPdO7S33S7Odd|*dd*22+52#4!!2!'&63!&54!2+!%5#"&46!2!5460P9<:H)"Z" )HJLP;))%&!!&**22$.2"&432!65463!2+!7#"&46!2!546 jjj."+''+# J LPjjj9:LkkL:9r*dd*22,62"&5477'632!65463!2+!7#"&46!2!546X/[3oo"o"."+''+# J LPk6NooN>Qo 9:LkkL:9r*dd*22",!!.54>7!2+!7#"&46!2!546X,%??M<=BmJ J LP9fQ?HSTTvK~*dd*22)2!546754!2#3#3#3#!"&546/R;.6p6.d6\uSpSuu;)N\6226\N)G6.dddddSuuSSudLL/3!2#!"&546!2#!"/!"&4?!"&=46!'|  % XW & dDdL D 2  % XX %  2 dddL#-7!2#4&+"#4&+"#546!2!46+"&=!+"&= Sud;));d;));du);P;ddLuS);;));;)Su ;),); 2222  !&4762 !2!546 'YV/ |UYY(n0U22!/.#!"3!26=326!546;546;33232!'p'q*}20/222,2 "!#!5463!#5!#!"&5463!#5,  w,, v  w, O,T    dGFV32676'&7>++"&?+"'+"&?&/.=46;67'&6;6#";26=4&KjI C   )V=>8'"d 1*) "dT,| -otE  GAkI ! "% ,=?W7|&F@Je5&2WO_e_ 2  2 ~ $4<Rb%6%32!2&'&#!"&=46#";2654&'&"2647>?&/&6%?6'.'.. +jCHf7" *:>XXP* @--@- -?0 !3P/|)( )f!% =  &* x"62&CX>>X83 D-@--@ۂ # =I+E( //}X&+ 5!H d9Q`o322#+"&=#+"&=#"&=46;#"&=46;546;23546!2>574.#!2>574.#q Oh ..40:*"6-@# d   KK   d)  )k)  ) m!mJ.M-(2N-;]<* K  KK  K X K  KK  "p "),!2#!"&'.546"!7.# Vz$RR(z }VG+0 )IU!zV`3BBWwvXZ3Vz&--% ,(1#32#!"&546+"&=ۖgT)>)TH66g )TT)g6633#!"&546+"&=`T)>)TH66B)TT)g66 %'5754&>?' %5%Ndd/\^^<ǔȖ  (Abd 2"&4$2"&4$2"&4|XX|X|XX|X|XX|X X|XX|XX|XX|XX|XX|L2"&42"&42"&4|XX|XX|XX|XX|XX|XLX|XX|X|XX|X|XX|ddLL/!2#!"&=46!2#!"&=46!2#!"&=46}  J    J    J L  p  p  /3!2#!"&546!"3!2654&!2#!"&546!5^ );;)X);; G ;));;)X);d,dddL;!2+32+32+32#!"&46;5#"&46;5#"&46;5#"&46222222222222L********, *.62"&%#462"&%#46"&=32W??WW??||||||*(CBB||||԰||||ӐB76+2+"47&"+".543#"&'&676/!'.6E*  '?) T 0I' *L #3{,# n  6F82 *5#"#!#4.+3#525#"#5!2 &2p"& 2D d 2d  dd R , W 22 L 05"'./#!5"&?!##!"&=463!2E  1;E%= !'y,2 " # 22+."A2VddGJ!2#!"&546#"3!26=4&#"'&?!#"3!26=4&'"'&'#&#2LFF &  7 ? 9   9 gLR   2 2  2 2 $ #'!5!!2#!"&546)2#!"&546!PpmpG,Ld|pd,#'!2#!"&546!2#!"&546!!5!2pmpG,P| pd,dd'+!235463!23##!"&=##!"&546!2dddpdp,d ,'3#3!2#!"&546!!2#!"&546dddpG,|dpd, pdL'+32+!2#!"&5463!5#"&546;53!X|^d,Lpdpdd,'!#3!2#!"&546!!2#!"&546ddvpG,|dpd, p,0o #"&54632a5*A2~ 6'&4O**{))*2A~ !2"'&6d)***2,~o #!"&762{))*a**( 5-5!5!Lc d 1#3!35#5!34>;!5".5323!,P2 &d2"d& 2dd,dd  dd & ,L%1#4.+!52>5#"#!#3!35#5! 2 &d2p"d& 2 ,, dd & ,dd,ddfrJ32 +"'&476 0  ) J 00   >fJ32+"&7 &6S )  0 J ))   fJr"'&=46 4 ))  w  )  0f>J ' &=4762j  00  )  0  =:#463267>"&#""'./.>'&6|Vd&O "(P3G*+*3M, :I G79_7&%*>7F1 ||5KmCKG\JBktl$#?hI7 !2+&5#"&546!5X,p dddL!2%!#4675'=DXDd dQ,[u}4]ddMo__<vsvsQQ(dpEHEd{ d&ndd ddddd5d!u ,d;I]ddQEJadd9'dddd dy'dddddddd,d,A22>ff****NNNNNNNNNNNNNN"~Fn2b\r bb 6 ( L 0  X * ^ h(T*v 8|t*<6`R.j(h6h^2Dl.vb F !2!v!"@""##"#8#z##$$0$^$$%4%`%&&~&'P''(4(p())*&*J*+ +z,,h,,---.(.f..//F/~//0>0011`112$2^223"3>3h344`445,556>6|677N7788B889 9J99::l::;;<:>>?(?n??@H@@AA~BBBCCBCvCCDD`DDEZEFFtFFG6GvGGHH2HNHjHHII8I^IIJJ.JR@. j (|  L 8 x6 6   $ $4 $X | 0 www.glyphicons.comCopyright 2014 by Jan Kovarik. All rights reserved.GLYPHICONS HalflingsRegular1.009;UKWN;GLYPHICONSHalflings-RegularGLYPHICONS Halflings RegularVersion 1.009;PS 001.009;hotconv 1.0.70;makeotf.lib2.5.58329GLYPHICONSHalflings-RegularJan KovarikJan Kovarikwww.glyphicons.comwww.glyphicons.comwww.glyphicons.comWebfont 1.0Wed Oct 29 06:36:07 2014Font Squirrel2       !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     glyph1glyph2uni00A0uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni202Funi205FEurouni20BDuni231Buni25FCuni2601uni26FAuni2709uni270FuniE001uniE002uniE003uniE005uniE006uniE007uniE008uniE009uniE010uniE011uniE012uniE013uniE014uniE015uniE016uniE017uniE018uniE019uniE020uniE021uniE022uniE023uniE024uniE025uniE026uniE027uniE028uniE029uniE030uniE031uniE032uniE033uniE034uniE035uniE036uniE037uniE038uniE039uniE040uniE041uniE042uniE043uniE044uniE045uniE046uniE047uniE048uniE049uniE050uniE051uniE052uniE053uniE054uniE055uniE056uniE057uniE058uniE059uniE060uniE062uniE063uniE064uniE065uniE066uniE067uniE068uniE069uniE070uniE071uniE072uniE073uniE074uniE075uniE076uniE077uniE078uniE079uniE080uniE081uniE082uniE083uniE084uniE085uniE086uniE087uniE088uniE089uniE090uniE091uniE092uniE093uniE094uniE095uniE096uniE097uniE101uniE102uniE103uniE104uniE105uniE106uniE107uniE108uniE109uniE110uniE111uniE112uniE113uniE114uniE115uniE116uniE117uniE118uniE119uniE120uniE121uniE122uniE123uniE124uniE125uniE126uniE127uniE128uniE129uniE130uniE131uniE132uniE133uniE134uniE135uniE136uniE137uniE138uniE139uniE140uniE141uniE142uniE143uniE144uniE145uniE146uniE148uniE149uniE150uniE151uniE152uniE153uniE154uniE155uniE156uniE157uniE158uniE159uniE160uniE161uniE162uniE163uniE164uniE165uniE166uniE167uniE168uniE169uniE170uniE171uniE172uniE173uniE174uniE175uniE176uniE177uniE178uniE179uniE180uniE181uniE182uniE183uniE184uniE185uniE186uniE187uniE188uniE189uniE190uniE191uniE192uniE193uniE194uniE195uniE197uniE198uniE199uniE200uniE201uniE202uniE203uniE204uniE205uniE206uniE209uniE210uniE211uniE212uniE213uniE214uniE215uniE216uniE218uniE219uniE221uniE223uniE224uniE225uniE226uniE227uniE230uniE231uniE232uniE233uniE234uniE235uniE236uniE237uniE238uniE239uniE240uniE241uniE242uniE243uniE244uniE245uniE246uniE247uniE248uniE249uniE250uniE251uniE252uniE253uniE254uniE255uniE256uniE257uniE258uniE259uniE260uniF8FFu1F511u1F6AATPhugo-0.92.2/examples/blog/static/fonts/glyphicons-halflings-regular.woff000066400000000000000000000556001420147000300263720ustar00rootroot00000000000000wOFF[\FFTMXm*GDEFt DOS/2E`gkcmaprڭcvt (gaspglyfM}]oheadQ46M/hheaQ$ DhmtxROt `locaS`'0omaxpU jnameU,postWH- Ѻ5webf[xTP=vuvsxc`d``b `b`d`d,`HJxc`fft! B3.a0b ?@u" @aF$% 1 x?hSAiSm߽44,qPK q XE](2 .ԩ] "ED i]DԡZJ\8wwV"FpUԯ.Χ(gK4O n;NR{g`'!PMUHEՠJʫ*Yq9c<U9!QIYׅ-KC+ դU)Q94JYp]Nq9.qyVV n)9[{vVכ־FWb++{>׍a|*gQ,K<'W@Ex̢D&Ud# & x Mx2c 5*.lN/h]GtT(xŽ |յ0>wm#Ye[%Y-YR'rYjD% ,@BKZjHڤ@b-R+nhK~룼$;h^fܹsn{ι ˴0 kb8Fd:%Lה"1AՔ AY>,ؔ#pZ4؟5made ?Ȝy=I:C D(nIxL .1!P'JDtHj@L4Ph' )b)vHX,f1c\'cGu>1 ~t?!xT_q?qBF#L%Dћ"?Yǯj??8>NSkemAYDb4 J);@jP$ 'qh8`;aX6CF*dYc"'?hLV㗌,>ce3eVh =C~xC\((qb@ 4xK&hׁ 4\2DZ6N1|-;j Yu@jѫxi䊧mK ٍDEwq3̷.cAw@4t.gkgr{~Wl~{lW2} 276a2\6oz@$HSH gbtX70Ktc1,7B oLƏ66[,%iZ ,l>TpKSGg\> #A#3Eyk6v;u3!ZI8Mk?8CWq{`C*h>H1_skh)ojOO' !~dXgB(0< kOYxeƧĭ5k =d ϧ> +tC-o Ǫ/_koܶs+fOztpu7-}d9 se \9.H4!0S\ ʱk2"?ip7\2zlްt=W\!KyOXimUnov 6: 2 LZkAA^qCޔ &PaFI0>&Q #FQl> A·q*OȦ_@27l,sf 6p7ܩ?M1vA2]$j";vlk~va0gjzRD:gc6yw%g(þ#'uB#=_@?>FVb0a!aL4tXv:Fh9j^xތz}Wn}7}jΚiHitKSaXEEbbBQ1ftxFȮ -"dqA\~F`6i䁕+ Ԣ^Ȳ}ש׆k&Ĺ<- \;g1>w00v^x 7l#Ot^5+xe.^]׼G8^ m(t1 sbfJ %<4H@e8C,5<(kc5YIA]|ךl6+=HVcbKՋB6i4 #_|&>NvQk#pW=u7HɰR$ [5싙 g %19}&@$&l=1RI}9#ςz??1z&ı_ac|PI[:u;l->k4GYm|Zw }HnR=-B ~m.ِ .Mz^,0%8EG**|sg|ozO֬0sz.WN^ yHk<v3t{8-|' ea~H94xA-@y bT4@0b#]DDljDSio:AgSP z:;-|yH"r {B{\5RLi6AAtM]taRKC!1CgC샂 +1EG!Xzٛnzv@x-#i^x*$)W=O\f[WX~V? `Lei::v4$?=Ra#c]8YFJb&'{%LCE Cf]^$/fߪM;À; 6CXV#X~ F< :vCcyBpLv1Fv#9 /8VF01_K?x>}#G7т\Wp!.@bwɡ+{o#ԍPQҮnī66 cZD(. u;nM}?vtxF{+` ="rPπlDV̶?Z@H䰅][35%O )\^ Z;>Ftf-IzӮ yu1uo<:oa:uqwykk ⋜}0?jvX+}VG$s ?26YI5c$Cfb!X*|F^$p7p55߶6[mjgl>* KO& 8ܝ:ǰokKm~oS-*4E}P/% k:e"1AJCAX8= LŢ>ܱav{|K.3 :\Bxwbeb>1ۿvH?f58 %6$ɲ'pL^HXbpIVqnA8Kg'i!UzSEI5N=hpV?(E Vr?޴7Vڋɿ.O;p 4NRZm.O> MuL'j5`;MtAQܶMyV<` $m)yڳXDa:݁q1JFq15-l\3~X-2pFDe/f!2i:=h{%{t^ *PBͽ]YD3jd *w|GLϽ}ˑk7Ç=06oz*zo1~Jw00SePw%#@BJB %+ ';%!& )Hq 7fqH.!Eǎf,9՚$9 H{~i Z)O|!"D.KQ a2 %2Wɂ\{*B{7,9.'ew U^W&$r9rcGBwll<ʷSQゅh! iѨvJ :Y?#_m4q[ },EA{VПP|Dg?9MId?{)/ /\[ Jҏ[f4G>QK^ m O -7w]„<U3jƏ,:Yq~0/mŵ@CCFq{,Θ쬷ΘQSo lsɿh?A2q`5Z&*X1L5:6ς+O]uej%?ۼ&aW?{2[}W?JbΙk-\b7sIkf&Λfx~nO-9V ~cW"ȗy)b\)2MrWf;MU7'[-c/.ؾuMl&.9) G!!W* 60Cф#qrqOKZOWq,8́/XpTȑg<>¤)[J8o` ;S\S%h~p|J˾F~K=E0NQX*8;D7Q1QC% *Eyy} UG?>I`>'6<+3IVgϮyOQ$WBvH v[Ϗ 2+ 'ø6N߆<ɕ 2S娚9X1\┣df>B~-t>W]pPrZ['+ƌl9]8qC!' @AAOuШ !?M\JMͭfǞ)ߕ=w?AN>¼}jQ<ǏpǠ^(}1+2q F4RiHďITr8^!gm>'ڸhE`s̊ol!(9~ o%#)~ƃj$@ՔLpGOa{߿fé)zؔY<~^cs潺ݴNRURTY%8Ks3qd]^QTb' zx)HFҩPmUZjQ&XƁo<0jYGz]$8c&hyݼwΞ{9^sf߹m[vӣ!(ZAsۧyB8RiԣBg6{UmtyW!bpǮd n/ŷʼ@v/%cxEn:4Y²,yZ-krcH&^ȩC'Ȯ'^T5r)((IJU&#݌! +YM.JEX^|Lw@ھZsgY洺\xԟxyLCyo?eV"_[Q/5Y|qI/\9diEBh$v wOL fpa ,?HgHf2RbL v >USo^1/,ēvcYGmŨ~Amz ?/40yj̸pk2H eERb/"M 75ul[drC&Y͐&I `!>p;J-b--.VM4>Fj/5σt5}>C*<'d?,cdGf2ҁ0w6Lh"fKζp;ǿ϶Pdc1EOi%Ř(DCWV2I)TiMFTz0U S7V mBW6;nYZUzSTg>(hF"޽T뽷R]L۶|Lx[s,'NU|E<4)Rp*vU#g*gjə*=~܃ASēA JHw3@NurbwȀʌx}[`7ZtPlh L.)NU}kq'vFQr׷{ˤS]ZL(@*Sf^+uPe_k#.8ɂ%ՠ,@TKх t`ߑXAD;b|pA7}q2 @Y`~iԬK0jY( R~^ҧ8>=F"˜A[DqvQCX|ZsO \/f.F;kPbdz7ԐeͶ-6bybaWjnh7YLF!4wssFCnh_0> MZ nC *#5/OUN\(3o@[7`Mg8xge;f\y|f֤ޑ]i5q5q&>'353kYꭑ=W7+΋yxIeOYǏs(p6[B/t爁*̠-n: <Ц) +ް~q_}oxt>LV FG@d9[2?2ȳ8笞={fgcsCmre#E>45qo:JX^ioP,xf:/yn9VѥS7=u-\%KϦUv,ⳀZ=vkN*+_.ڊ֞iڃ=w @lmr>Oo,VԲɝz &:'45!9pI 0@I[PU""sInvR>A9t$3/|k8yiE c8E!Q\ۂ} %Af4s*A8A΀>D=5uwjnG z?2Q/I=fH4n]澀YmG"2PEHfvZn<šPiA_q/PDտ $$~%NyhrOdM\-m(@\#ƼNJO>a+ uJ*(%¢FPJW,$))} B\_wV] 0TOCÊQ}5{Ho*;;葞rǨMc54S : M7(kY:z`gp Jstˉv'eG^~iD16dA @'N ֭N.?f…1bzJD V o@7R@6<%IF0mj= [}Nۊ57pyv4@<mЭ9Tp?R70қQG[jzib~/)wC? רa-/Cn.ĕH j63pKrhXIƎj o19 f\~:-ѓK47BY̆y%DC~em@]%rs4T G-Ug>HOpVB]{9&^6|m _PLLI7ǒi "'T }? 4|[Fǭtu/_y;Z?HK0Wzc#)~.rĥ+B&JG0[.ΡrOk;VCoX K۝S߳rt:zX\xmJhxNh5 K`;ydp.Ec4XD<-llip.^p: u/.Y[rl_4kz$~Dq]7/T_<菵4K$Ɩ &w S7|K^7MsMGhw㢴0]?fja5aiЦ6C2no• f=)d^v qNcԎl=u]?;f-E~nv}5%Oջd덿=Z%v  nKu ̓*J#1hu1Hr o}SZu=w;nϗU `FȶEn?߫k&l9YdgA8NSGD09MAK{ހK3݊[_]%W4zۈu9\~n3~zir X3k`Psn=m]ԃJksT9deYN`}/]U#b;Rt,lh*#JB+ (iGx\}~IֳFv@Tu֭J @-LwzYgw`wx-(d٢]F3_XcYmQԃWb-F K5d-0b球—֨T+_Zxcj*`}|x~LF*S*oMتAT1p71?R t>R'"Ey)oP7%$rv QeE+nzlVlFrkt''?R'ZCEIKy ga0^}pE;Kq{T/?i"%1ޒb-Ծqƛ˵+ 8]rIڣV{dȪ͜\AQvOS]0.NX9svb?OE~FPU}o[YKrA̓U%7Dw q b/h AhPbQؓJB8I ?I%=XtO;(PhLd S 'hݱ>|TV?,O"\`7.2>D fmg;-C'u, zA`-ټ$x vck2[xp\cbl΀ihsivaÛM,gĨlMz7JvˑVRWϋNo4(-XB^Cl&Vnnn D4[k6N&}f3YQw@$U$(Ǫo:-ZG#&/} ?N}ƥ7A!MhW>?iXprA١b?uϱι-h6;SB#/@ѿJ !%Q)Dq:{JI^ޑˡPY7UG(h?HmъvREH=N`P)QG9FMSMG@2E$Q $s~TkN"9Ն8cF^"?+G٠ ^*gUlFVxUpoC.XCƵ׵͉qK[k[K(l; ӡn%^Rj,$) 1n.G:Cf(,;ĴR—F_~^;իD;6|/jGGSSGGӎļDzbR/X?Up14u$`[ߜH477I~~Irߙs#6+heW6@wK̸h6, 1C"=meA =@z sls];kklr^"s青>&Մ-[{JiҴ9[ݵȩ-]dޢc An۹g}ꒇ6hTɖ?3s^kLcY 1Zn[bݴE߆դwk3f> fMDՠaD ~}&@5u gnOȢ<'` &bӬ-6;X"d*awYvtLXָkUߩa=HR_@+j2T*£%/͸oƤy 19/7 ~7_o+$DүsIH:r yiF:v(dO":omdM8 ;Z9uʩHCg\K/*ԙg*-I_ERqR'[f?GUAovb A$e]/Կo?|ԐQm4G7G833+ 74z*)$݋JpDNj5pqeDf/>%gW{U:g,nlU\t'%E}͝uCꘒܻߺp}U+^b'o(5gVBIOEm>5yzg}AP-P/ޫ6)x5/t;1p1L9Aܳ|)X]mkFEH/4}:,oLMo6]YM50u[yҫfVh?E-A_i﫝j . 6|5`#Z-svfqӟs͚>w7C{ A]Bz,iH'dv?`E x,mz`F[2avhp%(̒ʂ5Ԧ;Gюh\y";|"ٝʖrxzsPHCTvP$ly}iyhvMCr)#x-.(t%fu€(ۅeUUo pqeˡ啗syi Xk`>X@2P. 2͌>n|,/4} ?A&Jr+ɐCV]{Z0- A= F$+%UZyޗٲR B)wT8(aRΣ*-sr5v !^tZ:/K,'F  9=G<Cu"$-FS2(F 0Q+Xw,]=bh[qBQI ;)"Ō926r?}lV =b[j4AzKkQ?T[%$KQ-l_@l/ &;차Dr?P_dE1~z^I~breufP/պ# E+S\G-R4 SSV俑; *`G*5'dL ~ 5Fhb` ꁜ4[b$~GNAX$~ }[W}_z×6m&~O%j/r&|_Sy<-*Lϛ,JQzͤ𫷣|V|GVW~z  HE YnH4r7P?99ߡ|O-5 %4 dzO/4L_PsT>LQD( J8F+)jCb Mu2Xc8$t}&@Qr-֤U_o6q7P1ˤ+rc6I \ (*v24Uc(A ̣93]z;0'=*,e56Va,qh*P@wȬG/Oj|FIm #Pz;Jwʎ}< z Tt~`ȱGP%;? 5((u# vՊI#9,?Gb4K]Qgԟ]E[ phʯG+`Ęp?@>!}" ҽr=CD5 62ZY? iA T(E UJu;"}պ#LcӗVWO&CIԙu8*烞QaQ^*z(L|Jӏ^fp104~CUx*rV*N9π׳Pūsp_L3Z"}&rO|l~kC/Wj><SxMbSg(]J(Z#x\$OC68-f:{Sҳ蚨o4:)Wb"uiuh~d%BAM sWH.gv%4v+=¿ SGϋjWHWu>[B{[uɶs;laziW߭\zC|\fte&ߕ+Bk/t  CM /@S>Tm G`v`?G(,zb" eAAi7QR<"iX:I܋(aV;4R]}^1vԵ7=p|[Jοeµ{)e#ief0KJq"*F#(GjJFhX#шݍk5ERP΋ ^pCeoe:{6۬5͝sƙ8X K6V[=}V+hͧJlZZ5W;TeV-@HID<͙[)֐l^bXeNN"K]@b?.HH gzXaْA}MOeXHNrڟW;htgttOyu3=*פؿCFGsh9JͽZ-k]L-~hii.49Qr5I,Vݓ^jf_},Q6?5NV ޞˍYٜN%ezqƨ>Z Nt1 a %= yhޙ HJZ? hvrk@mY`^insF\*|Lz!/?)(0 MS4(ȗh{-'ho7cCҞ?6'|ubգ@!bÙf{tz1UA?=@ t%䕉iu[ NiD GT@:p<(cXUm2ϱ7zOM^FϴYUfwGs#t:/~Os]Fݑ((^?L$Sʽ WzT>m'_d:5Lh;H7WgzgZZb3{2d5Jj9c+\vqzDbbƶg "l@צpQBbS Q>+d p%}L!cdwHopx(Tpxp#:dvQ qdAQFdLKmPR pU?l zg-jPbGaR&^q>u8p&Ӯф `MGSܵaoWܛZaâٟݰV5Rs2NX qGB OKg BW)Sg\ӡl]z<߲o-_- AKMqӭ!æSigy۰]K;ST'kPqee7cZT{~*7b\H?jٵl3P оwT2jY;)l DueytOTjöUHXgɬ,WϢ^u![]vF| QGh`(# R'5XDQqM6gc'bu:'H( ?yյ6~.e[n *UyZst9R!GMM$xz$]{L<}4JZ~MVՕhy >@u +]2FqO8jѥWCQqrw.䄫ޥ\_y\On)IKGRHŁqI. d+u@ϴ kŤ}9Tv6*xge7?ì}S-AU OMlJ pժݧYwhi6\fAZc,rjFTMj8kO51TqW_n`7%KWsd0:`OXs$4?:SI1W-Pr}² 9.&P^f 8(WI``@5a}ziV pPԽ+:d\j"=aj)W$q{͜p)V|7hj$L֡9\ځn[ k{lG.m m~TEbȭm` wnyP&:PLJY_pNWzVS׃]7Ed%i癬| EWM7r HB6`UGZ 9N2l2ɅHY(ŗiwݓ[`cZR;Yz=TrvH9c. ֲG6*p΅'[:/ҪXCYхMt-']n,{@ cObIN.xN F9뛝NK[Xr=Wm ݏƦY+?sJgXuP%ȗV^[ W;W xvi/XS3ȼ2ԩZ f2/y?8M@Q*˄CXk?MzTy?ZYu׳)]͕1-a7j~ .d  'VztXK2k̹d?zzK.>,BZ`q'kHqy5j>a\C#H;#p7l4} IR7ފ0$=V#_.vs{g>h!Ab/p7=zmi%͟3)^Oj<_UNY63dsIr8EjU* 33|v ;OB@,,\cwd}6k.ukF9'26D]exGJK.׽}S$@ t";2ɩ*41_x7QbjX9Q;#{9eI -奐br B<9dpzIVQ:l+si #=T+R(MDC$ a̱ ONgj19gqXk}FdcG,&..^ɷwwc>E_]3U|t{Jf窂u_.\*W=}lNo+^Ṿ vP>~sTjWz~_ogS}-DTd -TAaYf3,PATcm ռ4g}mE$BwŪ8>9JW⁩O/9PJCXA{,@c,tEJTj98Q& HPl~K%ƞ1ѻ -eD zxNXuz.9}Mc&:Z5ә8% յսmomCB:l8~ܦEjTYHYvnV^IN]]ŽCXkg#s cSB$Ý=$k}cG&/z}_v6<7IVGGg*l\RXST)šE%Yu~Q~>XЅ`9Wk*@_ՊpM]0*%a3X팁KM|{FԔ 췾d7[nlͬD@m8e cż#gHdd@~.jllɛeRcxE(( Km¼GXA7S@[l.%գnMDs]n_Q 5i?zGTG3T@e i,r O2<l+/,%m ۚXn|E]lí[m<|#z+5 7&\5S-{AE^tK M^rq]FmC%2vJ)W-}OM"`9l+=%"T'8zH3QҐѩYP~VزNi 7ۛ ?w1xc`d```d?oAePBYt?;"@.Hc xc`d`` &]aA_x}SJAS<` b)6 >@D"X\o!ι{,_oggg #JVYp>uC4&*<=$g9W@.0q- ;:pt"HUe5 Vg([Ax9!޴EMߗ4N&ӞwjtԞeσLp>w>Gpfz`|^aż>)o oMg+RmRq,RJ1XTN7t{IE\F8U mb:fN&j9Yxc``ЂM /^0Kؘژ0=avcca>bĒIJk ."/ I888qqpnǥ5w)^-8 ||||[5? JPKLpPa) "Z"WDmDWc3K O~/cLuNN+9K8;99/p>"k676-nܷ0h8)iʋK+s9@.xڭNAwh /"TD#J$rqr|!'O3XFާ0wY 1fg;73;3xE0C q=qX4GA$x ZB8ڃ Dw!IaSX w.0?oN؍gڍ@\A`sb k`sݡ},0Ya DȵȵMyFMvYdS20~>/qJG i<#c0C~G9ee Kvв[ڷ{&V(Ө1j1MZqr7,gKܥX0QY{ MYжz=a:[jEݢ BZZ=ns`+ȍxmUSgFB]9I$uw-J;mPwwwwwwwwlޕ]<3)e׿7R^ VV_@$zГ^З~g`0m[czf`(3233 23s2s32  eD*954XXeXX14i++ kk [[ ۲3Qfvd ;1qgg& nLdOboa_c@`PpHhXxNDNdNarsgrgsrsrs rsWrWs rs7r7s rswrwsrOO // oo __ ?? f,˺eݳYϬW;MelP68s䘉GE{RαM 7nܺp;ڛZ[ݛƵ? ѵֵykx~yj?\3V+wE5=QMjzTӣ(vN؉k/셽d/Kd/Kdbbbbbbbbbbjjjjjjjjjj/r{^n/+v ;NaS)ԼffffffffnnnnnnnnnnaaaaaaaChQN-ܩ?C?C?C?C?݇C}>t݇C}C?C?C?C?vNjHMp[qn???????>>=<<<<<:::::::U>::::::::=;;;;;;;;;;;;}VhSoTPhugo-0.92.2/examples/blog/static/fonts/glyphicons-halflings-regular.woff2000066400000000000000000000431541420147000300264550ustar00rootroot00000000000000wOF2Fl\F M?FFTM `r $e6$t 0 "Q?webfe5옏@? t,3+2q FYO&>bm5ZH$Y{H jd Չ %٧y"+@]e{vNc)n?~?萤h_&iѝ?>^K v-cۍ12Ky,'n(3EwiB& Tlh0M҆dYrﲬnti]yurVXsjgMnәHW r2>iT`V7R(+o6'cB4ι㿚T ]a[Qd<3wq8,rTI80>E?*E痦#7'S ocʷ_7&#*+)+4aA6cy٣f(bF$;{ YA1vP-tG"Cf- WԙuKְK#*K< (Z`٫ [%YT{%Ɋ$s{oջvt"p4`ߩϤ}o `'ne> G5sz_N PKӦvmU ɾ{z"3`l W#Ԑ^@+,ckoAOpnuzzJ)Υ1}O=xR`J`qUs/+kv1xljlEl\nDƶVjg{Zdz7 5!xm5o[u&1ڂHBkAqrR (\gh7Ҋy=HZUPh$8RgzgͭN:1u$܅>R]"f7 K^'3+E/^YU5]NB.ʋ8+͏8,|{M|Aua|a˅՝% lKGP,Nukc8mX@d̘?Y&{?P(G]Or-\LF9,&y8r3ܟ?p>~sDz1?\U5q=tzԒ&Znj%mM"}tkDwh-=mB76&:һqt" 1:Еu;"K_/Jdc0l0'^B8VCzg[ ;d Ybȃuu;@*}y| .'C>\g=9VŐ[o|g^ >d 9 *E|A*M[[*mOQz?Pn?R)YoT&[U*5S MB [ oYDh{,}1f?NN ]O/^;\J BEsJrĚ'g/B%o Cn7:|yKt&$s|wP\i]$Z@+ Հ90x]r%+RUEm+ܰ;wu9/I77զQlu\yWN)8ܰvY*umm( fEG8 j#IRz #q߷ )Y$ Лc_%m-{!0-` ;公hyV]Hv! ta\K[1{"j 6@3T0%Θ"ԙZIGS.ΣpӬS1eٓ؛ Yv8d\BlSR)ӆ {Iӆ%>0Ўڦ\'cg2%4QD 0͒3B"MՎ&ۊhIڧRgME I(5UD] }b8$8>X h"l΀j.%ۀHH- Iݸ#1C4Y7YݖV o>P]6O47f ~AJdYF€.oy) 8l 22e1H[t@!ȅ 2\@5ٓ%Zkޒa@.`n3OFR(󅥶ZkLkF HWjY I5*6eSbk.5F,.N0ԙ|V||~N( 4],Jp|~xeA5/ڻSvy?'_v|rXHQēB@= XB94TBBcHP+_YH#$`FB;+BPR4̼ t:t"ZEJ^!XǓq4_dTW(5܀IUŇAz@U6n.WGXHRK&'swMjʎ<3)`#F@  F Ԣvob$x +u&}|X&[٪8F-E&/>/G.az^/})'x$O=<zoA9M؝&~3r3g'8ң\-MDzk5A G9|1-! 87[,mRu|57 =X,aJ^tN4\fЄ]AzH^7F&k"LU>}>rBX(ۂT% JdhKPKTFaA3HHC[r;ad54 lLkjG{8h~ fR@9wB0 zS'a7@@Nƹlbj3hNXF/es'DsQjw}Jz^:V.:ڋ{ͼ(ȲBɦx<Db#"S{PHuN/{r6;wUsPО p8+6g_2lΡ6H džH: dBtGNmx@j |{s9=wR/oDJs5z>;'xEq^r^=G?9AA_K%Dɮ:uikjkIeG՝#*)jm|t}`JZ؈H=4{g߁)qXMA,H71V"o,Y#hݨS_;a_ԗZ^cn4HE?} ȝ٤=}BWvުUehGF;@2S@f n2#fY:]JyH]-G׌wgv'|0e _7Ґn+fٸY<( ?y%wm+j&&!c^u'b&hm6¤*2 ?AIƲ5FWؙ[ƜBUzIE!m:xheǮnz|]% mrUFگ1 };!n F&gP;&$$F).tBQ3(C=Xes;iي@~NΡE SRh\BeobTnΒju g@'qQ딎nx.u6bVU& ];!C_  5*zɺmRQuqPZ0}mn^nOrT:U'h0nZp^R|DF_b\@mDE8{oGM᠜q}Sd C,iܚE/Ë[d8],MCI_u,]Vc"pg@`"y),;B^el2'.(Ęy>-|hw;jՍiԽ_o|!@)ɢ=̌SPz*!z})|ƧT}jEtCZný*՞4ۆ׽[ 9Юݓz`Wmeo|j8j59@.EV/ZW@|f_\"${v/;a:Sei3TG*]ơ/h2C32$1}DNXt?Fϝ~n,Pj9.>ף{ 9EN-v|3hCиE XT;P$=J-gݕigz~q(A<:h193N̽Q}CLWߧ׎~ b"|4u}cy62[ \d,ҎճbkD%0Tx{=;Է(i LS13Nh/6?'E^~P{sZZKĞB{Dt&z)Uoa5Q3ȗr~ F]$<tm(} MB@[GxFh8#},#u Laz(Qh4%xm`Uչ.Ev1a4_'/[d{FxI59 D<&8VEFg 芘#I䟍2S_]QqAn_Q>bޘ4g-0&E#ci8 vR/4rP7KsOWN3ՏvE\bqQ5ZڽVy5]h/ i)-/kNю#e)"P {KSQx>a&, _g-mc<n]Ч-52cz 7d PzVOPvfR Rఓ9Z -dC`,at=k?v4#P Bإ/[s.-bH)ɺz '}׶w!rXZ .:Vn;->: 6rUcs4kVW{#5ߑ0B`ܝ0u".QdB0Cr]#Q9lqN^ֳh~NU\ 16 ~SnTl\THҲڛ-~G~)$oQ7-C}q%/avO|[q4~Bc-$N76w{V餃.&(o*n NeRi4!3R"4nbm-y[X."!QKE\N4gՠםaNp >k)90BZBs yrer)vDtrv\v[>rJm a̼~uՏ>rMZcB<`)\yt|ۍr'<>[Îh7Z8caI! p⢟̮,G k5@`iw nО8pv *'O A[.rhT pR?+;\*HsLqUf:ql-ć *6!h+ˬ{h- jgkMMP#:}{/VŶC]옙&[W$ګ^#4fWa\ 5躺M[6)T3~ :. Z`si(RQ|/` il^L#f-;-C;_*{@EMCooÂ_7TrqzF%ׯ|UEƫUs^ݜv{fQ<ĐVPTfͦ?mpP*&QG{cJEPe2)xP0AMɪZHj"׻"AC+zqmVzᖞU%C:@1W [y)J@ob% jA>)Nǀi$At`>?f0gH36p6D|M 4N 4JJڃ jƇ\ p38Я6pV?:$sDNƹ2n,HO\[ոK-)W~im?T:޺UeY-#dJe)Z5?$\dW<,Ɇ;ط5SոTT̄f(PYv=Q ~DX*8辩s- ˨΀55 XRl QC l|5{ӦT\t꼕+en۸Psl3UO[ZS3*,:ÛZLS'̵**@ı~xgno2- WV;pZ9?~$6҄xJ>\QA_Cihbl] 64*A˯ɰqX7YX.-ոaɇVhiKgqNRĆN(r']%٘@3̀jZJ.;nm,S0xͻOF33ҧ<$'GE+}'1f3y5/&Z\RB7dm]8\3߂Ȫ@oT3eu^W@e7l!B,s1$Z&?dC (YЦSm>J"&pt܈P㇄BF4G5 t^Ć$j-a㠍g^ʐCAsT=kTS,|r9IBϘЬ'vGA@thQNj&T=xt;2]P|T- LÞe1ݽWZŚ*MrH5?=o"9K5='k-*AE| qҔ_?\7%|M6f++S*}W_]3fmܮ˳m w!.R#鬪;qq71$•ݙկ_iK&JάMemV5P0> Q5WHIh&4ҍIlE7}sm[cȾ|d^ %Uv1D>.T7*=tZ_㟾1Х:=0pZ6ҋNt(uƝ; B]$kڌ.{F*/UZN砦|oqKG;^侞9NexK \wh~ZpHb䉸 [k8k.bX.QXpxYa^"#Bwnbum5F~>8bN:p4 [gv^ BFUz)?60F8/2C8>N8G%l%5FH{46h4%# 7x oN t\'Ȩ E0#jNãVӹd?WlcW žֵu-}22EN}#䵵2H^a3rqs-S3&f퇣fwl.=W8,cHjcTWנs90ZDMC2ZMdjt"8:g{.Ʊ1Fb618"yԦ> W9 V `jT򔔑r,ni d qN .g+ S Q KaB?_QE rjh>Eӛ;C׭7^q `Ue#-;oJċԝ>) ;Jg׭9R;OgiI7}8Kہqjeؓ+ٗ'nϷk3eFρ0V#pMAzb^PVu~1uғwn ^.II_vdW[Q,+Lbćq 9V} ΏVw4qU3&jıHYb ttT7ρarBwP9?)uT/aA19kM \Psq+=[5͔?9W+^o^E8s)f 2aQxi& NE>"^Naa;f9]NE& t^CLz'e8ZRs&67_ãcyJ1 @TZ?SD2 |POӌ\dR7zH9iQ#zrc.4GR4qx<2~Xhnੳ2auBNC+kX0 aj5n>މe3vާ<>_ uH:XR%~9!4oѼ38? 1d#A&{A!i6 /Xa㇤=W;|) g~ ?*悽 }ڧKt>5|E.A Q6 (6 6є7<9_C f1Ўi8, V4$uti,.`v6r P gFBɎ t C3; ,oÂx| /KMp1S_X.fV#U>Ȓ#B] AIVoІϵGTV1nr+OXS% ³fOZ[_9P߰ {Gln%#hdwH= ye/W>,IP,*MV~ºK&eċM콣=)qFS"GTF*LX,h[wweWQEx ?{^چExhiׂJH|^͓e*^Я.uxEb#;ԝ<]z]\wNhochqE=4Q17W̓lÕ6᧿HE_̣qy YR۫9~l4sVy`Uߛ,#_u+DeM~hq벇#Yz$; 5ͯ9$ z> *jO$$O/xRtf-}*oɦ|3M;xިUl/.~XǎY4x3&x";$KI5dڭ ~w[M9O%4Q}S^t@w[Y;-s;bwH-* imI-1e/~TNN.p)H$W~ƦO (9, ]gM6r+#%/swA$q4O> d9}+$s?0a,>yڈs<=,c_*\D}2MT8/4g'ڦ8'}"C*\9#Y>z$7c[s|"$} ymzQx 5%o$jkp)x-:И|?ofgFr2SZq}q o,wyOgCF1l'L5T33yM92"s5uD6-JUbs O)wR -2/5frϛf@=BFCB&'F}@&yubC?'S49+ÓCIî+f/RU C Fu:C*} T:}{ݽⲷue[!>? ڸ"M 8gz0\HkZ:h~@+#N fjyio!B R'5>`[!T`mC Iѝ}n >W!M}Uav43)!kcȂm? dwv!ה;Xϡۨ}8vt"Ӽ# kvXJ[l[ZݙMÀXC3l[ TaVjʻѬ"œ t:(<cZveQTqHi{銀Q埓'ÖiP■mKAIBF =Tᅽ(&TS?/؁A:ַОV(@wFa^]o]*99Ri_2vM`Pf{QYH#V7v7Ұq>@~uɘ׆Ax/xB3Ġtyb0nG` EDٍA: PwI7nW2ED}.(h"U]9Ih_V@GZ0C pb :L 3tN*N 2!3 Cayn.ɋW`̳}QBCi 8*{57O#aTBUoi0 _^ ChrU}~rL 1z>..=%GG o EuPPsؘ޸8Pu&;*|i&Pbțh;[|y*cVhҼ(~_AqU2GIQ3`^v=@K'ЇZ#4sJ=:sY sڥbyj S_E܃"@~>86#y[cSŬ#SJGZyvvSя扝pwaT/, 9'Jkv%%.~o[ 衧RBjSȀ*$'腁pçSu +9\_f+8u\,tpэkخJ0h(]NQvW7 86:ݣ WcY_i>"R(e]6RA%U6&F]7@̳k3X h?KQ2Bk[?..KKAb65ke+]FeWHU0Oק5 e3Hco>l]02cH9{Z {sO!A,7?ŷ3w俎A Fj8B&8U$G$Y5FL5n1> q2.6e +@/kb{(7i={l͍݂濦81g(%h/EfMҍt5̼vgo ~ਜ਼WKi父UأݖwRSEFT% `=|*=1*SX^w)lfQH(YSSˌK1W]f7ך^&p@T'.%3 5zaTf6A5LX̡|L-ηTg{A)F."hjA;.~o% G#}&]׾c`ChH9xnNY lc\+v\EƧ1D9KX)2b.NWQש$/|6tð32ԛ72иyu0e)Nuh'd~xY ># b"k3 :9v$ПC:)H> զz;ed\jmfOa%9cKxۥ!k%HDn{Y"{n_} )9= _/Z(>lYVgQ#߭:Qbw$zwٮ#U?|Ghz{o$wϜ)|Vh? ZV7%Go/׆E"KӲlp76-z !l4n>$\zV?szqejQ]m^=^ !lHB4sL i9}2^K5OB)O v^~݀xrm\K&G^5CL}&FB]Kn3|sGjykObsܽaW?R6Jfh2 lBS\=jV*Y^˺^E)*\ rr(a@6nԌ?}dLgIvqNcaƮkmLcA!hdVwc=憖s_:җsLg>1*4-%&0Ub)Eܬ*b51 ++;<`!qfM*,[/GK+{,>CLR%%c~'EGAG=h䟔8:IDN)W̻AF)ucw'qhXèL@a~6Pc2L"A2bU & 9A#QLO:E9kfKFb93tL$cˬpLz5dp۰>$`.~X=?NͰ/LPNo0p b8AR4r Jj} Ӳ04ˋquۏAFP 'HfXDIVTM7Lv\(N,/ʪnڮi^m?~ QU Ӳ04ˋquۏb$tV&gϖr> 2)) { throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3') } }(jQuery); /* ======================================================================== * Bootstrap: transition.js v3.3.6 * http://getbootstrap.com/javascript/#transitions * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) // ============================================================ function transitionEnd() { var el = document.createElement('bootstrap') var transEndEventNames = { WebkitTransition : 'webkitTransitionEnd', MozTransition : 'transitionend', OTransition : 'oTransitionEnd otransitionend', transition : 'transitionend' } for (var name in transEndEventNames) { if (el.style[name] !== undefined) { return { end: transEndEventNames[name] } } } return false // explicit for ie8 ( ._.) } // http://blog.alexmaccaw.com/css-transitions $.fn.emulateTransitionEnd = function (duration) { var called = false var $el = this $(this).one('bsTransitionEnd', function () { called = true }) var callback = function () { if (!called) $($el).trigger($.support.transition.end) } setTimeout(callback, duration) return this } $(function () { $.support.transition = transitionEnd() if (!$.support.transition) return $.event.special.bsTransitionEnd = { bindType: $.support.transition.end, delegateType: $.support.transition.end, handle: function (e) { if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) } } }) }(jQuery); /* ======================================================================== * Bootstrap: alert.js v3.3.6 * http://getbootstrap.com/javascript/#alerts * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // ALERT CLASS DEFINITION // ====================== var dismiss = '[data-dismiss="alert"]' var Alert = function (el) { $(el).on('click', dismiss, this.close) } Alert.VERSION = '3.3.6' Alert.TRANSITION_DURATION = 150 Alert.prototype.close = function (e) { var $this = $(this) var selector = $this.attr('data-target') if (!selector) { selector = $this.attr('href') selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } var $parent = $(selector) if (e) e.preventDefault() if (!$parent.length) { $parent = $this.closest('.alert') } $parent.trigger(e = $.Event('close.bs.alert')) if (e.isDefaultPrevented()) return $parent.removeClass('in') function removeElement() { // detach from parent, fire event then clean up data $parent.detach().trigger('closed.bs.alert').remove() } $.support.transition && $parent.hasClass('fade') ? $parent .one('bsTransitionEnd', removeElement) .emulateTransitionEnd(Alert.TRANSITION_DURATION) : removeElement() } // ALERT PLUGIN DEFINITION // ======================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.alert') if (!data) $this.data('bs.alert', (data = new Alert(this))) if (typeof option == 'string') data[option].call($this) }) } var old = $.fn.alert $.fn.alert = Plugin $.fn.alert.Constructor = Alert // ALERT NO CONFLICT // ================= $.fn.alert.noConflict = function () { $.fn.alert = old return this } // ALERT DATA-API // ============== $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) }(jQuery); /* ======================================================================== * Bootstrap: button.js v3.3.6 * http://getbootstrap.com/javascript/#buttons * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // BUTTON PUBLIC CLASS DEFINITION // ============================== var Button = function (element, options) { this.$element = $(element) this.options = $.extend({}, Button.DEFAULTS, options) this.isLoading = false } Button.VERSION = '3.3.6' Button.DEFAULTS = { loadingText: 'loading...' } Button.prototype.setState = function (state) { var d = 'disabled' var $el = this.$element var val = $el.is('input') ? 'val' : 'html' var data = $el.data() state += 'Text' if (data.resetText == null) $el.data('resetText', $el[val]()) // push to event loop to allow forms to submit setTimeout($.proxy(function () { $el[val](data[state] == null ? this.options[state] : data[state]) if (state == 'loadingText') { this.isLoading = true $el.addClass(d).attr(d, d) } else if (this.isLoading) { this.isLoading = false $el.removeClass(d).removeAttr(d) } }, this), 0) } Button.prototype.toggle = function () { var changed = true var $parent = this.$element.closest('[data-toggle="buttons"]') if ($parent.length) { var $input = this.$element.find('input') if ($input.prop('type') == 'radio') { if ($input.prop('checked')) changed = false $parent.find('.active').removeClass('active') this.$element.addClass('active') } else if ($input.prop('type') == 'checkbox') { if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false this.$element.toggleClass('active') } $input.prop('checked', this.$element.hasClass('active')) if (changed) $input.trigger('change') } else { this.$element.attr('aria-pressed', !this.$element.hasClass('active')) this.$element.toggleClass('active') } } // BUTTON PLUGIN DEFINITION // ======================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.button') var options = typeof option == 'object' && option if (!data) $this.data('bs.button', (data = new Button(this, options))) if (option == 'toggle') data.toggle() else if (option) data.setState(option) }) } var old = $.fn.button $.fn.button = Plugin $.fn.button.Constructor = Button // BUTTON NO CONFLICT // ================== $.fn.button.noConflict = function () { $.fn.button = old return this } // BUTTON DATA-API // =============== $(document) .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { var $btn = $(e.target) if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') Plugin.call($btn, 'toggle') if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() }) .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) }) }(jQuery); /* ======================================================================== * Bootstrap: carousel.js v3.3.6 * http://getbootstrap.com/javascript/#carousel * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // CAROUSEL CLASS DEFINITION // ========================= var Carousel = function (element, options) { this.$element = $(element) this.$indicators = this.$element.find('.carousel-indicators') this.options = options this.paused = null this.sliding = null this.interval = null this.$active = null this.$items = null this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) } Carousel.VERSION = '3.3.6' Carousel.TRANSITION_DURATION = 600 Carousel.DEFAULTS = { interval: 5000, pause: 'hover', wrap: true, keyboard: true } Carousel.prototype.keydown = function (e) { if (/input|textarea/i.test(e.target.tagName)) return switch (e.which) { case 37: this.prev(); break case 39: this.next(); break default: return } e.preventDefault() } Carousel.prototype.cycle = function (e) { e || (this.paused = false) this.interval && clearInterval(this.interval) this.options.interval && !this.paused && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) return this } Carousel.prototype.getItemIndex = function (item) { this.$items = item.parent().children('.item') return this.$items.index(item || this.$active) } Carousel.prototype.getItemForDirection = function (direction, active) { var activeIndex = this.getItemIndex(active) var willWrap = (direction == 'prev' && activeIndex === 0) || (direction == 'next' && activeIndex == (this.$items.length - 1)) if (willWrap && !this.options.wrap) return active var delta = direction == 'prev' ? -1 : 1 var itemIndex = (activeIndex + delta) % this.$items.length return this.$items.eq(itemIndex) } Carousel.prototype.to = function (pos) { var that = this var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) if (pos > (this.$items.length - 1) || pos < 0) return if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" if (activeIndex == pos) return this.pause().cycle() return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) } Carousel.prototype.pause = function (e) { e || (this.paused = true) if (this.$element.find('.next, .prev').length && $.support.transition) { this.$element.trigger($.support.transition.end) this.cycle(true) } this.interval = clearInterval(this.interval) return this } Carousel.prototype.next = function () { if (this.sliding) return return this.slide('next') } Carousel.prototype.prev = function () { if (this.sliding) return return this.slide('prev') } Carousel.prototype.slide = function (type, next) { var $active = this.$element.find('.item.active') var $next = next || this.getItemForDirection(type, $active) var isCycling = this.interval var direction = type == 'next' ? 'left' : 'right' var that = this if ($next.hasClass('active')) return (this.sliding = false) var relatedTarget = $next[0] var slideEvent = $.Event('slide.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) this.$element.trigger(slideEvent) if (slideEvent.isDefaultPrevented()) return this.sliding = true isCycling && this.pause() if (this.$indicators.length) { this.$indicators.find('.active').removeClass('active') var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) $nextIndicator && $nextIndicator.addClass('active') } var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" if ($.support.transition && this.$element.hasClass('slide')) { $next.addClass(type) $next[0].offsetWidth // force reflow $active.addClass(direction) $next.addClass(direction) $active .one('bsTransitionEnd', function () { $next.removeClass([type, direction].join(' ')).addClass('active') $active.removeClass(['active', direction].join(' ')) that.sliding = false setTimeout(function () { that.$element.trigger(slidEvent) }, 0) }) .emulateTransitionEnd(Carousel.TRANSITION_DURATION) } else { $active.removeClass('active') $next.addClass('active') this.sliding = false this.$element.trigger(slidEvent) } isCycling && this.cycle() return this } // CAROUSEL PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.carousel') var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) var action = typeof option == 'string' ? option : options.slide if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) if (typeof option == 'number') data.to(option) else if (action) data[action]() else if (options.interval) data.pause().cycle() }) } var old = $.fn.carousel $.fn.carousel = Plugin $.fn.carousel.Constructor = Carousel // CAROUSEL NO CONFLICT // ==================== $.fn.carousel.noConflict = function () { $.fn.carousel = old return this } // CAROUSEL DATA-API // ================= var clickHandler = function (e) { var href var $this = $(this) var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 if (!$target.hasClass('carousel')) return var options = $.extend({}, $target.data(), $this.data()) var slideIndex = $this.attr('data-slide-to') if (slideIndex) options.interval = false Plugin.call($target, options) if (slideIndex) { $target.data('bs.carousel').to(slideIndex) } e.preventDefault() } $(document) .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) $(window).on('load', function () { $('[data-ride="carousel"]').each(function () { var $carousel = $(this) Plugin.call($carousel, $carousel.data()) }) }) }(jQuery); /* ======================================================================== * Bootstrap: collapse.js v3.3.6 * http://getbootstrap.com/javascript/#collapse * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // COLLAPSE PUBLIC CLASS DEFINITION // ================================ var Collapse = function (element, options) { this.$element = $(element) this.options = $.extend({}, Collapse.DEFAULTS, options) this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + '[data-toggle="collapse"][data-target="#' + element.id + '"]') this.transitioning = null if (this.options.parent) { this.$parent = this.getParent() } else { this.addAriaAndCollapsedClass(this.$element, this.$trigger) } if (this.options.toggle) this.toggle() } Collapse.VERSION = '3.3.6' Collapse.TRANSITION_DURATION = 350 Collapse.DEFAULTS = { toggle: true } Collapse.prototype.dimension = function () { var hasWidth = this.$element.hasClass('width') return hasWidth ? 'width' : 'height' } Collapse.prototype.show = function () { if (this.transitioning || this.$element.hasClass('in')) return var activesData var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') if (actives && actives.length) { activesData = actives.data('bs.collapse') if (activesData && activesData.transitioning) return } var startEvent = $.Event('show.bs.collapse') this.$element.trigger(startEvent) if (startEvent.isDefaultPrevented()) return if (actives && actives.length) { Plugin.call(actives, 'hide') activesData || actives.data('bs.collapse', null) } var dimension = this.dimension() this.$element .removeClass('collapse') .addClass('collapsing')[dimension](0) .attr('aria-expanded', true) this.$trigger .removeClass('collapsed') .attr('aria-expanded', true) this.transitioning = 1 var complete = function () { this.$element .removeClass('collapsing') .addClass('collapse in')[dimension]('') this.transitioning = 0 this.$element .trigger('shown.bs.collapse') } if (!$.support.transition) return complete.call(this) var scrollSize = $.camelCase(['scroll', dimension].join('-')) this.$element .one('bsTransitionEnd', $.proxy(complete, this)) .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) } Collapse.prototype.hide = function () { if (this.transitioning || !this.$element.hasClass('in')) return var startEvent = $.Event('hide.bs.collapse') this.$element.trigger(startEvent) if (startEvent.isDefaultPrevented()) return var dimension = this.dimension() this.$element[dimension](this.$element[dimension]())[0].offsetHeight this.$element .addClass('collapsing') .removeClass('collapse in') .attr('aria-expanded', false) this.$trigger .addClass('collapsed') .attr('aria-expanded', false) this.transitioning = 1 var complete = function () { this.transitioning = 0 this.$element .removeClass('collapsing') .addClass('collapse') .trigger('hidden.bs.collapse') } if (!$.support.transition) return complete.call(this) this.$element [dimension](0) .one('bsTransitionEnd', $.proxy(complete, this)) .emulateTransitionEnd(Collapse.TRANSITION_DURATION) } Collapse.prototype.toggle = function () { this[this.$element.hasClass('in') ? 'hide' : 'show']() } Collapse.prototype.getParent = function () { return $(this.options.parent) .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') .each($.proxy(function (i, element) { var $element = $(element) this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) }, this)) .end() } Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { var isOpen = $element.hasClass('in') $element.attr('aria-expanded', isOpen) $trigger .toggleClass('collapsed', !isOpen) .attr('aria-expanded', isOpen) } function getTargetFromTrigger($trigger) { var href var target = $trigger.attr('data-target') || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 return $(target) } // COLLAPSE PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.collapse') var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.collapse $.fn.collapse = Plugin $.fn.collapse.Constructor = Collapse // COLLAPSE NO CONFLICT // ==================== $.fn.collapse.noConflict = function () { $.fn.collapse = old return this } // COLLAPSE DATA-API // ================= $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { var $this = $(this) if (!$this.attr('data-target')) e.preventDefault() var $target = getTargetFromTrigger($this) var data = $target.data('bs.collapse') var option = data ? 'toggle' : $this.data() Plugin.call($target, option) }) }(jQuery); /* ======================================================================== * Bootstrap: dropdown.js v3.3.6 * http://getbootstrap.com/javascript/#dropdowns * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // DROPDOWN CLASS DEFINITION // ========================= var backdrop = '.dropdown-backdrop' var toggle = '[data-toggle="dropdown"]' var Dropdown = function (element) { $(element).on('click.bs.dropdown', this.toggle) } Dropdown.VERSION = '3.3.6' function getParent($this) { var selector = $this.attr('data-target') if (!selector) { selector = $this.attr('href') selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } var $parent = selector && $(selector) return $parent && $parent.length ? $parent : $this.parent() } function clearMenus(e) { if (e && e.which === 3) return $(backdrop).remove() $(toggle).each(function () { var $this = $(this) var $parent = getParent($this) var relatedTarget = { relatedTarget: this } if (!$parent.hasClass('open')) return if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) if (e.isDefaultPrevented()) return $this.attr('aria-expanded', 'false') $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) }) } Dropdown.prototype.toggle = function (e) { var $this = $(this) if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') clearMenus() if (!isActive) { if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { // if mobile we use a backdrop because click events don't delegate $(document.createElement('div')) .addClass('dropdown-backdrop') .insertAfter($(this)) .on('click', clearMenus) } var relatedTarget = { relatedTarget: this } $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) if (e.isDefaultPrevented()) return $this .trigger('focus') .attr('aria-expanded', 'true') $parent .toggleClass('open') .trigger($.Event('shown.bs.dropdown', relatedTarget)) } return false } Dropdown.prototype.keydown = function (e) { if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return var $this = $(this) e.preventDefault() e.stopPropagation() if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') if (!isActive && e.which != 27 || isActive && e.which == 27) { if (e.which == 27) $parent.find(toggle).trigger('focus') return $this.trigger('click') } var desc = ' li:not(.disabled):visible a' var $items = $parent.find('.dropdown-menu' + desc) if (!$items.length) return var index = $items.index(e.target) if (e.which == 38 && index > 0) index-- // up if (e.which == 40 && index < $items.length - 1) index++ // down if (!~index) index = 0 $items.eq(index).trigger('focus') } // DROPDOWN PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.dropdown') if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) if (typeof option == 'string') data[option].call($this) }) } var old = $.fn.dropdown $.fn.dropdown = Plugin $.fn.dropdown.Constructor = Dropdown // DROPDOWN NO CONFLICT // ==================== $.fn.dropdown.noConflict = function () { $.fn.dropdown = old return this } // APPLY TO STANDARD DROPDOWN ELEMENTS // =================================== $(document) .on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) }(jQuery); /* ======================================================================== * Bootstrap: modal.js v3.3.6 * http://getbootstrap.com/javascript/#modals * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // MODAL CLASS DEFINITION // ====================== var Modal = function (element, options) { this.options = options this.$body = $(document.body) this.$element = $(element) this.$dialog = this.$element.find('.modal-dialog') this.$backdrop = null this.isShown = null this.originalBodyPad = null this.scrollbarWidth = 0 this.ignoreBackdropClick = false if (this.options.remote) { this.$element .find('.modal-content') .load(this.options.remote, $.proxy(function () { this.$element.trigger('loaded.bs.modal') }, this)) } } Modal.VERSION = '3.3.6' Modal.TRANSITION_DURATION = 300 Modal.BACKDROP_TRANSITION_DURATION = 150 Modal.DEFAULTS = { backdrop: true, keyboard: true, show: true } Modal.prototype.toggle = function (_relatedTarget) { return this.isShown ? this.hide() : this.show(_relatedTarget) } Modal.prototype.show = function (_relatedTarget) { var that = this var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) this.$element.trigger(e) if (this.isShown || e.isDefaultPrevented()) return this.isShown = true this.checkScrollbar() this.setScrollbar() this.$body.addClass('modal-open') this.escape() this.resize() this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) this.$dialog.on('mousedown.dismiss.bs.modal', function () { that.$element.one('mouseup.dismiss.bs.modal', function (e) { if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true }) }) this.backdrop(function () { var transition = $.support.transition && that.$element.hasClass('fade') if (!that.$element.parent().length) { that.$element.appendTo(that.$body) // don't move modals dom position } that.$element .show() .scrollTop(0) that.adjustDialog() if (transition) { that.$element[0].offsetWidth // force reflow } that.$element.addClass('in') that.enforceFocus() var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) transition ? that.$dialog // wait for modal to slide in .one('bsTransitionEnd', function () { that.$element.trigger('focus').trigger(e) }) .emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger('focus').trigger(e) }) } Modal.prototype.hide = function (e) { if (e) e.preventDefault() e = $.Event('hide.bs.modal') this.$element.trigger(e) if (!this.isShown || e.isDefaultPrevented()) return this.isShown = false this.escape() this.resize() $(document).off('focusin.bs.modal') this.$element .removeClass('in') .off('click.dismiss.bs.modal') .off('mouseup.dismiss.bs.modal') this.$dialog.off('mousedown.dismiss.bs.modal') $.support.transition && this.$element.hasClass('fade') ? this.$element .one('bsTransitionEnd', $.proxy(this.hideModal, this)) .emulateTransitionEnd(Modal.TRANSITION_DURATION) : this.hideModal() } Modal.prototype.enforceFocus = function () { $(document) .off('focusin.bs.modal') // guard against infinite focus loop .on('focusin.bs.modal', $.proxy(function (e) { if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { this.$element.trigger('focus') } }, this)) } Modal.prototype.escape = function () { if (this.isShown && this.options.keyboard) { this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { e.which == 27 && this.hide() }, this)) } else if (!this.isShown) { this.$element.off('keydown.dismiss.bs.modal') } } Modal.prototype.resize = function () { if (this.isShown) { $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) } else { $(window).off('resize.bs.modal') } } Modal.prototype.hideModal = function () { var that = this this.$element.hide() this.backdrop(function () { that.$body.removeClass('modal-open') that.resetAdjustments() that.resetScrollbar() that.$element.trigger('hidden.bs.modal') }) } Modal.prototype.removeBackdrop = function () { this.$backdrop && this.$backdrop.remove() this.$backdrop = null } Modal.prototype.backdrop = function (callback) { var that = this var animate = this.$element.hasClass('fade') ? 'fade' : '' if (this.isShown && this.options.backdrop) { var doAnimate = $.support.transition && animate this.$backdrop = $(document.createElement('div')) .addClass('modal-backdrop ' + animate) .appendTo(this.$body) this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { if (this.ignoreBackdropClick) { this.ignoreBackdropClick = false return } if (e.target !== e.currentTarget) return this.options.backdrop == 'static' ? this.$element[0].focus() : this.hide() }, this)) if (doAnimate) this.$backdrop[0].offsetWidth // force reflow this.$backdrop.addClass('in') if (!callback) return doAnimate ? this.$backdrop .one('bsTransitionEnd', callback) .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callback() } else if (!this.isShown && this.$backdrop) { this.$backdrop.removeClass('in') var callbackRemove = function () { that.removeBackdrop() callback && callback() } $.support.transition && this.$element.hasClass('fade') ? this.$backdrop .one('bsTransitionEnd', callbackRemove) .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callbackRemove() } else if (callback) { callback() } } // these following methods are used to handle overflowing modals Modal.prototype.handleUpdate = function () { this.adjustDialog() } Modal.prototype.adjustDialog = function () { var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight this.$element.css({ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' }) } Modal.prototype.resetAdjustments = function () { this.$element.css({ paddingLeft: '', paddingRight: '' }) } Modal.prototype.checkScrollbar = function () { var fullWindowWidth = window.innerWidth if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 var documentElementRect = document.documentElement.getBoundingClientRect() fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) } this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth this.scrollbarWidth = this.measureScrollbar() } Modal.prototype.setScrollbar = function () { var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) this.originalBodyPad = document.body.style.paddingRight || '' if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) } Modal.prototype.resetScrollbar = function () { this.$body.css('padding-right', this.originalBodyPad) } Modal.prototype.measureScrollbar = function () { // thx walsh var scrollDiv = document.createElement('div') scrollDiv.className = 'modal-scrollbar-measure' this.$body.append(scrollDiv) var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth this.$body[0].removeChild(scrollDiv) return scrollbarWidth } // MODAL PLUGIN DEFINITION // ======================= function Plugin(option, _relatedTarget) { return this.each(function () { var $this = $(this) var data = $this.data('bs.modal') var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data) $this.data('bs.modal', (data = new Modal(this, options))) if (typeof option == 'string') data[option](_relatedTarget) else if (options.show) data.show(_relatedTarget) }) } var old = $.fn.modal $.fn.modal = Plugin $.fn.modal.Constructor = Modal // MODAL NO CONFLICT // ================= $.fn.modal.noConflict = function () { $.fn.modal = old return this } // MODAL DATA-API // ============== $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { var $this = $(this) var href = $this.attr('href') var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) if ($this.is('a')) e.preventDefault() $target.one('show.bs.modal', function (showEvent) { if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown $target.one('hidden.bs.modal', function () { $this.is(':visible') && $this.trigger('focus') }) }) Plugin.call($target, option, this) }) }(jQuery); /* ======================================================================== * Bootstrap: tooltip.js v3.3.6 * http://getbootstrap.com/javascript/#tooltip * Inspired by the original jQuery.tipsy by Jason Frame * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // TOOLTIP PUBLIC CLASS DEFINITION // =============================== var Tooltip = function (element, options) { this.type = null this.options = null this.enabled = null this.timeout = null this.hoverState = null this.$element = null this.inState = null this.init('tooltip', element, options) } Tooltip.VERSION = '3.3.6' Tooltip.TRANSITION_DURATION = 150 Tooltip.DEFAULTS = { animation: true, placement: 'top', selector: false, template: '', trigger: 'hover focus', title: '', delay: 0, html: false, container: false, viewport: { selector: 'body', padding: 0 } } Tooltip.prototype.init = function (type, element, options) { this.enabled = true this.type = type this.$element = $(element) this.options = this.getOptions(options) this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) this.inState = { click: false, hover: false, focus: false } if (this.$element[0] instanceof document.constructor && !this.options.selector) { throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') } var triggers = this.options.trigger.split(' ') for (var i = triggers.length; i--;) { var trigger = triggers[i] if (trigger == 'click') { this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) } else if (trigger != 'manual') { var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) } } this.options.selector ? (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : this.fixTitle() } Tooltip.prototype.getDefaults = function () { return Tooltip.DEFAULTS } Tooltip.prototype.getOptions = function (options) { options = $.extend({}, this.getDefaults(), this.$element.data(), options) if (options.delay && typeof options.delay == 'number') { options.delay = { show: options.delay, hide: options.delay } } return options } Tooltip.prototype.getDelegateOptions = function () { var options = {} var defaults = this.getDefaults() this._options && $.each(this._options, function (key, value) { if (defaults[key] != value) options[key] = value }) return options } Tooltip.prototype.enter = function (obj) { var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data('bs.' + this.type) if (!self) { self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) $(obj.currentTarget).data('bs.' + this.type, self) } if (obj instanceof $.Event) { self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true } if (self.tip().hasClass('in') || self.hoverState == 'in') { self.hoverState = 'in' return } clearTimeout(self.timeout) self.hoverState = 'in' if (!self.options.delay || !self.options.delay.show) return self.show() self.timeout = setTimeout(function () { if (self.hoverState == 'in') self.show() }, self.options.delay.show) } Tooltip.prototype.isInStateTrue = function () { for (var key in this.inState) { if (this.inState[key]) return true } return false } Tooltip.prototype.leave = function (obj) { var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data('bs.' + this.type) if (!self) { self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) $(obj.currentTarget).data('bs.' + this.type, self) } if (obj instanceof $.Event) { self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false } if (self.isInStateTrue()) return clearTimeout(self.timeout) self.hoverState = 'out' if (!self.options.delay || !self.options.delay.hide) return self.hide() self.timeout = setTimeout(function () { if (self.hoverState == 'out') self.hide() }, self.options.delay.hide) } Tooltip.prototype.show = function () { var e = $.Event('show.bs.' + this.type) if (this.hasContent() && this.enabled) { this.$element.trigger(e) var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) if (e.isDefaultPrevented() || !inDom) return var that = this var $tip = this.tip() var tipId = this.getUID(this.type) this.setContent() $tip.attr('id', tipId) this.$element.attr('aria-describedby', tipId) if (this.options.animation) $tip.addClass('fade') var placement = typeof this.options.placement == 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement var autoToken = /\s?auto?\s?/i var autoPlace = autoToken.test(placement) if (autoPlace) placement = placement.replace(autoToken, '') || 'top' $tip .detach() .css({ top: 0, left: 0, display: 'block' }) .addClass(placement) .data('bs.' + this.type, this) this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) this.$element.trigger('inserted.bs.' + this.type) var pos = this.getPosition() var actualWidth = $tip[0].offsetWidth var actualHeight = $tip[0].offsetHeight if (autoPlace) { var orgPlacement = placement var viewportDim = this.getPosition(this.$viewport) placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : placement $tip .removeClass(orgPlacement) .addClass(placement) } var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) this.applyPlacement(calculatedOffset, placement) var complete = function () { var prevHoverState = that.hoverState that.$element.trigger('shown.bs.' + that.type) that.hoverState = null if (prevHoverState == 'out') that.leave(that) } $.support.transition && this.$tip.hasClass('fade') ? $tip .one('bsTransitionEnd', complete) .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete() } } Tooltip.prototype.applyPlacement = function (offset, placement) { var $tip = this.tip() var width = $tip[0].offsetWidth var height = $tip[0].offsetHeight // manually read margins because getBoundingClientRect includes difference var marginTop = parseInt($tip.css('margin-top'), 10) var marginLeft = parseInt($tip.css('margin-left'), 10) // we must check for NaN for ie 8/9 if (isNaN(marginTop)) marginTop = 0 if (isNaN(marginLeft)) marginLeft = 0 offset.top += marginTop offset.left += marginLeft // $.fn.offset doesn't round pixel values // so we use setOffset directly with our own function B-0 $.offset.setOffset($tip[0], $.extend({ using: function (props) { $tip.css({ top: Math.round(props.top), left: Math.round(props.left) }) } }, offset), 0) $tip.addClass('in') // check to see if placing tip in new offset caused the tip to resize itself var actualWidth = $tip[0].offsetWidth var actualHeight = $tip[0].offsetHeight if (placement == 'top' && actualHeight != height) { offset.top = offset.top + height - actualHeight } var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) if (delta.left) offset.left += delta.left else offset.top += delta.top var isVertical = /top|bottom/.test(placement) var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' $tip.offset(offset) this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) } Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { this.arrow() .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') .css(isVertical ? 'top' : 'left', '') } Tooltip.prototype.setContent = function () { var $tip = this.tip() var title = this.getTitle() $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) $tip.removeClass('fade in top bottom left right') } Tooltip.prototype.hide = function (callback) { var that = this var $tip = $(this.$tip) var e = $.Event('hide.bs.' + this.type) function complete() { if (that.hoverState != 'in') $tip.detach() that.$element .removeAttr('aria-describedby') .trigger('hidden.bs.' + that.type) callback && callback() } this.$element.trigger(e) if (e.isDefaultPrevented()) return $tip.removeClass('in') $.support.transition && $tip.hasClass('fade') ? $tip .one('bsTransitionEnd', complete) .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete() this.hoverState = null return this } Tooltip.prototype.fixTitle = function () { var $e = this.$element if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') } } Tooltip.prototype.hasContent = function () { return this.getTitle() } Tooltip.prototype.getPosition = function ($element) { $element = $element || this.$element var el = $element[0] var isBody = el.tagName == 'BODY' var elRect = el.getBoundingClientRect() if (elRect.width == null) { // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) } var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null return $.extend({}, elRect, scroll, outerDims, elOffset) } Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } } Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { var delta = { top: 0, left: 0 } if (!this.$viewport) return delta var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 var viewportDimensions = this.getPosition(this.$viewport) if (/right|left/.test(placement)) { var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight if (topEdgeOffset < viewportDimensions.top) { // top overflow delta.top = viewportDimensions.top - topEdgeOffset } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset } } else { var leftEdgeOffset = pos.left - viewportPadding var rightEdgeOffset = pos.left + viewportPadding + actualWidth if (leftEdgeOffset < viewportDimensions.left) { // left overflow delta.left = viewportDimensions.left - leftEdgeOffset } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset } } return delta } Tooltip.prototype.getTitle = function () { var title var $e = this.$element var o = this.options title = $e.attr('data-original-title') || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) return title } Tooltip.prototype.getUID = function (prefix) { do prefix += ~~(Math.random() * 1000000) while (document.getElementById(prefix)) return prefix } Tooltip.prototype.tip = function () { if (!this.$tip) { this.$tip = $(this.options.template) if (this.$tip.length != 1) { throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') } } return this.$tip } Tooltip.prototype.arrow = function () { return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) } Tooltip.prototype.enable = function () { this.enabled = true } Tooltip.prototype.disable = function () { this.enabled = false } Tooltip.prototype.toggleEnabled = function () { this.enabled = !this.enabled } Tooltip.prototype.toggle = function (e) { var self = this if (e) { self = $(e.currentTarget).data('bs.' + this.type) if (!self) { self = new this.constructor(e.currentTarget, this.getDelegateOptions()) $(e.currentTarget).data('bs.' + this.type, self) } } if (e) { self.inState.click = !self.inState.click if (self.isInStateTrue()) self.enter(self) else self.leave(self) } else { self.tip().hasClass('in') ? self.leave(self) : self.enter(self) } } Tooltip.prototype.destroy = function () { var that = this clearTimeout(this.timeout) this.hide(function () { that.$element.off('.' + that.type).removeData('bs.' + that.type) if (that.$tip) { that.$tip.detach() } that.$tip = null that.$arrow = null that.$viewport = null }) } // TOOLTIP PLUGIN DEFINITION // ========================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.tooltip') var options = typeof option == 'object' && option if (!data && /destroy|hide/.test(option)) return if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.tooltip $.fn.tooltip = Plugin $.fn.tooltip.Constructor = Tooltip // TOOLTIP NO CONFLICT // =================== $.fn.tooltip.noConflict = function () { $.fn.tooltip = old return this } }(jQuery); /* ======================================================================== * Bootstrap: popover.js v3.3.6 * http://getbootstrap.com/javascript/#popovers * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // POPOVER PUBLIC CLASS DEFINITION // =============================== var Popover = function (element, options) { this.init('popover', element, options) } if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') Popover.VERSION = '3.3.6' Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { placement: 'right', trigger: 'click', content: '', template: '' }) // NOTE: POPOVER EXTENDS tooltip.js // ================================ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) Popover.prototype.constructor = Popover Popover.prototype.getDefaults = function () { return Popover.DEFAULTS } Popover.prototype.setContent = function () { var $tip = this.tip() var title = this.getTitle() var content = this.getContent() $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' ](content) $tip.removeClass('fade top bottom left right in') // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do // this manually by checking the contents. if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() } Popover.prototype.hasContent = function () { return this.getTitle() || this.getContent() } Popover.prototype.getContent = function () { var $e = this.$element var o = this.options return $e.attr('data-content') || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) } Popover.prototype.arrow = function () { return (this.$arrow = this.$arrow || this.tip().find('.arrow')) } // POPOVER PLUGIN DEFINITION // ========================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.popover') var options = typeof option == 'object' && option if (!data && /destroy|hide/.test(option)) return if (!data) $this.data('bs.popover', (data = new Popover(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.popover $.fn.popover = Plugin $.fn.popover.Constructor = Popover // POPOVER NO CONFLICT // =================== $.fn.popover.noConflict = function () { $.fn.popover = old return this } }(jQuery); /* ======================================================================== * Bootstrap: scrollspy.js v3.3.6 * http://getbootstrap.com/javascript/#scrollspy * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +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.6' 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) && $(href) 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.activeTarget = null return this.clear() } for (i = offsets.length; i--;) { activeTarget != targets[i] && scrollTop >= offsets[i] && (offsets[i + 1] === undefined || 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); /* ======================================================================== * Bootstrap: tab.js v3.3.6 * http://getbootstrap.com/javascript/#tabs * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // TAB CLASS DEFINITION // ==================== var Tab = function (element) { // jscs:disable requireDollarBeforejQueryAssignment this.element = $(element) // jscs:enable requireDollarBeforejQueryAssignment } Tab.VERSION = '3.3.6' Tab.TRANSITION_DURATION = 150 Tab.prototype.show = function () { var $this = this.element var $ul = $this.closest('ul:not(.dropdown-menu)') var selector = $this.data('target') if (!selector) { selector = $this.attr('href') selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } if ($this.parent('li').hasClass('active')) return var $previous = $ul.find('.active:last a') var hideEvent = $.Event('hide.bs.tab', { relatedTarget: $this[0] }) var showEvent = $.Event('show.bs.tab', { relatedTarget: $previous[0] }) $previous.trigger(hideEvent) $this.trigger(showEvent) if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return var $target = $(selector) this.activate($this.closest('li'), $ul) this.activate($target, $target.parent(), function () { $previous.trigger({ type: 'hidden.bs.tab', relatedTarget: $this[0] }) $this.trigger({ type: 'shown.bs.tab', relatedTarget: $previous[0] }) }) } Tab.prototype.activate = function (element, container, callback) { var $active = container.find('> .active') var transition = callback && $.support.transition && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) function next() { $active .removeClass('active') .find('> .dropdown-menu > .active') .removeClass('active') .end() .find('[data-toggle="tab"]') .attr('aria-expanded', false) element .addClass('active') .find('[data-toggle="tab"]') .attr('aria-expanded', true) if (transition) { element[0].offsetWidth // reflow for transition element.addClass('in') } else { element.removeClass('fade') } if (element.parent('.dropdown-menu').length) { element .closest('li.dropdown') .addClass('active') .end() .find('[data-toggle="tab"]') .attr('aria-expanded', true) } callback && callback() } $active.length && transition ? $active .one('bsTransitionEnd', next) .emulateTransitionEnd(Tab.TRANSITION_DURATION) : next() $active.removeClass('in') } // TAB PLUGIN DEFINITION // ===================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.tab') if (!data) $this.data('bs.tab', (data = new Tab(this))) if (typeof option == 'string') data[option]() }) } var old = $.fn.tab $.fn.tab = Plugin $.fn.tab.Constructor = Tab // TAB NO CONFLICT // =============== $.fn.tab.noConflict = function () { $.fn.tab = old return this } // TAB DATA-API // ============ var clickHandler = function (e) { e.preventDefault() Plugin.call($(this), 'show') } $(document) .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) }(jQuery); /* ======================================================================== * Bootstrap: affix.js v3.3.6 * 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.6' 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); hugo-0.92.2/examples/blog/static/js/jquery-1.11.3.min.js000066400000000000000000002733251420147000300223730ustar00rootroot00000000000000/*! jQuery v1.11.3 | (c) 2005, 2015 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="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,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=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.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},m.extend=m.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||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},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=r(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(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[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=r(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&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=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=ha(),z=ha(),A=ha(),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-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=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)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){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 ga(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(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(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 ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(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 ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(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 pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.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",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(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(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);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))&&(ja(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(".#.+[+~]")}),ja(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))&&ja(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 la(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?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.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 ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.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},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.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=ga.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=ga.selectors={cacheLength:50,createPseudo:ia,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(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===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]||ga.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]&&ga.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(ca,da).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=ga.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()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(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:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(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:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).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:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(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 ta(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 ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(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 wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(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=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(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=[sa(ta(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 wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(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=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.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(ca,da),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(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(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}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(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&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.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?m.extend(a,d):d}},e={};return d.pipe=d.then,m.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&&m.isFunction(a.promise)?e:0,g=1===f?a:m.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]&&m.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;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.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.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.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 m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;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},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
    a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!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(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/\s*$/g,ra={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:k.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(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=wa(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=wa(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?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(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,m.cleanData(ua(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,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m(".*?\n", }, // set class { `{{< youtube w7Ft2ymGmfc video>}}`, "(?s)\n
    .*?.*?
    \n", }, // set class and autoplay (using named params) { `{{< youtube id="w7Ft2ymGmfc" class="video" autoplay="true" >}}`, "(?s)\n
    .*?.*?
    ", }, // set custom title for accessibility) { `{{< youtube id="w7Ft2ymGmfc" title="A New Hugo Site in Under Two Minutes" >}}`, "(?s)\n
    .*?.*?
    ", }, } { var ( cfg, fs = newTestCfg() th = newTestHelper(cfg, fs, t) ) writeSource(t, fs, filepath.Join("content", "simple.md"), fmt.Sprintf(`--- title: Shorty --- %s`, this.in)) writeSource(t, fs, filepath.Join("layouts", "_default", "single.html"), `{{ .Content }}`) buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{}) th.assertFileContentRegexp(filepath.Join("public", "simple", "index.html"), this.expected) } } func TestShortcodeVimeo(t *testing.T) { t.Parallel() for _, this := range []struct { in, expected string }{ { `{{< vimeo 146022717 >}}`, "(?s)\n
    .*?.*?
    \n", }, // set class { `{{< vimeo 146022717 video >}}`, "(?s)\n
    .*?.*?
    \n", }, // set vimeo title { `{{< vimeo 146022717 video my-title >}}`, "(?s)\n
    .*?.*?
    \n", }, // set class (using named params) { `{{< vimeo id="146022717" class="video" >}}`, "(?s)^
    .*?.*?
    ", }, // set vimeo title (using named params) { `{{< vimeo id="146022717" class="video" title="my vimeo video" >}}`, "(?s)^
    .*?.*?
    ", }, } { var ( cfg, fs = newTestCfg() th = newTestHelper(cfg, fs, t) ) writeSource(t, fs, filepath.Join("content", "simple.md"), fmt.Sprintf(`--- title: Shorty --- %s`, this.in)) writeSource(t, fs, filepath.Join("layouts", "_default", "single.html"), `{{ .Content }}`) buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{}) th.assertFileContentRegexp(filepath.Join("public", "simple", "index.html"), this.expected) } } func TestShortcodeGist(t *testing.T) { t.Parallel() for _, this := range []struct { in, expected string }{ { `{{< gist spf13 7896402 >}}`, "(?s)^", }, { `{{< gist spf13 7896402 "img.html" >}}`, "(?s)^", }, } { var ( cfg, fs = newTestCfg() th = newTestHelper(cfg, fs, t) ) writeSource(t, fs, filepath.Join("content", "simple.md"), fmt.Sprintf(`--- title: Shorty --- %s`, this.in)) writeSource(t, fs, filepath.Join("layouts", "_default", "single.html"), `{{ .Content }}`) buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{}) th.assertFileContentRegexp(filepath.Join("public", "simple", "index.html"), this.expected) } } func TestShortcodeTweet(t *testing.T) { t.Parallel() for i, this := range []struct { privacy map[string]interface{} in, resp, expected string }{ { map[string]interface{}{ "twitter": map[string]interface{}{ "simple": true, }, }, `{{< tweet 666616452582129664 >}}`, `{"author_name":"Steve Francia","author_url":"https://twitter.com/spf13","cache_age":"3153600000","height":null,"html":"\u003cblockquote class=\"twitter-tweet\"\u003e\u003cp lang=\"en\" dir=\"ltr\"\u003eHugo 0.15 will have 30%+ faster render times thanks to this commit \u003ca href=\"https://t.co/FfzhM8bNhT\"\u003ehttps://t.co/FfzhM8bNhT\u003c/a\u003e \u003ca href=\"https://twitter.com/hashtag/gohugo?src=hash\u0026amp;ref_src=twsrc%5Etfw\"\u003e#gohugo\u003c/a\u003e \u003ca href=\"https://twitter.com/hashtag/golang?src=hash\u0026amp;ref_src=twsrc%5Etfw\"\u003e#golang\u003c/a\u003e \u003ca href=\"https://t.co/ITbMNU2BUf\"\u003ehttps://t.co/ITbMNU2BUf\u003c/a\u003e\u003c/p\u003e\u0026mdash; Steve Francia (@spf13) \u003ca href=\"https://twitter.com/spf13/status/666616452582129664?ref_src=twsrc%5Etfw\"\u003eNovember 17, 2015\u003c/a\u003e\u003c/blockquote\u003e\n\u003cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"\u003e\u003c/script\u003e\n","provider_name":"Twitter","provider_url":"https://twitter.com","type":"rich","url":"https://twitter.com/spf13/status/666616452582129664","version":"1.0","width":550}`, `.twitter-tweet a`, }, { map[string]interface{}{ "twitter": map[string]interface{}{ "simple": false, }, }, `{{< tweet 666616452582129664 >}}`, `{"author_name":"Steve Francia","author_url":"https://twitter.com/spf13","cache_age":"3153600000","height":null,"html":"\u003cblockquote class=\"twitter-tweet\"\u003e\u003cp lang=\"en\" dir=\"ltr\"\u003eHugo 0.15 will have 30%+ faster render times thanks to this commit \u003ca href=\"https://t.co/FfzhM8bNhT\"\u003ehttps://t.co/FfzhM8bNhT\u003c/a\u003e \u003ca href=\"https://twitter.com/hashtag/gohugo?src=hash\u0026amp;ref_src=twsrc%5Etfw\"\u003e#gohugo\u003c/a\u003e \u003ca href=\"https://twitter.com/hashtag/golang?src=hash\u0026amp;ref_src=twsrc%5Etfw\"\u003e#golang\u003c/a\u003e \u003ca href=\"https://t.co/ITbMNU2BUf\"\u003ehttps://t.co/ITbMNU2BUf\u003c/a\u003e\u003c/p\u003e\u0026mdash; Steve Francia (@spf13) \u003ca href=\"https://twitter.com/spf13/status/666616452582129664?ref_src=twsrc%5Etfw\"\u003eNovember 17, 2015\u003c/a\u003e\u003c/blockquote\u003e\n\u003cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"\u003e\u003c/script\u003e\n","provider_name":"Twitter","provider_url":"https://twitter.com","type":"rich","url":"https://twitter.com/spf13/status/666616452582129664","version":"1.0","width":550}`, `(?s)\s*`, }, { map[string]interface{}{ "twitter": map[string]interface{}{ "simple": false, }, }, `{{< tweet user="SanDiegoZoo" id="1453110110599868418" >}}`, `{"author_name":"San Diego Boo 👻 Wildlife Alliance","author_url":"https://twitter.com/sandiegozoo","cache_age":"3153600000","height":null,"html":"\u003cblockquote class=\"twitter-tweet\"\u003e\u003cp lang=\"en\" dir=\"ltr\"\u003eOwl bet you\u0026#39;ll lose this staring contest 🦉 \u003ca href=\"https://t.co/eJh4f2zncC\"\u003epic.twitter.com/eJh4f2zncC\u003c/a\u003e\u003c/p\u003e\u0026mdash; San Diego Boo 👻 Wildlife Alliance (@sandiegozoo) \u003ca href=\"https://twitter.com/sandiegozoo/status/1453110110599868418?ref_src=twsrc%5Etfw\"\u003eOctober 26, 2021\u003c/a\u003e\u003c/blockquote\u003e\n\u003cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"\u003e\u003c/script\u003e\n","provider_name":"Twitter","provider_url":"https://twitter.com","type":"rich","url":"https://twitter.com/sandiegozoo/status/1453110110599868418","version":"1.0","width":550}`, `(?s)\s*`, }, } { // overload getJSON to return mock API response from Twitter tweetFuncMap := template.FuncMap{ "getJSON": func(urlParts ...interface{}) interface{} { var v interface{} err := json.Unmarshal([]byte(this.resp), &v) if err != nil { t.Fatalf("[%d] unexpected error in json.Unmarshal: %s", i, err) return err } return v }, } var ( cfg, fs = newTestCfg() th = newTestHelper(cfg, fs, t) ) cfg.Set("privacy", this.privacy) writeSource(t, fs, filepath.Join("content", "simple.md"), fmt.Sprintf(`--- title: Shorty --- %s`, this.in)) writeSource(t, fs, filepath.Join("layouts", "_default", "single.html"), `{{ .Content }}`) buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg, OverloadedTemplateFuncs: tweetFuncMap}, BuildCfg{}) th.assertFileContentRegexp(filepath.Join("public", "simple", "index.html"), this.expected) } } func TestShortcodeInstagram(t *testing.T) { t.Parallel() for i, this := range []struct { in, hidecaption, resp, expected string }{ { `{{< instagram BMokmydjG-M >}}`, `0`, `{"provider_url": "https://www.instagram.com", "media_id": "1380514280986406796_25025320", "author_name": "instagram", "height": null, "thumbnail_url": "https://scontent-amt2-1.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/15048135_1880160212214218_7827880881132929024_n.jpg?ig_cache_key=MTM4MDUxNDI4MDk4NjQwNjc5Ng%3D%3D.2", "thumbnail_width": 640, "thumbnail_height": 640, "provider_name": "Instagram", "title": "Today, we\u2019re introducing a few new tools to help you make your story even more fun: Boomerang and mentions. We\u2019re also starting to test links inside some stories.\nBoomerang lets you turn everyday moments into something fun and unexpected. Now you can easily take a Boomerang right inside Instagram. Swipe right from your feed to open the stories camera. A new format picker under the record button lets you select \u201cBoomerang\u201d mode.\nYou can also now share who you\u2019re with or who you\u2019re thinking of by mentioning them in your story. When you add text to your story, type \u201c@\u201d followed by a username and select the person you\u2019d like to mention. Their username will appear underlined in your story. And when someone taps the mention, they'll see a pop-up that takes them to that profile.\nYou may begin to spot \u201cSee More\u201d links at the bottom of some stories. This is a test that lets verified accounts add links so it\u2019s easy to learn more. From your favorite chefs\u2019 recipes to articles from top journalists or concert dates from the musicians you love, tap \u201cSee More\u201d or swipe up to view the link right inside the app.\nTo learn more about today\u2019s updates, check out help.instagram.com.\nThese updates for Instagram Stories are available as part of Instagram version 9.7 available for iOS in the Apple App Store, for Android in Google Play and for Windows 10 in the Windows Store.", "html": "\u003cblockquote class=\"instagram-media\" data-instgrm-captioned data-instgrm-version=\"7\" style=\" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);\"\u003e\u003cdiv style=\"padding:8px;\"\u003e \u003cdiv style=\" background:#F8F8F8; line-height:0; margin-top:40px; padding:50.0% 0; text-align:center; width:100%;\"\u003e \u003cdiv style=\" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAMUExURczMzPf399fX1+bm5mzY9AMAAADiSURBVDjLvZXbEsMgCES5/P8/t9FuRVCRmU73JWlzosgSIIZURCjo/ad+EQJJB4Hv8BFt+IDpQoCx1wjOSBFhh2XssxEIYn3ulI/6MNReE07UIWJEv8UEOWDS88LY97kqyTliJKKtuYBbruAyVh5wOHiXmpi5we58Ek028czwyuQdLKPG1Bkb4NnM+VeAnfHqn1k4+GPT6uGQcvu2h2OVuIf/gWUFyy8OWEpdyZSa3aVCqpVoVvzZZ2VTnn2wU8qzVjDDetO90GSy9mVLqtgYSy231MxrY6I2gGqjrTY0L8fxCxfCBbhWrsYYAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;\"\u003e\u003c/div\u003e\u003c/div\u003e \u003cp style=\" margin:8px 0 0 0; padding:0 4px;\"\u003e \u003ca href=\"https://www.instagram.com/p/BMokmydjG-M/\" style=\" color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;\" target=\"_blank\"\u003eToday, we\u2019re introducing a few new tools to help you make your story even more fun: Boomerang and mentions. We\u2019re also starting to test links inside some stories. Boomerang lets you turn everyday moments into something fun and unexpected. Now you can easily take a Boomerang right inside Instagram. Swipe right from your feed to open the stories camera. A new format picker under the record button lets you select \u201cBoomerang\u201d mode. You can also now share who you\u2019re with or who you\u2019re thinking of by mentioning them in your story. When you add text to your story, type \u201c@\u201d followed by a username and select the person you\u2019d like to mention. Their username will appear underlined in your story. And when someone taps the mention, they\u0026#39;ll see a pop-up that takes them to that profile. You may begin to spot \u201cSee More\u201d links at the bottom of some stories. This is a test that lets verified accounts add links so it\u2019s easy to learn more. From your favorite chefs\u2019 recipes to articles from top journalists or concert dates from the musicians you love, tap \u201cSee More\u201d or swipe up to view the link right inside the app. To learn more about today\u2019s updates, check out help.instagram.com. These updates for Instagram Stories are available as part of Instagram version 9.7 available for iOS in the Apple App Store, for Android in Google Play and for Windows 10 in the Windows Store.\u003c/a\u003e\u003c/p\u003e \u003cp style=\" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;\"\u003eA photo posted by Instagram (@instagram) on \u003ctime style=\" font-family:Arial,sans-serif; font-size:14px; line-height:17px;\" datetime=\"2016-11-10T15:02:28+00:00\"\u003eNov 10, 2016 at 7:02am PST\u003c/time\u003e\u003c/p\u003e\u003c/div\u003e\u003c/blockquote\u003e\n\u003cscript async defer src=\"//platform.instagram.com/en_US/embeds.js\"\u003e\u003c/script\u003e", "width": 658, "version": "1.0", "author_url": "https://www.instagram.com/instagram", "author_id": 25025320, "type": "rich"}`, `(?s)
    `, }, { `{{< instagram BMokmydjG-M hidecaption >}}`, `1`, `{"provider_url": "https://www.instagram.com", "media_id": "1380514280986406796_25025320", "author_name": "instagram", "height": null, "thumbnail_url": "https://scontent-amt2-1.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/15048135_1880160212214218_7827880881132929024_n.jpg?ig_cache_key=MTM4MDUxNDI4MDk4NjQwNjc5Ng%3D%3D.2", "thumbnail_width": 640, "thumbnail_height": 640, "provider_name": "Instagram", "title": "Today, we\u2019re introducing a few new tools to help you make your story even more fun: Boomerang and mentions. We\u2019re also starting to test links inside some stories.\nBoomerang lets you turn everyday moments into something fun and unexpected. Now you can easily take a Boomerang right inside Instagram. Swipe right from your feed to open the stories camera. A new format picker under the record button lets you select \u201cBoomerang\u201d mode.\nYou can also now share who you\u2019re with or who you\u2019re thinking of by mentioning them in your story. When you add text to your story, type \u201c@\u201d followed by a username and select the person you\u2019d like to mention. Their username will appear underlined in your story. And when someone taps the mention, they'll see a pop-up that takes them to that profile.\nYou may begin to spot \u201cSee More\u201d links at the bottom of some stories. This is a test that lets verified accounts add links so it\u2019s easy to learn more. From your favorite chefs\u2019 recipes to articles from top journalists or concert dates from the musicians you love, tap \u201cSee More\u201d or swipe up to view the link right inside the app.\nTo learn more about today\u2019s updates, check out help.instagram.com.\nThese updates for Instagram Stories are available as part of Instagram version 9.7 available for iOS in the Apple App Store, for Android in Google Play and for Windows 10 in the Windows Store.", "html": "\u003cblockquote class=\"instagram-media\" data-instgrm-version=\"7\" style=\" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);\"\u003e\u003cdiv style=\"padding:8px;\"\u003e \u003cdiv style=\" background:#F8F8F8; line-height:0; margin-top:40px; padding:50.0% 0; text-align:center; width:100%;\"\u003e \u003cdiv style=\" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAMUExURczMzPf399fX1+bm5mzY9AMAAADiSURBVDjLvZXbEsMgCES5/P8/t9FuRVCRmU73JWlzosgSIIZURCjo/ad+EQJJB4Hv8BFt+IDpQoCx1wjOSBFhh2XssxEIYn3ulI/6MNReE07UIWJEv8UEOWDS88LY97kqyTliJKKtuYBbruAyVh5wOHiXmpi5we58Ek028czwyuQdLKPG1Bkb4NnM+VeAnfHqn1k4+GPT6uGQcvu2h2OVuIf/gWUFyy8OWEpdyZSa3aVCqpVoVvzZZ2VTnn2wU8qzVjDDetO90GSy9mVLqtgYSy231MxrY6I2gGqjrTY0L8fxCxfCBbhWrsYYAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;\"\u003e\u003c/div\u003e\u003c/div\u003e\u003cp style=\" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;\"\u003e\u003ca href=\"https://www.instagram.com/p/BMokmydjG-M/\" style=\" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none;\" target=\"_blank\"\u003eA photo posted by Instagram (@instagram)\u003c/a\u003e on \u003ctime style=\" font-family:Arial,sans-serif; font-size:14px; line-height:17px;\" datetime=\"2016-11-10T15:02:28+00:00\"\u003eNov 10, 2016 at 7:02am PST\u003c/time\u003e\u003c/p\u003e\u003c/div\u003e\u003c/blockquote\u003e\n\u003cscript async defer src=\"//platform.instagram.com/en_US/embeds.js\"\u003e\u003c/script\u003e", "width": 658, "version": "1.0", "author_url": "https://www.instagram.com/instagram", "author_id": 25025320, "type": "rich"}`, `(?s)
    `, }, } { // overload getJSON to return mock API response from Instagram instagramFuncMap := template.FuncMap{ "getJSON": func(args ...interface{}) interface{} { headers := args[len(args)-1].(map[string]interface{}) auth := headers["Authorization"] if auth != "Bearer dummytoken" { return fmt.Errorf("invalid access token: %q", auth) } var v interface{} err := json.Unmarshal([]byte(this.resp), &v) if err != nil { return fmt.Errorf("[%d] unexpected error in json.Unmarshal: %s", i, err) } return v }, } var ( cfg, fs = newTestCfg() th = newTestHelper(cfg, fs, t) ) cfg.Set("services.instagram.accessToken", "dummytoken") writeSource(t, fs, filepath.Join("content", "simple.md"), fmt.Sprintf(`--- title: Shorty --- %s`, this.in)) writeSource(t, fs, filepath.Join("layouts", "_default", "single.html"), `{{ .Content | safeHTML }}`) buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg, OverloadedTemplateFuncs: instagramFuncMap}, BuildCfg{}) th.assertFileContentRegexp(filepath.Join("public", "simple", "index.html"), this.expected) } } hugo-0.92.2/hugolib/embedded_templates_test.go000066400000000000000000000175051420147000300213730ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugolib import ( "testing" qt "github.com/frankban/quicktest" ) func TestInternalTemplatesImage(t *testing.T) { config := ` baseURL = "https://example.org" [params] images=["siteimg1.jpg", "siteimg2.jpg"] ` b := newTestSitesBuilder(t).WithConfigFile("toml", config) b.WithContent("mybundle/index.md", `--- title: My Bundle date: 2021-02-26T18:02:00-01:00 lastmod: 2021-05-22T19:25:00-01:00 --- `) b.WithContent("mypage.md", `--- title: My Page images: ["pageimg1.jpg", "pageimg2.jpg"] date: 2021-02-26T18:02:00+01:00 lastmod: 2021-05-22T19:25:00+01:00 --- `) b.WithContent("mysite.md", `--- title: My Site --- `) b.WithTemplatesAdded("_default/single.html", ` {{ template "_internal/twitter_cards.html" . }} {{ template "_internal/opengraph.html" . }} {{ template "_internal/schema.html" . }} `) b.WithSunset("content/mybundle/featured-sunset.jpg") b.Build(BuildCfg{}) b.AssertFileContent("public/mybundle/index.html", ` `) b.AssertFileContent("public/mypage/index.html", ` `) b.AssertFileContent("public/mysite/index.html", ` `) } // Just some simple test of the embedded templates to avoid // https://github.com/gohugoio/hugo/issues/4757 and similar. func TestEmbeddedTemplates(t *testing.T) { t.Parallel() c := qt.New(t) c.Assert(true, qt.Equals, true) home := []string{"index.html", ` GA: {{ template "_internal/google_analytics.html" . }} GA async: {{ template "_internal/google_analytics_async.html" . }} Disqus: {{ template "_internal/disqus.html" . }} `} b := newTestSitesBuilder(t) b.WithSimpleConfigFile().WithTemplatesAdded(home...) b.Build(BuildCfg{}) // Gheck GA regular and async b.AssertFileContent("public/index.html", "'anonymizeIp', true", "'script','https://www.google-analytics.com/analytics.js','ga');\n\tga('create', 'UA-ga_id', 'auto')", " {{/* Action/commands newlines, from Go 1.16, see https://github.com/golang/go/issues/29770 */}} {{ $norway := dict "country" "Norway" "population" "5 millions" "language" "Norwegian" "language_code" "nb" "weather" "freezing cold" "capitol" "Oslo" "largest_city" "Oslo" "currency" "Norwegian krone" "dialing_code" "+47" }} Population in Norway is {{ $norway.population | lower | upper }} `, ) b.Build(BuildCfg{}) b.AssertFileContent("public/index.html", ` Population in Norway is 5 MILLIONS `) } func collectIdentities(set map[identity.Identity]bool, provider identity.Provider) { if ids, ok := provider.(identity.IdentitiesProvider); ok { for _, id := range ids.GetIdentities() { collectIdentities(set, id) } } else { set[provider.GetIdentity()] = true } } func ident(level int) string { return strings.Repeat(" ", level) } func TestPartialInline(t *testing.T) { b := newTestSitesBuilder(t) b.WithContent("p1.md", "") b.WithTemplates( "index.html", ` {{ $p1 := partial "p1" . }} {{ $p2 := partial "p2" . }} P1: {{ $p1 }} P2: {{ $p2 }} {{ define "partials/p1" }}Inline: p1{{ end }} {{ define "partials/p2" }} {{ $value := 32 }} {{ return $value }} {{ end }} `, ) b.CreateSites().Build(BuildCfg{}) b.AssertFileContent("public/index.html", ` P1: Inline: p1 P2: 32`, ) } func TestPartialInlineBase(t *testing.T) { b := newTestSitesBuilder(t) b.WithContent("p1.md", "") b.WithTemplates( "baseof.html", `{{ $p3 := partial "p3" . }}P3: {{ $p3 }} {{ block "main" . }}{{ end }}{{ define "partials/p3" }}Inline: p3{{ end }}`, "index.html", ` {{ define "main" }} {{ $p1 := partial "p1" . }} {{ $p2 := partial "p2" . }} P1: {{ $p1 }} P2: {{ $p2 }} {{ end }} {{ define "partials/p1" }}Inline: p1{{ end }} {{ define "partials/p2" }} {{ $value := 32 }} {{ return $value }} {{ end }} `, ) b.CreateSites().Build(BuildCfg{}) b.AssertFileContent("public/index.html", ` P1: Inline: p1 P2: 32 P3: Inline: p3 `, ) } // https://github.com/gohugoio/hugo/issues/7478 func TestBaseWithAndWithoutDefine(t *testing.T) { b := newTestSitesBuilder(t) b.WithContent("p1.md", "---\ntitle: P\n---\nContent") b.WithTemplates( "_default/baseof.html", ` ::Header Start:{{ block "header" . }}{{ end }}:Header End: ::{{ block "main" . }}Main{{ end }}:: `, "index.html", ` {{ define "header" }} Home Header {{ end }} {{ define "main" }} This is home main {{ end }} `, "_default/single.html", ` {{ define "main" }} This is single main {{ end }} `, ) b.CreateSites().Build(BuildCfg{}) b.AssertFileContent("public/index.html", ` Home Header This is home main `, ) b.AssertFileContent("public/p1/index.html", ` ::Header Start::Header End: This is single main `, ) } // Issue 9393. func TestApplyWithNamespace(t *testing.T) { b := newTestSitesBuilder(t) b.WithTemplates( "index.html", ` {{ $b := slice " a " " b " " c" }} {{ $a := apply $b "strings.Trim" "." " " }} a: {{ $a }} `, ).WithContent("p1.md", "") b.Build(BuildCfg{}) b.AssertFileContent("public/index.html", `a: [a b c]`) } hugo-0.92.2/hugolib/testdata/000077500000000000000000000000001420147000300157775ustar00rootroot00000000000000hugo-0.92.2/hugolib/testdata/cities.csv000066400000000000000000000203221420147000300177730ustar00rootroot00000000000000"LatD", "LatM", "LatS", "NS", "LonD", "LonM", "LonS", "EW", "City", "State" 41, 5, 59, "N", 80, 39, 0, "W", "Youngstown", OH 42, 52, 48, "N", 97, 23, 23, "W", "Yankton", SD 46, 35, 59, "N", 120, 30, 36, "W", "Yakima", WA 42, 16, 12, "N", 71, 48, 0, "W", "Worcester", MA 43, 37, 48, "N", 89, 46, 11, "W", "Wisconsin Dells", WI 36, 5, 59, "N", 80, 15, 0, "W", "Winston-Salem", NC 49, 52, 48, "N", 97, 9, 0, "W", "Winnipeg", MB 39, 11, 23, "N", 78, 9, 36, "W", "Winchester", VA 34, 14, 24, "N", 77, 55, 11, "W", "Wilmington", NC 39, 45, 0, "N", 75, 33, 0, "W", "Wilmington", DE 48, 9, 0, "N", 103, 37, 12, "W", "Williston", ND 41, 15, 0, "N", 77, 0, 0, "W", "Williamsport", PA 37, 40, 48, "N", 82, 16, 47, "W", "Williamson", WV 33, 54, 0, "N", 98, 29, 23, "W", "Wichita Falls", TX 37, 41, 23, "N", 97, 20, 23, "W", "Wichita", KS 40, 4, 11, "N", 80, 43, 12, "W", "Wheeling", WV 26, 43, 11, "N", 80, 3, 0, "W", "West Palm Beach", FL 47, 25, 11, "N", 120, 19, 11, "W", "Wenatchee", WA 41, 25, 11, "N", 122, 23, 23, "W", "Weed", CA 31, 13, 11, "N", 82, 20, 59, "W", "Waycross", GA 44, 57, 35, "N", 89, 38, 23, "W", "Wausau", WI 42, 21, 36, "N", 87, 49, 48, "W", "Waukegan", IL 44, 54, 0, "N", 97, 6, 36, "W", "Watertown", SD 43, 58, 47, "N", 75, 55, 11, "W", "Watertown", NY 42, 30, 0, "N", 92, 20, 23, "W", "Waterloo", IA 41, 32, 59, "N", 73, 3, 0, "W", "Waterbury", CT 38, 53, 23, "N", 77, 1, 47, "W", "Washington", DC 41, 50, 59, "N", 79, 8, 23, "W", "Warren", PA 46, 4, 11, "N", 118, 19, 48, "W", "Walla Walla", WA 31, 32, 59, "N", 97, 8, 23, "W", "Waco", TX 38, 40, 48, "N", 87, 31, 47, "W", "Vincennes", IN 28, 48, 35, "N", 97, 0, 36, "W", "Victoria", TX 32, 20, 59, "N", 90, 52, 47, "W", "Vicksburg", MS 49, 16, 12, "N", 123, 7, 12, "W", "Vancouver", BC 46, 55, 11, "N", 98, 0, 36, "W", "Valley City", ND 30, 49, 47, "N", 83, 16, 47, "W", "Valdosta", GA 43, 6, 36, "N", 75, 13, 48, "W", "Utica", NY 39, 54, 0, "N", 79, 43, 48, "W", "Uniontown", PA 32, 20, 59, "N", 95, 18, 0, "W", "Tyler", TX 42, 33, 36, "N", 114, 28, 12, "W", "Twin Falls", ID 33, 12, 35, "N", 87, 34, 11, "W", "Tuscaloosa", AL 34, 15, 35, "N", 88, 42, 35, "W", "Tupelo", MS 36, 9, 35, "N", 95, 54, 36, "W", "Tulsa", OK 32, 13, 12, "N", 110, 58, 12, "W", "Tucson", AZ 37, 10, 11, "N", 104, 30, 36, "W", "Trinidad", CO 40, 13, 47, "N", 74, 46, 11, "W", "Trenton", NJ 44, 45, 35, "N", 85, 37, 47, "W", "Traverse City", MI 43, 39, 0, "N", 79, 22, 47, "W", "Toronto", ON 39, 2, 59, "N", 95, 40, 11, "W", "Topeka", KS 41, 39, 0, "N", 83, 32, 24, "W", "Toledo", OH 33, 25, 48, "N", 94, 3, 0, "W", "Texarkana", TX 39, 28, 12, "N", 87, 24, 36, "W", "Terre Haute", IN 27, 57, 0, "N", 82, 26, 59, "W", "Tampa", FL 30, 27, 0, "N", 84, 16, 47, "W", "Tallahassee", FL 47, 14, 24, "N", 122, 25, 48, "W", "Tacoma", WA 43, 2, 59, "N", 76, 9, 0, "W", "Syracuse", NY 32, 35, 59, "N", 82, 20, 23, "W", "Swainsboro", GA 33, 55, 11, "N", 80, 20, 59, "W", "Sumter", SC 40, 59, 24, "N", 75, 11, 24, "W", "Stroudsburg", PA 37, 57, 35, "N", 121, 17, 24, "W", "Stockton", CA 44, 31, 12, "N", 89, 34, 11, "W", "Stevens Point", WI 40, 21, 36, "N", 80, 37, 12, "W", "Steubenville", OH 40, 37, 11, "N", 103, 13, 12, "W", "Sterling", CO 38, 9, 0, "N", 79, 4, 11, "W", "Staunton", VA 39, 55, 11, "N", 83, 48, 35, "W", "Springfield", OH 37, 13, 12, "N", 93, 17, 24, "W", "Springfield", MO 42, 5, 59, "N", 72, 35, 23, "W", "Springfield", MA 39, 47, 59, "N", 89, 39, 0, "W", "Springfield", IL 47, 40, 11, "N", 117, 24, 36, "W", "Spokane", WA 41, 40, 48, "N", 86, 15, 0, "W", "South Bend", IN 43, 32, 24, "N", 96, 43, 48, "W", "Sioux Falls", SD 42, 29, 24, "N", 96, 23, 23, "W", "Sioux City", IA 32, 30, 35, "N", 93, 45, 0, "W", "Shreveport", LA 33, 38, 23, "N", 96, 36, 36, "W", "Sherman", TX 44, 47, 59, "N", 106, 57, 35, "W", "Sheridan", WY 35, 13, 47, "N", 96, 40, 48, "W", "Seminole", OK 32, 25, 11, "N", 87, 1, 11, "W", "Selma", AL 38, 42, 35, "N", 93, 13, 48, "W", "Sedalia", MO 47, 35, 59, "N", 122, 19, 48, "W", "Seattle", WA 41, 24, 35, "N", 75, 40, 11, "W", "Scranton", PA 41, 52, 11, "N", 103, 39, 36, "W", "Scottsbluff", NB 42, 49, 11, "N", 73, 56, 59, "W", "Schenectady", NY 32, 4, 48, "N", 81, 5, 23, "W", "Savannah", GA 46, 29, 24, "N", 84, 20, 59, "W", "Sault Sainte Marie", MI 27, 20, 24, "N", 82, 31, 47, "W", "Sarasota", FL 38, 26, 23, "N", 122, 43, 12, "W", "Santa Rosa", CA 35, 40, 48, "N", 105, 56, 59, "W", "Santa Fe", NM 34, 25, 11, "N", 119, 41, 59, "W", "Santa Barbara", CA 33, 45, 35, "N", 117, 52, 12, "W", "Santa Ana", CA 37, 20, 24, "N", 121, 52, 47, "W", "San Jose", CA 37, 46, 47, "N", 122, 25, 11, "W", "San Francisco", CA 41, 27, 0, "N", 82, 42, 35, "W", "Sandusky", OH 32, 42, 35, "N", 117, 9, 0, "W", "San Diego", CA 34, 6, 36, "N", 117, 18, 35, "W", "San Bernardino", CA 29, 25, 12, "N", 98, 30, 0, "W", "San Antonio", TX 31, 27, 35, "N", 100, 26, 24, "W", "San Angelo", TX 40, 45, 35, "N", 111, 52, 47, "W", "Salt Lake City", UT 38, 22, 11, "N", 75, 35, 59, "W", "Salisbury", MD 36, 40, 11, "N", 121, 39, 0, "W", "Salinas", CA 38, 50, 24, "N", 97, 36, 36, "W", "Salina", KS 38, 31, 47, "N", 106, 0, 0, "W", "Salida", CO 44, 56, 23, "N", 123, 1, 47, "W", "Salem", OR 44, 57, 0, "N", 93, 5, 59, "W", "Saint Paul", MN 38, 37, 11, "N", 90, 11, 24, "W", "Saint Louis", MO 39, 46, 12, "N", 94, 50, 23, "W", "Saint Joseph", MO 42, 5, 59, "N", 86, 28, 48, "W", "Saint Joseph", MI 44, 25, 11, "N", 72, 1, 11, "W", "Saint Johnsbury", VT 45, 34, 11, "N", 94, 10, 11, "W", "Saint Cloud", MN 29, 53, 23, "N", 81, 19, 11, "W", "Saint Augustine", FL 43, 25, 48, "N", 83, 56, 24, "W", "Saginaw", MI 38, 35, 24, "N", 121, 29, 23, "W", "Sacramento", CA 43, 36, 36, "N", 72, 58, 12, "W", "Rutland", VT 33, 24, 0, "N", 104, 31, 47, "W", "Roswell", NM 35, 56, 23, "N", 77, 48, 0, "W", "Rocky Mount", NC 41, 35, 24, "N", 109, 13, 48, "W", "Rock Springs", WY 42, 16, 12, "N", 89, 5, 59, "W", "Rockford", IL 43, 9, 35, "N", 77, 36, 36, "W", "Rochester", NY 44, 1, 12, "N", 92, 27, 35, "W", "Rochester", MN 37, 16, 12, "N", 79, 56, 24, "W", "Roanoke", VA 37, 32, 24, "N", 77, 26, 59, "W", "Richmond", VA 39, 49, 48, "N", 84, 53, 23, "W", "Richmond", IN 38, 46, 12, "N", 112, 5, 23, "W", "Richfield", UT 45, 38, 23, "N", 89, 25, 11, "W", "Rhinelander", WI 39, 31, 12, "N", 119, 48, 35, "W", "Reno", NV 50, 25, 11, "N", 104, 39, 0, "W", "Regina", SA 40, 10, 48, "N", 122, 14, 23, "W", "Red Bluff", CA 40, 19, 48, "N", 75, 55, 48, "W", "Reading", PA 41, 9, 35, "N", 81, 14, 23, "W", "Ravenna", OH hugo-0.92.2/hugolib/testdata/fruits.json000066400000000000000000000001021420147000300201770ustar00rootroot00000000000000{ "fruit": "Apple", "size": "Large", "color": "Red" } hugo-0.92.2/hugolib/testdata/redis.cn.md000066400000000000000000001617251420147000300200420ustar00rootroot00000000000000--- title: The Little Redis Book cn --- \thispagestyle{empty} \changepage{}{}{}{-0.5cm}{}{2cm}{}{}{} ![The Little Redis Book cn, By Karl Seguin, Translate By Jason Lai](title.png)\ \clearpage \changepage{}{}{}{0.5cm}{}{-2cm}{}{}{} ## 关于此书 ### 许可证 《The Little Redis Book》是经由Attribution-NonCommercial 3.0 Unported license许可的,你不需要为此书付钱。 你可以自由地对此书进行复制,分发,修改或者展示等操作。当然,你必须知道且认可这本书的作者是Karl Seguin,译者是赖立维,而且不应该将此书用于商业用途。 关于这个**许可证**的*详细描述*在这里: ### 关于作者 作者Karl Seguin是一名在多项技术领域浸淫多年的开发者。他是开源软件计划的活跃贡献者,同时也是一名技术作者以及业余演讲者。他写过若干关于Radis的文章以及一些工具。在他的一个面向业余游戏开发者的免费服务里,Redis为其中的评级和统计功能提供了支持:[mogade.com](http://mogade.com/)。 Karl之前还写了[《The Little MongoDB Book》](http://openmymind.net/2011/3/28/The-Little-MongoDB-Book/),这是一本免费且受好评,关于MongoDB的书。 他的博客是,你也可以关注他的Twitter帐号,via [@karlseguin](http://twitter.com/karlseguin)。 ### 关于译者 译者 赖立维 是一名长在天朝的普通程序员,对许多技术都有浓厚的兴趣,是开源软件的支持者,Emacs的轻度使用者。 虽然译者已经很认真地对待这次翻译,但是限于水平有限,肯定会有不少错漏,如果发现该书的翻译有什么需要修改,可以通过他的邮箱与他联系。他的邮箱是。 ### 致谢 必须特别感谢[Perry Neal](https://twitter.com/perryneal)一直以来的指导,我的眼界、触觉以及激情都来源于你。你为我提供了无价的帮助,感谢你。 ### 最新版本 此书的最新有效资源在: 中文版是英文版的一个分支,最新的中文版本在: \clearpage ## 简介 最近几年来,关于持久化和数据查询的相关技术,其需求已经增长到了让人惊讶的程度。可以断言,关系型数据库再也不是放之四海皆准。换一句话说,围绕数据的解决方案不可能再只有唯一一种。 对于我来说,在众多新出现的解决方案和工具里,最让人兴奋的,无疑是Redis。为什么?首先是因为其让人不可思议的容易学习,只需要简短的几个小时学习时间,就能对Redis有个大概的认识。还有,Redis在处理一组特定的问题集的同时能保持相当的通用性。更准确地说就是,Redis不会尝试去解决关于数据的所有事情。在你足够了解Redis后,事情就会变得越来越清晰,什么是可行的,什么是不应该由Redis来处理的。作为一名开发人员,如此的经验当是相当的美妙。 当你能仅使用Redis去构建一个完整系统时,我想大多数人将会发现,Redis能使得他们的许多数据方案变得更为通用,不论是一个传统的关系型数据库,一个面向文档的系统,或是其它更多的东西。这是一种用来实现某些特定特性的解决方法。就类似于一个索引引擎,你不会在Lucene上构建整个程序,但当你需要足够好的搜索,为什么不使用它呢?这对你和你的用户都有好处。当然,关于Redis和索引引擎之间相似性的讨论到此为止。 本书的目的是向读者传授掌握Redis所需要的基本知识。我们将会注重于学习Redis的5种数据结构,并研究各种数据建模方法。我们还会接触到一些主要的管理细节和调试技巧。 ## 入门 每个人的学习方式都不一样,有的人喜欢亲自实践学习,有的喜欢观看教学视频,还有的喜欢通过阅读来学习。对于Redis,没有什么比亲自实践学习来得效果更好的了。Redis的安装非常简单。而且通过随之安装的一个简单的命令解析程序,就能处理我们想做的一切事情。让我们先花几分钟的时间把Redis安装到我们的机器上。 ### Windows平台 Redis并没有官方支持Windows平台,但还是可供选择。你不会想在这里配置实际的生产环境,不过在我过往的开发经历里并没有感到有什么限制。 首先进入,然后下载最新的版本(应该会在列表的最上方)。 获取zip文件,然后根据你的系统架构,打开`64bit`或`32bit`文件夹。 ### *nix和MacOSX平台 对于*nix和MacOSX平台的用户,从源文件来安装是你的最佳选择。通过最新的版本号来选择,有效地址于。在编写此书的时候,最新的版本是2.4.6,我们可以运行下面的命令来安装该版本: wget http://redis.googlecode.com/files/redis-2.4.6.tar.gz tar xzf redis-2.4.6.tar.gz cd redis-2.4.6 make (当然,Redis同样可以通过套件管理程序来安装。例如,使用Homebrew的MaxOSX用户可以只键入`brew install redis`即可。) 如果你是通过源文件来安装,二进制可执行文件会被放置在`src`目录里。通过运行`cd src`可跳转到`src`目录。 ### 运行和连接Redis 如果一切都工作正常,那Redis的二进制文件应该已经可以曼妙地跳跃于你的指尖之下。Redis只有少量的可执行文件,我们将着重于Redis的服务器和命令行界面(一个类DOS的客户端)。首先,让我们来运行服务器。在Windows平台,双击`redis-server`,在*nix/MacOSX平台则运行`./redis-server`. 如果你仔细看了启动信息,你会看到一个警告,指没能找到`redis.conf`文件。Redis将会采用内置的默认设置,这对于我们将要做的已经足够了。 然后,通过双击`redis-cli`(Windows平台)或者运行`./redis-cli`(*nix/MacOSX平台),启动Redis的控制台。控制台将会通过默认的端口(6379)来连接本地运行的服务器。 可以在命令行界面键入`info`命令来查看一切是不是都运行正常。你会很乐意看到这么一大组关键字-值(key-value)对的显示,这为我们查看服务器的状态提供了大量有效信息。 如果在上面的启动步骤里遇到什么问题,我建议你到[Redis的官方支持组](https://groups.google.com/forum/#!forum/redis-db)里获取帮助。 ## 驱动Redis 很快你就会发现,Redis的API就如一组定义明确的函数那般容易理解。Redis具有让人难以置信的简单性,其操作过程也同样如此。这意味着,无论你是使用命令行程序,或是使用你喜欢的语言来驱动,整体的感觉都不会相差多少。因此,相对于命令行程序,如果你更愿意通过一种编程语言去驱动Redis,你不会感觉到有任何适应的问题。如果真想如此,可以到Redis的[客户端推荐页面](http://redis.io/clients)下载适合的Redis载体。 \clearpage ## 第1章 - 基础知识 是什么使Redis显得这么特别?Redis具体能解决什么类型的问题?要实际应用Redis,开发者必须储备什么知识?在我们能回答这么一些问题之前,我们需要明白Redis到底是什么。 Redis通常被人们认为是一种持久化的存储器关键字-值型存储(in-memory persistent key-value store)。我认为这种对Redis的描述并不太准确。Redis的确是将所有的数据存放于存储器(更多是是按位存储),而且也确实通过将数据写入磁盘来实现持久化,但是Redis的实际意义比单纯的关键字-值型存储要来得深远。纠正脑海里的这种误解观点非常关键,否则你对于Redis之道以及其应用的洞察力就会变得越发狭义。 事实是,Redis引入了5种不同的数据结构,只有一个是典型的关键字-值型结构。理解Redis的关键就在于搞清楚这5种数据结构,其工作的原理都是如何,有什么关联方法以及你能怎样应用这些数据结构去构建模型。首先,让我们来弄明白这些数据结构的实际意义。 应用上面提及的数据结构概念到我们熟悉的关系型数据库里,我们可以认为其引入了一个单独的数据结构——表格。表格既复杂又灵活,基于表格的存储和管理,没有多少东西是你不能进行建模的。然而,这种通用性并不是没有缺点。具体来说就是,事情并不是总能达到假设中的简单或者快速。相对于这种普遍适用(one-size-fits-all)的结构体系,我们可以使用更为专门化的结构体系。当然,因此可能有些事情我们会完成不了(至少,达不到很好的程度)。但话说回来,这样做就能确定我们可以获得想象中的简单性和速度吗? 针对特定类型的问题使用特定的数据结构?我们不就是这样进行编程的吗?你不会使用一个散列表去存储每份数据,也不会使用一个标量变量去存储。对我来说,这正是Redis的做法。如果你需要处理标量、列表、散列或者集合,为什么不直接就用标量、列表、散列和集合去存储他们?为什么不是直接调用`exists(key)`去检测一个已存在的值,而是要调用其他比O(1)(常量时间查找,不会因为待处理元素的增长而变慢)慢的操作? ### 数据库(Databases) 与你熟悉的关系型数据库一致,Redis有着相同的数据库基本概念,即一个数据库包含一组数据。典型的数据库应用案例是,将一个程序的所有数据组织起来,使之与另一个程序的数据保持独立。 在Redis里,数据库简单的使用一个数字编号来进行辨认,默认数据库的数字编号是`0`。如果你想切换到一个不同的数据库,你可以使用`select`命令来实现。在命令行界面里键入`select 1`,Redis应该会回复一条`OK`的信息,然后命令行界面里的提示符会变成类似`redis 127.0.0.1:6379[1]>`这样。如果你想切换回默认数据库,只要在命令行界面键入`select 0`即可。 ### 命令、关键字和值(Commands, Keys and Values) Redis不仅仅是一种简单的关键字-值型存储,从其核心概念来看,Redis的5种数据结构中的每一个都至少有一个关键字和一个值。在转入其它关于Redis的有用信息之前,我们必须理解关键字和值的概念。 关键字(Keys)是用来标识数据块。我们将会很常跟关键字打交道,不过在现在,明白关键字就是类似于`users:leto`这样的表述就足够了。一般都能很好地理解到,这样关键字包含的信息是一个名为`leto`的用户。这个关键字里的冒号没有任何特殊含义,对于Redis而言,使用分隔符来组织关键字是很常见的方法。 值(Values)是关联于关键字的实际值,可以是任何东西。有时候你会存储字符串,有时候是整数,还有时候你会存储序列化对象(使用JSON、XML或其他格式)。在大多数情况下,Redis会把值看做是一个字节序列,而不会关注它们实质上是什么。要注意,不同的Redis载体处理序列化会有所不同(一些会让你自己决定)。因此,在这本书里,我们将仅讨论字符串、整数和JSON。 现在让我们活动一下手指吧。在命令行界面键入下面的命令: set users:leto "{name: leto, planet: dune, likes: [spice]}" 这就是Redis命令的基本构成。首先我们要有一个确定的命令,在上面的语句里就是`set`。然后就是相应的参数,`set`命令接受两个参数,包括要设置的关键字,以及相应要设置的值。很多的情况是,命令接受一个关键字(当这种情况出现,其经常是第一个参数)。你能想到如何去获取这个值吗?我想你会说(当然一时拿不准也没什么): get users:leto 关键字和值的是Redis的基本概念,而`get`和`set`命令是对此最简单的使用。你可以创建更多的用户,去尝试不同类型的关键字以及不同的值,看看一些不同的组合。 ### 查询(Querying) 随着学习的持续深入,两件事情将变得清晰起来。对于Redis而言,关键字就是一切,而值是没有任何意义。更通俗来看就是,Redis不允许你通过值来进行查询。回到上面的例子,我们就不能查询生活在`dune`行星上的用户。 对许多人来说,这会引起一些担忧。在我们生活的世界里,数据查询是如此的灵活和强大,而Redis的方式看起来是这么的原始和不高效。不要让这些扰乱你太久。要记住,Redis不是一种普遍使用(one-size-fits-all)的解决方案,确实存在这么一些事情是不应该由Redis来解决的(因为其查询的限制)。事实上,在考虑了这些情况后,你会找到新的方法去构建你的数据。 很快,我们就能看到更多实际的用例。很重要的一点是,我们要明白关于Redis的这些基本事实。这能帮助我们弄清楚为什么值可以是任何东西,因为Redis从来不需要去读取或理解它们。而且,这也可以帮助我们理清思路,然后去思考如何在这个新世界里建立模型。 ### 存储器和持久化(Memory and Persistence) 我们之前提及过,Redis是一种持久化的存储器内存储(in-memory persistent store)。对于持久化,默认情况下,Redis会根据已变更的关键字数量来进行判断,然后在磁盘里创建数据库的快照(snapshot)。你可以对此进行设置,如果X个关键字已变更,那么每隔Y秒存储数据库一次。默认情况下,如果1000个或更多的关键字已变更,Redis会每隔60秒存储数据库;而如果9个或更少的关键字已变更,Redis会每隔15分钟存储数据库。 除了创建磁盘快照外,Redis可以在附加模式下运行。任何时候,如果有一个关键字变更,一个单一附加(append-only)的文件会在磁盘里进行更新。在一些情况里,虽然硬件或软件可能发生错误,但用那60秒有效数据存储去换取更好性能是可以接受的。而在另一些情况里,这种损失就难以让人接受,Redis为你提供了选择。在第5章里,我们将会看到第三种选择,其将持久化任务减荷到一个从属数据库里。 至于存储器,Redis会将所有数据都保留在存储器中。显而易见,运行Redis具有不低的成本:因为RAM仍然是最昂贵的服务器硬件部件。 我很清楚有一些开发者对即使是一点点的数据空间都是那么的敏感。一本《威廉·莎士比亚全集》需要近5.5MB的存储空间。对于缩放的需求,其它的解决方案趋向于IO-bound或者CPU-bound。这些限制(RAM或者IO)将会需要你去理解更多机器实际依赖的数据类型,以及应该如何去进行存储和查询。除非你是存储大容量的多媒体文件到Redis中,否则存储器内存储应该不会是一个问题。如果这对于一个程序是个问题,你就很可能不会用IO-bound的解决方案。 Redis有虚拟存储器的支持。然而,这个功能已经被认为是失败的了(通过Redis的开发者),而且它的使用已经被废弃了。 (从另一个角度来看,一本5.5MB的《威廉·莎士比亚全集》可以通过压缩减小到近2MB。当然,Redis不会自动对值进行压缩,但是因为其将所有值都看作是字节,没有什么限制让你不能对数据进行压缩/解压,通过牺牲处理时间来换取存储空间。) ### 整体来看(Putting It Together) 我们已经接触了好几个高层次的主题。在继续深入Redis之前,我想做的最后一件事情是将这些主题整合起来。这些主题包括,查询的限制,数据结构以及Redis在存储器内存储数据的方法。 当你将这3个主题整合起来,你最终会得出一个绝妙的结论:速度。一些人可能会想,当然Redis会很快速,要知道所以的东西都在存储器里。但这仅仅是其中的一部分,让Redis闪耀的真正原因是其不同于其它解决方案的特殊数据结构。 能有多快速?这依赖于很多东西,包括你正在使用着哪个命令,数据的类型等等。但Redis的性能测试是趋向于数万或数十万次操作**每秒**。你可以通过运行`redis-benchmark`(就在`redis-server`和`redis-cli`的同一个文件夹里)来进行测试。 我曾经试过将一组使用传统模型的代码转向使用Redis。在传统模型里,运行一个我写的载入测试,需要超过5分钟的时间来完成。而在Redis里,只需要150毫秒就完成了。你不会总能得到这么好的收获,但希望这能让你对我们所谈的东西有更清晰的理解。 理解Redis的这个特性很重要,因为这将影响到你如何去与Redis进行交互。拥有SQL背景的程序员通常会致力于让数据库的数据往返次数减至最小。这对于任何系统都是个好建议,包括Redis。然而,考虑到我们是在处理比较简单的数据结构,有时候我们还是需要与Redis服务器频繁交互,以达到我们的目的。刚开始的时候,可能会对这种数据访问模式感到不太自然。实际上,相对于我们通过Redis获得的高性能而言,这仅仅是微不足道的损失。 ### 小结 虽然我们只接触和摆弄了Redis的冰山一角,但我们讨论的主题已然覆盖了很大范围内的东西。如果觉得有些事情还是不太清楚(例如查询),不用为此而担心,在下一章我们将会继续深入探讨,希望你的问题都能得到解答。 这一章的要点包括: * 关键字(Keys)是用于标识一段数据的一个字符串 * 值(Values)是一段任意的字节序列,Redis不会关注它们实质上是什么 * Redis展示了(也实现了)5种专门的数据结构 * 上面的几点使得Redis快速而且容易使用,但要知道Redis并不适用于所有的应用场景 \clearpage ## 第2章 - 数据结构 现在开始将探究Redis的5种数据结构,我们会解释每种数据结构都是什么,包含了什么有效的方法(Method),以及你能用这些数据结构处理哪些类型的特性和数据。 目前为止,我们所知道的Redis构成仅包括命令、关键字和值,还没有接触到关于数据结构的具体概念。当我们使用`set`命令时,Redis是怎么知道我们是在使用哪个数据结构?其解决方法是,每个命令都相对应于一种特定的数据结构。例如,当你使用`set`命令,你就是将值存储到一个字符串数据结构里。而当你使用`hset`命令,你就是将值存储到一个散列数据结构里。考虑到Redis的关键字集很小,这样的机制具有相当的可管理性。 **[Redis的网站](http://redis.io/commands)里有着非常优秀的参考文档,没有任何理由去重造轮子。但为了搞清楚这些数据结构的作用,我们将会覆盖那些必须知道的重要命令。** 没有什么事情比高兴的玩和试验有趣的东西来得更重要的了。在任何时候,你都能通过键入`flushdb`命令将你数据库里的所有值清除掉,因此,不要再那么害羞了,去尝试做些疯狂的事情吧! ### 字符串(Strings) 在Redis里,字符串是最基本的数据结构。当你在思索着关键字-值对时,你就是在思索着字符串数据结构。不要被名字给搞混了,如之前说过的,你的值可以是任何东西。我更喜欢将他们称作“标量”(Scalars),但也许只有我才这样想。 我们已经看到了一个常见的字符串使用案例,即通过关键字存储对象的实例。有时候,你会频繁地用到这类操作: set users:leto "{name: leto, planet: dune, likes: [spice]}" 除了这些外,Redis还有一些常用的操作。例如,`strlen `能用来获取一个关键字对应值的长度;`getrange `将返回指定范围内的关键字对应值;`append `会将value附加到已存在的关键字对应值中(如果该关键字并不存在,则会创建一个新的关键字-值对)。不要犹豫,去试试看这些命令吧。下面是我得到的: > strlen users:leto (integer) 42 > getrange users:leto 27 40 "likes: [spice]" > append users:leto " OVER 9000!!" (integer) 54 现在你可能会想,这很好,但似乎没有什么意义。你不能有效地提取出一段范围内的JSON文件,或者为其附加一些值。你是对的,这里的经验是,一些命令,尤其是关于字符串数据结构的,只有在给定了明确的数据类型后,才会有实际意义。 之前我们知道了,Redis不会去关注你的值是什么东西。通常情况下,这没有错。然而,一些字符串命令是专门为一些类型或值的结构而设计的。作为一个有些含糊的用例,我们可以看到,对于一些自定义的空间效率很高的(space-efficient)串行化对象,`append`和`getrange`命令将会很有用。对于一个更为具体的用例,我们可以再看一下`incr`、`incrby`、`decr`和`decrby`命令。这些命令会增长或者缩减一个字符串数据结构的值: > incr stats:page:about (integer) 1 > incr stats:page:about (integer) 2 > incrby ratings:video:12333 5 (integer) 5 > incrby ratings:video:12333 3 (integer) 8 由此你可以想象到,Redis的字符串数据结构能很好地用于分析用途。你还可以去尝试增长`users:leto`(一个不是整数的值),然后看看会发生什么(应该会得到一个错误)。 更为进阶的用例是`setbit`和`getbit`命令。“今天我们有多少个独立用户访问”是个在Web应用里常见的问题,有一篇[精彩的博文](http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps/),在里面可以看到Spool是如何使用这两个命令有效地解决此问题。对于1.28亿个用户,一部笔记本电脑在不到50毫秒的时间里就给出了答复,而且只用了16MB的存储空间。 最重要的事情不是在于你是否明白位图(Bitmaps)的工作原理,或者Spool是如何去使用这些命令,而是应该要清楚Redis的字符串数据结构比你当初所想的要有用许多。然而,最常见的应用案例还是上面我们给出的:存储对象(简单或复杂)和计数。同时,由于通过关键字来获取一个值是如此之快,字符串数据结构很常被用来缓存数据。 ### 散列(Hashes) 我们已经知道把Redis称为一种关键字-值型存储是不太准确的,散列数据结构是一个很好的例证。你会看到,在很多方面里,散列数据结构很像字符串数据结构。两者显著的区别在于,散列数据结构提供了一个额外的间接层:一个域(Field)。因此,散列数据结构中的`set`和`get`是: hset users:goku powerlevel 9000 hget users:goku powerlevel 相关的操作还包括在同一时间设置多个域、同一时间获取多个域、获取所有的域和值、列出所有的域或者删除指定的一个域: hmset users:goku race saiyan age 737 hmget users:goku race powerlevel hgetall users:goku hkeys users:goku hdel users:goku age 如你所见,散列数据结构比普通的字符串数据结构具有更多的可操作性。我们可以使用一个散列数据结构去获得更精确的描述,是存储一个用户,而不是一个序列化对象。从而得到的好处是能够提取、更新和删除具体的数据片段,而不必去获取或写入整个值。 对于散列数据结构,可以从一个经过明确定义的对象的角度来考虑,例如一个用户,关键之处在于要理解他们是如何工作的。从性能上的原因来看,这是正确的,更具粒度化的控制可能会相当有用。在下一章我们将会看到,如何用散列数据结构去组织你的数据,使查询变得更为实效。在我看来,这是散列真正耀眼的地方。 ### 列表(Lists) 对于一个给定的关键字,列表数据结构让你可以存储和处理一组值。你可以添加一个值到列表里、获取列表的第一个值或最后一个值以及用给定的索引来处理值。列表数据结构维护了值的顺序,提供了基于索引的高效操作。为了跟踪在网站里注册的最新用户,我们可以维护一个`newusers`的列表: lpush newusers goku ltrim newusers 0 50 **(译注:`ltrim`命令的具体构成是`LTRIM Key start stop`。要理解`ltrim`命令,首先要明白Key所存储的值是一个列表,理论上列表可以存放任意个值。对于指定的列表,根据所提供的两个范围参数start和stop,`ltrim`命令会将指定范围外的值都删除掉,只留下范围内的值。)** 首先,我们将一个新用户推入到列表的前端,然后对列表进行调整,使得该列表只包含50个最近被推入的用户。这是一种常见的模式。`ltrim`是一个具有O(N)时间复杂度的操作,N是被删除的值的数量。从上面的例子来看,我们总是在插入了一个用户后再进行列表调整,实际上,其将具有O(1)的时间复杂度(因为N将永远等于1)的常数性能。 这是我们第一次看到一个关键字的对应值索引另一个值。如果我们想要获取最近的10个用户的详细资料,我们可以运行下面的组合操作: keys = redis.lrange('newusers', 0, 10) redis.mget(*keys.map {|u| "users:#{u}"}) 我们之前谈论过关于多次往返数据的模式,上面的两行Ruby代码为我们进行了很好的演示。 当然,对于存储和索引关键字的功能,并不是只有列表数据结构这种方式。值可以是任意的东西,你可以使用列表数据结构去存储日志,也可以用来跟踪用户浏览网站时的路径。如果你过往曾构建过游戏,你可能会使用列表数据结构去跟踪用户的排队活动。 ### 集合 集合数据结构常常被用来存储只能唯一存在的值,并提供了许多的基于集合的操作,例如并集。集合数据结构没有对值进行排序,但是其提供了高效的基于值的操作。使用集合数据结构的典型用例是朋友名单的实现: sadd friends:leto ghanima paul chani jessica sadd friends:duncan paul jessica alia 不管一个用户有多少个朋友,我们都能高效地(O(1)时间复杂度)识别出用户X是不是用户Y的朋友: sismember friends:leto jessica sismember friends:leto vladimir 而且,我们可以查看两个或更多的人是不是有共同的朋友: sinter friends:leto friends:duncan 甚至可以在一个新的关键字里存储结果: sinterstore friends:leto_duncan friends:leto friends:duncan 有时候需要对值的属性进行标记和跟踪处理,但不能通过简单的复制操作完成,集合数据结构是解决此类问题的最好方法之一。当然,对于那些需要运用集合操作的地方(例如交集和并集),集合数据结构就是最好的选择。 ### 分类集合(Sorted Sets) 最后也是最强大的数据结构是分类集合数据结构。如果说散列数据结构类似于字符串数据结构,主要区分是域(field)的概念;那么分类集合数据结构就类似于集合数据结构,主要区分是标记(score)的概念。标记提供了排序(sorting)和秩划分(ranking)的功能。如果我们想要一个秩分类的朋友名单,可以这样做: zadd friends:duncan 70 ghanima 95 paul 95 chani 75 jessica 1 vladimir 对于`duncan`的朋友,要怎样计算出标记(score)为90或更高的人数? zcount friends:duncan 90 100 如何获取`chani`在名单里的秩(rank)? zrevrank friends:duncan chani **(译注:`zrank`命令的具体构成是`ZRANK Key menber`,要知道Key存储的Sorted Set默认是根据Score对各个menber进行升序的排列,该命令就是用来获取menber在该排列里的次序,这就是所谓的秩。)** 我们使用了`zrevrank`命令而不是`zrank`命令,这是因为Redis的默认排序是从低到高,但是在这个例子里我们的秩划分是从高到低。对于分类集合数据结构,最常见的应用案例是用来实现排行榜系统。事实上,对于一些基于整数排序,且能以标记(score)来进行有效操作的东西,使用分类集合数据结构来处理应该都是不错的选择。 ### 小结 对于Redis的5种数据结构,我们进行了高层次的概述。一件有趣的事情是,相对于最初构建时的想法,你经常能用Redis创造出一些更具实效的事情。对于字符串数据结构和分类集合数据结构的使用,很有可能存在一些构建方法是还没有人想到的。当你理解了那些常用的应用案例后,你将发现Redis对于许多类型的问题,都是很理想的选择。还有,不要因为Redis展示了5种数据结构和相应的各种方法,就认为你必须要把所有的东西都用上。只使用一些命令去构建一个特性是很常见的。 \clearpage ## 第3章 - 使用数据结构 在上一章里,我们谈论了Redis的5种数据结构,对于一些可能的用途也给出了用例。现在是时候来看看一些更高级,但依然很常见的主题和设计模式。 ### 大O表示法(Big O Notation) 在本书中,我们之前就已经看到过大O表示法,包括O(1)和O(N)的表示。大O表示法的惯常用途是,描述一些用于处理一定数量元素的行为的综合表现。在Redis里,对于一个要处理一定数量元素的命令,大O表示法让我们能了解该命令的大概运行速度。 在Redis的文档里,每一个命令的时间复杂度都用大O表示法进行了描述,还能知道各命令的具体性能会受什么因素影响。让我们来看看一些用例。 常数时间复杂度O(1)被认为是最快速的,无论我们是在处理5个元素还是5百万个元素,最终都能得到相同的性能。对于`sismember`命令,其作用是告诉我们一个值是否属于一个集合,时间复杂度为O(1)。`sismember`命令很强大,很大部分的原因是其高效的性能特征。许多Redis命令都具有O(1)的时间复杂度。 对数时间复杂度O(log(N))被认为是第二快速的,其通过使需扫描的区间不断皱缩来快速完成处理。使用这种“分而治之”的方式,大量的元素能在几个迭代过程里被快速分解完整。`zadd`命令的时间复杂度就是O(log(N)),其中N是在分类集合中的元素数量。 再下来就是线性时间复杂度O(N),在一个表格的非索引列里进行查找就需要O(N)次操作。`ltrim`命令具有O(N)的时间复杂度,但是,在`ltrim`命令里,N不是列表所拥有的元素数量,而是被删除的元素数量。从一个具有百万元素的列表里用`ltrim`命令删除1个元素,要比从一个具有一千个元素的列表里用`ltrim`命令删除10个元素来的快速(实际上,两者很可能会是一样快,因为两个时间都非常的小)。 根据给定的最小和最大的值的标记,`zremrangebyscore`命令会在一个分类集合里进行删除元素操作,其时间复杂度是O(log(N)+M)。这看起来似乎有点儿杂乱,通过阅读文档可以知道,这里的N指的是在分类集合里的总元素数量,而M则是被删除的元素数量。可以看出,对于性能而言,被删除的元素数量很可能会比分类集合里的总元素数量更为重要。 **(译注:`zremrangebyscore`命令的具体构成是`ZREMRANGEBYSCORE Key max mix`。)** 对于`sort`命令,其时间复杂度为O(N+M*log(M)),我们将会在下一章谈论更多的相关细节。从`sort`命令的性能特征来看,可以说这是Redis里最复杂的一个命令。 还存在其他的时间复杂度描述,包括O(N^2)和O(C^N)。随着N的增大,其性能将急速下降。在Redis里,没有任何一个命令具有这些类型的时间复杂度。 值得指出的一点是,在Redis里,当我们发现一些操作具有O(N)的时间复杂度时,我们可能可以找到更为好的方法去处理。 **(译注:对于Big O Notation,相信大家都非常的熟悉,虽然原文仅仅是对该表示法进行简单的介绍,但限于个人的算法知识和文笔水平实在有限,此小节的翻译让我头痛颇久,最终成果也确实难以让人满意,望见谅。)** ### 仿多关键字查询(Pseudo Multi Key Queries) 时常,你会想通过不同的关键字去查询相同的值。例如,你会想通过电子邮件(当用户开始登录时)去获取用户的具体信息,或者通过用户id(在用户登录后)去获取。有一种很不实效的解决方法,其将用户对象分别放置到两个字符串值里去: set users:leto@dune.gov "{id: 9001, email: 'leto@dune.gov', ...}" set users:9001 "{id: 9001, email: 'leto@dune.gov', ...}" 这种方法很糟糕,如此不但会产生两倍数量的内存,而且这将会成为数据管理的恶梦。 如果Redis允许你将一个关键字链接到另一个的话,可能情况会好很多,可惜Redis并没有提供这样的功能(而且很可能永远都不会提供)。Redis发展到现在,其开发的首要目的是要保持代码和API的整洁简单,关键字链接功能的内部实现并不符合这个前提(对于关键字,我们还有很多相关方法没有谈论到)。其实,Redis已经提供了解决的方法:散列。 使用散列数据结构,我们可以摆脱重复的缠绕: set users:9001 "{id: 9001, email: leto@dune.gov, ...}" hset users:lookup:email leto@dune.gov 9001 我们所做的是,使用域来作为一个二级索引,然后去引用单个用户对象。要通过id来获取用户信息,我们可以使用一个普通的`get`命令: get users:9001 而如果想通过电子邮箱来获取用户信息,我们可以使用`hget`命令再配合使用`get`命令(Ruby代码): id = redis.hget('users:lookup:email', 'leto@dune.gov') user = redis.get("users:#{id}") 你很可能将会经常使用这类用法。在我看来,这就是散列真正耀眼的地方。在你了解这类用法之前,这可能不是一个明显的用例。 ### 引用和索引(References and Indexes) 我们已经看过几个关于值引用的用例,包括介绍列表数据结构时的用例,以及在上面使用散列数据结构来使查询更灵活一些。进行归纳后会发现,对于那些值与值间的索引和引用,我们都必须手动的去管理。诚实来讲,这确实会让人有点沮丧,尤其是当你想到那些引用相关的操作,如管理、更新和删除等,都必须手动的进行时。在Redis里,这个问题还没有很好的解决方法。 我们已经看到,集合数据结构很常被用来实现这类索引: sadd friends:leto ghanima paul chani jessica 这个集合里的每一个成员都是一个Redis字符串数据结构的引用,而每一个引用的值则包含着用户对象的具体信息。那么如果`chani`改变了她的名字,或者删除了她的帐号,应该如何处理?从整个朋友圈的关系结构来看可能会更好理解,我们知道,`chani`也有她的朋友: sadd friends_of:chani leto paul 如果你有什么待处理情况像上面那样,那在维护成本之外,还会有对于额外索引值的处理和存储空间的成本。这可能会令你感到有点退缩。在下一小节里,我们将会谈论减少使用额外数据交互的性能成本的一些方法(在第1章我们粗略地讨论了下)。 如果你确实在担忧着这些情况,其实,关系型数据库也有同样的开销。索引需要一定的存储空间,必须通过扫描或查找,然后才能找到相应的记录。其开销也是存在的,当然他们对此做了很多的优化工作,使之变得更为有效。 再次说明,需要在Redis里手动地管理引用确实是颇为棘手。但是,对于你关心的那些问题,包括性能或存储空间等,应该在经过测试后,才会有真正的理解。我想你会发现这不会是一个大问题。 ### 数据交互和流水线(Round Trips and Pipelining) 我们已经提到过,与服务器频繁交互是Redis的一种常见模式。这类情况可能很常出现,为了使我们能获益更多,值得仔细去看看我们能利用哪些特性。 许多命令能接受一个或更多的参数,也有一种关联命令(sister-command)可以接受多个参数。例如早前我们看到过`mget`命令,接受多个关键字,然后返回值: keys = redis.lrange('newusers', 0, 10) redis.mget(*keys.map {|u| "users:#{u}"}) 或者是`sadd`命令,能添加一个或多个成员到集合里: sadd friends:vladimir piter sadd friends:paul jessica leto "leto II" chani Redis还支持流水线功能。通常情况下,当一个客户端发送请求到Redis后,在发送下一个请求之前必须等待Redis的答复。使用流水线功能,你可以发送多个请求,而不需要等待Redis响应。这不但减少了网络开销,还能获得性能上的显著提高。 值得一提的是,Redis会使用存储器去排列命令,因此批量执行命令是一个好主意。至于具体要多大的批量,将取决于你要使用什么命令(更明确来说,该参数有多大)。另一方面来看,如果你要执行的命令需要差不多50个字符的关键字,你大概可以对此进行数千或数万的批量操作。 对于不同的Redis载体,在流水线里运行命令的方式会有所差异。在Ruby里,你传递一个代码块到`pipelined`方法: redis.pipelined do 9001.times do redis.incr('powerlevel') end end 正如你可能猜想到的,流水线功能可以实际地加速一连串命令的处理。 ### 事务(Transactions) 每一个Redis命令都具有原子性,包括那些一次处理多项事情的命令。此外,对于使用多个命令,Redis支持事务功能。 你可能不知道,但Redis实际上是单线程运行的,这就是为什么每一个Redis命令都能够保证具有原子性。当一个命令在执行时,没有其他命令会运行(我们会在往后的章节里简略谈论一下Scaling)。在你考虑到一些命令去做多项事情时,这会特别的有用。例如: `incr`命令实际上就是一个`get`命令然后紧随一个`set`命令。 `getset`命令设置一个新的值然后返回原始值。 `setnx`命令首先测试关键字是否存在,只有当关键字不存在时才设置值 虽然这些都很有用,但在实际开发时,往往会需要运行具有原子性的一组命令。若要这样做,首先要执行`multi`命令,紧随其后的是所有你想要执行的命令(作为事务的一部分),最后执行`exec`命令去实际执行命令,或者使用`discard`命令放弃执行命令。Redis的事务功能保证了什么? * 事务中的命令将会按顺序地被执行 * 事务中的命令将会如单个原子操作般被执行(没有其它的客户端命令会在中途被执行) * 事务中的命令要么全部被执行,要么不会执行 你可以(也应该)在命令行界面对事务功能进行一下测试。还有一点要注意到,没有什么理由不能结合流水线功能和事务功能。 multi hincrby groups:1percent balance -9000000000 hincrby groups:99percent balance 9000000000 exec 最后,Redis能让你指定一个关键字(或多个关键字),当关键字有改变时,可以查看或者有条件地应用一个事务。这是用于当你需要获取值,且待运行的命令基于那些值时,所有都在一个事务里。对于上面展示的代码,我们不能去实现自己的`incr`命令,因为一旦`exec`命令被调用,他们会全部被执行在一块。我们不能这么做: redis.multi() current = redis.get('powerlevel') redis.set('powerlevel', current + 1) redis.exec() **(译注:虽然Redis是单线程运行的,但是我们可以同时运行多个Redis客户端进程,常见的并发问题还是会出现。像上面的代码,在`get`运行之后,`set`运行之前,`powerlevel`的值可能会被另一个Redis客户端给改变,从而造成错误。)** 这些不是Redis的事务功能的工作。但是,如果我们增加一个`watch`到`powerlevel`,我们可以这样做: redis.watch('powerlevel') current = redis.get('powerlevel') redis.multi() redis.set('powerlevel', current + 1) redis.exec() 在我们调用`watch`后,如果另一个客户端改变了`powerlevel`的值,我们的事务将会运行失败。如果没有客户端改变`powerlevel`的值,那么事务会继续工作。我们可以在一个循环里运行这些代码,直到其能正常工作。 ### 关键字反模式(Keys Anti-Pattern) 在下一章中,我们将会谈论那些没有确切关联到数据结构的命令,其中的一些是管理或调试工具。然而有一个命令我想特别地在这里进行谈论:`keys`命令。这个命令需要一个模式,然后查找所有匹配的关键字。这个命令看起来很适合一些任务,但这不应该用在实际的产品代码里。为什么?因为这个命令通过线性扫描所有的关键字来进行匹配。或者,简单地说,这个命令太慢了。 人们会如此去使用这个命令?一般会用来构建一个本地的Bug追踪服务。每一个帐号都有一个`id`,你可能会通过一个看起来像`bug:account_id:bug_id`的关键字,把每一个Bug存储到一个字符串数据结构值中去。如果你在任何时候需要查询一个帐号的Bug(显示它们,或者当用户删除了帐号时删除掉这些Bugs),你可能会尝试去使用`keys`命令: keys bug:1233:* 更好的解决方法应该使用一个散列数据结构,就像我们可以使用散列数据结构来提供一种方法去展示二级索引,因此我们可以使用域来组织数据: hset bugs:1233 1 "{id:1, account: 1233, subject: '...'}" hset bugs:1233 2 "{id:2, account: 1233, subject: '...'}" 从一个帐号里获取所有的Bug标识,可以简单地调用`hkeys bugs:1233`。去删除一个指定的Bug,可以调用`hdel bugs:1233 2`。如果要删除了一个帐号,可以通过`del bugs:1233`把关键字删除掉。 ### 小结 结合这一章以及前一章,希望能让你得到一些洞察力,了解如何使用Redis去支持(Power)实际项目。还有其他的模式可以让你去构建各种类型的东西,但真正的关键是要理解基本的数据结构。你将能领悟到,这些数据结构是如何能够实现你最初视角之外的东西。 \clearpage ## 第4章 超越数据结构 5种数据结构组成了Redis的基础,其他没有关联特定数据结构的命令也有很多。我们已经看过一些这样的命令:`info`, `select`, `flushdb`, `multi`, `exec`, `discard`, `watch`和`keys `。这一章将看看其他的一些重要命令。 ### 使用期限(Expiration) Redis允许你标记一个关键字的使用期限。你可以给予一个Unix时间戳形式(自1970年1月1日起)的绝对时间,或者一个基于秒的存活时间。这是一个基于关键字的命令,因此其不在乎关键字表示的是哪种类型的数据结构。 expire pages:about 30 expireat pages:about 1356933600 第一个命令将会在30秒后删除掉关键字(包括其关联的值)。第二个命令则会在2012年12月31日上午12点删除掉关键字。 这让Redis能成为一个理想的缓冲引擎。通过`ttl`命令,你可以知道一个关键字还能够存活多久。而通过`persist`命令,你可以把一个关键字的使用期限删除掉。 ttl pages:about persist pages:about 最后,有个特殊的字符串命令,`setex`命令让你可以在一个单独的原子命令里设置一个字符串值,同时里指定一个生存期(这比任何事情都要方便)。 setex pages:about 30 '

    about us

    ....' ### 发布和订阅(Publication and Subscriptions) Redis的列表数据结构有`blpop`和`brpop`命令,能从列表里返回且删除第一个(或最后一个)元素,或者被堵塞,直到有一个元素可供操作。这可以用来实现一个简单的队列。 **(译注:对于`blpop`和`brpop`命令,如果列表里没有关键字可供操作,连接将被堵塞,直到有另外的Redis客户端使用`lpush`或`rpush`命令推入关键字为止。)** 此外,Redis对于消息发布和频道订阅有着一流的支持。你可以打开第二个`redis-cli`窗口,去尝试一下这些功能。在第一个窗口里订阅一个频道(我们会称它为`warnings`): subscribe warnings 其将会答复你订阅的信息。现在,在另一个窗口,发布一条消息到`warnings`频道: publish warnings "it's over 9000!" 如果你回到第一个窗口,你应该已经接收到`warnings`频道发来的消息。 你可以订阅多个频道(`subscribe channel1 channel2 ...`),订阅一组基于模式的频道(`psubscribe warnings:*`),以及使用`unsubscribe`和`punsubscribe`命令停止监听一个或多个频道,或一个频道模式。 最后,可以注意到`publish`命令的返回值是1,这指出了接收到消息的客户端数量。 ### 监控和延迟日志(Monitor and Slow Log) `monitor`命令可以让你查看Redis正在做什么。这是一个优秀的调试工具,能让你了解你的程序如何与Redis进行交互。在两个`redis-cli`窗口中选一个(如果其中一个还处于订阅状态,你可以使用`unsubscribe`命令退订,或者直接关掉窗口再重新打开一个新窗口)键入`monitor`命令。在另一个窗口,执行任何其他类型的命令(例如`get`或`set`命令)。在第一个窗口里,你应该可以看到这些命令,包括他们的参数。 在实际生产环境里,你应该谨慎运行`monitor`命令,这真的仅仅就是一个很有用的调试和开发工具。除此之外,没有更多要说的了。 随同`monitor`命令一起,Redis拥有一个`slowlog`命令,这是一个优秀的性能剖析工具。其会记录执行时间超过一定数量**微秒**的命令。在下一章节,我们会简略地涉及如何配置Redis,现在你可以按下面的输入配置Redis去记录所有的命令: config set slowlog-log-slower-than 0 然后,执行一些命令。最后,你可以检索到所有日志,或者检索最近的那些日志: slowlog get slowlog get 10 通过键入`slowlog len`,你可以获取延迟日志里的日志数量。 对于每个被你键入的命令,你应该查看4个参数: * 一个自动递增的id * 一个Unix时间戳,表示命令开始运行的时间 * 一个微妙级的时间,显示命令运行的总时间 * 该命令以及所带参数 延迟日志保存在存储器中,因此在生产环境中运行(即使有一个低阀值)也应该不是一个问题。默认情况下,它将会追踪最近的1024个日志。 ### 排序(Sort) `sort`命令是Redis最强大的命令之一。它让你可以在一个列表、集合或者分类集合里对值进行排序(分类集合是通过标记来进行排序,而不是集合里的成员)。下面是一个`sort`命令的简单用例: rpush users:leto:guesses 5 9 10 2 4 10 19 2 sort users:leto:guesses 这将返回进行升序排序后的值。这里有一个更高级的例子: sadd friends:ghanima leto paul chani jessica alia duncan sort friends:ghanima limit 0 3 desc alpha 上面的命令向我们展示了,如何对已排序的记录进行分页(通过`limit`),如何返回降序排序的结果(通过`desc`),以及如何用字典序排序代替数值序排序(通过`alpha`)。 `sort`命令的真正力量是其基于引用对象来进行排序的能力。早先的时候,我们说明了列表、集合和分类集合很常被用于引用其他的Redis对象,`sort`命令能够解引用这些关系,而且通过潜在值来进行排序。例如,假设我们有一个Bug追踪器能让用户看到各类已存在问题。我们可能使用一个集合数据结构去追踪正在被监视的问题: sadd watch:leto 12339 1382 338 9338 你可能会有强烈的感觉,想要通过id来排序这些问题(默认的排序就是这样的),但是,我们更可能是通过问题的严重性来对这些问题进行排序。为此,我们要告诉Redis将使用什么模式来进行排序。首先,为了可以看到一个有意义的结果,让我们添加多一点数据: set severity:12339 3 set severity:1382 2 set severity:338 5 set severity:9338 4 要通过问题的严重性来降序排序这些Bug,你可以这样做: sort watch:leto by severity:* desc Redis将会用存储在列表(集合或分类集合)中的值去替代模式中的`*`(通过`by`)。这会创建出关键字名字,Redis将通过查询其实际值来排序。 在Redis里,虽然你可以有成千上万个关键字,类似上面展示的关系还是会引起一些混乱。幸好,`sort`命令也可以工作在散列数据结构及其相关域里。相对于拥有大量的高层次关键字,你可以利用散列: hset bug:12339 severity 3 hset bug:12339 priority 1 hset bug:12339 details "{id: 12339, ....}" hset bug:1382 severity 2 hset bug:1382 priority 2 hset bug:1382 details "{id: 1382, ....}" hset bug:338 severity 5 hset bug:338 priority 3 hset bug:338 details "{id: 338, ....}" hset bug:9338 severity 4 hset bug:9338 priority 2 hset bug:9338 details "{id: 9338, ....}" 所有的事情不仅变得更为容易管理,而且我们能通过`severity`或`priority`来进行排序,还可以告诉`sort`命令具体要检索出哪一个域的数据: sort watch:leto by bug:*->priority get bug:*->details 相同的值替代出现了,但Redis还能识别`->`符号,用它来查看散列中指定的域。里面还包括了`get`参数,这里也会进行值替代和域查看,从而检索出Bug的细节(details域的数据)。 对于太大的集合,`sort`命令的执行可能会变得很慢。好消息是,`sort`命令的输出可以被存储起来: sort watch:leto by bug:*->priority get bug:*->details store watch_by_priority:leto 使用我们已经看过的`expiration`命令,再结合`sort`命令的`store`能力,这是一个美妙的组合。 ### 小结 这一章主要关注那些非特定数据结构关联的命令。和其他事情一样,它们的使用依情况而定。构建一个程序或特性时,可能不会用到使用期限、发布和订阅或者排序等功能。但知道这些功能的存在是很好的。而且,我们也只接触到了一些命令。还有更多的命令,当你消化理解完这本书后,非常值得去浏览一下[完整的命令列表](http://redis.io/commands)。 \clearpage ## 第5章 - 管理 在最后一章里,我们将集中谈论Redis运行中的一些管理方面内容。这是一个不完整的Redis管理指南,我们将会回答一些基本的问题,初接触Redis的新用户可能会很感兴趣。 ### 配置(Configuration) 当你第一次运行Redis的服务器,它会向你显示一个警告,指`redis.conf`文件没有被找到。这个文件可以被用来配置Redis的各个方面。一个充分定义(well-documented)的`redis.conf`文件对各个版本的Redis都有效。范例文件包含了默认的配置选项,因此,对于想要了解设置在干什么,或默认设置是什么,都会很有用。你可以在找到这个文件。 **这个配置文件针对的是Redis 2.4.6,你应该用你的版本号替代上面URL里的"2.4.6"。运行`info`命令,其显示的第一个值就是Redis的版本号。** 因为这个文件已经是充分定义(well-documented),我们就不去再进行设置了。 除了通过`redis.conf`文件来配置Redis,`config set`命令可以用来对个别值进行设置。实际上,在将`slowlog-log-slower-than`设置为0时,我们就已经使用过这个命令了。 还有一个`config get`命令能显示一个设置值。这个命令支持模式匹配,因此如果我们想要显示关联于日志(logging)的所有设置,我们可以这样做: config get *log* ### 验证(Authentication) 通过设置`requirepass`(使用`config set`命令或`redis.conf`文件),可以让Redis需要一个密码验证。当`requirepass`被设置了一个值(就是待用的密码),客户端将需要执行一个`auth password`命令。 一旦一个客户端通过了验证,就可以在任意数据库里执行任何一条命令,包括`flushall`命令,这将会清除掉每一个数据库里的所有关键字。通过配置,你可以重命名一些重要命令为混乱的字符串,从而获得一些安全性。 rename-command CONFIG 5ec4db169f9d4dddacbfb0c26ea7e5ef rename-command FLUSHALL 1041285018a942a4922cbf76623b741e 或者,你可以将新名字设置为一个空字符串,从而禁用掉一个命令。 ### 大小限制(Size Limitations) 当你开始使用Redis,你可能会想知道,我能使用多少个关键字?还可能想知道,一个散列数据结构能有多少个域(尤其是当你用它来组织数据时),或者是,一个列表数据结构或集合数据结构能有多少个元素?对于每一个实例,实际限制都能达到亿万级别(hundreds of millions)。 ### 复制(Replication) Redis支持复制功能,这意味着当你向一个Redis实例(Master)进行写入时,一个或多个其他实例(Slaves)能通过Master实例来保持更新。可以在配置文件里设置`slaveof`,或使用`slaveof`命令来配置一个Slave实例。对于那些没有进行这些设置的Redis实例,就可能一个Master实例。 为了更好保护你的数据,复制功能拷贝数据到不同的服务器。复制功能还能用于改善性能,因为读取请求可以被发送到Slave实例。他们可能会返回一些稍微滞后的数据,但对于大多数程序来说,这是一个值得做的折衷。 遗憾的是,Redis的复制功能还没有提供自动故障恢复。如果Master实例崩溃了,一个Slave实例需要手动的进行升级。如果你想使用Redis去达到某种高可用性,对于使用心跳监控(heartbeat monitoring)和脚本自动开关(scripts to automate the switch)的传统高可用性工具来说,现在还是一个棘手的难题。 ### 备份文件(Backups) 备份Redis非常简单,你可以将Redis的快照(snapshot)拷贝到任何地方,包括S3、FTP等。默认情况下,Redis会把快照存储为一个名为`dump.rdb`的文件。在任何时候,你都可以对这个文件执行`scp`、`ftp`或`cp`等常用命令。 有一种常见情况,在Master实例上会停用快照以及单一附加文件(aof),然后让一个Slave实例去处理备份事宜。这可以帮助减少Master实例的载荷。在不损害整体系统响应性的情况下,你还可以在Slave实例上设置更多主动存储的参数。 ### 缩放和Redis集群(Scaling and Redis Cluster) 复制功能(Replication)是一个成长中的网站可以利用的第一个工具。有一些命令会比另外一些来的昂贵(例如`sort`命令),将这些运行载荷转移到一个Slave实例里,可以保持整体系统对于查询的快速响应。 此外,通过分发你的关键字到多个Redis实例里,可以达到真正的缩放Redis(记住,Redis是单线程的,这些可以运行在同一个逻辑框里)。随着时间的推移,你将需要特别注意这些事情(尽管许多的Redis载体都提供了consistent-hashing算法)。对于数据水平分布(horizontal distribution)的考虑不在这本书所讨论的范围内。这些东西你也很可能不需要去担心,但是,无论你使用哪一种解决方案,有一些事情你还是必须意识到。 好消息是,这些工作都可在Redis集群下进行。不仅提供水平缩放(包括均衡),为了高可用性,还提供了自动故障恢复。 高可用性和缩放是可以达到的,只要你愿意为此付出时间和精力,Redis集群也使事情变得简单多了。 ### 小结 在过去的一段时间里,已经有许多的计划和网站使用了Redis,毫无疑问,Redis已经可以应用于实际生产中了。然而,一些工具还是不够成熟,尤其是一些安全性和可用性相关的工具。对于Redis集群,我们希望很快就能看到其实现,这应该能为一些现有的管理挑战提供处理帮忙。 \clearpage ## 总结 在许多方面,Redis体现了一种简易的数据处理方式,其剥离掉了大部分的复杂性和抽象,并可有效的在不同系统里运行。不少情况下,选择Redis不是最佳的选择。在另一些情况里,Redis就像是为你的数据提供了特别定制的解决方案。 最终,回到我最开始所说的:Redis很容易学习。现在有许多的新技术,很难弄清楚哪些才真正值得我们花时间去学习。如果你从实际好处来考虑,Redis提供了他的简单性。我坚信,对于你和你的团队,学习Redis是最好的技术投资之一。 hugo-0.92.2/hugolib/testdata/sunset.jpg000066400000000000000000002607331420147000300200350ustar00rootroot00000000000000ExifII* (1+2;i%(RICOH IMAGING COMPANY, LTD.PENTAX K-3 IIAdobe Photoshop Lightroom 6.12 (Macintosh)2017:11:23 09:56:54bjorn.erik.pedersen@gmail.comt|"'d0230       24+8 2017:10:27 08:38:522017:10:27 08:38:52Тt@BfK@B 4d    smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDMNW*BJ08 A 3 K bTjTrz $Ax''Dd& d8ddWGS-842017:10:27(HH          Adobed!a1AQ"2qRS#BCb%34QA1!#a2Bbr ?h- FĨ‚ !* h  P>+~DADAM 4"hM4 O 4($L?1QAFƪFĨFā  (B((B: h77ADPI}AA4PIQ_9@b[![lJlH FĨFā ",B(,B:     Dh8  }It}QFA.dlhdh* Vā[ l* l(-A  ,@(@: 3~DiADitA:@N@NDW+9dhvDfDlZ"Fª âl(l*  h  O 6)A^DFxmZò"M6u. ( 'ShN; k#] ȕȐt2-3"@ͅPͅ+a@6 #`6!6PD}[iAbD)tK)A ]IA>, QBmTl]\ĈdH* vDlHQJTB6P#a,+aK4K 4K }6DDbDM,P,W,khmK}րmE,DqnF8ă%dH%dIaXVDaa[XF斴fYEl ZQ[NfӥVӄ)#i(K)BD)d% ZFvK)vRdq,>D;R4lZ)ie:c,C#K)ie%:K(̈%vDZ[eQQYEk3#R3"K(͉,Q[eV¥,BR)e7Mg6)<btSeؠ ا;6)btQNMtlS8b1ŢdIlSFd:&Fl)[F›&l*lQ lhl ndI[ԭ75X75P7]UMYMXaMTTn7]BT$)𩹫4*c74uGJT4tL{'bꎔS!b莐NGC)e;CD43itSt3)tRy0(NXW}ЭfyZ3.Kqhj)u'jiF§iFQIܽJ'q ;pzbSzRcSzF:@'ztSF{Y7ɜCGtQgtvEStuG{)غ:cv.ڧbƩujvjv.kb b[}6&u 9ͳ,?.kx1f!`^yu3Xg bjNӬhSzօ^;mgzu,YNSz[S^Y%k%[ ϲ0Oez빤r3<I\L|,8*kKC*ƎۤC*wRmil}Ӫ:ܵNVGKC+"ɩYu-u0&e\}cS63gfmXcKdhj-ezmj t5 $rիy_?ʼnneK;9mS;քLUuz*Yfy+jbsj8*bskbԞF*by% w\畸gb[5ݗU6툯yĠ9xO|Č<&a&soM;Ecn]ӭr7T=ڷ">cڅߥ},~^Nwi(.Y G?qoN! ?\ǓFa㗉;cόYp|l:G.?^'z%E3Ŝ5sL#Yڭ[ofVW`s ;r/ [rMu8sc(jD{+D/kc6L<쵬&nmI#%ҋk1f)HFMf!3݄aM`I&֮tx`iCAk U]i/6`>_b"rC&p smc#n^2{Z%!n79-l`hT돋?[鴰ٱ@_BS]Ʊd8@p:^ܾo|0t=ݗq47F+ߗ֎m ΤFmE^~} ;)p49BH~ <8#/l0Zh8AxR{-{t3u`ųA,n?Sůk/g:6Z^wS}ok57#v]@o5OOi=D[%pu?뺛RG'^?^~O0K;{D9"i`1o|ywFYZxtxaS8Qm6xlcqxsg]3}`ǏLd fi=n8aye) $?~*3͟D[va crG[OWg`%l ̪8Jny+E A)r< HrAB\${悸`;d~ 1r3AxIX ŘV=wf:_ۜxTaY9̛p(LlM{׸ qayu-ԋQq)lx 4mBi!cYI&")d&hFہ_(-_ 0J9(I\h\5 WAdd)Eg g%Q7 q'!ſct0tGa{}Q˓O1"~(a{\ai xg6䀝b0]`A|QkI20171027?083852Pbjorn.erik.pedersen@gmail.comZ Benalmádena_ AndalucíadESeSpain8BIM           Adobed!a1AQ"2qRS#BCb%34QA1!#a2Bbr ?h- FĨ‚ !* h  P>+~DADAM 4"hM4 O 4($L?1QAFƪFĨFā  (B((B: h77ADPI}AA4PIQ_9@b[![lJlH FĨFā ",B(,B:     Dh8  }It}QFA.dlhdh* Vā[ l* l(-A  ,@(@: 3~DiADitA:@N@NDW+9dhvDfDlZ"Fª âl(l*  h  O 6)A^DFxmZò"M6u. ( 'ShN; k#] ȕȐt2-3"@ͅPͅ+a@6 #`6!6PD}[iAbD)tK)A ]IA>, QBmTl]\ĈdH* vDlHQJTB6P#a,+aK4K 4K }6DDbDM,P,W,khmK}րmE,DqnF8ă%dH%dIaXVDaa[XF斴fYEl ZQ[NfӥVӄ)#i(K)BD)d% ZFvK)vRdq,>D;R4lZ)ie:c,C#K)ie%:K(̈%vDZ[eQQYEk3#R3"K(͉,Q[eV¥,BR)e7Mg6)<btSeؠ ا;6)btQNMtlS8b1ŢdIlSFd:&Fl)[F›&l*lQ lhl ndI[ԭ75X75P7]UMYMXaMTTn7]BT$)𩹫4*c74uGJT4tL{'bꎔS!b莐NGC)e;CD43itSt3)tRy0(NXW}ЭfyZ3.Kqhj)u'jiF§iFQIܽJ'q ;pzbSzRcSzF:@'ztSF{Y7ɜCGtQgtvEStuG{)غ:cv.ڧbƩujvjv.kb b[}6&u 9ͳ,?.kx1f!`^yu3Xg bjNӬhSzօ^;mgzu,YNSz[S^Y%k%[ ϲ0Oez빤r3<I\L|,8*kKC*ƎۤC*wRmil}Ӫ:ܵNVGKC+"ɩYu-u0&e\}cS63gfmXcKdhj-ezmj t5 $rիy_?ʼnneK;9mS;քLUuz*Yfy+jbsj8*bskbԞF*by% w\畸gb[5ݗU6툯yĠ9xO|Č<&a&soM;Ecn]ӭr7T=ڷ">cڅߥ},~^Nwi(.Y G?qoN! ?\ǓFa㗉;cόYp|l:G.?^'z%E3Ŝ5sL#Yڭ[ofVW`s ;r/ [rMu8sc(jD{+D/kc6L<쵬&nmI#%ҋk1f)HFMf!3݄aM`I&֮tx`iCAk U]i/6`>_b"rC&p smc#n^2{Z%!n79-l`hT돋?[鴰ٱ@_BS]Ʊd8@p:^ܾo|0t=ݗq47F+ߗ֎m ΤFmE^~} ;)p49BH~ <8#/l0Zh8AxR{-{t3u`ųA,n?Sůk/g:6Z^wS}ok57#v]@o5OOi=D[%pu?뺛RG'^?^~O0K;{D9"i`1o|ywFYZxtxaS8Qm6xlcqxsg]3}`ǏLd fi=n8aye) $?~*3͟D[va crG[OWg`%l ̪8Jny+E A)r< HrAB\${悸`;d~ 1r3AxIX ŘV=wf:_ۜxTaY9̛p(LlM{׸ qayu-ԋQq)lx 4mBi!cYI&")d&hFہ_(-_ 0J9(I\h\5 WAdd)Eg g%Q7 q'!ſct0tGa{}Q˓O1"~(a{\ai xg6䀝b0]`A|QkIELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km[ehttp://ns.adobe.com/xap/1.0/ bjorn.erik.pedersen@gmail.com Malaga Torremolinos 160/10 500/10 28/10 28/10 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 centerX = 0.317495, centerY = 0.539287, radius = 0.037149, sourceState = sourceAutoComputed, sourceX = 0.437723, sourceY = 0.539840, spotType = heal, opacity = 0.1753 centerX = 0.319353, centerY = 0.539993, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.262521, sourceY = 0.539993, spotType = heal, opacity = 0.1753 centerX = 0.315717, centerY = 0.542001, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.258712, sourceY = 0.542001, spotType = heal, opacity = 0.3316 centerX = 0.311387, centerY = 0.538226, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.248336, sourceY = 0.555915, spotType = heal, opacity = 0.3316 centerX = 0.312516, centerY = 0.541311, radius = 0.045786, sourceState = sourceAutoComputed, sourceX = 0.460210, sourceY = 0.541864, spotType = heal, opacity = 0.3316 centerX = 0.978481, centerY = 0.252986, radius = 0.027387, sourceState = sourceAutoComputed, sourceX = 0.894010, sourceY = 0.252433, spotType = heal, opacity = 0.3316 centerX = 0.974345, centerY = 0.252157, radius = 0.027387, sourceState = sourceAutoComputed, sourceX = 0.889874, sourceY = 0.251604, spotType = heal, opacity = 0.3316 centerX = 0.975887, centerY = 0.251968, radius = 0.036587, sourceState = sourceAutoComputed, sourceX = 0.900226, sourceY = 0.251968, spotType = heal, opacity = 0.3316 centerX = 0.596090, centerY = 0.159539, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.657413, sourceY = 0.192430, spotType = heal, opacity = 0.3316 centerX = 0.857023, centerY = 0.075264, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.785508, sourceY = 0.074711, spotType = heal, opacity = 0.3316 centerX = 0.936523, centerY = 0.223695, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.874509, sourceY = 0.204900, spotType = heal, opacity = 0.3316 centerX = 0.050101, centerY = 0.345555, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.114879, sourceY = 0.315151, spotType = heal, opacity = 0.3316 centerX = 0.055633, centerY = 0.343137, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.129739, sourceY = 0.278460, spotType = heal, opacity = 0.3316        qAdobed2!1AQa"2q#BRb3SrC$4cs!1QAaBR"bq2C# ?7iq[@m(@m  h(P`,`P.0YE cqqB(XBc , P.0; .; @ \ P \ v;.; ap.;@@ w8p;  Á8 w@xp; aa L! 00@@ L L v&0;=iq[@@mZ iE hEQB` XE qPYE (X   \`\`P.2Apq\`P;  ppB@ \ vp@@ , L \ \ v;a @ v;r&; 8ap] @ Á0 @@@@H&&!H A0S aa_Aiq[@@@m(@[Bh (A`PXE q (X (X,P(X, #P*pBupp\ v...8$ appB pHUB&; Qp\ N*apB;p'pCN;aap 9 @@ 8aaac@ Giq[@@@VЪ"  T XU @@A`  ccBX,!c a, pqe$  @@@ \ \ P.;$a@ v \ \ v&&.av B&&; ÅB IQ8J@8@ B!H p @@- `uKiq[@[B(-[@V@mQm *.0 +@@J(X,B–02"BX` .2(A`P; ,  qqpppp@@`v;.;a0;@@ L v&&&RaaqHT)!@haxV)0 @`L L L!Da?Oip %(-P P% PX@@@@Ae, P qA` (YE h,  qB@`\`\`,`\wBv=P.@@@`P^(XpqpXP;h aax@@ L L!*aaaRĂ2@J@@% L v0 Y1J@%`v0&+110?UipP [@Vm % h,"(@@A`+@@J= >!,` 0X,QBXA`\`\` (X, `\`PXE `\!Uq\ \a B@.0  #qpp v;@ vaQH&&;(B 0Z) @8@d* @ L``B [ipP P +@J((),PAa,YB A{@A` YE .0X,  A`\`\a ,  (AdUTpYQpB@X;EAJ(YcP@X`\$ Ô7B@@ v;@`L v DüA @J; )aa BI) @%`B I( B0&0 _ip+@@@ !(  XB PA` X, c(X`,a,)BAa,  aBAqq,dP.2  cpP&8$  @@}v.;ahv;;u @ L9H&!(8H! R)J@%!D @%:@8@@$V)0&?hb8-P%BXC (A` X,PA` X, AaH,  A` (X`P Bd B B|@ ಄@A{@`P.0(X,a " L!T@!] "aa @!HA) H&!HShR@0 @%`L`!Xq1h8[J- !Z (a`PYB   A`0 0 0XB X`,L"2qd,c .> PQq   %$ (A \` ..;hp@ \ v0;"{B8! a0 0@ H @ % hR)!D"`L Vl8m(A` YB a` YB A` PaH,A`<`\` .0X,(,B2(X )  YQ.008,Eü $ B a..a L v@E @.&.:8a ?'($Pd @% !Hp O H @8BI)t8iB@(`0(X,T X , 0X,! Aa,  , PH(YB  ,`\`,`\`P(XBAB(d/x,ApJ.2"W$H@ v p;p\ waa~ N N p'4@&i&{‰pi4N) % JBORNEB?z8!P 0 P 0X,Paa,)0X,@XA` X, Aa- X , B@`,` (X$ QB0.8$aaPX/$, \ PB.7B8' \<@ v;t\ wᎰ''?'4N p d@%,aDӀ H IA) 8@%<@% B $Tz P@ZP@@aa,) ,  X .[@ae, aA`\`,` OX, BA`,~(H, (QpqBA (H pBB@E A7Pp pwAE9Ba ..a 8D8Wp'pGCN4OirP8Z4B)@ qJ@&R(L<@JX,h X ,˜XB Ae/H, P  A~X,  qP0> P.]@X`\w@X@`, P.0X, B" QBwp\> waxS8Ea1Bu\6xppBR@ i @<8XiITM9f)J@% ily@zsP0X,X ,Paa -BX (A` 09B A/X, ` (X - X.2 P@@Z X(X (X'@BPN@ʤ c" !/pxmk@ \!+p(YQBv #u%)\ L>&6p^80R)4COÁ ;Ȭ-* "H4fi ?'+{<8ӐLi̧p{@x & 8 @8`zsPa`0T0X ,(,` X}P@X, 0IE X@A PǼ  q !BN.  wwx@;@a?aB E(HS!N* \?@9GaH(@8} ^+~>;8pN<1ri!f4KĀpiii̤i pp<@ae, a` ʤ^ܠ0 (,hX , @a ,` X$  AzЅ@ PH  , PIQB$J(IJOB  (A < nPH $  vx{yE8'X v/4@m\a4@;Ӂ @& Á ?i0ix ,d, X, @,06cA )AdR" $ YB  " Ǭ aaL$!aEXxU "ԂB.)xqpHa @x0 @8@$a % BX( @̧R)2SR)<<@urh4P@ hh D `h@ 0?E@a`h@@oJ_HXR, H ,xˆ ,XAdS -,<-0a (]䰂XbzAaH/.`0XA` ?,0(X, y  aL ȍO@A PO4 A  aB`P.0.;; B+c1p0 @% H(%$2`Fe" ,c6HX ŀV,trj F$_@ QEXhCUūE4 _Xjm ^Y 0kF,0ņ䲌/h .jAa -Ԃa|@Ad(X C % @`@@Z ay@@@`@ao`0_az@A X,PzoH a(XB YŋX"cXŎ,\`v0K ;,qXq ʼn H`YHSX̬,Xb+3+%V,fV,` biͰzBF j5 4U(abƁzWXƁ{E-ZIhDX mL, /,0;@ab0 0XbG8 ,X ,, $ņX`mXV ,X`HXX,0ab -"  X0YFm ", "0"K(ŔaLYD, a1a(Ŕab0eX,-H,YEqRRQ)qhq)Be;c;YN,cIe;lK)EEZЕ) Ie XXbJI`( ER,)%̤Y@R,+S2X `ߔYODl `hō0"ƪ<@/`5HQ@ōō a*ũa 4 XXao%ņX/, ~QeX((Y-h(ŔX)p)q(Eai, , (_YD, K(w(ņ%OiF-h︋$QYD, a"҈,YFKR QAbֈ,YF,,,,, e2YD, Ab\b\b\b\b\bv1e.1e.1e;YKZcS\d,cRc&1e!X,+%%be Y,+P( Ŕ̬Y@%bf$YLŔ8)1hV-ZōUbUZ4UVƪc@o%,5cU_,hS@" -Z(CUVze4 DX , il %4 AbՠXY,/X %av(Eam%[ŔA/Q-ha (E" iDYKYF%A>FXeHĖQ(E$ab YDkFZQ(EX,Ab֌,YDEAb0eX,YDK(eY, Q)BŔAb֗/,,,cR)q)q֝ZSZ\bv1e;Z҅֓,bBYBV,-hJIe XY@WYBVK( Ŕbe3+%̬Y@V,edYCYOUm[*Ŕ,ZU[ōh,"Ɗe4 S@hSE_SEXZEH(,(~e_kF,-Qy,U)_YFYFWYFK((>kDK(EA" 0Zфx$YF, Q)ťX,YDQ, Q)B,{EI, SENZф֌$(}KF)BƊ0#EHD4Q(Ɗ h (F0/D4QAcEI4abҔ,ZA%,R)q()BŔŔŔb\bv1kN,,4$+%e;,-ibLbYBV,+P(JeXY@VK( Ŕ̯S2eX(JE Uktʟx)X*E4 %R,e4 SEASUA֍Sǘ~kFSUH$YM}䵢 .kF,dPhQEH 5Ne4 J,%A" eI-hEa$ %a$F, xSf[)pJ," [(҈,YFZф(PYE-h}IkMgKMBI ~$I 4dFI4eBF0$4Q$4Rhѓ 2Adѓ 2AcKD4dƌXd.H( $4eBƌ1+hʅ\cFWѕh2eNMcK4eƊv2ircE;1dє4Rc\1"VMBhȕ&D\X@V4S2h+J( ƊJ DhTwʑkM YM )ӷ,iťSQv)Oj'Qe4Z~7h)h)ƖS۔hM>!YMkN,hIS-4E/Ɗ0S&$h(F)(94Qq &$Z1NM-dhJ)Ɠ+)xV228N-M% QKEEY4Η-IɄY<$ɢ/I4Q,#FH$2A#FH$h.H$h&H$ira$ђ 2K$M $4dƌXђ4d\cK 2ƌѕ4eq\cF]h˱\eїc&ƌɥ˱Bhc2cFD2cK"4dH$ѐ"6#K"4h2#F@eѐa.ag,ȗEU>eSmrhkMuE4TiU&(堧&h)ߤih8M4SAHcE5ZDAO)MkOcFZ }ExFѢ _-&h)bM94Q^6-(-F1JMB4QqiƊ1NMB4BZ54b\&)E8ђˤʄIa..i)xqSa#EI4dIɊw$13kO).MRM5 3a&$M A$EhɄ4dPirAcFH( $4dɣ*4 $4d hPc2ƌ1*6eqfWBƌYveqv1.6e.6eɳ.6v2mpckc&V6a mpIhف"6`H#i"6`i"6a Dl2#iaLa5,]3f]3"]%?!D>.J"I-8MV4iѢZlXіi4SEHMKM(іLiɢ[kF b bM-4ZqShK)4bhANMh?4QqZ}hLIRHwF1J4d?2BhƊ1N4QKEÍP&S@ihI Z\#IZ]L-J\eeBv2Jxѓ 2A$ђ &$i4 :\iraftL,\Y4\D(-Y4R(ƌY4Q-(XEh &,h &Xђ4Ph irAcFT,hc\2hc&*h2Vv2ir̨XmLkZ6e֍ukZ6e֓kZM]i6ѳk i6aKI0%d #0I#f`fci"6al0ͥ8dffy'T?=צ֛*)q&ɢ4SUKIFl&-FjMPF-U>Ѣ*IƗ-oh $MFh#KEh?Ɗ5AZhMa#EM4Q-4Uh h oZ,dD4QadKDMAd&ܣE-E(4RFˤ4dƌY4dɥɅKM.H,ΚɅ6MeBɣ&M.Vh˱.HdFY4d.HђMFirAcFH,\Y4d.H 4d.T 4d\ѕ4 $ٕM.Vѳ*\lɵ̬\]Y6e6e֍tmr6t\mMiZMmpk"O1p$I06` a"<2#0<4l30ǘeac3fn9<7'.+Q~br/-is)UIkMUzFjI"jM@ZhYMTFhiiYMmZh&06)cFMG4S@ZhhZjM`Ecq)Eo&&"1(hYEi4RZ $DihEZҁ%e-X)YUc 4SO=f=: O_Pר2% (؅Ӯsy/<~Z.L&&2@IɁ&3&$Z $KhNh4dh$ђirhZ4dKM $䀍@Iʁ&$$ђMTI̔\FHF+&+&̬mrMY6]2mrٕtlˣfV6tyL5535I5LQ:gj8:O1pB$m''`0<3b` yym0 ˴622c5ٞ 6'6"tns3q͉m?+] lZЛu%6SZUjD)Ɨ-I,irsMF("M1).LFE4XіM-FɥAxѓ$#FZ(ţE,hYJ2YD YF$e֖i,ZӷJ[ŭ8 e?/>ޗ}kV:_QtPi}] i>ӎ|xViJ.QNTXoGOWǩ~I~{ XQkji§Rv0{?9O>|=h$Ě\h 4L 4[IMB4@IR@I$$ɣ$$ѕirQ+\䄚\kirM.TII*$lʃ\dٗ^M mmrk^Mxم\,y^Mu\,cXtϘ[a.&|Ʋ섞ae3-&Rl6S%ei6mPk@ZM3&6d 1pɌba1&i|6i12c,sfx3c7&3sbx1flO-(FoB3mD=66Sa3kMkMP䵦d{e6F%5SKZhx)֚)e5[Ie4XPd~E4FQ-)1kD QSAƖI'h4\RiK}ŔQkF$%B-hKZX%e:kMa%]O=IW&;ky(i?I5ҙ|T2`+7 .Ȍ.\q}[xSӅB}V%TfU>Po">^IE2hɥZ3M--(2YKxђF"MFH4 DirFTI$$AKirBgK:k%&$-3^M.]q2@4Pdѕ\n$ddD\ˤd;k+&.l˯&.)IMvRe&LvRM6.2mD ڳ&6kLFڦemS3RM3/jɵll_10͚n:Mea%_YFKZ0,VZ@m0K(ÁQ^'.V(-;/AZ@K(Abeq줲;E;9,epΪ2i,WOmT3Rtڛ=0i88'yWXSQQp;lw5uPh+9><23g&> QU`~Bߡ+Ei-hIkDIkFf֔<-W卻u_b9,,KZ K(ihI)4A)CFiiAFH0Md 5I:)AM[ɥM-ї&%y4[鬭o3by5ΚM-:ftS&LƊvBME.S:JL)2hd&vRLy6((mGZ6 la&fDi G2i62cj1 mL]Li4͜FMS2j9dF'"t6J|Jj iJ d;&&j*"Z ?9)m䡨JiW% ּU;V[+E kơE@ j+E1\m cQhS1\w!@Mu?;9^Vh%J!\EbkF+kMaQo2Zq,xZDS~-L^4]w6 ZO"gctqj{?<9rro`=si~Q|Oak躍kzR؟{QE( fy>!?\gZ-OEQ%4DQ Z $|kJ*֋$^(ֈVZq Z fmiEi-r\i, ZaK\&mrBLY1VKZ.,^',qd弔u1CEjIKf5]j2REAWh5^d!%5^bƯ̔JR;5~d!bz05#-kdZh5^dZ5ijyjK2-/⤵Ϣ Vm+>Yx^;q|?wEu 7>*^78ޠWu+=*wO_.:{=.YD߬5_`~ P)FEEE2CR;ȴcP;ȴ_i ^d~&fڎ%3-~'ns3-GDxw&mp<͘N<͘w͘wKL;%!^few$*2Bh&mWͱ0LķM̹KusNS- 2a6l[90mLIX:Mi%樢kN/-KKn"[v X[uy%8XM7Xo3M-^n,Zj8mG͵f,P;5'R:D1yS\JĈ}<'N>|rʇ޹F5ST5t=:֝qzD<O>+M?^HRp?u"N^ > +z{+NS#'<=?&r~>OOSāF~O _V_M'9{Ci/h15(6Co<SS]G5rH{#~mCQN~|\#O#Xl<9x>&jußK;wN|/S9r%CBTJTGTw=.@rH2ս[mZT"M.\98_JA8*=6CyӚOǜ\>Վp˭O8ʣ*U͕]’O`H3 <>Bom'puFJSm!(!<~PGRWQ^k?IMG=#Rv|&/ZJjʐJkRJS甔5d1%) )HkJC_i)TkA~8\O3JW:fGkT"@# =6koY~ю}iqo^zQ7NJ@Dy^ 3~P}ƪO"ᦉӨfxx.jzܧZ5&;)E7fe0"ae0CQeDEaky'texJ9̸L=t̸r')p)qlg794ͧ/6Lq樖Xb][i/ V<5זVxԯ,Cqyjj<Α87[ Un8w#Q[W_n3P2< v+* øPAdR@ J ǸׯTV3fcG,(`wm^UƧGTҬ9؃q-wxq]O%mB %WQ##=g((Z:pF9rt׌:GWzL]UZmQن >6 &lP2$1L-/Yj/3~~NY{({Qqjݪ/ҟtԏOO]R 5^ӵ n:6pnO ;|R~u>ۏUB[pNm1?-Ǎ4>znz֕cor"|pKѥt*Ҭkgz\%Q>f2ҍo.̘S38[1Y2cW~e1&K=۟KCCG:G\09O{Z3˩=ӫze!ĩJ}K*OQE| ?QϗGwywgZ- jPpC'fi筴ZXliMU|?(֦ͦafeYQ/g>Xo9sFU9."~9}u/eQ&Vky2_&K!=RamFߜ[!L[!=מa/8U=Q&=@ D8n$ǩmbx5_G1]̘h|WG̘U0=G̘U&!'UL)P&z5D=@w QPpC^;市39j ƿ338t13<"kykOH38t13<[0CWLY gCULy313'ey.sW3<\JpPS,YrУiHx~O/){i *yKKO|N˝=?8&|ܼזx;qoY>G_>Ks)cyM}W tuHtr'qg^k]EQ 2Rөc c:^pԞ}Yy}>TPI$s幟Gs}.qȹ#G9^?/VB&UR c옧B7WMU:*/agD ofz1GՏ&bg_i'jyd{D4RH.z'!O&Wpڃ'Q)<U_]ei<=Yg]V_j9VO昞'L-8/di赸!gɖ OO&WpCՓO%VCgkpi8z?yyRVz!c3ZKLqeW'-nz?y&[pcfz2rOfz2Ǭ'&]#4_Xbz2)8F]#4_X}e9CUz?>їX 8OF]c6_V}e9CUJ}'.R}Fy-'-W]HzS5 .sҟg9 pӟgר>]9} '}rsϳ4vfx|OivbxKχ'ԡZ>ϧ/>2ZvHOz]J8ЊLq~+=W.YR4ݙ`}BO|3u9"|Ʀ3zyxz=zzvtr Ckg3üwSsӚ>ꏧ'I17@_qOt:X#juq{}.PpZ y|MVH/α^.^ω 6&ㄽ:\Qtҗ˯47~=)z#/W4)vVDz}o[ӯzx~R˫ËWN/OO s=\|ƾT\Lә* /^V66po&͟gQ%CFPTّK9 Y>>VttƵ%6/ vytOJ} [F3Λ ~Sk|~Ѩב>czZ5UkJ-Pl~>B0'PN=0WBmcүV>=7VޝZhV:pD9xC[I+ѿP`xo>rzƛ_@: :}= SxR='Pjڇdҁ]@$LJ|}j=7KP(!C#ǧ]9R9mmVu^Ԫ 5j``Ia:q1\kׄ͢L\α.2WIvnv[^s8<}Zȫu$oM~{EԭUVq7-D/ϲO^yYx#W+ZypǓϷ#ҵءXz<>n}j\h54Zf:5ߕoL];}?W;9^$]xW>CvPRȆ3}C뉶TlN>UP V%CHrT=AH Fy>S#_@Ԥ֓8#?3> ;G+Y`MJ`r8{SNH$\n{|%_J)x>uO@pv>S '%[ob_{w:s>~}w4>ԧ긚ʊ]hPL^WbX~lŹz /7kHVZE]r x>^HHS.y}Sdk:EE6b>`.ݯzN_7"c}ڏ}:TB%6|Ou}4[nD!#n-gtGTOM1S>V̓x}ڏuV:m73>ۏuߔS>]ZLO.k)}'TvIc>G+[U b5H3/isQz۲ngmǼG/};2ײvt}t_ݺiu3J+-L_~\LO:>gXO+оF8F}tG׏?ݰ_V F?x~ԁ#ISc"m<>qt9/=&T <|t G/zTH7ښ'b񷗭Δn?iiFdS{}'t:c+Ǐ\ӏOOw߿qhUM\|#=^]^q9|Oח).ސ~\8\~u^zܮ<g<}xZh_k*S-F=QOmז':^?g|}_z5=B5@,WFgqkkuՂz?9~_ǤWPg=M;1jhݽ;_K#_ǧ?<R:*v' |ʭ/܏{:6T|OH'r=~<ܾ;r(6ө# U5Q$k?)ߏ~<3~I?W4mf NC"'+G_Q );GZnYҁS>̀'݇)_ߗkq'HqrS짦KTUn@7.#`j =7?1>#Kl6^bۇ$vR@YM.RQlƐck66S%RDEE[]&ǟ>vh/kn<mEXb]+[ m~R m"›J X-MQr`(zH ੷E F2lznPKast ,vSQ7_R(_Y%U(7İ[IpdW=q%(隟[kX\4/Le2 ^~rQc(*ïwT"$nrTzAT,SkHí7jPzCLw$}L|tLQmI-*R6NH?蚑 u *w@k8|N%zg;Ө>,9>~(j5)P*p#a3I?~Zm}\Wpy݇a5"S/tꞞ]]:=7"y[SZz\.dwn(;U\,0ldyF$t?ziϰ 뵹=E,Vװ1j P9 ڙơ' ExXZ~:-­/a[ff;rּj@i(O"X.VP)2'eQNVȲw~ E[= i}1F2b-V5ic`//5hizF{q3ݽj[IzZm[7bBߙɁ;s {FTPo*,a/OPj,rbK\;#*hFjzAHN50;7=^fxDZSZikraB}Ѧz5IVMIǘGڲ૾TbrR|MzUڕGRPCkx>2s5.~&7~[%4?U{L+42.N=Ox p~s.rn:o*VU9BG"T>Ǵ?^jתʌ]|JaEôx^!:cWY:*uEF[Hg>=.\#ֿO&C؄jGB8,(n5>}'6hQY~=ӗ.Ru<^Whe}[\:V*BE [{_@zy¨Pε(ud_S3_1}?hi 2dפP =x)}nofU,I `H>gSOtlLwWdu4NO2 $o|D<zGm:=M>w4us䚡ϬSnj[Q{5N᢬IާO7x؇Ʃ]2uj*YvjfVSDv|N3?UƦhMu7;G<|?wޟKE*zcz0.t`@mwDQp[tț ޺u!* E"P|Ko=ͫ ޓd [T$sT8}V!ڄ*hF(Wo*@GJ>]4:QAa+Xމvw2OK6ɕbڰ_7Z*QZiSH}bTZJVɳćEUJܨc`Ou"jq~P5J+En6TpdC}=V &V5 y"u*X+0`r߮3oy`%CԪj|cFZ04k H/ :r0KJ] ?P )i.AC^>A"uLBO=Tba'/R J;FI%nM[ X97rk;%F֊j&y)b^mYkaߑ:yޗzALv,@/+_tԙ{u X=\lGn9qzL%^yyz}j}g [y'GuYeer6?ˣ暿5JGӟRs1o1bx|g N 7^q~󝣋=O5T?WNB5 䝘\75\5DAOrvZXf[\RdC:7V',R+snnI?KgV=@/9Y{4~jtm=FRñxr GV1VB,ZFې<}X];+iF |deFu5Y8Y81ו[Zw .'0W?c3EZqV!ו+oQ> D;m#ÜZsmOA`eYI.N<(j/H;ub NbjGL^ɨ}52@{-&SMed ˙pz2ԥWRjihܙ+ά؞P: 恟d!:oU7-s{PvĠTi9޻|P|O{= WT3!եV*m)7Ӯ/l-\o}ȭRss i|P0<_*('*6EEFԝ5BBi:8VsM㐔x)j]6="Gn7(7cM 6$^+2l8}IiSD)r?v & 4t54 @[<% #5lJk[{wx*{ST{2 cwX2J4Gms#ad~6R@5Ht}P;<{mQS`O.R-0` YO/*lo4s@RNGe_Ơis{@ JPP:Xs6$-j@Y6jRےdPU"Jkkc̙,IQtZ:tvΛWNqsy5keâoqr1N(N O3Ӈ&R 9az5d14ﱹڎM6۱2rìjjYc˘Gg˽R11^y򺳮h.I 9 Ei L*i$j!s~v4h91߬$w@{>!S|(;Kei)-lO8UaqXhFE-iKS\cw|YH=8ݻJiAFɷN#,A2֚%{ Ԙ:ǼazthHJ1;8j}=+r} %)PJ~WvP݇+ZJ |"NhuȸS~KzFD*jG?S%JaL髵jWYѭJm(?/oHj&?uj9?mR,z =.$RWT7sk|(iiEjF;Y곭JqӥK"s6MtZjf*Pij-AM~@$SіWAMf6 OɌ]uZ=+QSGK Q&b:Q /K=KSzզ4fYo~@3Q́EFu9@Β8U`{Ǹ,ʠ*Q 2LW±UJ;ELyohMYx0>m h5He13@r\@y5T,+Mk۸Vv8$GYF0(z|ףFXVpP~re %6U9v6L)w{ALn-ONRot2+SEJأx}7ӛ%F@W8h2oUs(Z {VLkE룪ALT#6 ؃S0;?5K"ݤf~_)@զtG26>G( Gmn%-SRj>DmjV(Lv5,`9 P̼ug_ۘAo}UoETnIkߜ[Uf{`nB gMK ôt*TEI2D9;(=Ѷ]y:4+\rKiO==JAG6?ia㙦Hw: D(<ܟ"Qu ccrdz\wvt5⧸ʬ ok%Pq#V# [9' w}WˬJ`_GPBUkM2т̀@:j IM*ÖC}( ȫ^ܘjCvf=4 n{j_ O}V9ToO9| ήA?IRΝv@zbZSjYЙoN׽"ir2$cf@\#dG'9H+H/eO(ɖK5 頢7rp9TcU. 6Lp-&3{NL>JoPV¡^)rFv; HZfdQ1',˱ y.@@QQs"gyxP R&]]"rizccM#ɨt#ѥњx5BQi&kiڍR eM/KiONR9-iRE۽S"V\˴Q.Wsͪ,H^*(P)+sGeh騫K::vxkӦ+)JovPn?YQtɤ4J^ٙ,~L޵pk)R+\?2A^Fz 9^تEK2w5 [AGCPE}YSTAQoVӲ2 u[nDQDDYzDA)$XUkvUC__uյʭf-mEE2󕸵-:fvdČxVS"A)Pҝ ^R+Q>;H6ckU9GӧMh Jd\2u4)h+dz L)d~7ZiP..Vw*5>p70<:ƒL{oQy9%TG7 ҽ,~VcT|nBTAM mRI*+lwKlo(ū~k2lj q_UV \_-XCajy*Ң5hŋHTrI[[x긬(ZÖ=zju4੢B)kuPֶT D%jTeP`;^%IoPmJVXiF#I!*A;b9(X.bA|o֘SUi vn630+zZsr-v#)m 6Kٱm,KoIYgY*5cPEXs1*vbVWT-33-b~v^ Iױ5#3yfBjU fЖ(} 7!^zt[TDwWD`KP.5&mc6'8)J %9/9{o+Jnԏ&Vl̎FiL~x8N" ɌuYOQ9،B(gYq]-њ.ʟUP7V?U1u*ZFZ y"s[ގu5 bC@'\I3KMihm;X4 MP:LFCdZj6,*n-T{"j gX31Q1t2w/\܏-kE>%KªX߸;Lw^ua+o ȄN6U!]B_e;Q ZlrT ٢x nծ7j6]ŀK6~jkVAr"$kz -$n " (SlLnx^*T[0(WPI'V?A3nsOFsr^A,Q[A8@MP6ב^J["U]UB^Q@#s+:a رi6B&Fطuj{ʷ^PMV gZL{-ɵJԂUT ڍUʱս7=R}=b%M ]V6Eĵm,fb0er=߻cZzA[N+M iҵTMIRjMQ*?XPBԀժFA+u*3R_K&nKq{I_u>EFUoCn*e4t15NnێpeOTutҦ:\!lWzOOM4 i@7aoםX,ܑ~{JҚ-suyuf$S-`PzcH~vQS`jW`-f[ ®9T6TKW z\ۜOMAkE@Qhs]hW=5ahUIT7O#Z_H-FۜM}E@@x" @@,HzčE`ڬv3+SV^B62ZW̦j: 4>tgfnBѢHe iCQv=!H-C{32V&ROrl?)-irC1,drDq{=GӞ Z3-qoJf!|Xe򗆄1S"L5j]U{A%-`T_kY`X Gj\S{ [ q9֮^aBx#Q*eϼE ߠJjlOx"1Q\8?r䚘gJGMV7%}[u (e3Kmkjd[ Fn|n iѾ}dWT "\xHí` [!ΫT!eeS@R*GSR[l2:\@?C2MЫ>^aItM^-̙u5l(~(R6&\dw5j7X$KGR2/S{s2[ΩӪ9:VG"7=yf91$daR@'x k+ehZlv0MNûlyWe ^QA}--%U̢׮qͰ7W)N*㜀kcqVO䲛#{WQp.vTiJuZ4H.w0^a=[[0DT73(q$5 p $CӚ"k0b}|3bzHvO½= śXF Q,*u$;\U XH &X.*IaNmxZT~gdMxa`@8UɑD!Lf*sc Gd/ -itV@w٦hg6s&!rqE5aO+ ؞QXUٓ6&Tvb}5?/8& M609#Xu&}![k?nCnV yhխ{o$>N!P6eݷLbnzJz@Y ,Ս%0E-ui$[xq);Ef{G6AsR {VJqn`9ܑ`>҂Wk1fbd0 B *ZLVQ(5p7!Wro (Z5KqP6b[H9f6qLXXrfyP]q!-Ak:NJt!\B("MDR[.+'\~RX:ٹ x\]m:@6!Oޕ `tEStSTRzF1%\5kyW5g[`Ve 0 oњ3[CjNj;(۰]t"[Jj( MD`Ijʥ kPS#ıJx*ך\MSTT6a-X4:}a\#Rf:F{c~<:@4^v7H u0#TdMޕ%fMPç)KXT A8x(@-^A =47nMo UTs')K۔XT$EȧU.ͤa"c{Y:/&ԨbhUn9㜀TR <|vzk-O){QV߹߼(2H (T[bf(7`9ʎ|Ù*<*]Z+amZ s&Bބvds24+Qā M /l&0\[``hW,J+oRRTR0/-4JiNulFĂ9J o&ñr8K Zk Ԫ5Yk KI^vIkOuLP},m6=/Ӻ0Z׾ZiXT9_CR-bOV*d&jֆ"=d.qrX%&jvb,qm:R +S{)iկQv/~RtpS)BΛ|-x03\`m#mow"bKERەy5^/y\ G(KM$ANrs[P꾑P OZSCQMd*SUم!\sM{/n%ZQlK5/?Żӛ(;:@Ω[yfH 6<ŷfNaB發MC ;NC-$ `TTjVR4* 옐2 FJf6\QTcƩH A|8-^"jRZt2#wZeBe[ҫQNKEwۙ%\#dK?DDBܱ]~ jw7[}H0W+6lIskIWYp5l.YrO[^VXҪ_D\n`]Vj dP [x5:UUo q綗RXSXkW5΅OkH\SR[Sح۔(H:B@t0:+ FغGv6@Zj ,mdP\XQ';@Y;]nЛs0mB9@ƵEg\(Sfa!V_j~NMꕳύ ZK>UV<,LmHoAZAu ケZjdQP(̫5rHnpWTY{n XPƟ izLPU+֑m8:-1lߔӢLYI ^7Qia$v8j5 Ew =K_tkI-DU<%3QΩ,.K,lFU?EG~%Sf# ݿ)P8)$Tf&۬#Q5̂{?_}q+W4Jfj+](6^PQ~!p*mm1xLwX[H+}Rfz_MTcq@3]?QIjB[2gZ 6%AlIKQ ܮO:^5S }& fJE.(kh XpWߜ0+tNm]ME핟}9}MyliZ}bwoa&5RRQsa(w P9[M9f + sG֥ J=?wxF&N%#đIߕGm9@b1=z!tt:@?hh@t: em BL tvqrw Ɂ/#/bts+ndw ?a*0BT6˼rXx`lihss"ժF9XkK`IaVF`uk uBhX} {s<¾MR#jhwݻLM ]~kLk; K ΂v&T㔶 !bZ**e]: X{ve {%C 0CzP݀)*[&AOL^-N"cS&W^!;»xE5+U!G!PQrۤ&[<{PQb[*r BԽ9rmB1>I@@*8m ,%D'{¸akHs̢EG]M@G+}IѤPj-R)[4|,3@_( z[F΋P}=jWл/U)dv$+Q[:;UL4Qb)wjckRMǛf KS[TTɪVw!.?A,ԉ*Uj \{ߜQiR;Sz|BMbG@T)z(wzCj*rַɨ̽FGN/o5~2oFWzvKs%[䝞M7- p{W?,vyu^OAh6R߇|וToۤ2M>OSPn@+ێ*)#w_u.|ܕxMӪ.m!5'\-!<,̄EפDTdP J1%&crj.oHJԢrXU :IEבFJl,CTLm 5eEJ `D -*Zo8\͂{ߵ" cD`pq \FOHv:`w=uvt+w8c`wO08xr??"Bc+'PE07a(U=6< KCtVa{{B[YA MVnuN*{~ =a+򋐽Z \ txhHrHn"gSPŹj6Icb7Cr/ ӈiչ]9@9 Gp9y@,I6%`9S6MO@=E[`fyKOP!"6=KsQ3Q pm݂Ju~$2~JӦoʫU);zO@Ԋ.&jMl^`X`9bdSBApF*vvHpT3aD$}6Kmk*1Q*{PEwVGb}gS5t\骾qMW鵺TiT}A7iu2PivΊ~r%IkLYGj W :>"}|UTpU[RqM"iVTL؊"6J81͗v$<֬ZAvAUED;YE*~c#%%*ڮ4MflimM=\=FPMFh&aD=@ Ev4rn$WV*i!`6 /Y֭*|T<Ko0Sy}ЦYHQX_:bosN?!4ĺ*<(5ZVn.5 FwZi~́GmFE6O,RuXSϼ|(z)lf<jѷH\^ۈVliG@p&#ۗ":ؑߥ?$6m)!b- Qrld(J &/n " JwʍNÖwňӯ8ңglX HIu ״&ِ~$]I.V s عۺ" JlXZoq!۩$NȮ'ŠHЄy@|Hij%XVdZʤ@ F͍&FJ#Op YO+y pf>U|'HUߙhAP67=`lo(vLVvm)}ii- MJ}+m iЎqWdhYNYB,ݶ*/ G3x 9 %3$ Pkʕ!ISQmVb݋Obf5UXNN 7DQoE-FPTV;=Z`2LAgհ=@ o"PYZP؟=>)]ѫgpwyZd,@njL:Cۈ7Z]*?徹rRԨ[NY'b}vSAް-)P֊UNSIp:rh骓Ι-,T) }+OD}Z+5liGQ@Kc(CFj4VlyK|TMR [{hRVO(a) Rl\Y nW\H. @D>茧 ~=JޔBE/ol QʮUO6 0vXGQUժp7=}Pʅ-=P2jk5Ŀ3]j=*IAkf~{" yF5MMscX3TG80 pZelvFImѦa]u4od]SS;ö5ii\*Tp>r;!n2кMf-E.u 󰖒ؽ E Keb6vr 1b67+Qi(VԐj GjRFQU\_Kcwyx:(x%+ Jd>'F !O6 (]yQ4:ZAH ȦUE%[Q*p tn#BKZmO UtQȫL);uß73*)q֥M@[򥳭@Kn Wbו›} ԃjj ?bbۥ-+VO?QR 2$&ElޟQE,%,~PS#zbŰ /J8[)rjdh !r2no-֏ UVDz2{QEt-Bjʰ98݋۟EMYDL?i^ 3*6(8=ժfbGܐ%*n2O5 bLʊ7l:moh? Tr/,x'6x(D"%CQ KǼ@B{*R۪P('nf(boȋ[BAo*$ܯ\`uȁU9iTv;BFW<f܉ H%ź.%VnyB:9ۮѩkZ׵2W)!Q.pD9"㔡ܟlڎ*Io{򁌃Q ֓*[@hD,~c6>|-kbn2`KS[UDU*eQl[UE䇑48iRmM\yNpՏ}$ 﩯jcek*!'u`.eԥ75!STʼn2+_&ѩJ}FXR/]>+1o0kaÝx#˩J5=7ҩҵ,"&}b@J: )[fz"W@ɞ+QJ/lCT* 3[*T6*j#-kL~PҟWQ:g$q:iƜ@*xekG8fx} Vg4RzP˳'[KXi6r-q ~r̤hk5 i֓N@Gk%4EL@܉GjUi SZ߽>l(>I?k@!r{%TܕQaTfWuz5TqQVQiӚ*S"ĭ*Hn)ʘj]UEeZYAE0 TiiښZ:H8P_ʅ ~?hh UlO[dh+4RP.ȨܥCj4 2ZfSďJoN芔V "yk+Рk& oٌ.K(Qe5BZ4\(?4}R55;*6_BvrdmmWnZ #QGMBT[S:Ҭ|:/xѣM:G>@oJzom MdӑEH, T/9>Υ&KF"¢vѐQT,>Nݎ!*Ҧ馨lG r>7YPPyQb7=̮8Y-SJG#BUe*Rw/66[ZECj5Z&pt/d*e7ЭO[az /gjw4'牼wriaH8U4R!$+iiu ZQ[?(F .XLQo-*Tiبiԏ,|GU5SMi"<32 Q*A`-ne.tVOGOׅEact:*QiUh}"ѣo{GQ[niQZ 5Gu#z&]JPÕ9-^m:jj%JZjPqCuLQ5 uf6kʼnFH;ީnX c|M~S$TH}'ZT=ESni-ۚdq6j&ÇPOq E)wZcsHYTĬ)K^H4}[w)d.\$(bt̀:,yj_t!خ$礃" `~+t%ZmTdr@|-kX~qJKq9_R3" ] \3xU ^1Kl7cRġ;.iA` ݱ Gnp!lEfI?(WH:TH@WN}+iN9}XPyX}oS8u*ߚeosxe?̇l:xnrSw;!▔ck}w},jQεZQw\EƁ**Z=;W;[^E89OM]$~R՞WTHedh5:iM߹`~qP/y[VjSCٜ KEE[7>Nur?95_BkzQZiP+Rԋ/eo/%Oħ=Aj=6,Zj٤8t/HjWr)bm/kQq!J[Ij ?8]Ea|jOA~쫗*i)TLP@"jlPӨ)geHSJtuȰ7r2i(ĭ*f;ۑ05SSZTWuLvo#gze5ڋos %zuLB髕ÕPG 4Y¿ڏX'躦NEp?sER3 PF2jE_P9ڮ$[ToWOSĭGKtH P|ȸy.-)j)FS@iZ*>E|E@9UbTEM70"ƪ = i-iX,DYOU%J0&\Eǔi4?Θ7QP@5[V3TAj;Ŷi,+h%m!57%-M--Vm= Y]U3wɵUON`Wlk;zmPYX2 ]JzkH_QpA)8r)M ^ZOk!e.j:]=[ƺۗޡ+5tE͛Pž셥SRfh SԻ!,-F*RW< ,lQQr$oEIE[PSTFB,4UuNW{EjRLЩPOE-:?D4^ʕX#=6)-_O_Pi;7FSQno`bxByKoWG--5TLEfQRin-Ԗ GJҠ*諵@DmvSF_JhӬGQ*W J 2o!~.ӐV;a| dOH\*T=Oaɀ̊::lj1ff'~w+*L΂iTkܢV@.h^ۆHA\#hT,i;Sv悡u~| MHV:-fs<ԇ*x!LӦޢUlQȇR/-i@Ѭ\G$Zq,  pj7kiSț//U)ONVWFZ\)v*H6h-TZ)Rz5 Tc@-Jdd(-M@f g@Zß3}{ E+"-"t:@zEZ",BE N [= jʌ;l:5*2cɼi$NUO~RzȬv[_,9Ef\ra#m8`NP:$ FNSZgpfZ%V2%EO̘*I1ƗqS,q^i:hRU]mᝬzc2КgQtP\SZT-JLr+ša|9mNuөH)!i[SԊt:Ujtϸj*GsͤP+j}V9rD./!S7AN(Q(`q6` ۣji_jkjuh U_UZiOZlpQkӪ;lK5"At)j!:6M2UjW9y)+fhZ`Yj-{EKD~"u@XϤ#SҿZ.Ts%-4BhzW7,2m(bKTmk//tzcS%>#RE|zA&Ae2IEzOZRj " *QJob~ =jl)wSQXdrM= j=FG7+Y#sȓqcU j4RЁ܃ T91UoӬF/Mwm~״ M*R"wT4Sž%+``WTc6`\sSoNDBOܩ6̌G%ĔEm=UKlʕ6"*Hۃx *j6\AH%Ў c`UB s>7ŸK QMPd8\X5RE@*w#/)xeyJKȮ۴sxB$Ю&ڤvɖ7pLJ/NGu6~vWknN?1pTКdq5:]bM}-""5s\7\ j~N'PE־R4i, ᚗ* ~6ZfU2~mY2(?3%<ѸJ,E~_]Jd MGKٟ^Xƀ??%^8@>ZG2x楪>'JI+_LhuWO? aQLXiFPuEB؂|^T3& xʎJL«e' gN|IS0 bTj]*&OznMl͌T)ׯQoUPjn$k,q zAjWI$ ן¬HEցU\Vze֦WJu,*y1@SM_K]Ɓ$YTOQT{V}AңU-e?3+%[~QHKrU(MC) \bs&XSk nY_M@CkzrQi}kFŪ%j5&,g7i.S9~Qe>P2xe:PQ CѣYXTBìjV%{Iyly)RN ckA_FtZmh9ު*(*wnCQ(5K6m,);#Wʢ JRVONC֚:JIm-ͪGKTk^R8gWk ]P[j4NJi`~VeZR!m1 XHmznOz|JezqT ]KR*5Q֣oQһPҝC8  AQQT AF(qk;}JUP~$:2-a&[w4ZsTzsE9z3OLM*&TkE+-WG RVX.*WU*=T ~5-gԥSMxU)Z@Y[Mֆ+h^UKD|]Hl Uߕ[CO[-%$,j ;n,Q=%]Z(zX V?(755:ZR4 R}ă5-Ik-&eUJon۹0F᬴8ԫM8;.h2*&H] *,xk~E}AG]KQF*=@@~:R(tҔո{7g[XN +j*Se{AQlZs_I-ApzA2 M3k=L)#q=>3=OA) K.-*ۭ}W)jj5.AEݻUw" SҧlB'Pv;FSJLڍUPB*Y66&د^;S&BI5idWxj)9UJk]Ÿ*ڕP@Fﱴg-:^4Hǰ FJ*DA2 PPtx6PO`-5 ) M`ErEӿ+*Jt.WcFցM5tA$ eKz-%1 'ԥV .mpJ+l•S}B\NGljŏH%57,~}dVQE\s' YseM#R@<(C/;"kZc~f®!ׁ$t:fR;SEF@򜯻L*VnC6Z;LLP@bHm5\bаDw V;_a-َLO.@¶NB?:_㦭Pfy,>LN> zY['cϙ&vqeWs/7)u==B!/P{h}KwmUBSZa[ lTAMI`ykU=4RG*U]_ oeΨKWMi(E;]^j16HmYe*H)QvjIzD@΀ =U&$էMUJr֭Y\`HiV/VeYb =/b^/i0#HکEed=I *TvN8[_֥Hh0E ) HZBƫ$Fgzf{ܓ2ZIa%=TT$A^1 to make it as readable as possible. The idea is that a > Markdown-formatted document should be publishable as-is, as > plain text, without looking like it's been marked up with tags > or formatting instructions. > () The point can be illustrated by comparing a sample of [AsciiDoc](http://www.methods.co.nz/asciidoc/) with an equivalent sample of Markdown. Here is a sample of AsciiDoc from the AsciiDoc manual: ``` 1. List item one. + List item one continued with a second paragraph followed by an Indented block. + ................. $ ls *.sh $ mv *.sh ~/tmp ................. + List item continued with a third paragraph. 2. List item two continued with an open block. + -- This paragraph is part of the preceding list item. a. This list is nested and does not require explicit item continuation. + This paragraph is part of the preceding list item. b. List item b. This paragraph belongs to item two of the outer list. -- ``` And here is the equivalent in Markdown: ``` 1. List item one. List item one continued with a second paragraph followed by an Indented block. $ ls *.sh $ mv *.sh ~/tmp List item continued with a third paragraph. 2. List item two continued with an open block. This paragraph is part of the preceding list item. 1. This list is nested and does not require explicit item continuation. This paragraph is part of the preceding list item. 2. List item b. This paragraph belongs to item two of the outer list. ``` The AsciiDoc version is, arguably, easier to write. You don't need to worry about indentation. But the Markdown version is much easier to read. The nesting of list items is apparent to the eye in the source, not just in the processed document. ## Why is a spec needed? John Gruber's [canonical description of Markdown's syntax](http://daringfireball.net/projects/markdown/syntax) does not specify the syntax unambiguously. Here are some examples of questions it does not answer: 1. How much indentation is needed for a sublist? The spec says that continuation paragraphs need to be indented four spaces, but is not fully explicit about sublists. It is natural to think that they, too, must be indented four spaces, but `Markdown.pl` does not require that. This is hardly a "corner case," and divergences between implementations on this issue often lead to surprises for users in real documents. (See [this comment by John Gruber](http://article.gmane.org/gmane.text.markdown.general/1997).) 2. Is a blank line needed before a block quote or heading? Most implementations do not require the blank line. However, this can lead to unexpected results in hard-wrapped text, and also to ambiguities in parsing (note that some implementations put the heading inside the blockquote, while others do not). (John Gruber has also spoken [in favor of requiring the blank lines](http://article.gmane.org/gmane.text.markdown.general/2146).) 3. Is a blank line needed before an indented code block? (`Markdown.pl` requires it, but this is not mentioned in the documentation, and some implementations do not require it.) ``` markdown paragraph code? ``` 4. What is the exact rule for determining when list items get wrapped in `

    ` tags? Can a list be partially "loose" and partially "tight"? What should we do with a list like this? ``` markdown 1. one 2. two 3. three ``` Or this? ``` markdown 1. one - a - b 2. two ``` (There are some relevant comments by John Gruber [here](http://article.gmane.org/gmane.text.markdown.general/2554).) 5. Can list markers be indented? Can ordered list markers be right-aligned? ``` markdown 8. item 1 9. item 2 10. item 2a ``` 6. Is this one list with a thematic break in its second item, or two lists separated by a thematic break? ``` markdown * a * * * * * * b ``` 7. When list markers change from numbers to bullets, do we have two lists or one? (The Markdown syntax description suggests two, but the perl scripts and many other implementations produce one.) ``` markdown 1. fee 2. fie - foe - fum ``` 8. What are the precedence rules for the markers of inline structure? For example, is the following a valid link, or does the code span take precedence ? ``` markdown [a backtick (`)](/url) and [another backtick (`)](/url). ``` 9. What are the precedence rules for markers of emphasis and strong emphasis? For example, how should the following be parsed? ``` markdown *foo *bar* baz* ``` 10. What are the precedence rules between block-level and inline-level structure? For example, how should the following be parsed? ``` markdown - `a long code span can contain a hyphen like this - and it can screw things up` ``` 11. Can list items include section headings? (`Markdown.pl` does not allow this, but does allow blockquotes to include headings.) ``` markdown - # Heading ``` 12. Can list items be empty? ``` markdown * a * * b ``` 13. Can link references be defined inside block quotes or list items? ``` markdown > Blockquote [foo]. > > [foo]: /url ``` 14. If there are multiple definitions for the same reference, which takes precedence? ``` markdown [foo]: /url1 [foo]: /url2 [foo][] ``` In the absence of a spec, early implementers consulted `Markdown.pl` to resolve these ambiguities. But `Markdown.pl` was quite buggy, and gave manifestly bad results in many cases, so it was not a satisfactory replacement for a spec. Because there is no unambiguous spec, implementations have diverged considerably. As a result, users are often surprised to find that a document that renders one way on one system (say, a GitHub wiki) renders differently on another (say, converting to docbook using pandoc). To make matters worse, because nothing in Markdown counts as a "syntax error," the divergence often isn't discovered right away. ## About this document This document attempts to specify Markdown syntax unambiguously. It contains many examples with side-by-side Markdown and HTML. These are intended to double as conformance tests. An accompanying script `spec_tests.py` can be used to run the tests against any Markdown program: python test/spec_tests.py --spec spec.txt --program PROGRAM Since this document describes how Markdown is to be parsed into an abstract syntax tree, it would have made sense to use an abstract representation of the syntax tree instead of HTML. But HTML is capable of representing the structural distinctions we need to make, and the choice of HTML for the tests makes it possible to run the tests against an implementation without writing an abstract syntax tree renderer. This document is generated from a text file, `spec.txt`, written in Markdown with a small extension for the side-by-side tests. The script `tools/makespec.py` can be used to convert `spec.txt` into HTML or CommonMark (which can then be converted into other formats). In the examples, the `→` character is used to represent tabs. # Preliminaries ## Characters and lines Any sequence of [characters] is a valid CommonMark document. A [character](@) is a Unicode code point. Although some code points (for example, combining accents) do not correspond to characters in an intuitive sense, all code points count as characters for purposes of this spec. This spec does not specify an encoding; it thinks of lines as composed of [characters] rather than bytes. A conforming parser may be limited to a certain encoding. A [line](@) is a sequence of zero or more [characters] other than newline (`U+000A`) or carriage return (`U+000D`), followed by a [line ending] or by the end of file. A [line ending](@) is a newline (`U+000A`), a carriage return (`U+000D`) not followed by a newline, or a carriage return and a following newline. A line containing no characters, or a line containing only spaces (`U+0020`) or tabs (`U+0009`), is called a [blank line](@). The following definitions of character classes will be used in this spec: A [whitespace character](@) is a space (`U+0020`), tab (`U+0009`), newline (`U+000A`), line tabulation (`U+000B`), form feed (`U+000C`), or carriage return (`U+000D`). [Whitespace](@) is a sequence of one or more [whitespace characters]. A [Unicode whitespace character](@) is any code point in the Unicode `Zs` general category, or a tab (`U+0009`), carriage return (`U+000D`), newline (`U+000A`), or form feed (`U+000C`). [Unicode whitespace](@) is a sequence of one or more [Unicode whitespace characters]. A [space](@) is `U+0020`. A [non-whitespace character](@) is any character that is not a [whitespace character]. An [ASCII punctuation character](@) is `!`, `"`, `#`, `$`, `%`, `&`, `'`, `(`, `)`, `*`, `+`, `,`, `-`, `.`, `/` (U+0021–2F), `:`, `;`, `<`, `=`, `>`, `?`, `@` (U+003A–0040), `[`, `\`, `]`, `^`, `_`, `` ` `` (U+005B–0060), `{`, `|`, `}`, or `~` (U+007B–007E). A [punctuation character](@) is an [ASCII punctuation character] or anything in the general Unicode categories `Pc`, `Pd`, `Pe`, `Pf`, `Pi`, `Po`, or `Ps`. ## Tabs Tabs in lines are not expanded to [spaces]. However, in contexts where whitespace helps to define block structure, tabs behave as if they were replaced by spaces with a tab stop of 4 characters. Thus, for example, a tab can be used instead of four spaces in an indented code block. (Note, however, that internal tabs are passed through as literal tabs, not expanded to spaces.) ```````````````````````````````` example →foo→baz→→bim .

    foo→baz→→bim
    
    ```````````````````````````````` ```````````````````````````````` example →foo→baz→→bim .
    foo→baz→→bim
    
    ```````````````````````````````` ```````````````````````````````` example a→a ὐ→a .
    a→a
    ὐ→a
    
    ```````````````````````````````` In the following example, a continuation paragraph of a list item is indented with a tab; this has exactly the same effect as indentation with four spaces would: ```````````````````````````````` example - foo →bar .
    • foo

      bar

    ```````````````````````````````` ```````````````````````````````` example - foo →→bar .
    • foo

        bar
      
    ```````````````````````````````` Normally the `>` that begins a block quote may be followed optionally by a space, which is not considered part of the content. In the following case `>` is followed by a tab, which is treated as if it were expanded into three spaces. Since one of these spaces is considered part of the delimiter, `foo` is considered to be indented six spaces inside the block quote context, so we get an indented code block starting with two spaces. ```````````````````````````````` example >→→foo .
      foo
    
    ```````````````````````````````` ```````````````````````````````` example -→→foo .
    •   foo
      
    ```````````````````````````````` ```````````````````````````````` example foo →bar .
    foo
    bar
    
    ```````````````````````````````` ```````````````````````````````` example - foo - bar → - baz .
    • foo
      • bar
        • baz
    ```````````````````````````````` ```````````````````````````````` example #→Foo .

    Foo

    ```````````````````````````````` ```````````````````````````````` example *→*→*→ .
    ```````````````````````````````` ## Insecure characters For security reasons, the Unicode character `U+0000` must be replaced with the REPLACEMENT CHARACTER (`U+FFFD`). # Blocks and inlines We can think of a document as a sequence of [blocks](@)---structural elements like paragraphs, block quotations, lists, headings, rules, and code blocks. Some blocks (like block quotes and list items) contain other blocks; others (like headings and paragraphs) contain [inline](@) content---text, links, emphasized text, images, code spans, and so on. ## Precedence Indicators of block structure always take precedence over indicators of inline structure. So, for example, the following is a list with two items, not a list with one item containing a code span: ```````````````````````````````` example - `one - two` .
    • `one
    • two`
    ```````````````````````````````` This means that parsing can proceed in two steps: first, the block structure of the document can be discerned; second, text lines inside paragraphs, headings, and other block constructs can be parsed for inline structure. The second step requires information about link reference definitions that will be available only at the end of the first step. Note that the first step requires processing lines in sequence, but the second can be parallelized, since the inline parsing of one block element does not affect the inline parsing of any other. ## Container blocks and leaf blocks We can divide blocks into two types: [container blocks](@), which can contain other blocks, and [leaf blocks](@), which cannot. # Leaf blocks This section describes the different kinds of leaf block that make up a Markdown document. ## Thematic breaks A line consisting of 0-3 spaces of indentation, followed by a sequence of three or more matching `-`, `_`, or `*` characters, each followed optionally by any number of spaces or tabs, forms a [thematic break](@). ```````````````````````````````` example *** --- ___ .


    ```````````````````````````````` Wrong characters: ```````````````````````````````` example +++ .

    +++

    ```````````````````````````````` ```````````````````````````````` example === .

    ===

    ```````````````````````````````` Not enough characters: ```````````````````````````````` example -- ** __ .

    -- ** __

    ```````````````````````````````` One to three spaces indent are allowed: ```````````````````````````````` example *** *** *** .


    ```````````````````````````````` Four spaces is too many: ```````````````````````````````` example *** .
    ***
    
    ```````````````````````````````` ```````````````````````````````` example Foo *** .

    Foo ***

    ```````````````````````````````` More than three characters may be used: ```````````````````````````````` example _____________________________________ .
    ```````````````````````````````` Spaces are allowed between the characters: ```````````````````````````````` example - - - .
    ```````````````````````````````` ```````````````````````````````` example ** * ** * ** * ** .
    ```````````````````````````````` ```````````````````````````````` example - - - - .
    ```````````````````````````````` Spaces are allowed at the end: ```````````````````````````````` example - - - - .
    ```````````````````````````````` However, no other characters may occur in the line: ```````````````````````````````` example _ _ _ _ a a------ ---a--- .

    _ _ _ _ a

    a------

    ---a---

    ```````````````````````````````` It is required that all of the [non-whitespace characters] be the same. So, this is not a thematic break: ```````````````````````````````` example *-* .

    -

    ```````````````````````````````` Thematic breaks do not need blank lines before or after: ```````````````````````````````` example - foo *** - bar .
    • foo

    • bar
    ```````````````````````````````` Thematic breaks can interrupt a paragraph: ```````````````````````````````` example Foo *** bar .

    Foo


    bar

    ```````````````````````````````` If a line of dashes that meets the above conditions for being a thematic break could also be interpreted as the underline of a [setext heading], the interpretation as a [setext heading] takes precedence. Thus, for example, this is a setext heading, not a paragraph followed by a thematic break: ```````````````````````````````` example Foo --- bar .

    Foo

    bar

    ```````````````````````````````` When both a thematic break and a list item are possible interpretations of a line, the thematic break takes precedence: ```````````````````````````````` example * Foo * * * * Bar .
    • Foo

    • Bar
    ```````````````````````````````` If you want a thematic break in a list item, use a different bullet: ```````````````````````````````` example - Foo - * * * .
    • Foo

    ```````````````````````````````` ## ATX headings An [ATX heading](@) consists of a string of characters, parsed as inline content, between an opening sequence of 1--6 unescaped `#` characters and an optional closing sequence of any number of unescaped `#` characters. The opening sequence of `#` characters must be followed by a [space] or by the end of line. The optional closing sequence of `#`s must be preceded by a [space] and may be followed by spaces only. The opening `#` character may be indented 0-3 spaces. The raw contents of the heading are stripped of leading and trailing spaces before being parsed as inline content. The heading level is equal to the number of `#` characters in the opening sequence. Simple headings: ```````````````````````````````` example # foo ## foo ### foo #### foo ##### foo ###### foo .

    foo

    foo

    foo

    foo

    foo
    foo
    ```````````````````````````````` More than six `#` characters is not a heading: ```````````````````````````````` example ####### foo .

    ####### foo

    ```````````````````````````````` At least one space is required between the `#` characters and the heading's contents, unless the heading is empty. Note that many implementations currently do not require the space. However, the space was required by the [original ATX implementation](http://www.aaronsw.com/2002/atx/atx.py), and it helps prevent things like the following from being parsed as headings: ```````````````````````````````` example #5 bolt #hashtag .

    #5 bolt

    #hashtag

    ```````````````````````````````` This is not a heading, because the first `#` is escaped: ```````````````````````````````` example \## foo .

    ## foo

    ```````````````````````````````` Contents are parsed as inlines: ```````````````````````````````` example # foo *bar* \*baz\* .

    foo bar *baz*

    ```````````````````````````````` Leading and trailing [whitespace] is ignored in parsing inline content: ```````````````````````````````` example # foo .

    foo

    ```````````````````````````````` One to three spaces indentation are allowed: ```````````````````````````````` example ### foo ## foo # foo .

    foo

    foo

    foo

    ```````````````````````````````` Four spaces are too much: ```````````````````````````````` example # foo .
    # foo
    
    ```````````````````````````````` ```````````````````````````````` example foo # bar .

    foo # bar

    ```````````````````````````````` A closing sequence of `#` characters is optional: ```````````````````````````````` example ## foo ## ### bar ### .

    foo

    bar

    ```````````````````````````````` It need not be the same length as the opening sequence: ```````````````````````````````` example # foo ################################## ##### foo ## .

    foo

    foo
    ```````````````````````````````` Spaces are allowed after the closing sequence: ```````````````````````````````` example ### foo ### .

    foo

    ```````````````````````````````` A sequence of `#` characters with anything but [spaces] following it is not a closing sequence, but counts as part of the contents of the heading: ```````````````````````````````` example ### foo ### b .

    foo ### b

    ```````````````````````````````` The closing sequence must be preceded by a space: ```````````````````````````````` example # foo# .

    foo#

    ```````````````````````````````` Backslash-escaped `#` characters do not count as part of the closing sequence: ```````````````````````````````` example ### foo \### ## foo #\## # foo \# .

    foo ###

    foo ###

    foo #

    ```````````````````````````````` ATX headings need not be separated from surrounding content by blank lines, and they can interrupt paragraphs: ```````````````````````````````` example **** ## foo **** .

    foo


    ```````````````````````````````` ```````````````````````````````` example Foo bar # baz Bar foo .

    Foo bar

    baz

    Bar foo

    ```````````````````````````````` ATX headings can be empty: ```````````````````````````````` example ## # ### ### .

    ```````````````````````````````` ## Setext headings A [setext heading](@) consists of one or more lines of text, each containing at least one [non-whitespace character], with no more than 3 spaces indentation, followed by a [setext heading underline]. The lines of text must be such that, were they not followed by the setext heading underline, they would be interpreted as a paragraph: they cannot be interpretable as a [code fence], [ATX heading][ATX headings], [block quote][block quotes], [thematic break][thematic breaks], [list item][list items], or [HTML block][HTML blocks]. A [setext heading underline](@) is a sequence of `=` characters or a sequence of `-` characters, with no more than 3 spaces indentation and any number of trailing spaces. If a line containing a single `-` can be interpreted as an empty [list items], it should be interpreted this way and not as a [setext heading underline]. The heading is a level 1 heading if `=` characters are used in the [setext heading underline], and a level 2 heading if `-` characters are used. The contents of the heading are the result of parsing the preceding lines of text as CommonMark inline content. In general, a setext heading need not be preceded or followed by a blank line. However, it cannot interrupt a paragraph, so when a setext heading comes after a paragraph, a blank line is needed between them. Simple examples: ```````````````````````````````` example Foo *bar* ========= Foo *bar* --------- .

    Foo bar

    Foo bar

    ```````````````````````````````` The content of the header may span more than one line: ```````````````````````````````` example Foo *bar baz* ==== .

    Foo bar baz

    ```````````````````````````````` The contents are the result of parsing the headings's raw content as inlines. The heading's raw content is formed by concatenating the lines and removing initial and final [whitespace]. ```````````````````````````````` example Foo *bar baz*→ ==== .

    Foo bar baz

    ```````````````````````````````` The underlining can be any length: ```````````````````````````````` example Foo ------------------------- Foo = .

    Foo

    Foo

    ```````````````````````````````` The heading content can be indented up to three spaces, and need not line up with the underlining: ```````````````````````````````` example Foo --- Foo ----- Foo === .

    Foo

    Foo

    Foo

    ```````````````````````````````` Four spaces indent is too much: ```````````````````````````````` example Foo --- Foo --- .
    Foo
    ---
    
    Foo
    

    ```````````````````````````````` The setext heading underline can be indented up to three spaces, and may have trailing spaces: ```````````````````````````````` example Foo ---- .

    Foo

    ```````````````````````````````` Four spaces is too much: ```````````````````````````````` example Foo --- .

    Foo ---

    ```````````````````````````````` The setext heading underline cannot contain internal spaces: ```````````````````````````````` example Foo = = Foo --- - .

    Foo = =

    Foo


    ```````````````````````````````` Trailing spaces in the content line do not cause a line break: ```````````````````````````````` example Foo ----- .

    Foo

    ```````````````````````````````` Nor does a backslash at the end: ```````````````````````````````` example Foo\ ---- .

    Foo\

    ```````````````````````````````` Since indicators of block structure take precedence over indicators of inline structure, the following are setext headings: ```````````````````````````````` example `Foo ---- ` .

    `Foo

    `

    <a title="a lot

    of dashes"/>

    ```````````````````````````````` The setext heading underline cannot be a [lazy continuation line] in a list item or block quote: ```````````````````````````````` example > Foo --- .

    Foo


    ```````````````````````````````` ```````````````````````````````` example > foo bar === .

    foo bar ===

    ```````````````````````````````` ```````````````````````````````` example - Foo --- .
    • Foo

    ```````````````````````````````` A blank line is needed between a paragraph and a following setext heading, since otherwise the paragraph becomes part of the heading's content: ```````````````````````````````` example Foo Bar --- .

    Foo Bar

    ```````````````````````````````` But in general a blank line is not required before or after setext headings: ```````````````````````````````` example --- Foo --- Bar --- Baz .

    Foo

    Bar

    Baz

    ```````````````````````````````` Setext headings cannot be empty: ```````````````````````````````` example ==== .

    ====

    ```````````````````````````````` Setext heading text lines must not be interpretable as block constructs other than paragraphs. So, the line of dashes in these examples gets interpreted as a thematic break: ```````````````````````````````` example --- --- .

    ```````````````````````````````` ```````````````````````````````` example - foo ----- .
    • foo

    ```````````````````````````````` ```````````````````````````````` example foo --- .
    foo
    

    ```````````````````````````````` ```````````````````````````````` example > foo ----- .

    foo


    ```````````````````````````````` If you want a heading with `> foo` as its literal text, you can use backslash escapes: ```````````````````````````````` example \> foo ------ .

    > foo

    ```````````````````````````````` **Compatibility note:** Most existing Markdown implementations do not allow the text of setext headings to span multiple lines. But there is no consensus about how to interpret ``` markdown Foo bar --- baz ``` One can find four different interpretations: 1. paragraph "Foo", heading "bar", paragraph "baz" 2. paragraph "Foo bar", thematic break, paragraph "baz" 3. paragraph "Foo bar --- baz" 4. heading "Foo bar", paragraph "baz" We find interpretation 4 most natural, and interpretation 4 increases the expressive power of CommonMark, by allowing multiline headings. Authors who want interpretation 1 can put a blank line after the first paragraph: ```````````````````````````````` example Foo bar --- baz .

    Foo

    bar

    baz

    ```````````````````````````````` Authors who want interpretation 2 can put blank lines around the thematic break, ```````````````````````````````` example Foo bar --- baz .

    Foo bar


    baz

    ```````````````````````````````` or use a thematic break that cannot count as a [setext heading underline], such as ```````````````````````````````` example Foo bar * * * baz .

    Foo bar


    baz

    ```````````````````````````````` Authors who want interpretation 3 can use backslash escapes: ```````````````````````````````` example Foo bar \--- baz .

    Foo bar --- baz

    ```````````````````````````````` ## Indented code blocks An [indented code block](@) is composed of one or more [indented chunks] separated by blank lines. An [indented chunk](@) is a sequence of non-blank lines, each indented four or more spaces. The contents of the code block are the literal contents of the lines, including trailing [line endings], minus four spaces of indentation. An indented code block has no [info string]. An indented code block cannot interrupt a paragraph, so there must be a blank line between a paragraph and a following indented code block. (A blank line is not needed, however, between a code block and a following paragraph.) ```````````````````````````````` example a simple indented code block .
    a simple
      indented code block
    
    ```````````````````````````````` If there is any ambiguity between an interpretation of indentation as a code block and as indicating that material belongs to a [list item][list items], the list item interpretation takes precedence: ```````````````````````````````` example - foo bar .
    • foo

      bar

    ```````````````````````````````` ```````````````````````````````` example 1. foo - bar .
    1. foo

      • bar
    ```````````````````````````````` The contents of a code block are literal text, and do not get parsed as Markdown: ```````````````````````````````` example
    *hi* - one .
    <a/>
    *hi*
    
    - one
    
    ```````````````````````````````` Here we have three chunks separated by blank lines: ```````````````````````````````` example chunk1 chunk2 chunk3 .
    chunk1
    
    chunk2
    
    
    
    chunk3
    
    ```````````````````````````````` Any initial spaces beyond four will be included in the content, even in interior blank lines: ```````````````````````````````` example chunk1 chunk2 .
    chunk1
      
      chunk2
    
    ```````````````````````````````` An indented code block cannot interrupt a paragraph. (This allows hanging indents and the like.) ```````````````````````````````` example Foo bar .

    Foo bar

    ```````````````````````````````` However, any non-blank line with fewer than four leading spaces ends the code block immediately. So a paragraph may occur immediately after indented code: ```````````````````````````````` example foo bar .
    foo
    

    bar

    ```````````````````````````````` And indented code can occur immediately before and after other kinds of blocks: ```````````````````````````````` example # Heading foo Heading ------ foo ---- .

    Heading

    foo
    

    Heading

    foo
    

    ```````````````````````````````` The first line can be indented more than four spaces: ```````````````````````````````` example foo bar .
        foo
    bar
    
    ```````````````````````````````` Blank lines preceding or following an indented code block are not included in it: ```````````````````````````````` example foo .
    foo
    
    ```````````````````````````````` Trailing spaces are included in the code block's content: ```````````````````````````````` example foo .
    foo  
    
    ```````````````````````````````` ## Fenced code blocks A [code fence](@) is a sequence of at least three consecutive backtick characters (`` ` ``) or tildes (`~`). (Tildes and backticks cannot be mixed.) A [fenced code block](@) begins with a code fence, indented no more than three spaces. The line with the opening code fence may optionally contain some text following the code fence; this is trimmed of leading and trailing whitespace and called the [info string](@). If the [info string] comes after a backtick fence, it may not contain any backtick characters. (The reason for this restriction is that otherwise some inline code would be incorrectly interpreted as the beginning of a fenced code block.) The content of the code block consists of all subsequent lines, until a closing [code fence] of the same type as the code block began with (backticks or tildes), and with at least as many backticks or tildes as the opening code fence. If the leading code fence is indented N spaces, then up to N spaces of indentation are removed from each line of the content (if present). (If a content line is not indented, it is preserved unchanged. If it is indented less than N spaces, all of the indentation is removed.) The closing code fence may be indented up to three spaces, and may be followed only by spaces, which are ignored. If the end of the containing block (or document) is reached and no closing code fence has been found, the code block contains all of the lines after the opening code fence until the end of the containing block (or document). (An alternative spec would require backtracking in the event that a closing code fence is not found. But this makes parsing much less efficient, and there seems to be no real down side to the behavior described here.) A fenced code block may interrupt a paragraph, and does not require a blank line either before or after. The content of a code fence is treated as literal text, not parsed as inlines. The first word of the [info string] is typically used to specify the language of the code sample, and rendered in the `class` attribute of the `code` tag. However, this spec does not mandate any particular treatment of the [info string]. Here is a simple example with backticks: ```````````````````````````````` example ``` < > ``` .
    <
     >
    
    ```````````````````````````````` With tildes: ```````````````````````````````` example ~~~ < > ~~~ .
    <
     >
    
    ```````````````````````````````` Fewer than three backticks is not enough: ```````````````````````````````` example `` foo `` .

    foo

    ```````````````````````````````` The closing code fence must use the same character as the opening fence: ```````````````````````````````` example ``` aaa ~~~ ``` .
    aaa
    ~~~
    
    ```````````````````````````````` ```````````````````````````````` example ~~~ aaa ``` ~~~ .
    aaa
    ```
    
    ```````````````````````````````` The closing code fence must be at least as long as the opening fence: ```````````````````````````````` example ```` aaa ``` `````` .
    aaa
    ```
    
    ```````````````````````````````` ```````````````````````````````` example ~~~~ aaa ~~~ ~~~~ .
    aaa
    ~~~
    
    ```````````````````````````````` Unclosed code blocks are closed by the end of the document (or the enclosing [block quote][block quotes] or [list item][list items]): ```````````````````````````````` example ``` .
    ```````````````````````````````` ```````````````````````````````` example ````` ``` aaa .
    
    ```
    aaa
    
    ```````````````````````````````` ```````````````````````````````` example > ``` > aaa bbb .
    aaa
    

    bbb

    ```````````````````````````````` A code block can have all empty lines as its content: ```````````````````````````````` example ``` ``` .
    
      
    
    ```````````````````````````````` A code block can be empty: ```````````````````````````````` example ``` ``` .
    ```````````````````````````````` Fences can be indented. If the opening fence is indented, content lines will have equivalent opening indentation removed, if present: ```````````````````````````````` example ``` aaa aaa ``` .
    aaa
    aaa
    
    ```````````````````````````````` ```````````````````````````````` example ``` aaa aaa aaa ``` .
    aaa
    aaa
    aaa
    
    ```````````````````````````````` ```````````````````````````````` example ``` aaa aaa aaa ``` .
    aaa
     aaa
    aaa
    
    ```````````````````````````````` Four spaces indentation produces an indented code block: ```````````````````````````````` example ``` aaa ``` .
    ```
    aaa
    ```
    
    ```````````````````````````````` Closing fences may be indented by 0-3 spaces, and their indentation need not match that of the opening fence: ```````````````````````````````` example ``` aaa ``` .
    aaa
    
    ```````````````````````````````` ```````````````````````````````` example ``` aaa ``` .
    aaa
    
    ```````````````````````````````` This is not a closing fence, because it is indented 4 spaces: ```````````````````````````````` example ``` aaa ``` .
    aaa
        ```
    
    ```````````````````````````````` Code fences (opening and closing) cannot contain internal spaces: ```````````````````````````````` example ``` ``` aaa .

    aaa

    ```````````````````````````````` ```````````````````````````````` example ~~~~~~ aaa ~~~ ~~ .
    aaa
    ~~~ ~~
    
    ```````````````````````````````` Fenced code blocks can interrupt paragraphs, and can be followed directly by paragraphs, without a blank line between: ```````````````````````````````` example foo ``` bar ``` baz .

    foo

    bar
    

    baz

    ```````````````````````````````` Other blocks can also occur before and after fenced code blocks without an intervening blank line: ```````````````````````````````` example foo --- ~~~ bar ~~~ # baz .

    foo

    bar
    

    baz

    ```````````````````````````````` An [info string] can be provided after the opening code fence. Although this spec doesn't mandate any particular treatment of the info string, the first word is typically used to specify the language of the code block. In HTML output, the language is normally indicated by adding a class to the `code` element consisting of `language-` followed by the language name. ```````````````````````````````` example ```ruby def foo(x) return 3 end ``` .
    def foo(x)
      return 3
    end
    
    ```````````````````````````````` ```````````````````````````````` example ~~~~ ruby startline=3 $%@#$ def foo(x) return 3 end ~~~~~~~ .
    def foo(x)
      return 3
    end
    
    ```````````````````````````````` ```````````````````````````````` example ````; ```` .
    ```````````````````````````````` [Info strings] for backtick code blocks cannot contain backticks: ```````````````````````````````` example ``` aa ``` foo .

    aa foo

    ```````````````````````````````` [Info strings] for tilde code blocks can contain backticks and tildes: ```````````````````````````````` example ~~~ aa ``` ~~~ foo ~~~ .
    foo
    
    ```````````````````````````````` Closing code fences cannot have [info strings]: ```````````````````````````````` example ``` ``` aaa ``` .
    ``` aaa
    
    ```````````````````````````````` ## HTML blocks An [HTML block](@) is a group of lines that is treated as raw HTML (and will not be escaped in HTML output). There are seven kinds of [HTML block], which can be defined by their start and end conditions. The block begins with a line that meets a [start condition](@) (after up to three spaces optional indentation). It ends with the first subsequent line that meets a matching [end condition](@), or the last line of the document, or the last line of the [container block](#container-blocks) containing the current HTML block, if no line is encountered that meets the [end condition]. If the first line meets both the [start condition] and the [end condition], the block will contain just that line. 1. **Start condition:** line begins with the string ``, or the end of the line.\ **End condition:** line contains an end tag ``, ``, or `` (case-insensitive; it need not match the start tag). 2. **Start condition:** line begins with the string ``. 3. **Start condition:** line begins with the string ``. 4. **Start condition:** line begins with the string ``. 5. **Start condition:** line begins with the string ``. 6. **Start condition:** line begins the string `<` or ``, or the string `/>`.\ **End condition:** line is followed by a [blank line]. 7. **Start condition:** line begins with a complete [open tag] (with any [tag name] other than `script`, `style`, or `pre`) or a complete [closing tag], followed only by [whitespace] or the end of the line.\ **End condition:** line is followed by a [blank line]. HTML blocks continue until they are closed by their appropriate [end condition], or the last line of the document or other [container block](#container-blocks). This means any HTML **within an HTML block** that might otherwise be recognised as a start condition will be ignored by the parser and passed through as-is, without changing the parser's state. For instance, `
    ` within a HTML block started by `
    ` will not affect the parser state; as the HTML block was started in by start condition 6, it will end at any blank line. This can be surprising: ```````````````````````````````` example
    **Hello**,
    
    _world_.
    
    .
    **Hello**,
    

    world.

    ```````````````````````````````` In this case, the HTML block is terminated by the newline — the `**Hello**` text remains verbatim — and regular parsing resumes, with a paragraph, emphasised `world` and inline and block HTML following. All types of [HTML blocks] except type 7 may interrupt a paragraph. Blocks of type 7 may not interrupt a paragraph. (This restriction is intended to prevent unwanted interpretation of long tags inside a wrapped paragraph as starting HTML blocks.) Some simple examples follow. Here are some basic HTML blocks of type 6: ```````````````````````````````` example
    hi
    okay. .
    hi

    okay.

    ```````````````````````````````` ```````````````````````````````` example
    *foo* ```````````````````````````````` Here we have two HTML blocks with a Markdown paragraph between them: ```````````````````````````````` example
    *Markdown*
    .

    Markdown

    ```````````````````````````````` The tag on the first line can be partial, as long as it is split where there would be whitespace: ```````````````````````````````` example
    .
    ```````````````````````````````` ```````````````````````````````` example
    .
    ```````````````````````````````` An open tag need not be closed: ```````````````````````````````` example
    *foo* *bar* .
    *foo*

    bar

    ```````````````````````````````` A partial tag need not even be completed (garbage in, garbage out): ```````````````````````````````` example
    . ```````````````````````````````` ```````````````````````````````` example
    foo
    .
    foo
    ```````````````````````````````` Everything until the next blank line or end of document gets included in the HTML block. So, in the following example, what looks like a Markdown code block is actually part of the HTML block, which continues until a blank line or the end of the document is reached: ```````````````````````````````` example
    ``` c int x = 33; ``` .
    ``` c int x = 33; ``` ```````````````````````````````` To start an [HTML block] with a tag that is *not* in the list of block-level tags in (6), you must put the tag by itself on the first line (and it must be complete): ```````````````````````````````` example *bar* . *bar* ```````````````````````````````` In type 7 blocks, the [tag name] can be anything: ```````````````````````````````` example *bar* . *bar* ```````````````````````````````` ```````````````````````````````` example *bar* . *bar* ```````````````````````````````` ```````````````````````````````` example *bar* . *bar* ```````````````````````````````` These rules are designed to allow us to work with tags that can function as either block-level or inline-level tags. The `` tag is a nice example. We can surround content with `` tags in three different ways. In this case, we get a raw HTML block, because the `` tag is on a line by itself: ```````````````````````````````` example *foo* . *foo* ```````````````````````````````` In this case, we get a raw HTML block that just includes the `` tag (because it ends with the following blank line). So the contents get interpreted as CommonMark: ```````````````````````````````` example *foo* .

    foo

    ```````````````````````````````` Finally, in this case, the `` tags are interpreted as [raw HTML] *inside* the CommonMark paragraph. (Because the tag is not on a line by itself, we get inline HTML rather than an [HTML block].) ```````````````````````````````` example *foo* .

    foo

    ```````````````````````````````` HTML tags designed to contain literal content (`script`, `style`, `pre`), comments, processing instructions, and declarations are treated somewhat differently. Instead of ending at the first blank line, these blocks end at the first line containing a corresponding end tag. As a result, these blocks can contain blank lines: A pre tag (type 1): ```````````````````````````````` example
    
    import Text.HTML.TagSoup
    
    main :: IO ()
    main = print $ parseTags tags
    
    okay .
    
    import Text.HTML.TagSoup
    
    main :: IO ()
    main = print $ parseTags tags
    

    okay

    ```````````````````````````````` A script tag (type 1): ```````````````````````````````` example okay .

    okay

    ```````````````````````````````` A style tag (type 1): ```````````````````````````````` example okay .

    okay

    ```````````````````````````````` If there is no matching end tag, the block will end at the end of the document (or the enclosing [block quote][block quotes] or [list item][list items]): ```````````````````````````````` example *foo* .

    foo

    ```````````````````````````````` ```````````````````````````````` example *bar* *baz* . *bar*

    baz

    ```````````````````````````````` Note that anything on the last line after the end tag will be included in the [HTML block]: ```````````````````````````````` example 1. *bar* . 1. *bar* ```````````````````````````````` A comment (type 2): ```````````````````````````````` example okay .

    okay

    ```````````````````````````````` A processing instruction (type 3): ```````````````````````````````` example '; ?> okay . '; ?>

    okay

    ```````````````````````````````` A declaration (type 4): ```````````````````````````````` example . ```````````````````````````````` CDATA (type 5): ```````````````````````````````` example okay .

    okay

    ```````````````````````````````` The opening tag can be indented 1-3 spaces, but not 4: ```````````````````````````````` example .
    <!-- foo -->
    
    ```````````````````````````````` ```````````````````````````````` example
    .
    <div>
    
    ```````````````````````````````` An HTML block of types 1--6 can interrupt a paragraph, and need not be preceded by a blank line. ```````````````````````````````` example Foo
    bar
    .

    Foo

    bar
    ```````````````````````````````` However, a following blank line is needed, except at the end of a document, and except for blocks of types 1--5, [above][HTML block]: ```````````````````````````````` example
    bar
    *foo* .
    bar
    *foo* ```````````````````````````````` HTML blocks of type 7 cannot interrupt a paragraph: ```````````````````````````````` example Foo baz .

    Foo baz

    ```````````````````````````````` This rule differs from John Gruber's original Markdown syntax specification, which says: > The only restrictions are that block-level HTML elements — > e.g. `
    `, ``, `
    `, `

    `, etc. — must be separated from > surrounding content by blank lines, and the start and end tags of the > block should not be indented with tabs or spaces. In some ways Gruber's rule is more restrictive than the one given here: - It requires that an HTML block be preceded by a blank line. - It does not allow the start tag to be indented. - It requires a matching end tag, which it also does not allow to be indented. Most Markdown implementations (including some of Gruber's own) do not respect all of these restrictions. There is one respect, however, in which Gruber's rule is more liberal than the one given here, since it allows blank lines to occur inside an HTML block. There are two reasons for disallowing them here. First, it removes the need to parse balanced tags, which is expensive and can require backtracking from the end of the document if no matching end tag is found. Second, it provides a very simple and flexible way of including Markdown content inside HTML tags: simply separate the Markdown from the HTML using blank lines: Compare: ```````````````````````````````` example

    *Emphasized* text.
    .

    Emphasized text.

    ```````````````````````````````` ```````````````````````````````` example
    *Emphasized* text.
    .
    *Emphasized* text.
    ```````````````````````````````` Some Markdown implementations have adopted a convention of interpreting content inside tags as text if the open tag has the attribute `markdown=1`. The rule given above seems a simpler and more elegant way of achieving the same expressive power, which is also much simpler to parse. The main potential drawback is that one can no longer paste HTML blocks into Markdown documents with 100% reliability. However, *in most cases* this will work fine, because the blank lines in HTML are usually followed by HTML block tags. For example: ```````````````````````````````` example
    Hi
    .
    Hi
    ```````````````````````````````` There are problems, however, if the inner tags are indented *and* separated by spaces, as then they will be interpreted as an indented code block: ```````````````````````````````` example
    Hi
    .
    <td>
      Hi
    </td>
    
    ```````````````````````````````` Fortunately, blank lines are usually not necessary and can be deleted. The exception is inside `
    ` tags, but as described
    [above][HTML blocks], raw HTML blocks starting with `
    `
    *can* contain blank lines.
    
    ## Link reference definitions
    
    A [link reference definition](@)
    consists of a [link label], indented up to three spaces, followed
    by a colon (`:`), optional [whitespace] (including up to one
    [line ending]), a [link destination],
    optional [whitespace] (including up to one
    [line ending]), and an optional [link
    title], which if it is present must be separated
    from the [link destination] by [whitespace].
    No further [non-whitespace characters] may occur on the line.
    
    A [link reference definition]
    does not correspond to a structural element of a document.  Instead, it
    defines a label which can be used in [reference links]
    and reference-style [images] elsewhere in the document.  [Link
    reference definitions] can come either before or after the links that use
    them.
    
    ```````````````````````````````` example
    [foo]: /url "title"
    
    [foo]
    .
    

    foo

    ```````````````````````````````` ```````````````````````````````` example [foo]: /url 'the title' [foo] .

    foo

    ```````````````````````````````` ```````````````````````````````` example [Foo*bar\]]:my_(url) 'title (with parens)' [Foo*bar\]] .

    Foo*bar]

    ```````````````````````````````` ```````````````````````````````` example [Foo bar]: 'title' [Foo bar] .

    Foo bar

    ```````````````````````````````` The title may extend over multiple lines: ```````````````````````````````` example [foo]: /url ' title line1 line2 ' [foo] .

    foo

    ```````````````````````````````` However, it may not contain a [blank line]: ```````````````````````````````` example [foo]: /url 'title with blank line' [foo] .

    [foo]: /url 'title

    with blank line'

    [foo]

    ```````````````````````````````` The title may be omitted: ```````````````````````````````` example [foo]: /url [foo] .

    foo

    ```````````````````````````````` The link destination may not be omitted: ```````````````````````````````` example [foo]: [foo] .

    [foo]:

    [foo]

    ```````````````````````````````` However, an empty link destination may be specified using angle brackets: ```````````````````````````````` example [foo]: <> [foo] .

    foo

    ```````````````````````````````` The title must be separated from the link destination by whitespace: ```````````````````````````````` example [foo]: (baz) [foo] .

    [foo]: (baz)

    [foo]

    ```````````````````````````````` Both title and destination can contain backslash escapes and literal backslashes: ```````````````````````````````` example [foo]: /url\bar\*baz "foo\"bar\baz" [foo] .

    foo

    ```````````````````````````````` A link can come before its corresponding definition: ```````````````````````````````` example [foo] [foo]: url .

    foo

    ```````````````````````````````` If there are several matching definitions, the first one takes precedence: ```````````````````````````````` example [foo] [foo]: first [foo]: second .

    foo

    ```````````````````````````````` As noted in the section on [Links], matching of labels is case-insensitive (see [matches]). ```````````````````````````````` example [FOO]: /url [Foo] .

    Foo

    ```````````````````````````````` ```````````````````````````````` example [ΑΓΩ]: /φου [αγω] .

    αγω

    ```````````````````````````````` Here is a link reference definition with no corresponding link. It contributes nothing to the document. ```````````````````````````````` example [foo]: /url . ```````````````````````````````` Here is another one: ```````````````````````````````` example [ foo ]: /url bar .

    bar

    ```````````````````````````````` This is not a link reference definition, because there are [non-whitespace characters] after the title: ```````````````````````````````` example [foo]: /url "title" ok .

    [foo]: /url "title" ok

    ```````````````````````````````` This is a link reference definition, but it has no title: ```````````````````````````````` example [foo]: /url "title" ok .

    "title" ok

    ```````````````````````````````` This is not a link reference definition, because it is indented four spaces: ```````````````````````````````` example [foo]: /url "title" [foo] .
    [foo]: /url "title"
    

    [foo]

    ```````````````````````````````` This is not a link reference definition, because it occurs inside a code block: ```````````````````````````````` example ``` [foo]: /url ``` [foo] .
    [foo]: /url
    

    [foo]

    ```````````````````````````````` A [link reference definition] cannot interrupt a paragraph. ```````````````````````````````` example Foo [bar]: /baz [bar] .

    Foo [bar]: /baz

    [bar]

    ```````````````````````````````` However, it can directly follow other block elements, such as headings and thematic breaks, and it need not be followed by a blank line. ```````````````````````````````` example # [Foo] [foo]: /url > bar .

    Foo

    bar

    ```````````````````````````````` ```````````````````````````````` example [foo]: /url bar === [foo] .

    bar

    foo

    ```````````````````````````````` ```````````````````````````````` example [foo]: /url === [foo] .

    === foo

    ```````````````````````````````` Several [link reference definitions] can occur one after another, without intervening blank lines. ```````````````````````````````` example [foo]: /foo-url "foo" [bar]: /bar-url "bar" [baz]: /baz-url [foo], [bar], [baz] .

    foo, bar, baz

    ```````````````````````````````` [Link reference definitions] can occur inside block containers, like lists and block quotations. They affect the entire document, not just the container in which they are defined: ```````````````````````````````` example [foo] > [foo]: /url .

    foo

    ```````````````````````````````` Whether something is a [link reference definition] is independent of whether the link reference it defines is used in the document. Thus, for example, the following document contains just a link reference definition, and no visible content: ```````````````````````````````` example [foo]: /url . ```````````````````````````````` ## Paragraphs A sequence of non-blank lines that cannot be interpreted as other kinds of blocks forms a [paragraph](@). The contents of the paragraph are the result of parsing the paragraph's raw content as inlines. The paragraph's raw content is formed by concatenating the lines and removing initial and final [whitespace]. A simple example with two paragraphs: ```````````````````````````````` example aaa bbb .

    aaa

    bbb

    ```````````````````````````````` Paragraphs can contain multiple lines, but no blank lines: ```````````````````````````````` example aaa bbb ccc ddd .

    aaa bbb

    ccc ddd

    ```````````````````````````````` Multiple blank lines between paragraph have no effect: ```````````````````````````````` example aaa bbb .

    aaa

    bbb

    ```````````````````````````````` Leading spaces are skipped: ```````````````````````````````` example aaa bbb .

    aaa bbb

    ```````````````````````````````` Lines after the first may be indented any amount, since indented code blocks cannot interrupt paragraphs. ```````````````````````````````` example aaa bbb ccc .

    aaa bbb ccc

    ```````````````````````````````` However, the first line may be indented at most three spaces, or an indented code block will be triggered: ```````````````````````````````` example aaa bbb .

    aaa bbb

    ```````````````````````````````` ```````````````````````````````` example aaa bbb .
    aaa
    

    bbb

    ```````````````````````````````` Final spaces are stripped before inline parsing, so a paragraph that ends with two or more spaces will not end with a [hard line break]: ```````````````````````````````` example aaa bbb .

    aaa
    bbb

    ```````````````````````````````` ## Blank lines [Blank lines] between block-level elements are ignored, except for the role they play in determining whether a [list] is [tight] or [loose]. Blank lines at the beginning and end of the document are also ignored. ```````````````````````````````` example aaa # aaa .

    aaa

    aaa

    ```````````````````````````````` # Container blocks A [container block](#container-blocks) is a block that has other blocks as its contents. There are two basic kinds of container blocks: [block quotes] and [list items]. [Lists] are meta-containers for [list items]. We define the syntax for container blocks recursively. The general form of the definition is: > If X is a sequence of blocks, then the result of > transforming X in such-and-such a way is a container of type Y > with these blocks as its content. So, we explain what counts as a block quote or list item by explaining how these can be *generated* from their contents. This should suffice to define the syntax, although it does not give a recipe for *parsing* these constructions. (A recipe is provided below in the section entitled [A parsing strategy](#appendix-a-parsing-strategy).) ## Block quotes A [block quote marker](@) consists of 0-3 spaces of initial indent, plus (a) the character `>` together with a following space, or (b) a single character `>` not followed by a space. The following rules define [block quotes]: 1. **Basic case.** If a string of lines *Ls* constitute a sequence of blocks *Bs*, then the result of prepending a [block quote marker] to the beginning of each line in *Ls* is a [block quote](#block-quotes) containing *Bs*. 2. **Laziness.** If a string of lines *Ls* constitute a [block quote](#block-quotes) with contents *Bs*, then the result of deleting the initial [block quote marker] from one or more lines in which the next [non-whitespace character] after the [block quote marker] is [paragraph continuation text] is a block quote with *Bs* as its content. [Paragraph continuation text](@) is text that will be parsed as part of the content of a paragraph, but does not occur at the beginning of the paragraph. 3. **Consecutiveness.** A document cannot contain two [block quotes] in a row unless there is a [blank line] between them. Nothing else counts as a [block quote](#block-quotes). Here is a simple example: ```````````````````````````````` example > # Foo > bar > baz .

    Foo

    bar baz

    ```````````````````````````````` The spaces after the `>` characters can be omitted: ```````````````````````````````` example ># Foo >bar > baz .

    Foo

    bar baz

    ```````````````````````````````` The `>` characters can be indented 1-3 spaces: ```````````````````````````````` example > # Foo > bar > baz .

    Foo

    bar baz

    ```````````````````````````````` Four spaces gives us a code block: ```````````````````````````````` example > # Foo > bar > baz .
    > # Foo
    > bar
    > baz
    
    ```````````````````````````````` The Laziness clause allows us to omit the `>` before [paragraph continuation text]: ```````````````````````````````` example > # Foo > bar baz .

    Foo

    bar baz

    ```````````````````````````````` A block quote can contain some lazy and some non-lazy continuation lines: ```````````````````````````````` example > bar baz > foo .

    bar baz foo

    ```````````````````````````````` Laziness only applies to lines that would have been continuations of paragraphs had they been prepended with [block quote markers]. For example, the `> ` cannot be omitted in the second line of ``` markdown > foo > --- ``` without changing the meaning: ```````````````````````````````` example > foo --- .

    foo


    ```````````````````````````````` Similarly, if we omit the `> ` in the second line of ``` markdown > - foo > - bar ``` then the block quote ends after the first line: ```````````````````````````````` example > - foo - bar .
    • foo
    • bar
    ```````````````````````````````` For the same reason, we can't omit the `> ` in front of subsequent lines of an indented or fenced code block: ```````````````````````````````` example > foo bar .
    foo
    
    bar
    
    ```````````````````````````````` ```````````````````````````````` example > ``` foo ``` .

    foo

    ```````````````````````````````` Note that in the following case, we have a [lazy continuation line]: ```````````````````````````````` example > foo - bar .

    foo - bar

    ```````````````````````````````` To see why, note that in ```markdown > foo > - bar ``` the `- bar` is indented too far to start a list, and can't be an indented code block because indented code blocks cannot interrupt paragraphs, so it is [paragraph continuation text]. A block quote can be empty: ```````````````````````````````` example > .
    ```````````````````````````````` ```````````````````````````````` example > > > .
    ```````````````````````````````` A block quote can have initial or final blank lines: ```````````````````````````````` example > > foo > .

    foo

    ```````````````````````````````` A blank line always separates block quotes: ```````````````````````````````` example > foo > bar .

    foo

    bar

    ```````````````````````````````` (Most current Markdown implementations, including John Gruber's original `Markdown.pl`, will parse this example as a single block quote with two paragraphs. But it seems better to allow the author to decide whether two block quotes or one are wanted.) Consecutiveness means that if we put these block quotes together, we get a single block quote: ```````````````````````````````` example > foo > bar .

    foo bar

    ```````````````````````````````` To get a block quote with two paragraphs, use: ```````````````````````````````` example > foo > > bar .

    foo

    bar

    ```````````````````````````````` Block quotes can interrupt paragraphs: ```````````````````````````````` example foo > bar .

    foo

    bar

    ```````````````````````````````` In general, blank lines are not needed before or after block quotes: ```````````````````````````````` example > aaa *** > bbb .

    aaa


    bbb

    ```````````````````````````````` However, because of laziness, a blank line is needed between a block quote and a following paragraph: ```````````````````````````````` example > bar baz .

    bar baz

    ```````````````````````````````` ```````````````````````````````` example > bar baz .

    bar

    baz

    ```````````````````````````````` ```````````````````````````````` example > bar > baz .

    bar

    baz

    ```````````````````````````````` It is a consequence of the Laziness rule that any number of initial `>`s may be omitted on a continuation line of a nested block quote: ```````````````````````````````` example > > > foo bar .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example >>> foo > bar >>baz .

    foo bar baz

    ```````````````````````````````` When including an indented code block in a block quote, remember that the [block quote marker] includes both the `>` and a following space. So *five spaces* are needed after the `>`: ```````````````````````````````` example > code > not code .
    code
    

    not code

    ```````````````````````````````` ## List items A [list marker](@) is a [bullet list marker] or an [ordered list marker]. A [bullet list marker](@) is a `-`, `+`, or `*` character. An [ordered list marker](@) is a sequence of 1--9 arabic digits (`0-9`), followed by either a `.` character or a `)` character. (The reason for the length limit is that with 10 digits we start seeing integer overflows in some browsers.) The following rules define [list items]: 1. **Basic case.** If a sequence of lines *Ls* constitute a sequence of blocks *Bs* starting with a [non-whitespace character], and *M* is a list marker of width *W* followed by 1 ≤ *N* ≤ 4 spaces, then the result of prepending *M* and the following spaces to the first line of *Ls*, and indenting subsequent lines of *Ls* by *W + N* spaces, is a list item with *Bs* as its contents. The type of the list item (bullet or ordered) is determined by the type of its list marker. If the list item is ordered, then it is also assigned a start number, based on the ordered list marker. Exceptions: 1. When the first list item in a [list] interrupts a paragraph---that is, when it starts on a line that would otherwise count as [paragraph continuation text]---then (a) the lines *Ls* must not begin with a blank line, and (b) if the list item is ordered, the start number must be 1. 2. If any line is a [thematic break][thematic breaks] then that line is not a list item. For example, let *Ls* be the lines ```````````````````````````````` example A paragraph with two lines. indented code > A block quote. .

    A paragraph with two lines.

    indented code
    

    A block quote.

    ```````````````````````````````` And let *M* be the marker `1.`, and *N* = 2. Then rule #1 says that the following is an ordered list item with start number 1, and the same contents as *Ls*: ```````````````````````````````` example 1. A paragraph with two lines. indented code > A block quote. .
    1. A paragraph with two lines.

      indented code
      

      A block quote.

    ```````````````````````````````` The most important thing to notice is that the position of the text after the list marker determines how much indentation is needed in subsequent blocks in the list item. If the list marker takes up two spaces, and there are three spaces between the list marker and the next [non-whitespace character], then blocks must be indented five spaces in order to fall under the list item. Here are some examples showing how far content must be indented to be put under the list item: ```````````````````````````````` example - one two .
    • one

    two

    ```````````````````````````````` ```````````````````````````````` example - one two .
    • one

      two

    ```````````````````````````````` ```````````````````````````````` example - one two .
    • one
     two
    
    ```````````````````````````````` ```````````````````````````````` example - one two .
    • one

      two

    ```````````````````````````````` It is tempting to think of this in terms of columns: the continuation blocks must be indented at least to the column of the first [non-whitespace character] after the list marker. However, that is not quite right. The spaces after the list marker determine how much relative indentation is needed. Which column this indentation reaches will depend on how the list item is embedded in other constructions, as shown by this example: ```````````````````````````````` example > > 1. one >> >> two .
    1. one

      two

    ```````````````````````````````` Here `two` occurs in the same column as the list marker `1.`, but is actually contained in the list item, because there is sufficient indentation after the last containing blockquote marker. The converse is also possible. In the following example, the word `two` occurs far to the right of the initial text of the list item, `one`, but it is not considered part of the list item, because it is not indented far enough past the blockquote marker: ```````````````````````````````` example >>- one >> > > two .
    • one

    two

    ```````````````````````````````` Note that at least one space is needed between the list marker and any following content, so these are not list items: ```````````````````````````````` example -one 2.two .

    -one

    2.two

    ```````````````````````````````` A list item may contain blocks that are separated by more than one blank line. ```````````````````````````````` example - foo bar .
    • foo

      bar

    ```````````````````````````````` A list item may contain any kind of block: ```````````````````````````````` example 1. foo ``` bar ``` baz > bam .
    1. foo

      bar
      

      baz

      bam

    ```````````````````````````````` A list item that contains an indented code block will preserve empty lines within the code block verbatim. ```````````````````````````````` example - Foo bar baz .
    • Foo

      bar
      
      
      baz
      
    ```````````````````````````````` Note that ordered list start numbers must be nine digits or less: ```````````````````````````````` example 123456789. ok .
    1. ok
    ```````````````````````````````` ```````````````````````````````` example 1234567890. not ok .

    1234567890. not ok

    ```````````````````````````````` A start number may begin with 0s: ```````````````````````````````` example 0. ok .
    1. ok
    ```````````````````````````````` ```````````````````````````````` example 003. ok .
    1. ok
    ```````````````````````````````` A start number may not be negative: ```````````````````````````````` example -1. not ok .

    -1. not ok

    ```````````````````````````````` 2. **Item starting with indented code.** If a sequence of lines *Ls* constitute a sequence of blocks *Bs* starting with an indented code block, and *M* is a list marker of width *W* followed by one space, then the result of prepending *M* and the following space to the first line of *Ls*, and indenting subsequent lines of *Ls* by *W + 1* spaces, is a list item with *Bs* as its contents. If a line is empty, then it need not be indented. The type of the list item (bullet or ordered) is determined by the type of its list marker. If the list item is ordered, then it is also assigned a start number, based on the ordered list marker. An indented code block will have to be indented four spaces beyond the edge of the region where text will be included in the list item. In the following case that is 6 spaces: ```````````````````````````````` example - foo bar .
    • foo

      bar
      
    ```````````````````````````````` And in this case it is 11 spaces: ```````````````````````````````` example 10. foo bar .
    1. foo

      bar
      
    ```````````````````````````````` If the *first* block in the list item is an indented code block, then by rule #2, the contents must be indented *one* space after the list marker: ```````````````````````````````` example indented code paragraph more code .
    indented code
    

    paragraph

    more code
    
    ```````````````````````````````` ```````````````````````````````` example 1. indented code paragraph more code .
    1. indented code
      

      paragraph

      more code
      
    ```````````````````````````````` Note that an additional space indent is interpreted as space inside the code block: ```````````````````````````````` example 1. indented code paragraph more code .
    1.  indented code
      

      paragraph

      more code
      
    ```````````````````````````````` Note that rules #1 and #2 only apply to two cases: (a) cases in which the lines to be included in a list item begin with a [non-whitespace character], and (b) cases in which they begin with an indented code block. In a case like the following, where the first block begins with a three-space indent, the rules do not allow us to form a list item by indenting the whole thing and prepending a list marker: ```````````````````````````````` example foo bar .

    foo

    bar

    ```````````````````````````````` ```````````````````````````````` example - foo bar .
    • foo

    bar

    ```````````````````````````````` This is not a significant restriction, because when a block begins with 1-3 spaces indent, the indentation can always be removed without a change in interpretation, allowing rule #1 to be applied. So, in the above case: ```````````````````````````````` example - foo bar .
    • foo

      bar

    ```````````````````````````````` 3. **Item starting with a blank line.** If a sequence of lines *Ls* starting with a single [blank line] constitute a (possibly empty) sequence of blocks *Bs*, not separated from each other by more than one blank line, and *M* is a list marker of width *W*, then the result of prepending *M* to the first line of *Ls*, and indenting subsequent lines of *Ls* by *W + 1* spaces, is a list item with *Bs* as its contents. If a line is empty, then it need not be indented. The type of the list item (bullet or ordered) is determined by the type of its list marker. If the list item is ordered, then it is also assigned a start number, based on the ordered list marker. Here are some list items that start with a blank line but are not empty: ```````````````````````````````` example - foo - ``` bar ``` - baz .
    • foo
    • bar
      
    • baz
      
    ```````````````````````````````` When the list item starts with a blank line, the number of spaces following the list marker doesn't change the required indentation: ```````````````````````````````` example - foo .
    • foo
    ```````````````````````````````` A list item can begin with at most one blank line. In the following example, `foo` is not part of the list item: ```````````````````````````````` example - foo .

    foo

    ```````````````````````````````` Here is an empty bullet list item: ```````````````````````````````` example - foo - - bar .
    • foo
    • bar
    ```````````````````````````````` It does not matter whether there are spaces following the [list marker]: ```````````````````````````````` example - foo - - bar .
    • foo
    • bar
    ```````````````````````````````` Here is an empty ordered list item: ```````````````````````````````` example 1. foo 2. 3. bar .
    1. foo
    2. bar
    ```````````````````````````````` A list may start or end with an empty list item: ```````````````````````````````` example * .
    ```````````````````````````````` However, an empty list item cannot interrupt a paragraph: ```````````````````````````````` example foo * foo 1. .

    foo *

    foo 1.

    ```````````````````````````````` 4. **Indentation.** If a sequence of lines *Ls* constitutes a list item according to rule #1, #2, or #3, then the result of indenting each line of *Ls* by 1-3 spaces (the same for each line) also constitutes a list item with the same contents and attributes. If a line is empty, then it need not be indented. Indented one space: ```````````````````````````````` example 1. A paragraph with two lines. indented code > A block quote. .
    1. A paragraph with two lines.

      indented code
      

      A block quote.

    ```````````````````````````````` Indented two spaces: ```````````````````````````````` example 1. A paragraph with two lines. indented code > A block quote. .
    1. A paragraph with two lines.

      indented code
      

      A block quote.

    ```````````````````````````````` Indented three spaces: ```````````````````````````````` example 1. A paragraph with two lines. indented code > A block quote. .
    1. A paragraph with two lines.

      indented code
      

      A block quote.

    ```````````````````````````````` Four spaces indent gives a code block: ```````````````````````````````` example 1. A paragraph with two lines. indented code > A block quote. .
    1.  A paragraph
        with two lines.
    
            indented code
    
        > A block quote.
    
    ```````````````````````````````` 5. **Laziness.** If a string of lines *Ls* constitute a [list item](#list-items) with contents *Bs*, then the result of deleting some or all of the indentation from one or more lines in which the next [non-whitespace character] after the indentation is [paragraph continuation text] is a list item with the same contents and attributes. The unindented lines are called [lazy continuation line](@)s. Here is an example with [lazy continuation lines]: ```````````````````````````````` example 1. A paragraph with two lines. indented code > A block quote. .
    1. A paragraph with two lines.

      indented code
      

      A block quote.

    ```````````````````````````````` Indentation can be partially deleted: ```````````````````````````````` example 1. A paragraph with two lines. .
    1. A paragraph with two lines.
    ```````````````````````````````` These examples show how laziness can work in nested structures: ```````````````````````````````` example > 1. > Blockquote continued here. .
    1. Blockquote continued here.

    ```````````````````````````````` ```````````````````````````````` example > 1. > Blockquote > continued here. .
    1. Blockquote continued here.

    ```````````````````````````````` 6. **That's all.** Nothing that is not counted as a list item by rules #1--5 counts as a [list item](#list-items). The rules for sublists follow from the general rules [above][List items]. A sublist must be indented the same number of spaces a paragraph would need to be in order to be included in the list item. So, in this case we need two spaces indent: ```````````````````````````````` example - foo - bar - baz - boo .
    • foo
      • bar
        • baz
          • boo
    ```````````````````````````````` One is not enough: ```````````````````````````````` example - foo - bar - baz - boo .
    • foo
    • bar
    • baz
    • boo
    ```````````````````````````````` Here we need four, because the list marker is wider: ```````````````````````````````` example 10) foo - bar .
    1. foo
      • bar
    ```````````````````````````````` Three is not enough: ```````````````````````````````` example 10) foo - bar .
    1. foo
    • bar
    ```````````````````````````````` A list may be the first block in a list item: ```````````````````````````````` example - - foo .
      • foo
    ```````````````````````````````` ```````````````````````````````` example 1. - 2. foo .
        1. foo
    ```````````````````````````````` A list item can contain a heading: ```````````````````````````````` example - # Foo - Bar --- baz .
    • Foo

    • Bar

      baz
    ```````````````````````````````` ### Motivation John Gruber's Markdown spec says the following about list items: 1. "List markers typically start at the left margin, but may be indented by up to three spaces. List markers must be followed by one or more spaces or a tab." 2. "To make lists look nice, you can wrap items with hanging indents.... But if you don't want to, you don't have to." 3. "List items may consist of multiple paragraphs. Each subsequent paragraph in a list item must be indented by either 4 spaces or one tab." 4. "It looks nice if you indent every line of the subsequent paragraphs, but here again, Markdown will allow you to be lazy." 5. "To put a blockquote within a list item, the blockquote's `>` delimiters need to be indented." 6. "To put a code block within a list item, the code block needs to be indented twice — 8 spaces or two tabs." These rules specify that a paragraph under a list item must be indented four spaces (presumably, from the left margin, rather than the start of the list marker, but this is not said), and that code under a list item must be indented eight spaces instead of the usual four. They also say that a block quote must be indented, but not by how much; however, the example given has four spaces indentation. Although nothing is said about other kinds of block-level content, it is certainly reasonable to infer that *all* block elements under a list item, including other lists, must be indented four spaces. This principle has been called the *four-space rule*. The four-space rule is clear and principled, and if the reference implementation `Markdown.pl` had followed it, it probably would have become the standard. However, `Markdown.pl` allowed paragraphs and sublists to start with only two spaces indentation, at least on the outer level. Worse, its behavior was inconsistent: a sublist of an outer-level list needed two spaces indentation, but a sublist of this sublist needed three spaces. It is not surprising, then, that different implementations of Markdown have developed very different rules for determining what comes under a list item. (Pandoc and python-Markdown, for example, stuck with Gruber's syntax description and the four-space rule, while discount, redcarpet, marked, PHP Markdown, and others followed `Markdown.pl`'s behavior more closely.) Unfortunately, given the divergences between implementations, there is no way to give a spec for list items that will be guaranteed not to break any existing documents. However, the spec given here should correctly handle lists formatted with either the four-space rule or the more forgiving `Markdown.pl` behavior, provided they are laid out in a way that is natural for a human to read. The strategy here is to let the width and indentation of the list marker determine the indentation necessary for blocks to fall under the list item, rather than having a fixed and arbitrary number. The writer can think of the body of the list item as a unit which gets indented to the right enough to fit the list marker (and any indentation on the list marker). (The laziness rule, #5, then allows continuation lines to be unindented if needed.) This rule is superior, we claim, to any rule requiring a fixed level of indentation from the margin. The four-space rule is clear but unnatural. It is quite unintuitive that ``` markdown - foo bar - baz ``` should be parsed as two lists with an intervening paragraph, ``` html
    • foo

    bar

    • baz
    ``` as the four-space rule demands, rather than a single list, ``` html
    • foo

      bar

      • baz
    ``` The choice of four spaces is arbitrary. It can be learned, but it is not likely to be guessed, and it trips up beginners regularly. Would it help to adopt a two-space rule? The problem is that such a rule, together with the rule allowing 1--3 spaces indentation of the initial list marker, allows text that is indented *less than* the original list marker to be included in the list item. For example, `Markdown.pl` parses ``` markdown - one two ``` as a single list item, with `two` a continuation paragraph: ``` html
    • one

      two

    ``` and similarly ``` markdown > - one > > two ``` as ``` html
    • one

      two

    ``` This is extremely unintuitive. Rather than requiring a fixed indent from the margin, we could require a fixed indent (say, two spaces, or even one space) from the list marker (which may itself be indented). This proposal would remove the last anomaly discussed. Unlike the spec presented above, it would count the following as a list item with a subparagraph, even though the paragraph `bar` is not indented as far as the first paragraph `foo`: ``` markdown 10. foo bar ``` Arguably this text does read like a list item with `bar` as a subparagraph, which may count in favor of the proposal. However, on this proposal indented code would have to be indented six spaces after the list marker. And this would break a lot of existing Markdown, which has the pattern: ``` markdown 1. foo indented code ``` where the code is indented eight spaces. The spec above, by contrast, will parse this text as expected, since the code block's indentation is measured from the beginning of `foo`. The one case that needs special treatment is a list item that *starts* with indented code. How much indentation is required in that case, since we don't have a "first paragraph" to measure from? Rule #2 simply stipulates that in such cases, we require one space indentation from the list marker (and then the normal four spaces for the indented code). This will match the four-space rule in cases where the list marker plus its initial indentation takes four spaces (a common case), but diverge in other cases. ## Lists A [list](@) is a sequence of one or more list items [of the same type]. The list items may be separated by any number of blank lines. Two list items are [of the same type](@) if they begin with a [list marker] of the same type. Two list markers are of the same type if (a) they are bullet list markers using the same character (`-`, `+`, or `*`) or (b) they are ordered list numbers with the same delimiter (either `.` or `)`). A list is an [ordered list](@) if its constituent list items begin with [ordered list markers], and a [bullet list](@) if its constituent list items begin with [bullet list markers]. The [start number](@) of an [ordered list] is determined by the list number of its initial list item. The numbers of subsequent list items are disregarded. A list is [loose](@) if any of its constituent list items are separated by blank lines, or if any of its constituent list items directly contain two block-level elements with a blank line between them. Otherwise a list is [tight](@). (The difference in HTML output is that paragraphs in a loose list are wrapped in `

    ` tags, while paragraphs in a tight list are not.) Changing the bullet or ordered list delimiter starts a new list: ```````````````````````````````` example - foo - bar + baz .

    • foo
    • bar
    • baz
    ```````````````````````````````` ```````````````````````````````` example 1. foo 2. bar 3) baz .
    1. foo
    2. bar
    1. baz
    ```````````````````````````````` In CommonMark, a list can interrupt a paragraph. That is, no blank line is needed to separate a paragraph from a following list: ```````````````````````````````` example Foo - bar - baz .

    Foo

    • bar
    • baz
    ```````````````````````````````` `Markdown.pl` does not allow this, through fear of triggering a list via a numeral in a hard-wrapped line: ``` markdown The number of windows in my house is 14. The number of doors is 6. ``` Oddly, though, `Markdown.pl` *does* allow a blockquote to interrupt a paragraph, even though the same considerations might apply. In CommonMark, we do allow lists to interrupt paragraphs, for two reasons. First, it is natural and not uncommon for people to start lists without blank lines: ``` markdown I need to buy - new shoes - a coat - a plane ticket ``` Second, we are attracted to a > [principle of uniformity](@): > if a chunk of text has a certain > meaning, it will continue to have the same meaning when put into a > container block (such as a list item or blockquote). (Indeed, the spec for [list items] and [block quotes] presupposes this principle.) This principle implies that if ``` markdown * I need to buy - new shoes - a coat - a plane ticket ``` is a list item containing a paragraph followed by a nested sublist, as all Markdown implementations agree it is (though the paragraph may be rendered without `

    ` tags, since the list is "tight"), then ``` markdown I need to buy - new shoes - a coat - a plane ticket ``` by itself should be a paragraph followed by a nested sublist. Since it is well established Markdown practice to allow lists to interrupt paragraphs inside list items, the [principle of uniformity] requires us to allow this outside list items as well. ([reStructuredText](http://docutils.sourceforge.net/rst.html) takes a different approach, requiring blank lines before lists even inside other list items.) In order to solve of unwanted lists in paragraphs with hard-wrapped numerals, we allow only lists starting with `1` to interrupt paragraphs. Thus, ```````````````````````````````` example The number of windows in my house is 14. The number of doors is 6. .

    The number of windows in my house is 14. The number of doors is 6.

    ```````````````````````````````` We may still get an unintended result in cases like ```````````````````````````````` example The number of windows in my house is 1. The number of doors is 6. .

    The number of windows in my house is

    1. The number of doors is 6.
    ```````````````````````````````` but this rule should prevent most spurious list captures. There can be any number of blank lines between items: ```````````````````````````````` example - foo - bar - baz .
    • foo

    • bar

    • baz

    ```````````````````````````````` ```````````````````````````````` example - foo - bar - baz bim .
    • foo
      • bar
        • baz

          bim

    ```````````````````````````````` To separate consecutive lists of the same type, or to separate a list from an indented code block that would otherwise be parsed as a subparagraph of the final list item, you can insert a blank HTML comment: ```````````````````````````````` example - foo - bar - baz - bim .
    • foo
    • bar
    • baz
    • bim
    ```````````````````````````````` ```````````````````````````````` example - foo notcode - foo code .
    • foo

      notcode

    • foo

    code
    
    ```````````````````````````````` List items need not be indented to the same level. The following list items will be treated as items at the same list level, since none is indented enough to belong to the previous list item: ```````````````````````````````` example - a - b - c - d - e - f - g .
    • a
    • b
    • c
    • d
    • e
    • f
    • g
    ```````````````````````````````` ```````````````````````````````` example 1. a 2. b 3. c .
    1. a

    2. b

    3. c

    ```````````````````````````````` Note, however, that list items may not be indented more than three spaces. Here `- e` is treated as a paragraph continuation line, because it is indented more than three spaces: ```````````````````````````````` example - a - b - c - d - e .
    • a
    • b
    • c
    • d - e
    ```````````````````````````````` And here, `3. c` is treated as in indented code block, because it is indented four spaces and preceded by a blank line. ```````````````````````````````` example 1. a 2. b 3. c .
    1. a

    2. b

    3. c
    
    ```````````````````````````````` This is a loose list, because there is a blank line between two of the list items: ```````````````````````````````` example - a - b - c .
    • a

    • b

    • c

    ```````````````````````````````` So is this, with a empty second item: ```````````````````````````````` example * a * * c .
    • a

    • c

    ```````````````````````````````` These are loose lists, even though there is no space between the items, because one of the items directly contains two block-level elements with a blank line between them: ```````````````````````````````` example - a - b c - d .
    • a

    • b

      c

    • d

    ```````````````````````````````` ```````````````````````````````` example - a - b [ref]: /url - d .
    • a

    • b

    • d

    ```````````````````````````````` This is a tight list, because the blank lines are in a code block: ```````````````````````````````` example - a - ``` b ``` - c .
    • a
    • b
      
      
      
    • c
    ```````````````````````````````` This is a tight list, because the blank line is between two paragraphs of a sublist. So the sublist is loose while the outer list is tight: ```````````````````````````````` example - a - b c - d .
    • a
      • b

        c

    • d
    ```````````````````````````````` This is a tight list, because the blank line is inside the block quote: ```````````````````````````````` example * a > b > * c .
    • a

      b

    • c
    ```````````````````````````````` This list is tight, because the consecutive block elements are not separated by blank lines: ```````````````````````````````` example - a > b ``` c ``` - d .
    • a

      b

      c
      
    • d
    ```````````````````````````````` A single-paragraph list is tight: ```````````````````````````````` example - a .
    • a
    ```````````````````````````````` ```````````````````````````````` example - a - b .
    • a
      • b
    ```````````````````````````````` This list is loose, because of the blank line between the two block elements in the list item: ```````````````````````````````` example 1. ``` foo ``` bar .
    1. foo
      

      bar

    ```````````````````````````````` Here the outer list is loose, the inner list tight: ```````````````````````````````` example * foo * bar baz .
    • foo

      • bar

      baz

    ```````````````````````````````` ```````````````````````````````` example - a - b - c - d - e - f .
    • a

      • b
      • c
    • d

      • e
      • f
    ```````````````````````````````` # Inlines Inlines are parsed sequentially from the beginning of the character stream to the end (left to right, in left-to-right languages). Thus, for example, in ```````````````````````````````` example `hi`lo` .

    hilo`

    ```````````````````````````````` `hi` is parsed as code, leaving the backtick at the end as a literal backtick. ## Backslash escapes Any ASCII punctuation character may be backslash-escaped: ```````````````````````````````` example \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~ .

    !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

    ```````````````````````````````` Backslashes before other characters are treated as literal backslashes: ```````````````````````````````` example \→\A\a\ \3\φ\« .

    \→\A\a\ \3\φ\«

    ```````````````````````````````` Escaped characters are treated as regular characters and do not have their usual Markdown meanings: ```````````````````````````````` example \*not emphasized* \
    not a tag \[not a link](/foo) \`not code` 1\. not a list \* not a list \# not a heading \[foo]: /url "not a reference" \ö not a character entity .

    *not emphasized* <br/> not a tag [not a link](/foo) `not code` 1. not a list * not a list # not a heading [foo]: /url "not a reference" &ouml; not a character entity

    ```````````````````````````````` If a backslash is itself escaped, the following character is not: ```````````````````````````````` example \\*emphasis* .

    \emphasis

    ```````````````````````````````` A backslash at the end of the line is a [hard line break]: ```````````````````````````````` example foo\ bar .

    foo
    bar

    ```````````````````````````````` Backslash escapes do not work in code blocks, code spans, autolinks, or raw HTML: ```````````````````````````````` example `` \[\` `` .

    \[\`

    ```````````````````````````````` ```````````````````````````````` example \[\] .
    \[\]
    
    ```````````````````````````````` ```````````````````````````````` example ~~~ \[\] ~~~ .
    \[\]
    
    ```````````````````````````````` ```````````````````````````````` example .

    http://example.com?find=\*

    ```````````````````````````````` ```````````````````````````````` example . ```````````````````````````````` But they work in all other contexts, including URLs and link titles, link references, and [info strings] in [fenced code blocks]: ```````````````````````````````` example [foo](/bar\* "ti\*tle") .

    foo

    ```````````````````````````````` ```````````````````````````````` example [foo] [foo]: /bar\* "ti\*tle" .

    foo

    ```````````````````````````````` ```````````````````````````````` example ``` foo\+bar foo ``` .
    foo
    
    ```````````````````````````````` ## Entity and numeric character references Valid HTML entity references and numeric character references can be used in place of the corresponding Unicode character, with the following exceptions: - Entity and character references are not recognized in code blocks and code spans. - Entity and character references cannot stand in place of special characters that define structural elements in CommonMark. For example, although `*` can be used in place of a literal `*` character, `*` cannot replace `*` in emphasis delimiters, bullet list markers, or thematic breaks. Conforming CommonMark parsers need not store information about whether a particular character was represented in the source using a Unicode character or an entity reference. [Entity references](@) consist of `&` + any of the valid HTML5 entity names + `;`. The document is used as an authoritative source for the valid entity references and their corresponding code points. ```````````````````````````````` example   & © Æ Ď ¾ ℋ ⅆ ∲ ≧̸ .

      & © Æ Ď ¾ ℋ ⅆ ∲ ≧̸

    ```````````````````````````````` [Decimal numeric character references](@) consist of `&#` + a string of 1--7 arabic digits + `;`. A numeric character reference is parsed as the corresponding Unicode character. Invalid Unicode code points will be replaced by the REPLACEMENT CHARACTER (`U+FFFD`). For security reasons, the code point `U+0000` will also be replaced by `U+FFFD`. ```````````````````````````````` example # Ӓ Ϡ � .

    # Ӓ Ϡ �

    ```````````````````````````````` [Hexadecimal numeric character references](@) consist of `&#` + either `X` or `x` + a string of 1-6 hexadecimal digits + `;`. They too are parsed as the corresponding Unicode character (this time specified with a hexadecimal numeral instead of decimal). ```````````````````````````````` example " ആ ಫ .

    " ആ ಫ

    ```````````````````````````````` Here are some nonentities: ```````````````````````````````` example   &x; &#; &#x; � &#abcdef0; &ThisIsNotDefined; &hi?; .

    &nbsp &x; &#; &#x; &#87654321; &#abcdef0; &ThisIsNotDefined; &hi?;

    ```````````````````````````````` Although HTML5 does accept some entity references without a trailing semicolon (such as `©`), these are not recognized here, because it makes the grammar too ambiguous: ```````````````````````````````` example © .

    &copy

    ```````````````````````````````` Strings that are not on the list of HTML5 named entities are not recognized as entity references either: ```````````````````````````````` example &MadeUpEntity; .

    &MadeUpEntity;

    ```````````````````````````````` Entity and numeric character references are recognized in any context besides code spans or code blocks, including URLs, [link titles], and [fenced code block][] [info strings]: ```````````````````````````````` example . ```````````````````````````````` ```````````````````````````````` example [foo](/föö "föö") .

    foo

    ```````````````````````````````` ```````````````````````````````` example [foo] [foo]: /föö "föö" .

    foo

    ```````````````````````````````` ```````````````````````````````` example ``` föö foo ``` .
    foo
    
    ```````````````````````````````` Entity and numeric character references are treated as literal text in code spans and code blocks: ```````````````````````````````` example `föö` .

    f&ouml;&ouml;

    ```````````````````````````````` ```````````````````````````````` example föfö .
    f&ouml;f&ouml;
    
    ```````````````````````````````` Entity and numeric character references cannot be used in place of symbols indicating structure in CommonMark documents. ```````````````````````````````` example *foo* *foo* .

    *foo* foo

    ```````````````````````````````` ```````````````````````````````` example * foo * foo .

    * foo

    • foo
    ```````````````````````````````` ```````````````````````````````` example foo bar .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example foo .

    →foo

    ```````````````````````````````` ```````````````````````````````` example [a](url "tit") .

    [a](url "tit")

    ```````````````````````````````` ## Code spans A [backtick string](@) is a string of one or more backtick characters (`` ` ``) that is neither preceded nor followed by a backtick. A [code span](@) begins with a backtick string and ends with a backtick string of equal length. The contents of the code span are the characters between the two backtick strings, normalized in the following ways: - First, [line endings] are converted to [spaces]. - If the resulting string both begins *and* ends with a [space] character, but does not consist entirely of [space] characters, a single [space] character is removed from the front and back. This allows you to include code that begins or ends with backtick characters, which must be separated by whitespace from the opening or closing backtick strings. This is a simple code span: ```````````````````````````````` example `foo` .

    foo

    ```````````````````````````````` Here two backticks are used, because the code contains a backtick. This example also illustrates stripping of a single leading and trailing space: ```````````````````````````````` example `` foo ` bar `` .

    foo ` bar

    ```````````````````````````````` This example shows the motivation for stripping leading and trailing spaces: ```````````````````````````````` example ` `` ` .

    ``

    ```````````````````````````````` Note that only *one* space is stripped: ```````````````````````````````` example ` `` ` .

    ``

    ```````````````````````````````` The stripping only happens if the space is on both sides of the string: ```````````````````````````````` example ` a` .

    a

    ```````````````````````````````` Only [spaces], and not [unicode whitespace] in general, are stripped in this way: ```````````````````````````````` example ` b ` .

     b 

    ```````````````````````````````` No stripping occurs if the code span contains only spaces: ```````````````````````````````` example ` ` ` ` .

     

    ```````````````````````````````` [Line endings] are treated like spaces: ```````````````````````````````` example `` foo bar baz `` .

    foo bar baz

    ```````````````````````````````` ```````````````````````````````` example `` foo `` .

    foo

    ```````````````````````````````` Interior spaces are not collapsed: ```````````````````````````````` example `foo bar baz` .

    foo bar baz

    ```````````````````````````````` Note that browsers will typically collapse consecutive spaces when rendering `` elements, so it is recommended that the following CSS be used: code{white-space: pre-wrap;} Note that backslash escapes do not work in code spans. All backslashes are treated literally: ```````````````````````````````` example `foo\`bar` .

    foo\bar`

    ```````````````````````````````` Backslash escapes are never needed, because one can always choose a string of *n* backtick characters as delimiters, where the code does not contain any strings of exactly *n* backtick characters. ```````````````````````````````` example ``foo`bar`` .

    foo`bar

    ```````````````````````````````` ```````````````````````````````` example ` foo `` bar ` .

    foo `` bar

    ```````````````````````````````` Code span backticks have higher precedence than any other inline constructs except HTML tags and autolinks. Thus, for example, this is not parsed as emphasized text, since the second `*` is part of a code span: ```````````````````````````````` example *foo`*` .

    *foo*

    ```````````````````````````````` And this is not parsed as a link: ```````````````````````````````` example [not a `link](/foo`) .

    [not a link](/foo)

    ```````````````````````````````` Code spans, HTML tags, and autolinks have the same precedence. Thus, this is code: ```````````````````````````````` example `` .

    <a href="">`

    ```````````````````````````````` But this is an HTML tag: ```````````````````````````````` example
    ` .

    `

    ```````````````````````````````` And this is code: ```````````````````````````````` example `` .

    <http://foo.bar.baz>`

    ```````````````````````````````` But this is an autolink: ```````````````````````````````` example ` .

    http://foo.bar.`baz`

    ```````````````````````````````` When a backtick string is not closed by a matching backtick string, we just have literal backticks: ```````````````````````````````` example ```foo`` .

    ```foo``

    ```````````````````````````````` ```````````````````````````````` example `foo .

    `foo

    ```````````````````````````````` The following case also illustrates the need for opening and closing backtick strings to be equal in length: ```````````````````````````````` example `foo``bar`` .

    `foobar

    ```````````````````````````````` ## Emphasis and strong emphasis John Gruber's original [Markdown syntax description](http://daringfireball.net/projects/markdown/syntax#em) says: > Markdown treats asterisks (`*`) and underscores (`_`) as indicators of > emphasis. Text wrapped with one `*` or `_` will be wrapped with an HTML > `` tag; double `*`'s or `_`'s will be wrapped with an HTML `` > tag. This is enough for most users, but these rules leave much undecided, especially when it comes to nested emphasis. The original `Markdown.pl` test suite makes it clear that triple `***` and `___` delimiters can be used for strong emphasis, and most implementations have also allowed the following patterns: ``` markdown ***strong emph*** ***strong** in emph* ***emph* in strong** **in strong *emph*** *in emph **strong*** ``` The following patterns are less widely supported, but the intent is clear and they are useful (especially in contexts like bibliography entries): ``` markdown *emph *with emph* in it* **strong **with strong** in it** ``` Many implementations have also restricted intraword emphasis to the `*` forms, to avoid unwanted emphasis in words containing internal underscores. (It is best practice to put these in code spans, but users often do not.) ``` markdown internal emphasis: foo*bar*baz no emphasis: foo_bar_baz ``` The rules given below capture all of these patterns, while allowing for efficient parsing strategies that do not backtrack. First, some definitions. A [delimiter run](@) is either a sequence of one or more `*` characters that is not preceded or followed by a non-backslash-escaped `*` character, or a sequence of one or more `_` characters that is not preceded or followed by a non-backslash-escaped `_` character. A [left-flanking delimiter run](@) is a [delimiter run] that is (1) not followed by [Unicode whitespace], and either (2a) not followed by a [punctuation character], or (2b) followed by a [punctuation character] and preceded by [Unicode whitespace] or a [punctuation character]. For purposes of this definition, the beginning and the end of the line count as Unicode whitespace. A [right-flanking delimiter run](@) is a [delimiter run] that is (1) not preceded by [Unicode whitespace], and either (2a) not preceded by a [punctuation character], or (2b) preceded by a [punctuation character] and followed by [Unicode whitespace] or a [punctuation character]. For purposes of this definition, the beginning and the end of the line count as Unicode whitespace. Here are some examples of delimiter runs. - left-flanking but not right-flanking: ``` ***abc _abc **"abc" _"abc" ``` - right-flanking but not left-flanking: ``` abc*** abc_ "abc"** "abc"_ ``` - Both left and right-flanking: ``` abc***def "abc"_"def" ``` - Neither left nor right-flanking: ``` abc *** def a _ b ``` (The idea of distinguishing left-flanking and right-flanking delimiter runs based on the character before and the character after comes from Roopesh Chander's [vfmd](http://www.vfmd.org/vfmd-spec/specification/#procedure-for-identifying-emphasis-tags). vfmd uses the terminology "emphasis indicator string" instead of "delimiter run," and its rules for distinguishing left- and right-flanking runs are a bit more complex than the ones given here.) The following rules define emphasis and strong emphasis: 1. A single `*` character [can open emphasis](@) iff (if and only if) it is part of a [left-flanking delimiter run]. 2. A single `_` character [can open emphasis] iff it is part of a [left-flanking delimiter run] and either (a) not part of a [right-flanking delimiter run] or (b) part of a [right-flanking delimiter run] preceded by punctuation. 3. A single `*` character [can close emphasis](@) iff it is part of a [right-flanking delimiter run]. 4. A single `_` character [can close emphasis] iff it is part of a [right-flanking delimiter run] and either (a) not part of a [left-flanking delimiter run] or (b) part of a [left-flanking delimiter run] followed by punctuation. 5. A double `**` [can open strong emphasis](@) iff it is part of a [left-flanking delimiter run]. 6. A double `__` [can open strong emphasis] iff it is part of a [left-flanking delimiter run] and either (a) not part of a [right-flanking delimiter run] or (b) part of a [right-flanking delimiter run] preceded by punctuation. 7. A double `**` [can close strong emphasis](@) iff it is part of a [right-flanking delimiter run]. 8. A double `__` [can close strong emphasis] iff it is part of a [right-flanking delimiter run] and either (a) not part of a [left-flanking delimiter run] or (b) part of a [left-flanking delimiter run] followed by punctuation. 9. Emphasis begins with a delimiter that [can open emphasis] and ends with a delimiter that [can close emphasis], and that uses the same character (`_` or `*`) as the opening delimiter. The opening and closing delimiters must belong to separate [delimiter runs]. If one of the delimiters can both open and close emphasis, then the sum of the lengths of the delimiter runs containing the opening and closing delimiters must not be a multiple of 3 unless both lengths are multiples of 3. 10. Strong emphasis begins with a delimiter that [can open strong emphasis] and ends with a delimiter that [can close strong emphasis], and that uses the same character (`_` or `*`) as the opening delimiter. The opening and closing delimiters must belong to separate [delimiter runs]. If one of the delimiters can both open and close strong emphasis, then the sum of the lengths of the delimiter runs containing the opening and closing delimiters must not be a multiple of 3 unless both lengths are multiples of 3. 11. A literal `*` character cannot occur at the beginning or end of `*`-delimited emphasis or `**`-delimited strong emphasis, unless it is backslash-escaped. 12. A literal `_` character cannot occur at the beginning or end of `_`-delimited emphasis or `__`-delimited strong emphasis, unless it is backslash-escaped. Where rules 1--12 above are compatible with multiple parsings, the following principles resolve ambiguity: 13. The number of nestings should be minimized. Thus, for example, an interpretation `...` is always preferred to `...`. 14. An interpretation `...` is always preferred to `...`. 15. When two potential emphasis or strong emphasis spans overlap, so that the second begins before the first ends and ends after the first ends, the first takes precedence. Thus, for example, `*foo _bar* baz_` is parsed as `foo _bar baz_` rather than `*foo bar* baz`. 16. When there are two potential emphasis or strong emphasis spans with the same closing delimiter, the shorter one (the one that opens later) takes precedence. Thus, for example, `**foo **bar baz**` is parsed as `**foo bar baz` rather than `foo **bar baz`. 17. Inline code spans, links, images, and HTML tags group more tightly than emphasis. So, when there is a choice between an interpretation that contains one of these elements and one that does not, the former always wins. Thus, for example, `*[foo*](bar)` is parsed as `*foo*` rather than as `[foo](bar)`. These rules can be illustrated through a series of examples. Rule 1: ```````````````````````````````` example *foo bar* .

    foo bar

    ```````````````````````````````` This is not emphasis, because the opening `*` is followed by whitespace, and hence not part of a [left-flanking delimiter run]: ```````````````````````````````` example a * foo bar* .

    a * foo bar*

    ```````````````````````````````` This is not emphasis, because the opening `*` is preceded by an alphanumeric and followed by punctuation, and hence not part of a [left-flanking delimiter run]: ```````````````````````````````` example a*"foo"* .

    a*"foo"*

    ```````````````````````````````` Unicode nonbreaking spaces count as whitespace, too: ```````````````````````````````` example * a * .

    * a *

    ```````````````````````````````` Intraword emphasis with `*` is permitted: ```````````````````````````````` example foo*bar* .

    foobar

    ```````````````````````````````` ```````````````````````````````` example 5*6*78 .

    5678

    ```````````````````````````````` Rule 2: ```````````````````````````````` example _foo bar_ .

    foo bar

    ```````````````````````````````` This is not emphasis, because the opening `_` is followed by whitespace: ```````````````````````````````` example _ foo bar_ .

    _ foo bar_

    ```````````````````````````````` This is not emphasis, because the opening `_` is preceded by an alphanumeric and followed by punctuation: ```````````````````````````````` example a_"foo"_ .

    a_"foo"_

    ```````````````````````````````` Emphasis with `_` is not allowed inside words: ```````````````````````````````` example foo_bar_ .

    foo_bar_

    ```````````````````````````````` ```````````````````````````````` example 5_6_78 .

    5_6_78

    ```````````````````````````````` ```````````````````````````````` example пристаням_стремятся_ .

    пристаням_стремятся_

    ```````````````````````````````` Here `_` does not generate emphasis, because the first delimiter run is right-flanking and the second left-flanking: ```````````````````````````````` example aa_"bb"_cc .

    aa_"bb"_cc

    ```````````````````````````````` This is emphasis, even though the opening delimiter is both left- and right-flanking, because it is preceded by punctuation: ```````````````````````````````` example foo-_(bar)_ .

    foo-(bar)

    ```````````````````````````````` Rule 3: This is not emphasis, because the closing delimiter does not match the opening delimiter: ```````````````````````````````` example _foo* .

    _foo*

    ```````````````````````````````` This is not emphasis, because the closing `*` is preceded by whitespace: ```````````````````````````````` example *foo bar * .

    *foo bar *

    ```````````````````````````````` A newline also counts as whitespace: ```````````````````````````````` example *foo bar * .

    *foo bar *

    ```````````````````````````````` This is not emphasis, because the second `*` is preceded by punctuation and followed by an alphanumeric (hence it is not part of a [right-flanking delimiter run]: ```````````````````````````````` example *(*foo) .

    *(*foo)

    ```````````````````````````````` The point of this restriction is more easily appreciated with this example: ```````````````````````````````` example *(*foo*)* .

    (foo)

    ```````````````````````````````` Intraword emphasis with `*` is allowed: ```````````````````````````````` example *foo*bar .

    foobar

    ```````````````````````````````` Rule 4: This is not emphasis, because the closing `_` is preceded by whitespace: ```````````````````````````````` example _foo bar _ .

    _foo bar _

    ```````````````````````````````` This is not emphasis, because the second `_` is preceded by punctuation and followed by an alphanumeric: ```````````````````````````````` example _(_foo) .

    _(_foo)

    ```````````````````````````````` This is emphasis within emphasis: ```````````````````````````````` example _(_foo_)_ .

    (foo)

    ```````````````````````````````` Intraword emphasis is disallowed for `_`: ```````````````````````````````` example _foo_bar .

    _foo_bar

    ```````````````````````````````` ```````````````````````````````` example _пристаням_стремятся .

    _пристаням_стремятся

    ```````````````````````````````` ```````````````````````````````` example _foo_bar_baz_ .

    foo_bar_baz

    ```````````````````````````````` This is emphasis, even though the closing delimiter is both left- and right-flanking, because it is followed by punctuation: ```````````````````````````````` example _(bar)_. .

    (bar).

    ```````````````````````````````` Rule 5: ```````````````````````````````` example **foo bar** .

    foo bar

    ```````````````````````````````` This is not strong emphasis, because the opening delimiter is followed by whitespace: ```````````````````````````````` example ** foo bar** .

    ** foo bar**

    ```````````````````````````````` This is not strong emphasis, because the opening `**` is preceded by an alphanumeric and followed by punctuation, and hence not part of a [left-flanking delimiter run]: ```````````````````````````````` example a**"foo"** .

    a**"foo"**

    ```````````````````````````````` Intraword strong emphasis with `**` is permitted: ```````````````````````````````` example foo**bar** .

    foobar

    ```````````````````````````````` Rule 6: ```````````````````````````````` example __foo bar__ .

    foo bar

    ```````````````````````````````` This is not strong emphasis, because the opening delimiter is followed by whitespace: ```````````````````````````````` example __ foo bar__ .

    __ foo bar__

    ```````````````````````````````` A newline counts as whitespace: ```````````````````````````````` example __ foo bar__ .

    __ foo bar__

    ```````````````````````````````` This is not strong emphasis, because the opening `__` is preceded by an alphanumeric and followed by punctuation: ```````````````````````````````` example a__"foo"__ .

    a__"foo"__

    ```````````````````````````````` Intraword strong emphasis is forbidden with `__`: ```````````````````````````````` example foo__bar__ .

    foo__bar__

    ```````````````````````````````` ```````````````````````````````` example 5__6__78 .

    5__6__78

    ```````````````````````````````` ```````````````````````````````` example пристаням__стремятся__ .

    пристаням__стремятся__

    ```````````````````````````````` ```````````````````````````````` example __foo, __bar__, baz__ .

    foo, bar, baz

    ```````````````````````````````` This is strong emphasis, even though the opening delimiter is both left- and right-flanking, because it is preceded by punctuation: ```````````````````````````````` example foo-__(bar)__ .

    foo-(bar)

    ```````````````````````````````` Rule 7: This is not strong emphasis, because the closing delimiter is preceded by whitespace: ```````````````````````````````` example **foo bar ** .

    **foo bar **

    ```````````````````````````````` (Nor can it be interpreted as an emphasized `*foo bar *`, because of Rule 11.) This is not strong emphasis, because the second `**` is preceded by punctuation and followed by an alphanumeric: ```````````````````````````````` example **(**foo) .

    **(**foo)

    ```````````````````````````````` The point of this restriction is more easily appreciated with these examples: ```````````````````````````````` example *(**foo**)* .

    (foo)

    ```````````````````````````````` ```````````````````````````````` example **Gomphocarpus (*Gomphocarpus physocarpus*, syn. *Asclepias physocarpa*)** .

    Gomphocarpus (Gomphocarpus physocarpus, syn. Asclepias physocarpa)

    ```````````````````````````````` ```````````````````````````````` example **foo "*bar*" foo** .

    foo "bar" foo

    ```````````````````````````````` Intraword emphasis: ```````````````````````````````` example **foo**bar .

    foobar

    ```````````````````````````````` Rule 8: This is not strong emphasis, because the closing delimiter is preceded by whitespace: ```````````````````````````````` example __foo bar __ .

    __foo bar __

    ```````````````````````````````` This is not strong emphasis, because the second `__` is preceded by punctuation and followed by an alphanumeric: ```````````````````````````````` example __(__foo) .

    __(__foo)

    ```````````````````````````````` The point of this restriction is more easily appreciated with this example: ```````````````````````````````` example _(__foo__)_ .

    (foo)

    ```````````````````````````````` Intraword strong emphasis is forbidden with `__`: ```````````````````````````````` example __foo__bar .

    __foo__bar

    ```````````````````````````````` ```````````````````````````````` example __пристаням__стремятся .

    __пристаням__стремятся

    ```````````````````````````````` ```````````````````````````````` example __foo__bar__baz__ .

    foo__bar__baz

    ```````````````````````````````` This is strong emphasis, even though the closing delimiter is both left- and right-flanking, because it is followed by punctuation: ```````````````````````````````` example __(bar)__. .

    (bar).

    ```````````````````````````````` Rule 9: Any nonempty sequence of inline elements can be the contents of an emphasized span. ```````````````````````````````` example *foo [bar](/url)* .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example *foo bar* .

    foo bar

    ```````````````````````````````` In particular, emphasis and strong emphasis can be nested inside emphasis: ```````````````````````````````` example _foo __bar__ baz_ .

    foo bar baz

    ```````````````````````````````` ```````````````````````````````` example _foo _bar_ baz_ .

    foo bar baz

    ```````````````````````````````` ```````````````````````````````` example __foo_ bar_ .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example *foo *bar** .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example *foo **bar** baz* .

    foo bar baz

    ```````````````````````````````` ```````````````````````````````` example *foo**bar**baz* .

    foobarbaz

    ```````````````````````````````` Note that in the preceding case, the interpretation ``` markdown

    foobarbaz

    ``` is precluded by the condition that a delimiter that can both open and close (like the `*` after `foo`) cannot form emphasis if the sum of the lengths of the delimiter runs containing the opening and closing delimiters is a multiple of 3 unless both lengths are multiples of 3. For the same reason, we don't get two consecutive emphasis sections in this example: ```````````````````````````````` example *foo**bar* .

    foo**bar

    ```````````````````````````````` The same condition ensures that the following cases are all strong emphasis nested inside emphasis, even when the interior spaces are omitted: ```````````````````````````````` example ***foo** bar* .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example *foo **bar*** .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example *foo**bar*** .

    foobar

    ```````````````````````````````` When the lengths of the interior closing and opening delimiter runs are *both* multiples of 3, though, they can match to create emphasis: ```````````````````````````````` example foo***bar***baz .

    foobarbaz

    ```````````````````````````````` ```````````````````````````````` example foo******bar*********baz .

    foobar***baz

    ```````````````````````````````` Indefinite levels of nesting are possible: ```````````````````````````````` example *foo **bar *baz* bim** bop* .

    foo bar baz bim bop

    ```````````````````````````````` ```````````````````````````````` example *foo [*bar*](/url)* .

    foo bar

    ```````````````````````````````` There can be no empty emphasis or strong emphasis: ```````````````````````````````` example ** is not an empty emphasis .

    ** is not an empty emphasis

    ```````````````````````````````` ```````````````````````````````` example **** is not an empty strong emphasis .

    **** is not an empty strong emphasis

    ```````````````````````````````` Rule 10: Any nonempty sequence of inline elements can be the contents of an strongly emphasized span. ```````````````````````````````` example **foo [bar](/url)** .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example **foo bar** .

    foo bar

    ```````````````````````````````` In particular, emphasis and strong emphasis can be nested inside strong emphasis: ```````````````````````````````` example __foo _bar_ baz__ .

    foo bar baz

    ```````````````````````````````` ```````````````````````````````` example __foo __bar__ baz__ .

    foo bar baz

    ```````````````````````````````` ```````````````````````````````` example ____foo__ bar__ .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example **foo **bar**** .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example **foo *bar* baz** .

    foo bar baz

    ```````````````````````````````` ```````````````````````````````` example **foo*bar*baz** .

    foobarbaz

    ```````````````````````````````` ```````````````````````````````` example ***foo* bar** .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example **foo *bar*** .

    foo bar

    ```````````````````````````````` Indefinite levels of nesting are possible: ```````````````````````````````` example **foo *bar **baz** bim* bop** .

    foo bar baz bim bop

    ```````````````````````````````` ```````````````````````````````` example **foo [*bar*](/url)** .

    foo bar

    ```````````````````````````````` There can be no empty emphasis or strong emphasis: ```````````````````````````````` example __ is not an empty emphasis .

    __ is not an empty emphasis

    ```````````````````````````````` ```````````````````````````````` example ____ is not an empty strong emphasis .

    ____ is not an empty strong emphasis

    ```````````````````````````````` Rule 11: ```````````````````````````````` example foo *** .

    foo ***

    ```````````````````````````````` ```````````````````````````````` example foo *\** .

    foo *

    ```````````````````````````````` ```````````````````````````````` example foo *_* .

    foo _

    ```````````````````````````````` ```````````````````````````````` example foo ***** .

    foo *****

    ```````````````````````````````` ```````````````````````````````` example foo **\*** .

    foo *

    ```````````````````````````````` ```````````````````````````````` example foo **_** .

    foo _

    ```````````````````````````````` Note that when delimiters do not match evenly, Rule 11 determines that the excess literal `*` characters will appear outside of the emphasis, rather than inside it: ```````````````````````````````` example **foo* .

    *foo

    ```````````````````````````````` ```````````````````````````````` example *foo** .

    foo*

    ```````````````````````````````` ```````````````````````````````` example ***foo** .

    *foo

    ```````````````````````````````` ```````````````````````````````` example ****foo* .

    ***foo

    ```````````````````````````````` ```````````````````````````````` example **foo*** .

    foo*

    ```````````````````````````````` ```````````````````````````````` example *foo**** .

    foo***

    ```````````````````````````````` Rule 12: ```````````````````````````````` example foo ___ .

    foo ___

    ```````````````````````````````` ```````````````````````````````` example foo _\__ .

    foo _

    ```````````````````````````````` ```````````````````````````````` example foo _*_ .

    foo *

    ```````````````````````````````` ```````````````````````````````` example foo _____ .

    foo _____

    ```````````````````````````````` ```````````````````````````````` example foo __\___ .

    foo _

    ```````````````````````````````` ```````````````````````````````` example foo __*__ .

    foo *

    ```````````````````````````````` ```````````````````````````````` example __foo_ .

    _foo

    ```````````````````````````````` Note that when delimiters do not match evenly, Rule 12 determines that the excess literal `_` characters will appear outside of the emphasis, rather than inside it: ```````````````````````````````` example _foo__ .

    foo_

    ```````````````````````````````` ```````````````````````````````` example ___foo__ .

    _foo

    ```````````````````````````````` ```````````````````````````````` example ____foo_ .

    ___foo

    ```````````````````````````````` ```````````````````````````````` example __foo___ .

    foo_

    ```````````````````````````````` ```````````````````````````````` example _foo____ .

    foo___

    ```````````````````````````````` Rule 13 implies that if you want emphasis nested directly inside emphasis, you must use different delimiters: ```````````````````````````````` example **foo** .

    foo

    ```````````````````````````````` ```````````````````````````````` example *_foo_* .

    foo

    ```````````````````````````````` ```````````````````````````````` example __foo__ .

    foo

    ```````````````````````````````` ```````````````````````````````` example _*foo*_ .

    foo

    ```````````````````````````````` However, strong emphasis within strong emphasis is possible without switching delimiters: ```````````````````````````````` example ****foo**** .

    foo

    ```````````````````````````````` ```````````````````````````````` example ____foo____ .

    foo

    ```````````````````````````````` Rule 13 can be applied to arbitrarily long sequences of delimiters: ```````````````````````````````` example ******foo****** .

    foo

    ```````````````````````````````` Rule 14: ```````````````````````````````` example ***foo*** .

    foo

    ```````````````````````````````` ```````````````````````````````` example _____foo_____ .

    foo

    ```````````````````````````````` Rule 15: ```````````````````````````````` example *foo _bar* baz_ .

    foo _bar baz_

    ```````````````````````````````` ```````````````````````````````` example *foo __bar *baz bim__ bam* .

    foo bar *baz bim bam

    ```````````````````````````````` Rule 16: ```````````````````````````````` example **foo **bar baz** .

    **foo bar baz

    ```````````````````````````````` ```````````````````````````````` example *foo *bar baz* .

    *foo bar baz

    ```````````````````````````````` Rule 17: ```````````````````````````````` example *[bar*](/url) .

    *bar*

    ```````````````````````````````` ```````````````````````````````` example _foo [bar_](/url) .

    _foo bar_

    ```````````````````````````````` ```````````````````````````````` example * .

    *

    ```````````````````````````````` ```````````````````````````````` example ** .

    **

    ```````````````````````````````` ```````````````````````````````` example __ .

    __

    ```````````````````````````````` ```````````````````````````````` example *a `*`* .

    a *

    ```````````````````````````````` ```````````````````````````````` example _a `_`_ .

    a _

    ```````````````````````````````` ```````````````````````````````` example **a .

    **ahttp://foo.bar/?q=**

    ```````````````````````````````` ```````````````````````````````` example __a .

    __ahttp://foo.bar/?q=__

    ```````````````````````````````` ## Links A link contains [link text] (the visible text), a [link destination] (the URI that is the link destination), and optionally a [link title]. There are two basic kinds of links in Markdown. In [inline links] the destination and title are given immediately after the link text. In [reference links] the destination and title are defined elsewhere in the document. A [link text](@) consists of a sequence of zero or more inline elements enclosed by square brackets (`[` and `]`). The following rules apply: - Links may not contain other links, at any level of nesting. If multiple otherwise valid link definitions appear nested inside each other, the inner-most definition is used. - Brackets are allowed in the [link text] only if (a) they are backslash-escaped or (b) they appear as a matched pair of brackets, with an open bracket `[`, a sequence of zero or more inlines, and a close bracket `]`. - Backtick [code spans], [autolinks], and raw [HTML tags] bind more tightly than the brackets in link text. Thus, for example, `` [foo`]` `` could not be a link text, since the second `]` is part of a code span. - The brackets in link text bind more tightly than markers for [emphasis and strong emphasis]. Thus, for example, `*[foo*](url)` is a link. A [link destination](@) consists of either - a sequence of zero or more characters between an opening `<` and a closing `>` that contains no line breaks or unescaped `<` or `>` characters, or - a nonempty sequence of characters that does not start with `<`, does not include ASCII space or control characters, and includes parentheses only if (a) they are backslash-escaped or (b) they are part of a balanced pair of unescaped parentheses. (Implementations may impose limits on parentheses nesting to avoid performance issues, but at least three levels of nesting should be supported.) A [link title](@) consists of either - a sequence of zero or more characters between straight double-quote characters (`"`), including a `"` character only if it is backslash-escaped, or - a sequence of zero or more characters between straight single-quote characters (`'`), including a `'` character only if it is backslash-escaped, or - a sequence of zero or more characters between matching parentheses (`(...)`), including a `(` or `)` character only if it is backslash-escaped. Although [link titles] may span multiple lines, they may not contain a [blank line]. An [inline link](@) consists of a [link text] followed immediately by a left parenthesis `(`, optional [whitespace], an optional [link destination], an optional [link title] separated from the link destination by [whitespace], optional [whitespace], and a right parenthesis `)`. The link's text consists of the inlines contained in the [link text] (excluding the enclosing square brackets). The link's URI consists of the link destination, excluding enclosing `<...>` if present, with backslash-escapes in effect as described above. The link's title consists of the link title, excluding its enclosing delimiters, with backslash-escapes in effect as described above. Here is a simple inline link: ```````````````````````````````` example [link](/uri "title") .

    link

    ```````````````````````````````` The title may be omitted: ```````````````````````````````` example [link](/uri) .

    link

    ```````````````````````````````` Both the title and the destination may be omitted: ```````````````````````````````` example [link]() .

    link

    ```````````````````````````````` ```````````````````````````````` example [link](<>) .

    link

    ```````````````````````````````` The destination can only contain spaces if it is enclosed in pointy brackets: ```````````````````````````````` example [link](/my uri) .

    [link](/my uri)

    ```````````````````````````````` ```````````````````````````````` example [link](
    ) .

    link

    ```````````````````````````````` The destination cannot contain line breaks, even if enclosed in pointy brackets: ```````````````````````````````` example [link](foo bar) .

    [link](foo bar)

    ```````````````````````````````` ```````````````````````````````` example [link]() .

    [link]()

    ```````````````````````````````` The destination can contain `)` if it is enclosed in pointy brackets: ```````````````````````````````` example [a]() .

    a

    ```````````````````````````````` Pointy brackets that enclose links must be unescaped: ```````````````````````````````` example [link]() .

    [link](<foo>)

    ```````````````````````````````` These are not links, because the opening pointy bracket is not matched properly: ```````````````````````````````` example [a]( [a](c) .

    [a](<b)c [a](<b)c> [a](c)

    ```````````````````````````````` Parentheses inside the link destination may be escaped: ```````````````````````````````` example [link](\(foo\)) .

    link

    ```````````````````````````````` Any number of parentheses are allowed without escaping, as long as they are balanced: ```````````````````````````````` example [link](foo(and(bar))) .

    link

    ```````````````````````````````` However, if you have unbalanced parentheses, you need to escape or use the `<...>` form: ```````````````````````````````` example [link](foo\(and\(bar\)) .

    link

    ```````````````````````````````` ```````````````````````````````` example [link]() .

    link

    ```````````````````````````````` Parentheses and other symbols can also be escaped, as usual in Markdown: ```````````````````````````````` example [link](foo\)\:) .

    link

    ```````````````````````````````` A link can contain fragment identifiers and queries: ```````````````````````````````` example [link](#fragment) [link](http://example.com#fragment) [link](http://example.com?foo=3#frag) .

    link

    link

    link

    ```````````````````````````````` Note that a backslash before a non-escapable character is just a backslash: ```````````````````````````````` example [link](foo\bar) .

    link

    ```````````````````````````````` URL-escaping should be left alone inside the destination, as all URL-escaped characters are also valid URL characters. Entity and numerical character references in the destination will be parsed into the corresponding Unicode code points, as usual. These may be optionally URL-escaped when written as HTML, but this spec does not enforce any particular policy for rendering URLs in HTML or other formats. Renderers may make different decisions about how to escape or normalize URLs in the output. ```````````````````````````````` example [link](foo%20bä) .

    link

    ```````````````````````````````` Note that, because titles can often be parsed as destinations, if you try to omit the destination and keep the title, you'll get unexpected results: ```````````````````````````````` example [link]("title") .

    link

    ```````````````````````````````` Titles may be in single quotes, double quotes, or parentheses: ```````````````````````````````` example [link](/url "title") [link](/url 'title') [link](/url (title)) .

    link link link

    ```````````````````````````````` Backslash escapes and entity and numeric character references may be used in titles: ```````````````````````````````` example [link](/url "title \""") .

    link

    ```````````````````````````````` Titles must be separated from the link using a [whitespace]. Other [Unicode whitespace] like non-breaking space doesn't work. ```````````````````````````````` example [link](/url "title") .

    link

    ```````````````````````````````` Nested balanced quotes are not allowed without escaping: ```````````````````````````````` example [link](/url "title "and" title") .

    [link](/url "title "and" title")

    ```````````````````````````````` But it is easy to work around this by using a different quote type: ```````````````````````````````` example [link](/url 'title "and" title') .

    link

    ```````````````````````````````` (Note: `Markdown.pl` did allow double quotes inside a double-quoted title, and its test suite included a test demonstrating this. But it is hard to see a good rationale for the extra complexity this brings, since there are already many ways---backslash escaping, entity and numeric character references, or using a different quote type for the enclosing title---to write titles containing double quotes. `Markdown.pl`'s handling of titles has a number of other strange features. For example, it allows single-quoted titles in inline links, but not reference links. And, in reference links but not inline links, it allows a title to begin with `"` and end with `)`. `Markdown.pl` 1.0.1 even allows titles with no closing quotation mark, though 1.0.2b8 does not. It seems preferable to adopt a simple, rational rule that works the same way in inline links and link reference definitions.) [Whitespace] is allowed around the destination and title: ```````````````````````````````` example [link]( /uri "title" ) .

    link

    ```````````````````````````````` But it is not allowed between the link text and the following parenthesis: ```````````````````````````````` example [link] (/uri) .

    [link] (/uri)

    ```````````````````````````````` The link text may contain balanced brackets, but not unbalanced ones, unless they are escaped: ```````````````````````````````` example [link [foo [bar]]](/uri) .

    link [foo [bar]]

    ```````````````````````````````` ```````````````````````````````` example [link] bar](/uri) .

    [link] bar](/uri)

    ```````````````````````````````` ```````````````````````````````` example [link [bar](/uri) .

    [link bar

    ```````````````````````````````` ```````````````````````````````` example [link \[bar](/uri) .

    link [bar

    ```````````````````````````````` The link text may contain inline content: ```````````````````````````````` example [link *foo **bar** `#`*](/uri) .

    link foo bar #

    ```````````````````````````````` ```````````````````````````````` example [![moon](moon.jpg)](/uri) .

    moon

    ```````````````````````````````` However, links may not contain other links, at any level of nesting. ```````````````````````````````` example [foo [bar](/uri)](/uri) .

    [foo bar](/uri)

    ```````````````````````````````` ```````````````````````````````` example [foo *[bar [baz](/uri)](/uri)*](/uri) .

    [foo [bar baz](/uri)](/uri)

    ```````````````````````````````` ```````````````````````````````` example ![[[foo](uri1)](uri2)](uri3) .

    [foo](uri2)

    ```````````````````````````````` These cases illustrate the precedence of link text grouping over emphasis grouping: ```````````````````````````````` example *[foo*](/uri) .

    *foo*

    ```````````````````````````````` ```````````````````````````````` example [foo *bar](baz*) .

    foo *bar

    ```````````````````````````````` Note that brackets that *aren't* part of links do not take precedence: ```````````````````````````````` example *foo [bar* baz] .

    foo [bar baz]

    ```````````````````````````````` These cases illustrate the precedence of HTML tags, code spans, and autolinks over link grouping: ```````````````````````````````` example [foo .

    [foo

    ```````````````````````````````` ```````````````````````````````` example [foo`](/uri)` .

    [foo](/uri)

    ```````````````````````````````` ```````````````````````````````` example [foo .

    [foohttp://example.com/?search=](uri)

    ```````````````````````````````` There are three kinds of [reference link](@)s: [full](#full-reference-link), [collapsed](#collapsed-reference-link), and [shortcut](#shortcut-reference-link). A [full reference link](@) consists of a [link text] immediately followed by a [link label] that [matches] a [link reference definition] elsewhere in the document. A [link label](@) begins with a left bracket (`[`) and ends with the first right bracket (`]`) that is not backslash-escaped. Between these brackets there must be at least one [non-whitespace character]. Unescaped square bracket characters are not allowed inside the opening and closing square brackets of [link labels]. A link label can have at most 999 characters inside the square brackets. One label [matches](@) another just in case their normalized forms are equal. To normalize a label, strip off the opening and closing brackets, perform the *Unicode case fold*, strip leading and trailing [whitespace] and collapse consecutive internal [whitespace] to a single space. If there are multiple matching reference link definitions, the one that comes first in the document is used. (It is desirable in such cases to emit a warning.) The contents of the first link label are parsed as inlines, which are used as the link's text. The link's URI and title are provided by the matching [link reference definition]. Here is a simple example: ```````````````````````````````` example [foo][bar] [bar]: /url "title" .

    foo

    ```````````````````````````````` The rules for the [link text] are the same as with [inline links]. Thus: The link text may contain balanced brackets, but not unbalanced ones, unless they are escaped: ```````````````````````````````` example [link [foo [bar]]][ref] [ref]: /uri .

    link [foo [bar]]

    ```````````````````````````````` ```````````````````````````````` example [link \[bar][ref] [ref]: /uri .

    link [bar

    ```````````````````````````````` The link text may contain inline content: ```````````````````````````````` example [link *foo **bar** `#`*][ref] [ref]: /uri .

    link foo bar #

    ```````````````````````````````` ```````````````````````````````` example [![moon](moon.jpg)][ref] [ref]: /uri .

    moon

    ```````````````````````````````` However, links may not contain other links, at any level of nesting. ```````````````````````````````` example [foo [bar](/uri)][ref] [ref]: /uri .

    [foo bar]ref

    ```````````````````````````````` ```````````````````````````````` example [foo *bar [baz][ref]*][ref] [ref]: /uri .

    [foo bar baz]ref

    ```````````````````````````````` (In the examples above, we have two [shortcut reference links] instead of one [full reference link].) The following cases illustrate the precedence of link text grouping over emphasis grouping: ```````````````````````````````` example *[foo*][ref] [ref]: /uri .

    *foo*

    ```````````````````````````````` ```````````````````````````````` example [foo *bar][ref] [ref]: /uri .

    foo *bar

    ```````````````````````````````` These cases illustrate the precedence of HTML tags, code spans, and autolinks over link grouping: ```````````````````````````````` example [foo [ref]: /uri .

    [foo

    ```````````````````````````````` ```````````````````````````````` example [foo`][ref]` [ref]: /uri .

    [foo][ref]

    ```````````````````````````````` ```````````````````````````````` example [foo [ref]: /uri .

    [foohttp://example.com/?search=][ref]

    ```````````````````````````````` Matching is case-insensitive: ```````````````````````````````` example [foo][BaR] [bar]: /url "title" .

    foo

    ```````````````````````````````` Unicode case fold is used: ```````````````````````````````` example [Толпой][Толпой] is a Russian word. [ТОЛПОЙ]: /url .

    Толпой is a Russian word.

    ```````````````````````````````` Consecutive internal [whitespace] is treated as one space for purposes of determining matching: ```````````````````````````````` example [Foo bar]: /url [Baz][Foo bar] .

    Baz

    ```````````````````````````````` No [whitespace] is allowed between the [link text] and the [link label]: ```````````````````````````````` example [foo] [bar] [bar]: /url "title" .

    [foo] bar

    ```````````````````````````````` ```````````````````````````````` example [foo] [bar] [bar]: /url "title" .

    [foo] bar

    ```````````````````````````````` This is a departure from John Gruber's original Markdown syntax description, which explicitly allows whitespace between the link text and the link label. It brings reference links in line with [inline links], which (according to both original Markdown and this spec) cannot have whitespace after the link text. More importantly, it prevents inadvertent capture of consecutive [shortcut reference links]. If whitespace is allowed between the link text and the link label, then in the following we will have a single reference link, not two shortcut reference links, as intended: ``` markdown [foo] [bar] [foo]: /url1 [bar]: /url2 ``` (Note that [shortcut reference links] were introduced by Gruber himself in a beta version of `Markdown.pl`, but never included in the official syntax description. Without shortcut reference links, it is harmless to allow space between the link text and link label; but once shortcut references are introduced, it is too dangerous to allow this, as it frequently leads to unintended results.) When there are multiple matching [link reference definitions], the first is used: ```````````````````````````````` example [foo]: /url1 [foo]: /url2 [bar][foo] .

    bar

    ```````````````````````````````` Note that matching is performed on normalized strings, not parsed inline content. So the following does not match, even though the labels define equivalent inline content: ```````````````````````````````` example [bar][foo\!] [foo!]: /url .

    [bar][foo!]

    ```````````````````````````````` [Link labels] cannot contain brackets, unless they are backslash-escaped: ```````````````````````````````` example [foo][ref[] [ref[]: /uri .

    [foo][ref[]

    [ref[]: /uri

    ```````````````````````````````` ```````````````````````````````` example [foo][ref[bar]] [ref[bar]]: /uri .

    [foo][ref[bar]]

    [ref[bar]]: /uri

    ```````````````````````````````` ```````````````````````````````` example [[[foo]]] [[[foo]]]: /url .

    [[[foo]]]

    [[[foo]]]: /url

    ```````````````````````````````` ```````````````````````````````` example [foo][ref\[] [ref\[]: /uri .

    foo

    ```````````````````````````````` Note that in this example `]` is not backslash-escaped: ```````````````````````````````` example [bar\\]: /uri [bar\\] .

    bar\

    ```````````````````````````````` A [link label] must contain at least one [non-whitespace character]: ```````````````````````````````` example [] []: /uri .

    []

    []: /uri

    ```````````````````````````````` ```````````````````````````````` example [ ] [ ]: /uri .

    [ ]

    [ ]: /uri

    ```````````````````````````````` A [collapsed reference link](@) consists of a [link label] that [matches] a [link reference definition] elsewhere in the document, followed by the string `[]`. The contents of the first link label are parsed as inlines, which are used as the link's text. The link's URI and title are provided by the matching reference link definition. Thus, `[foo][]` is equivalent to `[foo][foo]`. ```````````````````````````````` example [foo][] [foo]: /url "title" .

    foo

    ```````````````````````````````` ```````````````````````````````` example [*foo* bar][] [*foo* bar]: /url "title" .

    foo bar

    ```````````````````````````````` The link labels are case-insensitive: ```````````````````````````````` example [Foo][] [foo]: /url "title" .

    Foo

    ```````````````````````````````` As with full reference links, [whitespace] is not allowed between the two sets of brackets: ```````````````````````````````` example [foo] [] [foo]: /url "title" .

    foo []

    ```````````````````````````````` A [shortcut reference link](@) consists of a [link label] that [matches] a [link reference definition] elsewhere in the document and is not followed by `[]` or a link label. The contents of the first link label are parsed as inlines, which are used as the link's text. The link's URI and title are provided by the matching link reference definition. Thus, `[foo]` is equivalent to `[foo][]`. ```````````````````````````````` example [foo] [foo]: /url "title" .

    foo

    ```````````````````````````````` ```````````````````````````````` example [*foo* bar] [*foo* bar]: /url "title" .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example [[*foo* bar]] [*foo* bar]: /url "title" .

    [foo bar]

    ```````````````````````````````` ```````````````````````````````` example [[bar [foo] [foo]: /url .

    [[bar foo

    ```````````````````````````````` The link labels are case-insensitive: ```````````````````````````````` example [Foo] [foo]: /url "title" .

    Foo

    ```````````````````````````````` A space after the link text should be preserved: ```````````````````````````````` example [foo] bar [foo]: /url .

    foo bar

    ```````````````````````````````` If you just want bracketed text, you can backslash-escape the opening bracket to avoid links: ```````````````````````````````` example \[foo] [foo]: /url "title" .

    [foo]

    ```````````````````````````````` Note that this is a link, because a link label ends with the first following closing bracket: ```````````````````````````````` example [foo*]: /url *[foo*] .

    *foo*

    ```````````````````````````````` Full and compact references take precedence over shortcut references: ```````````````````````````````` example [foo][bar] [foo]: /url1 [bar]: /url2 .

    foo

    ```````````````````````````````` ```````````````````````````````` example [foo][] [foo]: /url1 .

    foo

    ```````````````````````````````` Inline links also take precedence: ```````````````````````````````` example [foo]() [foo]: /url1 .

    foo

    ```````````````````````````````` ```````````````````````````````` example [foo](not a link) [foo]: /url1 .

    foo(not a link)

    ```````````````````````````````` In the following case `[bar][baz]` is parsed as a reference, `[foo]` as normal text: ```````````````````````````````` example [foo][bar][baz] [baz]: /url .

    [foo]bar

    ```````````````````````````````` Here, though, `[foo][bar]` is parsed as a reference, since `[bar]` is defined: ```````````````````````````````` example [foo][bar][baz] [baz]: /url1 [bar]: /url2 .

    foobaz

    ```````````````````````````````` Here `[foo]` is not parsed as a shortcut reference, because it is followed by a link label (even though `[bar]` is not defined): ```````````````````````````````` example [foo][bar][baz] [baz]: /url1 [foo]: /url2 .

    [foo]bar

    ```````````````````````````````` ## Images Syntax for images is like the syntax for links, with one difference. Instead of [link text], we have an [image description](@). The rules for this are the same as for [link text], except that (a) an image description starts with `![` rather than `[`, and (b) an image description may contain links. An image description has inline elements as its contents. When an image is rendered to HTML, this is standardly used as the image's `alt` attribute. ```````````````````````````````` example ![foo](/url "title") .

    foo

    ```````````````````````````````` ```````````````````````````````` example ![foo *bar*] [foo *bar*]: train.jpg "train & tracks" .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example ![foo ![bar](/url)](/url2) .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example ![foo [bar](/url)](/url2) .

    foo bar

    ```````````````````````````````` Though this spec is concerned with parsing, not rendering, it is recommended that in rendering to HTML, only the plain string content of the [image description] be used. Note that in the above example, the alt attribute's value is `foo bar`, not `foo [bar](/url)` or `foo bar`. Only the plain string content is rendered, without formatting. ```````````````````````````````` example ![foo *bar*][] [foo *bar*]: train.jpg "train & tracks" .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example ![foo *bar*][foobar] [FOOBAR]: train.jpg "train & tracks" .

    foo bar

    ```````````````````````````````` ```````````````````````````````` example ![foo](train.jpg) .

    foo

    ```````````````````````````````` ```````````````````````````````` example My ![foo bar](/path/to/train.jpg "title" ) .

    My foo bar

    ```````````````````````````````` ```````````````````````````````` example ![foo]() .

    foo

    ```````````````````````````````` ```````````````````````````````` example ![](/url) .

    ```````````````````````````````` Reference-style: ```````````````````````````````` example ![foo][bar] [bar]: /url .

    foo

    ```````````````````````````````` ```````````````````````````````` example ![foo][bar] [BAR]: /url .

    foo

    ```````````````````````````````` Collapsed: ```````````````````````````````` example ![foo][] [foo]: /url "title" .

    foo

    ```````````````````````````````` ```````````````````````````````` example ![*foo* bar][] [*foo* bar]: /url "title" .

    foo bar

    ```````````````````````````````` The labels are case-insensitive: ```````````````````````````````` example ![Foo][] [foo]: /url "title" .

    Foo

    ```````````````````````````````` As with reference links, [whitespace] is not allowed between the two sets of brackets: ```````````````````````````````` example ![foo] [] [foo]: /url "title" .

    foo []

    ```````````````````````````````` Shortcut: ```````````````````````````````` example ![foo] [foo]: /url "title" .

    foo

    ```````````````````````````````` ```````````````````````````````` example ![*foo* bar] [*foo* bar]: /url "title" .

    foo bar

    ```````````````````````````````` Note that link labels cannot contain unescaped brackets: ```````````````````````````````` example ![[foo]] [[foo]]: /url "title" .

    ![[foo]]

    [[foo]]: /url "title"

    ```````````````````````````````` The link labels are case-insensitive: ```````````````````````````````` example ![Foo] [foo]: /url "title" .

    Foo

    ```````````````````````````````` If you just want a literal `!` followed by bracketed text, you can backslash-escape the opening `[`: ```````````````````````````````` example !\[foo] [foo]: /url "title" .

    ![foo]

    ```````````````````````````````` If you want a link after a literal `!`, backslash-escape the `!`: ```````````````````````````````` example \![foo] [foo]: /url "title" .

    !foo

    ```````````````````````````````` ## Autolinks [Autolink](@)s are absolute URIs and email addresses inside `<` and `>`. They are parsed as links, with the URL or email address as the link label. A [URI autolink](@) consists of `<`, followed by an [absolute URI] followed by `>`. It is parsed as a link to the URI, with the URI as the link's label. An [absolute URI](@), for these purposes, consists of a [scheme] followed by a colon (`:`) followed by zero or more characters other than ASCII [whitespace] and control characters, `<`, and `>`. If the URI includes these characters, they must be percent-encoded (e.g. `%20` for a space). For purposes of this spec, a [scheme](@) is any sequence of 2--32 characters beginning with an ASCII letter and followed by any combination of ASCII letters, digits, or the symbols plus ("+"), period ("."), or hyphen ("-"). Here are some valid autolinks: ```````````````````````````````` example .

    http://foo.bar.baz

    ```````````````````````````````` ```````````````````````````````` example .

    http://foo.bar.baz/test?q=hello&id=22&boolean

    ```````````````````````````````` ```````````````````````````````` example .

    irc://foo.bar:2233/baz

    ```````````````````````````````` Uppercase is also fine: ```````````````````````````````` example .

    MAILTO:FOO@BAR.BAZ

    ```````````````````````````````` Note that many strings that count as [absolute URIs] for purposes of this spec are not valid URIs, because their schemes are not registered or because of other problems with their syntax: ```````````````````````````````` example .

    a+b+c:d

    ```````````````````````````````` ```````````````````````````````` example .

    made-up-scheme://foo,bar

    ```````````````````````````````` ```````````````````````````````` example .

    http://../

    ```````````````````````````````` ```````````````````````````````` example .

    localhost:5001/foo

    ```````````````````````````````` Spaces are not allowed in autolinks: ```````````````````````````````` example .

    <http://foo.bar/baz bim>

    ```````````````````````````````` Backslash-escapes do not work inside autolinks: ```````````````````````````````` example .

    http://example.com/\[\

    ```````````````````````````````` An [email autolink](@) consists of `<`, followed by an [email address], followed by `>`. The link's label is the email address, and the URL is `mailto:` followed by the email address. An [email address](@), for these purposes, is anything that matches the [non-normative regex from the HTML5 spec](https://html.spec.whatwg.org/multipage/forms.html#e-mail-state-(type=email)): /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ Examples of email autolinks: ```````````````````````````````` example .

    foo@bar.example.com

    ```````````````````````````````` ```````````````````````````````` example .

    foo+special@Bar.baz-bar0.com

    ```````````````````````````````` Backslash-escapes do not work inside email autolinks: ```````````````````````````````` example .

    <foo+@bar.example.com>

    ```````````````````````````````` These are not autolinks: ```````````````````````````````` example <> .

    <>

    ```````````````````````````````` ```````````````````````````````` example < http://foo.bar > .

    < http://foo.bar >

    ```````````````````````````````` ```````````````````````````````` example .

    <m:abc>

    ```````````````````````````````` ```````````````````````````````` example .

    <foo.bar.baz>

    ```````````````````````````````` ```````````````````````````````` example http://example.com .

    http://example.com

    ```````````````````````````````` ```````````````````````````````` example foo@bar.example.com .

    foo@bar.example.com

    ```````````````````````````````` ## Raw HTML Text between `<` and `>` that looks like an HTML tag is parsed as a raw HTML tag and will be rendered in HTML without escaping. Tag and attribute names are not limited to current HTML tags, so custom tags (and even, say, DocBook tags) may be used. Here is the grammar for tags: A [tag name](@) consists of an ASCII letter followed by zero or more ASCII letters, digits, or hyphens (`-`). An [attribute](@) consists of [whitespace], an [attribute name], and an optional [attribute value specification]. An [attribute name](@) consists of an ASCII letter, `_`, or `:`, followed by zero or more ASCII letters, digits, `_`, `.`, `:`, or `-`. (Note: This is the XML specification restricted to ASCII. HTML5 is laxer.) An [attribute value specification](@) consists of optional [whitespace], a `=` character, optional [whitespace], and an [attribute value]. An [attribute value](@) consists of an [unquoted attribute value], a [single-quoted attribute value], or a [double-quoted attribute value]. An [unquoted attribute value](@) is a nonempty string of characters not including [whitespace], `"`, `'`, `=`, `<`, `>`, or `` ` ``. A [single-quoted attribute value](@) consists of `'`, zero or more characters not including `'`, and a final `'`. A [double-quoted attribute value](@) consists of `"`, zero or more characters not including `"`, and a final `"`. An [open tag](@) consists of a `<` character, a [tag name], zero or more [attributes], optional [whitespace], an optional `/` character, and a `>` character. A [closing tag](@) consists of the string ``. An [HTML comment](@) consists of ``, where *text* does not start with `>` or `->`, does not end with `-`, and does not contain `--`. (See the [HTML5 spec](http://www.w3.org/TR/html5/syntax.html#comments).) A [processing instruction](@) consists of the string ``, and the string `?>`. A [declaration](@) consists of the string ``, and the character `>`. A [CDATA section](@) consists of the string ``, and the string `]]>`. An [HTML tag](@) consists of an [open tag], a [closing tag], an [HTML comment], a [processing instruction], a [declaration], or a [CDATA section]. Here are some simple open tags: ```````````````````````````````` example .

    ```````````````````````````````` Empty elements: ```````````````````````````````` example .

    ```````````````````````````````` [Whitespace] is allowed: ```````````````````````````````` example .

    ```````````````````````````````` With attributes: ```````````````````````````````` example .

    ```````````````````````````````` Custom tag names can be used: ```````````````````````````````` example Foo .

    Foo

    ```````````````````````````````` Illegal tag names, not parsed as HTML: ```````````````````````````````` example <33> <__> .

    <33> <__>

    ```````````````````````````````` Illegal attribute names: ```````````````````````````````` example
    .

    <a h*#ref="hi">

    ```````````````````````````````` Illegal attribute values: ```````````````````````````````` example
    .

    </a href="foo">

    ```````````````````````````````` Comments: ```````````````````````````````` example foo .

    foo

    ```````````````````````````````` ```````````````````````````````` example foo .

    foo <!-- not a comment -- two hyphens -->

    ```````````````````````````````` Not comments: ```````````````````````````````` example foo foo --> foo .

    foo <!--> foo -->

    foo <!-- foo--->

    ```````````````````````````````` Processing instructions: ```````````````````````````````` example foo .

    foo

    ```````````````````````````````` Declarations: ```````````````````````````````` example foo .

    foo

    ```````````````````````````````` CDATA sections: ```````````````````````````````` example foo &<]]> .

    foo &<]]>

    ```````````````````````````````` Entity and numeric character references are preserved in HTML attributes: ```````````````````````````````` example foo
    .

    foo

    ```````````````````````````````` Backslash escapes do not work in HTML attributes: ```````````````````````````````` example foo .

    foo

    ```````````````````````````````` ```````````````````````````````` example .

    <a href=""">

    ```````````````````````````````` ## Hard line breaks A line break (not in a code span or HTML tag) that is preceded by two or more spaces and does not occur at the end of a block is parsed as a [hard line break](@) (rendered in HTML as a `
    ` tag): ```````````````````````````````` example foo baz .

    foo
    baz

    ```````````````````````````````` For a more visible alternative, a backslash before the [line ending] may be used instead of two spaces: ```````````````````````````````` example foo\ baz .

    foo
    baz

    ```````````````````````````````` More than two spaces can be used: ```````````````````````````````` example foo baz .

    foo
    baz

    ```````````````````````````````` Leading spaces at the beginning of the next line are ignored: ```````````````````````````````` example foo bar .

    foo
    bar

    ```````````````````````````````` ```````````````````````````````` example foo\ bar .

    foo
    bar

    ```````````````````````````````` Line breaks can occur inside emphasis, links, and other constructs that allow inline content: ```````````````````````````````` example *foo bar* .

    foo
    bar

    ```````````````````````````````` ```````````````````````````````` example *foo\ bar* .

    foo
    bar

    ```````````````````````````````` Line breaks do not occur inside code spans ```````````````````````````````` example `code span` .

    code span

    ```````````````````````````````` ```````````````````````````````` example `code\ span` .

    code\ span

    ```````````````````````````````` or HTML tags: ```````````````````````````````` example
    .

    ```````````````````````````````` ```````````````````````````````` example .

    ```````````````````````````````` Hard line breaks are for separating inline content within a block. Neither syntax for hard line breaks works at the end of a paragraph or other block element: ```````````````````````````````` example foo\ .

    foo\

    ```````````````````````````````` ```````````````````````````````` example foo .

    foo

    ```````````````````````````````` ```````````````````````````````` example ### foo\ .

    foo\

    ```````````````````````````````` ```````````````````````````````` example ### foo .

    foo

    ```````````````````````````````` ## Soft line breaks A regular line break (not in a code span or HTML tag) that is not preceded by two or more spaces or a backslash is parsed as a [softbreak](@). (A softbreak may be rendered in HTML either as a [line ending] or as a space. The result will be the same in browsers. In the examples here, a [line ending] will be used.) ```````````````````````````````` example foo baz .

    foo baz

    ```````````````````````````````` Spaces at the end of the line and beginning of the next line are removed: ```````````````````````````````` example foo baz .

    foo baz

    ```````````````````````````````` A conforming parser may render a soft line break in HTML either as a line break or as a space. A renderer may also provide an option to render soft line breaks as hard line breaks. ## Textual content Any characters not given an interpretation by the above rules will be parsed as plain textual content. ```````````````````````````````` example hello $.;'there .

    hello $.;'there

    ```````````````````````````````` ```````````````````````````````` example Foo χρῆν .

    Foo χρῆν

    ```````````````````````````````` Internal spaces are preserved verbatim: ```````````````````````````````` example Multiple spaces .

    Multiple spaces

    ```````````````````````````````` # Appendix: A parsing strategy In this appendix we describe some features of the parsing strategy used in the CommonMark reference implementations. ## Overview Parsing has two phases: 1. In the first phase, lines of input are consumed and the block structure of the document---its division into paragraphs, block quotes, list items, and so on---is constructed. Text is assigned to these blocks but not parsed. Link reference definitions are parsed and a map of links is constructed. 2. In the second phase, the raw text contents of paragraphs and headings are parsed into sequences of Markdown inline elements (strings, code spans, links, emphasis, and so on), using the map of link references constructed in phase 1. At each point in processing, the document is represented as a tree of **blocks**. The root of the tree is a `document` block. The `document` may have any number of other blocks as **children**. These children may, in turn, have other blocks as children. The last child of a block is normally considered **open**, meaning that subsequent lines of input can alter its contents. (Blocks that are not open are **closed**.) Here, for example, is a possible document tree, with the open blocks marked by arrows: ``` tree -> document -> block_quote paragraph "Lorem ipsum dolor\nsit amet." -> list (type=bullet tight=true bullet_char=-) list_item paragraph "Qui *quodsi iracundia*" -> list_item -> paragraph "aliquando id" ``` ## Phase 1: block structure Each line that is processed has an effect on this tree. The line is analyzed and, depending on its contents, the document may be altered in one or more of the following ways: 1. One or more open blocks may be closed. 2. One or more new blocks may be created as children of the last open block. 3. Text may be added to the last (deepest) open block remaining on the tree. Once a line has been incorporated into the tree in this way, it can be discarded, so input can be read in a stream. For each line, we follow this procedure: 1. First we iterate through the open blocks, starting with the root document, and descending through last children down to the last open block. Each block imposes a condition that the line must satisfy if the block is to remain open. For example, a block quote requires a `>` character. A paragraph requires a non-blank line. In this phase we may match all or just some of the open blocks. But we cannot close unmatched blocks yet, because we may have a [lazy continuation line]. 2. Next, after consuming the continuation markers for existing blocks, we look for new block starts (e.g. `>` for a block quote). If we encounter a new block start, we close any blocks unmatched in step 1 before creating the new block as a child of the last matched block. 3. Finally, we look at the remainder of the line (after block markers like `>`, list markers, and indentation have been consumed). This is text that can be incorporated into the last open block (a paragraph, code block, heading, or raw HTML). Setext headings are formed when we see a line of a paragraph that is a [setext heading underline]. Reference link definitions are detected when a paragraph is closed; the accumulated text lines are parsed to see if they begin with one or more reference link definitions. Any remainder becomes a normal paragraph. We can see how this works by considering how the tree above is generated by four lines of Markdown: ``` markdown > Lorem ipsum dolor sit amet. > - Qui *quodsi iracundia* > - aliquando id ``` At the outset, our document model is just ``` tree -> document ``` The first line of our text, ``` markdown > Lorem ipsum dolor ``` causes a `block_quote` block to be created as a child of our open `document` block, and a `paragraph` block as a child of the `block_quote`. Then the text is added to the last open block, the `paragraph`: ``` tree -> document -> block_quote -> paragraph "Lorem ipsum dolor" ``` The next line, ``` markdown sit amet. ``` is a "lazy continuation" of the open `paragraph`, so it gets added to the paragraph's text: ``` tree -> document -> block_quote -> paragraph "Lorem ipsum dolor\nsit amet." ``` The third line, ``` markdown > - Qui *quodsi iracundia* ``` causes the `paragraph` block to be closed, and a new `list` block opened as a child of the `block_quote`. A `list_item` is also added as a child of the `list`, and a `paragraph` as a child of the `list_item`. The text is then added to the new `paragraph`: ``` tree -> document -> block_quote paragraph "Lorem ipsum dolor\nsit amet." -> list (type=bullet tight=true bullet_char=-) -> list_item -> paragraph "Qui *quodsi iracundia*" ``` The fourth line, ``` markdown > - aliquando id ``` causes the `list_item` (and its child the `paragraph`) to be closed, and a new `list_item` opened up as child of the `list`. A `paragraph` is added as a child of the new `list_item`, to contain the text. We thus obtain the final tree: ``` tree -> document -> block_quote paragraph "Lorem ipsum dolor\nsit amet." -> list (type=bullet tight=true bullet_char=-) list_item paragraph "Qui *quodsi iracundia*" -> list_item -> paragraph "aliquando id" ``` ## Phase 2: inline structure Once all of the input has been parsed, all open blocks are closed. We then "walk the tree," visiting every node, and parse raw string contents of paragraphs and headings as inlines. At this point we have seen all the link reference definitions, so we can resolve reference links as we go. ``` tree document block_quote paragraph str "Lorem ipsum dolor" softbreak str "sit amet." list (type=bullet tight=true bullet_char=-) list_item paragraph str "Qui " emph str "quodsi iracundia" list_item paragraph str "aliquando id" ``` Notice how the [line ending] in the first paragraph has been parsed as a `softbreak`, and the asterisks in the first list item have become an `emph`. ### An algorithm for parsing nested emphasis and links By far the trickiest part of inline parsing is handling emphasis, strong emphasis, links, and images. This is done using the following algorithm. When we're parsing inlines and we hit either - a run of `*` or `_` characters, or - a `[` or `![` we insert a text node with these symbols as its literal content, and we add a pointer to this text node to the [delimiter stack](@). The [delimiter stack] is a doubly linked list. Each element contains a pointer to a text node, plus information about - the type of delimiter (`[`, `![`, `*`, `_`) - the number of delimiters, - whether the delimiter is "active" (all are active to start), and - whether the delimiter is a potential opener, a potential closer, or both (which depends on what sort of characters precede and follow the delimiters). When we hit a `]` character, we call the *look for link or image* procedure (see below). When we hit the end of the input, we call the *process emphasis* procedure (see below), with `stack_bottom` = NULL. #### *look for link or image* Starting at the top of the delimiter stack, we look backwards through the stack for an opening `[` or `![` delimiter. - If we don't find one, we return a literal text node `]`. - If we do find one, but it's not *active*, we remove the inactive delimiter from the stack, and return a literal text node `]`. - If we find one and it's active, then we parse ahead to see if we have an inline link/image, reference link/image, compact reference link/image, or shortcut reference link/image. + If we don't, then we remove the opening delimiter from the delimiter stack and return a literal text node `]`. + If we do, then * We return a link or image node whose children are the inlines after the text node pointed to by the opening delimiter. * We run *process emphasis* on these inlines, with the `[` opener as `stack_bottom`. * We remove the opening delimiter. * If we have a link (and not an image), we also set all `[` delimiters before the opening delimiter to *inactive*. (This will prevent us from getting links within links.) #### *process emphasis* Parameter `stack_bottom` sets a lower bound to how far we descend in the [delimiter stack]. If it is NULL, we can go all the way to the bottom. Otherwise, we stop before visiting `stack_bottom`. Let `current_position` point to the element on the [delimiter stack] just above `stack_bottom` (or the first element if `stack_bottom` is NULL). We keep track of the `openers_bottom` for each delimiter type (`*`, `_`) and each length of the closing delimiter run (modulo 3). Initialize this to `stack_bottom`. Then we repeat the following until we run out of potential closers: - Move `current_position` forward in the delimiter stack (if needed) until we find the first potential closer with delimiter `*` or `_`. (This will be the potential closer closest to the beginning of the input -- the first one in parse order.) - Now, look back in the stack (staying above `stack_bottom` and the `openers_bottom` for this delimiter type) for the first matching potential opener ("matching" means same delimiter). - If one is found: + Figure out whether we have emphasis or strong emphasis: if both closer and opener spans have length >= 2, we have strong, otherwise regular. + Insert an emph or strong emph node accordingly, after the text node corresponding to the opener. + Remove any delimiters between the opener and closer from the delimiter stack. + Remove 1 (for regular emph) or 2 (for strong emph) delimiters from the opening and closing text nodes. If they become empty as a result, remove them and remove the corresponding element of the delimiter stack. If the closing node is removed, reset `current_position` to the next element in the stack. - If none is found: + Set `openers_bottom` to the element before `current_position`. (We know that there are no openers for this kind of closer up to and including this point, so this puts a lower bound on future searches.) + If the closer at `current_position` is not a potential opener, remove it from the delimiter stack (since we know it can't be a closer either). + Advance `current_position` to the next element in the stack. After we're done, we remove all delimiters above `stack_bottom` from the delimiter stack. hugo-0.92.2/hugolib/testhelpers_test.go000066400000000000000000000671141420147000300201270ustar00rootroot00000000000000package hugolib import ( "bytes" "fmt" "image/jpeg" "io" "io/fs" "math/rand" "os" "path/filepath" "regexp" "runtime" "sort" "strconv" "strings" "testing" "text/template" "time" "unicode/utf8" "github.com/gohugoio/hugo/config/security" "github.com/gohugoio/hugo/htesting" "github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/parser/metadecoders" "github.com/google/go-cmp/cmp" "github.com/gohugoio/hugo/parser" "github.com/pkg/errors" "github.com/fsnotify/fsnotify" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/resources/page" "github.com/sanity-io/litter" "github.com/spf13/afero" "github.com/spf13/cast" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/tpl" "github.com/gohugoio/hugo/resources/resource" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/hugofs" ) var ( deepEqualsPages = qt.CmpEquals(cmp.Comparer(func(p1, p2 *pageState) bool { return p1 == p2 })) deepEqualsOutputFormats = qt.CmpEquals(cmp.Comparer(func(o1, o2 output.Format) bool { return o1.Name == o2.Name && o1.MediaType.Type() == o2.MediaType.Type() })) ) type sitesBuilder struct { Cfg config.Provider environ []string Fs *hugofs.Fs T testing.TB depsCfg deps.DepsCfg *qt.C logger loggers.Logger rnd *rand.Rand dumper litter.Options // Used to test partial rebuilds. changedFiles []string removedFiles []string // Aka the Hugo server mode. running bool H *HugoSites theme string // Default toml configFormat string configFileSet bool configSet bool // Default is empty. // TODO(bep) revisit this and consider always setting it to something. // Consider this in relation to using the BaseFs.PublishFs to all publishing. workingDir string addNothing bool // Base data/content contentFilePairs []filenameContent templateFilePairs []filenameContent i18nFilePairs []filenameContent dataFilePairs []filenameContent // Additional data/content. // As in "use the base, but add these on top". contentFilePairsAdded []filenameContent templateFilePairsAdded []filenameContent i18nFilePairsAdded []filenameContent dataFilePairsAdded []filenameContent } type filenameContent struct { filename string content string } func newTestSitesBuilder(t testing.TB) *sitesBuilder { v := config.New() fs := hugofs.NewMem(v) litterOptions := litter.Options{ HidePrivateFields: true, StripPackageNames: true, Separator: " ", } return &sitesBuilder{ T: t, C: qt.New(t), Fs: fs, configFormat: "toml", dumper: litterOptions, rnd: rand.New(rand.NewSource(time.Now().Unix())), } } func newTestSitesBuilderFromDepsCfg(t testing.TB, d deps.DepsCfg) *sitesBuilder { c := qt.New(t) litterOptions := litter.Options{ HidePrivateFields: true, StripPackageNames: true, Separator: " ", } b := &sitesBuilder{T: t, C: c, depsCfg: d, Fs: d.Fs, dumper: litterOptions, rnd: rand.New(rand.NewSource(time.Now().Unix()))} workingDir := d.Cfg.GetString("workingDir") b.WithWorkingDir(workingDir) return b.WithViper(d.Cfg.(config.Provider)) } func (s *sitesBuilder) Running() *sitesBuilder { s.running = true return s } func (s *sitesBuilder) WithNothingAdded() *sitesBuilder { s.addNothing = true return s } func (s *sitesBuilder) WithLogger(logger loggers.Logger) *sitesBuilder { s.logger = logger return s } func (s *sitesBuilder) WithWorkingDir(dir string) *sitesBuilder { s.workingDir = filepath.FromSlash(dir) return s } func (s *sitesBuilder) WithEnviron(env ...string) *sitesBuilder { for i := 0; i < len(env); i += 2 { s.environ = append(s.environ, fmt.Sprintf("%s=%s", env[i], env[i+1])) } return s } func (s *sitesBuilder) WithConfigTemplate(data interface{}, format, configTemplate string) *sitesBuilder { s.T.Helper() if format == "" { format = "toml" } templ, err := template.New("test").Parse(configTemplate) if err != nil { s.Fatalf("Template parse failed: %s", err) } var b bytes.Buffer templ.Execute(&b, data) return s.WithConfigFile(format, b.String()) } func (s *sitesBuilder) WithViper(v config.Provider) *sitesBuilder { s.T.Helper() if s.configFileSet { s.T.Fatal("WithViper: use Viper or config.toml, not both") } defer func() { s.configSet = true }() // Write to a config file to make sure the tests follow the same code path. var buff bytes.Buffer m := v.Get("").(maps.Params) s.Assert(parser.InterfaceToConfig(m, metadecoders.TOML, &buff), qt.IsNil) return s.WithConfigFile("toml", buff.String()) } func (s *sitesBuilder) WithConfigFile(format, conf string) *sitesBuilder { s.T.Helper() if s.configSet { s.T.Fatal("WithConfigFile: use config.Config or config.toml, not both") } s.configFileSet = true filename := s.absFilename("config." + format) writeSource(s.T, s.Fs, filename, conf) s.configFormat = format return s } func (s *sitesBuilder) WithThemeConfigFile(format, conf string) *sitesBuilder { s.T.Helper() if s.theme == "" { s.theme = "test-theme" } filename := filepath.Join("themes", s.theme, "config."+format) writeSource(s.T, s.Fs, s.absFilename(filename), conf) return s } func (s *sitesBuilder) WithSourceFile(filenameContent ...string) *sitesBuilder { s.T.Helper() for i := 0; i < len(filenameContent); i += 2 { writeSource(s.T, s.Fs, s.absFilename(filenameContent[i]), filenameContent[i+1]) } return s } func (s *sitesBuilder) absFilename(filename string) string { filename = filepath.FromSlash(filename) if filepath.IsAbs(filename) { return filename } if s.workingDir != "" && !strings.HasPrefix(filename, s.workingDir) { filename = filepath.Join(s.workingDir, filename) } return filename } const commonConfigSections = ` [services] [services.disqus] shortname = "disqus_shortname" [services.googleAnalytics] id = "UA-ga_id" [privacy] [privacy.disqus] disable = false [privacy.googleAnalytics] respectDoNotTrack = true anonymizeIP = true [privacy.instagram] simple = true [privacy.twitter] enableDNT = true [privacy.vimeo] disable = false [privacy.youtube] disable = false privacyEnhanced = true ` func (s *sitesBuilder) WithSimpleConfigFile() *sitesBuilder { s.T.Helper() return s.WithSimpleConfigFileAndBaseURL("http://example.com/") } func (s *sitesBuilder) WithSimpleConfigFileAndBaseURL(baseURL string) *sitesBuilder { s.T.Helper() return s.WithSimpleConfigFileAndSettings(map[string]interface{}{"baseURL": baseURL}) } func (s *sitesBuilder) WithSimpleConfigFileAndSettings(settings interface{}) *sitesBuilder { s.T.Helper() var buf bytes.Buffer parser.InterfaceToConfig(settings, metadecoders.TOML, &buf) config := buf.String() + commonConfigSections return s.WithConfigFile("toml", config) } func (s *sitesBuilder) WithDefaultMultiSiteConfig() *sitesBuilder { defaultMultiSiteConfig := ` baseURL = "http://example.com/blog" paginate = 1 disablePathToLower = true defaultContentLanguage = "en" defaultContentLanguageInSubdir = true [permalinks] other = "/somewhere/else/:filename" [blackfriday] angledQuotes = true [Taxonomies] tag = "tags" [Languages] [Languages.en] weight = 10 title = "In English" languageName = "English" [Languages.en.blackfriday] angledQuotes = false [[Languages.en.menu.main]] url = "/" name = "Home" weight = 0 [Languages.fr] weight = 20 title = "Le Français" languageName = "Français" [Languages.fr.Taxonomies] plaque = "plaques" [Languages.nn] weight = 30 title = "På nynorsk" languageName = "Nynorsk" paginatePath = "side" [Languages.nn.Taxonomies] lag = "lag" [[Languages.nn.menu.main]] url = "/" name = "Heim" weight = 1 [Languages.nb] weight = 40 title = "På bokmål" languageName = "Bokmål" paginatePath = "side" [Languages.nb.Taxonomies] lag = "lag" ` + commonConfigSections return s.WithConfigFile("toml", defaultMultiSiteConfig) } func (s *sitesBuilder) WithSunset(in string) { // Write a real image into one of the bundle above. src, err := os.Open(filepath.FromSlash("testdata/sunset.jpg")) s.Assert(err, qt.IsNil) out, err := s.Fs.Source.Create(filepath.FromSlash(filepath.Join(s.workingDir, in))) s.Assert(err, qt.IsNil) _, err = io.Copy(out, src) s.Assert(err, qt.IsNil) out.Close() src.Close() } func (s *sitesBuilder) createFilenameContent(pairs []string) []filenameContent { var slice []filenameContent s.appendFilenameContent(&slice, pairs...) return slice } func (s *sitesBuilder) appendFilenameContent(slice *[]filenameContent, pairs ...string) { if len(pairs)%2 != 0 { panic("file content mismatch") } for i := 0; i < len(pairs); i += 2 { c := filenameContent{ filename: pairs[i], content: pairs[i+1], } *slice = append(*slice, c) } } func (s *sitesBuilder) WithContent(filenameContent ...string) *sitesBuilder { s.appendFilenameContent(&s.contentFilePairs, filenameContent...) return s } func (s *sitesBuilder) WithContentAdded(filenameContent ...string) *sitesBuilder { s.appendFilenameContent(&s.contentFilePairsAdded, filenameContent...) return s } func (s *sitesBuilder) WithTemplates(filenameContent ...string) *sitesBuilder { s.appendFilenameContent(&s.templateFilePairs, filenameContent...) return s } func (s *sitesBuilder) WithTemplatesAdded(filenameContent ...string) *sitesBuilder { s.appendFilenameContent(&s.templateFilePairsAdded, filenameContent...) return s } func (s *sitesBuilder) WithData(filenameContent ...string) *sitesBuilder { s.appendFilenameContent(&s.dataFilePairs, filenameContent...) return s } func (s *sitesBuilder) WithDataAdded(filenameContent ...string) *sitesBuilder { s.appendFilenameContent(&s.dataFilePairsAdded, filenameContent...) return s } func (s *sitesBuilder) WithI18n(filenameContent ...string) *sitesBuilder { s.appendFilenameContent(&s.i18nFilePairs, filenameContent...) return s } func (s *sitesBuilder) WithI18nAdded(filenameContent ...string) *sitesBuilder { s.appendFilenameContent(&s.i18nFilePairsAdded, filenameContent...) return s } func (s *sitesBuilder) EditFiles(filenameContent ...string) *sitesBuilder { for i := 0; i < len(filenameContent); i += 2 { filename, content := filepath.FromSlash(filenameContent[i]), filenameContent[i+1] absFilename := s.absFilename(filename) s.changedFiles = append(s.changedFiles, absFilename) writeSource(s.T, s.Fs, absFilename, content) } return s } func (s *sitesBuilder) RemoveFiles(filenames ...string) *sitesBuilder { for _, filename := range filenames { absFilename := s.absFilename(filename) s.removedFiles = append(s.removedFiles, absFilename) s.Assert(s.Fs.Source.Remove(absFilename), qt.IsNil) } return s } func (s *sitesBuilder) writeFilePairs(folder string, files []filenameContent) *sitesBuilder { // We have had some "filesystem ordering" bugs that we have not discovered in // our tests running with the in memory filesystem. // That file system is backed by a map so not sure how this helps, but some // randomness in tests doesn't hurt. // TODO(bep) this turns out to be more confusing than helpful. // s.rnd.Shuffle(len(files), func(i, j int) { files[i], files[j] = files[j], files[i] }) for _, fc := range files { target := folder // TODO(bep) clean up this magic. if strings.HasPrefix(fc.filename, folder) { target = "" } if s.workingDir != "" { target = filepath.Join(s.workingDir, target) } writeSource(s.T, s.Fs, filepath.Join(target, fc.filename), fc.content) } return s } func (s *sitesBuilder) CreateSites() *sitesBuilder { if err := s.CreateSitesE(); err != nil { herrors.PrintStackTraceFromErr(err) s.Fatalf("Failed to create sites: %s", err) } return s } func (s *sitesBuilder) LoadConfig() error { if !s.configFileSet { s.WithSimpleConfigFile() } cfg, _, err := LoadConfig(ConfigSourceDescriptor{ WorkingDir: s.workingDir, Fs: s.Fs.Source, Logger: s.logger, Environ: s.environ, Filename: "config." + s.configFormat, }, func(cfg config.Provider) error { return nil }) if err != nil { return err } s.Cfg = cfg return nil } func (s *sitesBuilder) CreateSitesE() error { if !s.addNothing { if _, ok := s.Fs.Source.(*afero.OsFs); ok { for _, dir := range []string{ "content/sect", "layouts/_default", "layouts/_default/_markup", "layouts/partials", "layouts/shortcodes", "data", "i18n", } { if err := os.MkdirAll(filepath.Join(s.workingDir, dir), 0777); err != nil { return errors.Wrapf(err, "failed to create %q", dir) } } } s.addDefaults() s.writeFilePairs("content", s.contentFilePairsAdded) s.writeFilePairs("layouts", s.templateFilePairsAdded) s.writeFilePairs("data", s.dataFilePairsAdded) s.writeFilePairs("i18n", s.i18nFilePairsAdded) s.writeFilePairs("i18n", s.i18nFilePairs) s.writeFilePairs("data", s.dataFilePairs) s.writeFilePairs("content", s.contentFilePairs) s.writeFilePairs("layouts", s.templateFilePairs) } if err := s.LoadConfig(); err != nil { return errors.Wrap(err, "failed to load config") } s.Fs.Destination = hugofs.NewCreateCountingFs(s.Fs.Destination) depsCfg := s.depsCfg depsCfg.Fs = s.Fs depsCfg.Cfg = s.Cfg depsCfg.Logger = s.logger depsCfg.Running = s.running sites, err := NewHugoSites(depsCfg) if err != nil { return errors.Wrap(err, "failed to create sites") } s.H = sites return nil } func (s *sitesBuilder) BuildE(cfg BuildCfg) error { if s.H == nil { s.CreateSites() } return s.H.Build(cfg) } func (s *sitesBuilder) Build(cfg BuildCfg) *sitesBuilder { s.T.Helper() return s.build(cfg, false) } func (s *sitesBuilder) BuildFail(cfg BuildCfg) *sitesBuilder { s.T.Helper() return s.build(cfg, true) } func (s *sitesBuilder) changeEvents() []fsnotify.Event { var events []fsnotify.Event for _, v := range s.changedFiles { events = append(events, fsnotify.Event{ Name: v, Op: fsnotify.Write, }) } for _, v := range s.removedFiles { events = append(events, fsnotify.Event{ Name: v, Op: fsnotify.Remove, }) } return events } func (s *sitesBuilder) build(cfg BuildCfg, shouldFail bool) *sitesBuilder { s.Helper() defer func() { s.changedFiles = nil }() if s.H == nil { s.CreateSites() } err := s.H.Build(cfg, s.changeEvents()...) if err == nil { logErrorCount := s.H.NumLogErrors() if logErrorCount > 0 { err = fmt.Errorf("logged %d errors", logErrorCount) } } if err != nil && !shouldFail { herrors.PrintStackTraceFromErr(err) s.Fatalf("Build failed: %s", err) } else if err == nil && shouldFail { s.Fatalf("Expected error") } return s } func (s *sitesBuilder) addDefaults() { var ( contentTemplate = `--- title: doc1 weight: 1 tags: - tag1 date: "2018-02-28" --- # doc1 *some "content"* {{< shortcode >}} {{< lingo >}} ` defaultContent = []string{ "content/sect/doc1.en.md", contentTemplate, "content/sect/doc1.fr.md", contentTemplate, "content/sect/doc1.nb.md", contentTemplate, "content/sect/doc1.nn.md", contentTemplate, } listTemplateCommon = "{{ $p := .Paginator }}{{ $p.PageNumber }}|{{ .Title }}|{{ i18n \"hello\" }}|{{ .Permalink }}|Pager: {{ template \"_internal/pagination.html\" . }}|Kind: {{ .Kind }}|Content: {{ .Content }}|Len Pages: {{ len .Pages }}|Len RegularPages: {{ len .RegularPages }}| HasParent: {{ if .Parent }}YES{{ else }}NO{{ end }}" defaultTemplates = []string{ "_default/single.html", "Single: {{ .Title }}|{{ i18n \"hello\" }}|{{.Language.Lang}}|RelPermalink: {{ .RelPermalink }}|Permalink: {{ .Permalink }}|{{ .Content }}|Resources: {{ range .Resources }}{{ .MediaType }}: {{ .RelPermalink}} -- {{ end }}|Summary: {{ .Summary }}|Truncated: {{ .Truncated }}|Parent: {{ .Parent.Title }}", "_default/list.html", "List Page " + listTemplateCommon, "index.html", "{{ $p := .Paginator }}Default Home Page {{ $p.PageNumber }}: {{ .Title }}|{{ .IsHome }}|{{ i18n \"hello\" }}|{{ .Permalink }}|{{ .Site.Data.hugo.slogan }}|String Resource: {{ ( \"Hugo Pipes\" | resources.FromString \"text/pipes.txt\").RelPermalink }}", "index.fr.html", "{{ $p := .Paginator }}French Home Page {{ $p.PageNumber }}: {{ .Title }}|{{ .IsHome }}|{{ i18n \"hello\" }}|{{ .Permalink }}|{{ .Site.Data.hugo.slogan }}|String Resource: {{ ( \"Hugo Pipes\" | resources.FromString \"text/pipes.txt\").RelPermalink }}", "_default/terms.html", "Taxonomy Term Page " + listTemplateCommon, "_default/taxonomy.html", "Taxonomy List Page " + listTemplateCommon, // Shortcodes "shortcodes/shortcode.html", "Shortcode: {{ i18n \"hello\" }}", // A shortcode in multiple languages "shortcodes/lingo.html", "LingoDefault", "shortcodes/lingo.fr.html", "LingoFrench", // Special templates "404.html", "404|{{ .Lang }}|{{ .Title }}", "robots.txt", "robots|{{ .Lang }}|{{ .Title }}", } defaultI18n = []string{ "en.yaml", ` hello: other: "Hello" `, "fr.yaml", ` hello: other: "Bonjour" `, } defaultData = []string{ "hugo.toml", "slogan = \"Hugo Rocks!\"", } ) if len(s.contentFilePairs) == 0 { s.writeFilePairs("content", s.createFilenameContent(defaultContent)) } if len(s.templateFilePairs) == 0 { s.writeFilePairs("layouts", s.createFilenameContent(defaultTemplates)) } if len(s.dataFilePairs) == 0 { s.writeFilePairs("data", s.createFilenameContent(defaultData)) } if len(s.i18nFilePairs) == 0 { s.writeFilePairs("i18n", s.createFilenameContent(defaultI18n)) } } func (s *sitesBuilder) Fatalf(format string, args ...interface{}) { s.T.Helper() s.T.Fatalf(format, args...) } func (s *sitesBuilder) AssertFileContentFn(filename string, f func(s string) bool) { s.T.Helper() content := s.FileContent(filename) if !f(content) { s.Fatalf("Assert failed for %q in content\n%s", filename, content) } } // Helper to migrate tests to new format. func (s *sitesBuilder) DumpTxtar() string { var sb strings.Builder skipRe := regexp.MustCompile(`^(public|resources|package-lock.json|go.sum)`) afero.Walk(s.Fs.Source, s.workingDir, func(path string, info fs.FileInfo, err error) error { rel := strings.TrimPrefix(path, s.workingDir+"/") if skipRe.MatchString(rel) { if info.IsDir() { return filepath.SkipDir } return nil } if info == nil || info.IsDir() { return nil } sb.WriteString(fmt.Sprintf("-- %s --\n", rel)) b, err := afero.ReadFile(s.Fs.Source, path) s.Assert(err, qt.IsNil) sb.WriteString(strings.TrimSpace(string(b))) sb.WriteString("\n") return nil }) return sb.String() } func (s *sitesBuilder) AssertHome(matches ...string) { s.AssertFileContent("public/index.html", matches...) } func (s *sitesBuilder) AssertFileContent(filename string, matches ...string) { s.T.Helper() content := s.FileContent(filename) for _, m := range matches { lines := strings.Split(m, "\n") for _, match := range lines { match = strings.TrimSpace(match) if match == "" { continue } if !strings.Contains(content, match) { s.Fatalf("No match for %q in content for %s\n%s\n%q", match, filename, content, content) } } } } func (s *sitesBuilder) AssertFileDoesNotExist(filename string) { if s.CheckExists(filename) { s.Fatalf("File %q exists but must not exist.", filename) } } func (s *sitesBuilder) AssertImage(width, height int, filename string) { filename = filepath.Join(s.workingDir, filename) f, err := s.Fs.Destination.Open(filename) s.Assert(err, qt.IsNil) defer f.Close() cfg, err := jpeg.DecodeConfig(f) s.Assert(err, qt.IsNil) s.Assert(cfg.Width, qt.Equals, width) s.Assert(cfg.Height, qt.Equals, height) } func (s *sitesBuilder) AssertNoDuplicateWrites() { s.Helper() d := s.Fs.Destination.(hugofs.DuplicatesReporter) s.Assert(d.ReportDuplicates(), qt.Equals, "") } func (s *sitesBuilder) FileContent(filename string) string { s.T.Helper() filename = filepath.FromSlash(filename) if !strings.HasPrefix(filename, s.workingDir) { filename = filepath.Join(s.workingDir, filename) } return readDestination(s.T, s.Fs, filename) } func (s *sitesBuilder) AssertObject(expected string, object interface{}) { s.T.Helper() got := s.dumper.Sdump(object) expected = strings.TrimSpace(expected) if expected != got { fmt.Println(got) diff := htesting.DiffStrings(expected, got) s.Fatalf("diff:\n%s\nexpected\n%s\ngot\n%s", diff, expected, got) } } func (s *sitesBuilder) AssertFileContentRe(filename string, matches ...string) { content := readDestination(s.T, s.Fs, filename) for _, match := range matches { r := regexp.MustCompile("(?s)" + match) if !r.MatchString(content) { s.Fatalf("No match for %q in content for %s\n%q", match, filename, content) } } } func (s *sitesBuilder) CheckExists(filename string) bool { return destinationExists(s.Fs, filepath.Clean(filename)) } func (s *sitesBuilder) GetPage(ref string) page.Page { p, err := s.H.Sites[0].getPageNew(nil, ref) s.Assert(err, qt.IsNil) return p } func (s *sitesBuilder) GetPageRel(p page.Page, ref string) page.Page { p, err := s.H.Sites[0].getPageNew(p, ref) s.Assert(err, qt.IsNil) return p } func (s *sitesBuilder) NpmInstall() hexec.Runner { sc := security.DefaultConfig sc.Exec.Allow = security.NewWhitelist("npm") ex := hexec.New(sc) command, err := ex.New("npm", "install") s.Assert(err, qt.IsNil) return command } func newTestHelper(cfg config.Provider, fs *hugofs.Fs, t testing.TB) testHelper { return testHelper{ Cfg: cfg, Fs: fs, C: qt.New(t), } } type testHelper struct { Cfg config.Provider Fs *hugofs.Fs *qt.C } func (th testHelper) assertFileContent(filename string, matches ...string) { th.Helper() filename = th.replaceDefaultContentLanguageValue(filename) content := readDestination(th, th.Fs, filename) for _, match := range matches { match = th.replaceDefaultContentLanguageValue(match) th.Assert(strings.Contains(content, match), qt.Equals, true, qt.Commentf(match+" not in: \n"+content)) } } func (th testHelper) assertFileContentRegexp(filename string, matches ...string) { filename = th.replaceDefaultContentLanguageValue(filename) content := readDestination(th, th.Fs, filename) for _, match := range matches { match = th.replaceDefaultContentLanguageValue(match) r := regexp.MustCompile(match) matches := r.MatchString(content) if !matches { fmt.Println(match+":\n", content) } th.Assert(matches, qt.Equals, true) } } func (th testHelper) assertFileNotExist(filename string) { exists, err := helpers.Exists(filename, th.Fs.Destination) th.Assert(err, qt.IsNil) th.Assert(exists, qt.Equals, false) } func (th testHelper) replaceDefaultContentLanguageValue(value string) string { defaultInSubDir := th.Cfg.GetBool("defaultContentLanguageInSubDir") replace := th.Cfg.GetString("defaultContentLanguage") + "/" if !defaultInSubDir { value = strings.Replace(value, replace, "", 1) } return value } func loadTestConfig(fs afero.Fs, withConfig ...func(cfg config.Provider) error) (config.Provider, error) { v, _, err := LoadConfig(ConfigSourceDescriptor{Fs: fs}, withConfig...) return v, err } func newTestCfgBasic() (config.Provider, *hugofs.Fs) { mm := afero.NewMemMapFs() v := config.New() v.Set("defaultContentLanguageInSubdir", true) fs := hugofs.NewFrom(hugofs.NewBaseFileDecorator(mm), v) return v, fs } func newTestCfg(withConfig ...func(cfg config.Provider) error) (config.Provider, *hugofs.Fs) { mm := afero.NewMemMapFs() v, err := loadTestConfig(mm, func(cfg config.Provider) error { // Default is false, but true is easier to use as default in tests cfg.Set("defaultContentLanguageInSubdir", true) for _, w := range withConfig { w(cfg) } return nil }) if err != nil && err != ErrNoConfigFile { panic(err) } fs := hugofs.NewFrom(hugofs.NewBaseFileDecorator(mm), v) return v, fs } func newTestSitesFromConfig(t testing.TB, afs afero.Fs, tomlConfig string, layoutPathContentPairs ...string) (testHelper, *HugoSites) { if len(layoutPathContentPairs)%2 != 0 { t.Fatalf("Layouts must be provided in pairs") } c := qt.New(t) writeToFs(t, afs, filepath.Join("content", ".gitkeep"), "") writeToFs(t, afs, "config.toml", tomlConfig) cfg, err := LoadConfigDefault(afs) c.Assert(err, qt.IsNil) fs := hugofs.NewFrom(afs, cfg) th := newTestHelper(cfg, fs, t) for i := 0; i < len(layoutPathContentPairs); i += 2 { writeSource(t, fs, layoutPathContentPairs[i], layoutPathContentPairs[i+1]) } h, err := NewHugoSites(deps.DepsCfg{Fs: fs, Cfg: cfg}) c.Assert(err, qt.IsNil) return th, h } func createWithTemplateFromNameValues(additionalTemplates ...string) func(templ tpl.TemplateManager) error { return func(templ tpl.TemplateManager) error { for i := 0; i < len(additionalTemplates); i += 2 { err := templ.AddTemplate(additionalTemplates[i], additionalTemplates[i+1]) if err != nil { return err } } return nil } } // TODO(bep) replace these with the builder func buildSingleSite(t testing.TB, depsCfg deps.DepsCfg, buildCfg BuildCfg) *Site { t.Helper() return buildSingleSiteExpected(t, false, false, depsCfg, buildCfg) } func buildSingleSiteExpected(t testing.TB, expectSiteInitError, expectBuildError bool, depsCfg deps.DepsCfg, buildCfg BuildCfg) *Site { t.Helper() b := newTestSitesBuilderFromDepsCfg(t, depsCfg).WithNothingAdded() err := b.CreateSitesE() if expectSiteInitError { b.Assert(err, qt.Not(qt.IsNil)) return nil } else { b.Assert(err, qt.IsNil) } h := b.H b.Assert(len(h.Sites), qt.Equals, 1) if expectBuildError { b.Assert(h.Build(buildCfg), qt.Not(qt.IsNil)) return nil } b.Assert(h.Build(buildCfg), qt.IsNil) return h.Sites[0] } func writeSourcesToSource(t *testing.T, base string, fs *hugofs.Fs, sources ...[2]string) { for _, src := range sources { writeSource(t, fs, filepath.Join(base, src[0]), src[1]) } } func getPage(in page.Page, ref string) page.Page { p, err := in.GetPage(ref) if err != nil { panic(err) } return p } func content(c resource.ContentProvider) string { cc, err := c.Content() if err != nil { panic(err) } ccs, err := cast.ToStringE(cc) if err != nil { panic(err) } return ccs } func pagesToString(pages ...page.Page) string { var paths []string for _, p := range pages { paths = append(paths, p.Pathc()) } sort.Strings(paths) return strings.Join(paths, "|") } func dumpPagesLinks(pages ...page.Page) { var links []string for _, p := range pages { links = append(links, p.RelPermalink()) } sort.Strings(links) for _, link := range links { fmt.Println(link) } } func dumpPages(pages ...page.Page) { fmt.Println("---------") for _, p := range pages { fmt.Printf("Kind: %s Title: %-10s RelPermalink: %-10s Path: %-10s sections: %s Lang: %s\n", p.Kind(), p.Title(), p.RelPermalink(), p.Pathc(), p.SectionsPath(), p.Lang()) } } func dumpSPages(pages ...*pageState) { for i, p := range pages { fmt.Printf("%d: Kind: %s Title: %-10s RelPermalink: %-10s Path: %-10s sections: %s\n", i+1, p.Kind(), p.Title(), p.RelPermalink(), p.Pathc(), p.SectionsPath()) } } func printStringIndexes(s string) { lines := strings.Split(s, "\n") i := 0 for _, line := range lines { for _, r := range line { fmt.Printf("%-3s", strconv.Itoa(i)) i += utf8.RuneLen(r) } i++ fmt.Println() for _, r := range line { fmt.Printf("%-3s", string(r)) } fmt.Println() } } // See https://github.com/golang/go/issues/19280 // Not in use. var parallelEnabled = true func parallel(t *testing.T) { if parallelEnabled { t.Parallel() } } func skipSymlink(t *testing.T) { if runtime.GOOS == "windows" && os.Getenv("CI") == "" { t.Skip("skip symlink test on local Windows (needs admin)") } } func captureStderr(f func() error) (string, error) { old := os.Stderr r, w, _ := os.Pipe() os.Stderr = w err := f() w.Close() os.Stderr = old var buf bytes.Buffer io.Copy(&buf, r) return buf.String(), err } func captureStdout(f func() error) (string, error) { old := os.Stdout r, w, _ := os.Pipe() os.Stdout = w err := f() w.Close() os.Stdout = old var buf bytes.Buffer io.Copy(&buf, r) return buf.String(), err } hugo-0.92.2/hugolib/testsite/000077500000000000000000000000001420147000300160325ustar00rootroot00000000000000hugo-0.92.2/hugolib/testsite/.gitignore000066400000000000000000000000131420147000300200140ustar00rootroot00000000000000config.tomlhugo-0.92.2/hugolib/testsite/content/000077500000000000000000000000001420147000300175045ustar00rootroot00000000000000hugo-0.92.2/hugolib/testsite/content/first-post.md000066400000000000000000000000621420147000300221360ustar00rootroot00000000000000--- title: "My First Post" lastmod: 2018-02-28 ---hugo-0.92.2/hugolib/testsite/content_nn/000077500000000000000000000000001420147000300201775ustar00rootroot00000000000000hugo-0.92.2/hugolib/testsite/content_nn/first-post.md000066400000000000000000000000641420147000300226330ustar00rootroot00000000000000--- title: "Min første dag" lastmod: 1972-02-28 ---hugo-0.92.2/hugolib/translations.go000066400000000000000000000030441420147000300172370ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugolib import ( "github.com/gohugoio/hugo/resources/page" ) func pagesToTranslationsMap(sites []*Site) map[string]page.Pages { out := make(map[string]page.Pages) for _, s := range sites { s.pageMap.pageTrees.Walk(func(ss string, n *contentNode) bool { p := n.p // TranslationKey is implemented for all page types. base := p.TranslationKey() pageTranslations, found := out[base] if !found { pageTranslations = make(page.Pages, 0) } pageTranslations = append(pageTranslations, p) out[base] = pageTranslations return false }) } return out } func assignTranslationsToPages(allTranslations map[string]page.Pages, sites []*Site) { for _, s := range sites { s.pageMap.pageTrees.Walk(func(ss string, n *contentNode) bool { p := n.p base := p.TranslationKey() translations, found := allTranslations[base] if !found { return false } p.setTranslations(translations) return false }) } } hugo-0.92.2/identity/000077500000000000000000000000001420147000300143665ustar00rootroot00000000000000hugo-0.92.2/identity/identity.go000066400000000000000000000065761420147000300165640ustar00rootroot00000000000000package identity import ( "path/filepath" "strings" "sync" "sync/atomic" ) // NewIdentityManager creates a new Manager starting at id. func NewManager(id Provider) Manager { return &identityManager{ Provider: id, ids: Identities{id.GetIdentity(): id}, } } // NewPathIdentity creates a new Identity with the two identifiers // type and path. func NewPathIdentity(typ, pat string) PathIdentity { pat = strings.ToLower(strings.TrimPrefix(filepath.ToSlash(pat), "/")) return PathIdentity{Type: typ, Path: pat} } // Identities stores identity providers. type Identities map[Identity]Provider func (ids Identities) search(depth int, id Identity) Provider { if v, found := ids[id.GetIdentity()]; found { return v } depth++ // There may be infinite recursion in templates. if depth > 100 { // Bail out. return nil } for _, v := range ids { switch t := v.(type) { case IdentitiesProvider: if nested := t.GetIdentities().search(depth, id); nested != nil { return nested } } } return nil } // IdentitiesProvider provides all Identities. type IdentitiesProvider interface { GetIdentities() Identities } // Identity represents an thing that can provide an identify. This can be // any Go type, but the Identity returned by GetIdentify must be hashable. type Identity interface { Provider Name() string } // Manager manages identities, and is itself a Provider of Identity. type Manager interface { SearchProvider Add(ids ...Provider) Reset() } // SearchProvider provides access to the chained set of identities. type SearchProvider interface { Provider IdentitiesProvider Search(id Identity) Provider } // A PathIdentity is a common identity identified by a type and a path, e.g. "layouts" and "_default/single.html". type PathIdentity struct { Type string Path string } // GetIdentity returns itself. func (id PathIdentity) GetIdentity() Identity { return id } // Name returns the Path. func (id PathIdentity) Name() string { return id.Path } // A KeyValueIdentity a general purpose identity. type KeyValueIdentity struct { Key string Value string } // GetIdentity returns itself. func (id KeyValueIdentity) GetIdentity() Identity { return id } // Name returns the Key. func (id KeyValueIdentity) Name() string { return id.Key } // Provider provides the hashable Identity. type Provider interface { GetIdentity() Identity } type identityManager struct { sync.Mutex Provider ids Identities } func (im *identityManager) Add(ids ...Provider) { im.Lock() for _, id := range ids { im.ids[id.GetIdentity()] = id } im.Unlock() } func (im *identityManager) Reset() { im.Lock() id := im.GetIdentity() im.ids = Identities{id.GetIdentity(): id} im.Unlock() } // TODO(bep) these identities are currently only read on server reloads // so there should be no concurrency issues, but that may change. func (im *identityManager) GetIdentities() Identities { im.Lock() defer im.Unlock() return im.ids } func (im *identityManager) Search(id Identity) Provider { im.Lock() defer im.Unlock() return im.ids.search(0, id.GetIdentity()) } // Incrementer increments and returns the value. // Typically used for IDs. type Incrementer interface { Incr() int } // IncrementByOne implements Incrementer adding 1 every time Incr is called. type IncrementByOne struct { counter uint64 } func (c *IncrementByOne) Incr() int { return int(atomic.AddUint64(&c.counter, uint64(1))) } hugo-0.92.2/identity/identity_test.go000066400000000000000000000037371420147000300176170ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package identity import ( "fmt" "math/rand" "strconv" "testing" qt "github.com/frankban/quicktest" ) func TestIdentityManager(t *testing.T) { c := qt.New(t) id1 := testIdentity{name: "id1"} im := NewManager(id1) c.Assert(im.Search(id1).GetIdentity(), qt.Equals, id1) c.Assert(im.Search(testIdentity{name: "notfound"}), qt.Equals, nil) } func BenchmarkIdentityManager(b *testing.B) { createIds := func(num int) []Identity { ids := make([]Identity, num) for i := 0; i < num; i++ { ids[i] = testIdentity{name: fmt.Sprintf("id%d", i)} } return ids } b.Run("Add", func(b *testing.B) { c := qt.New(b) b.StopTimer() ids := createIds(b.N) im := NewManager(testIdentity{"first"}) b.StartTimer() for i := 0; i < b.N; i++ { im.Add(ids[i]) } b.StopTimer() c.Assert(im.GetIdentities(), qt.HasLen, b.N+1) }) b.Run("Search", func(b *testing.B) { c := qt.New(b) b.StopTimer() ids := createIds(b.N) im := NewManager(testIdentity{"first"}) for i := 0; i < b.N; i++ { im.Add(ids[i]) } b.StartTimer() for i := 0; i < b.N; i++ { name := "id" + strconv.Itoa(rand.Intn(b.N)) id := im.Search(testIdentity{name: name}) c.Assert(id.GetIdentity().Name(), qt.Equals, name) } }) } type testIdentity struct { name string } func (id testIdentity) GetIdentity() Identity { return id } func (id testIdentity) Name() string { return id.name } hugo-0.92.2/langs/000077500000000000000000000000001420147000300136415ustar00rootroot00000000000000hugo-0.92.2/langs/config.go000066400000000000000000000134631420147000300154440ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package langs import ( "fmt" "path/filepath" "sort" "strings" "github.com/gohugoio/hugo/common/maps" "github.com/spf13/cast" "github.com/pkg/errors" "github.com/gohugoio/hugo/config" ) type LanguagesConfig struct { Languages Languages Multihost bool DefaultContentLanguageInSubdir bool } func LoadLanguageSettings(cfg config.Provider, oldLangs Languages) (c LanguagesConfig, err error) { defaultLang := strings.ToLower(cfg.GetString("defaultContentLanguage")) if defaultLang == "" { defaultLang = "en" cfg.Set("defaultContentLanguage", defaultLang) } var languages map[string]interface{} languagesFromConfig := cfg.GetParams("languages") disableLanguages := cfg.GetStringSlice("disableLanguages") if len(disableLanguages) == 0 { languages = languagesFromConfig } else { languages = make(maps.Params) for k, v := range languagesFromConfig { for _, disabled := range disableLanguages { if disabled == defaultLang { return c, fmt.Errorf("cannot disable default language %q", defaultLang) } if strings.EqualFold(k, disabled) { v.(maps.Params)["disabled"] = true break } } languages[k] = v } } var languages2 Languages if len(languages) == 0 { languages2 = append(languages2, NewDefaultLanguage(cfg)) } else { languages2, err = toSortedLanguages(cfg, languages) if err != nil { return c, errors.Wrap(err, "Failed to parse multilingual config") } } if oldLangs != nil { // When in multihost mode, the languages are mapped to a server, so // some structural language changes will need a restart of the dev server. // The validation below isn't complete, but should cover the most // important cases. var invalid bool if languages2.IsMultihost() != oldLangs.IsMultihost() { invalid = true } else { if languages2.IsMultihost() && len(languages2) != len(oldLangs) { invalid = true } } if invalid { return c, errors.New("language change needing a server restart detected") } if languages2.IsMultihost() { // We need to transfer any server baseURL to the new language for i, ol := range oldLangs { nl := languages2[i] nl.Set("baseURL", ol.GetString("baseURL")) } } } // The defaultContentLanguage is something the user has to decide, but it needs // to match a language in the language definition list. langExists := false for _, lang := range languages2 { if lang.Lang == defaultLang { langExists = true break } } if !langExists { return c, fmt.Errorf("site config value %q for defaultContentLanguage does not match any language definition", defaultLang) } c.Languages = languages2 c.Multihost = languages2.IsMultihost() c.DefaultContentLanguageInSubdir = c.Multihost sortedDefaultFirst := make(Languages, len(c.Languages)) for i, v := range c.Languages { sortedDefaultFirst[i] = v } sort.Slice(sortedDefaultFirst, func(i, j int) bool { li, lj := sortedDefaultFirst[i], sortedDefaultFirst[j] if li.Lang == defaultLang { return true } if lj.Lang == defaultLang { return false } return i < j }) cfg.Set("languagesSorted", c.Languages) cfg.Set("languagesSortedDefaultFirst", sortedDefaultFirst) cfg.Set("multilingual", len(languages2) > 1) multihost := c.Multihost if multihost { cfg.Set("defaultContentLanguageInSubdir", true) cfg.Set("multihost", true) } if multihost { // The baseURL may be provided at the language level. If that is true, // then every language must have a baseURL. In this case we always render // to a language sub folder, which is then stripped from all the Permalink URLs etc. for _, l := range languages2 { burl := l.GetLocal("baseURL") if burl == nil { return c, errors.New("baseURL must be set on all or none of the languages") } } } for _, language := range c.Languages { if language.initErr != nil { return c, language.initErr } } return c, nil } func toSortedLanguages(cfg config.Provider, l map[string]interface{}) (Languages, error) { languages := make(Languages, len(l)) i := 0 for lang, langConf := range l { langsMap, err := maps.ToStringMapE(langConf) if err != nil { return nil, fmt.Errorf("Language config is not a map: %T", langConf) } language := NewLanguage(lang, cfg) for loki, v := range langsMap { switch loki { case "title": language.Title = cast.ToString(v) case "languagename": language.LanguageName = cast.ToString(v) case "languagedirection": language.LanguageDirection = cast.ToString(v) case "weight": language.Weight = cast.ToInt(v) case "contentdir": language.ContentDir = filepath.Clean(cast.ToString(v)) case "disabled": language.Disabled = cast.ToBool(v) case "params": m := maps.ToStringMap(v) // Needed for case insensitive fetching of params values maps.PrepareParams(m) for k, vv := range m { language.SetParam(k, vv) } case "timezone": if err := language.loadLocation(cast.ToString(v)); err != nil { return nil, err } } // Put all into the Params map language.SetParam(loki, v) // Also set it in the configuration map (for baseURL etc.) language.Set(loki, v) } languages[i] = language i++ } sort.Sort(languages) return languages, nil } hugo-0.92.2/langs/i18n/000077500000000000000000000000001420147000300144205ustar00rootroot00000000000000hugo-0.92.2/langs/i18n/i18n.go000066400000000000000000000130641420147000300155320ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package i18n import ( "fmt" "reflect" "strings" "github.com/spf13/cast" "github.com/gohugoio/hugo/common/hreflect" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/go-i18n/v2/i18n" ) type translateFunc func(translationID string, templateData interface{}) string var i18nWarningLogger = helpers.NewDistinctErrorLogger() // Translator handles i18n translations. type Translator struct { translateFuncs map[string]translateFunc cfg config.Provider logger loggers.Logger } // NewTranslator creates a new Translator for the given language bundle and configuration. func NewTranslator(b *i18n.Bundle, cfg config.Provider, logger loggers.Logger) Translator { t := Translator{cfg: cfg, logger: logger, translateFuncs: make(map[string]translateFunc)} t.initFuncs(b) return t } // Func gets the translate func for the given language, or for the default // configured language if not found. func (t Translator) Func(lang string) translateFunc { if f, ok := t.translateFuncs[lang]; ok { return f } t.logger.Infof("Translation func for language %v not found, use default.", lang) if f, ok := t.translateFuncs[t.cfg.GetString("defaultContentLanguage")]; ok { return f } t.logger.Infoln("i18n not initialized; if you need string translations, check that you have a bundle in /i18n that matches the site language or the default language.") return func(translationID string, args interface{}) string { return "" } } func (t Translator) initFuncs(bndl *i18n.Bundle) { enableMissingTranslationPlaceholders := t.cfg.GetBool("enableMissingTranslationPlaceholders") for _, lang := range bndl.LanguageTags() { currentLang := lang currentLangStr := currentLang.String() // This may be pt-BR; make it case insensitive. currentLangKey := strings.ToLower(strings.TrimPrefix(currentLangStr, artificialLangTagPrefix)) localizer := i18n.NewLocalizer(bndl, currentLangStr) t.translateFuncs[currentLangKey] = func(translationID string, templateData interface{}) string { pluralCount := getPluralCount(templateData) if templateData != nil { tp := reflect.TypeOf(templateData) if hreflect.IsInt(tp.Kind()) { // This was how go-i18n worked in v1, // and we keep it like this to avoid breaking // lots of sites in the wild. templateData = intCount(cast.ToInt(templateData)) } } translated, translatedLang, err := localizer.LocalizeWithTag(&i18n.LocalizeConfig{ MessageID: translationID, TemplateData: templateData, PluralCount: pluralCount, }) sameLang := currentLang == translatedLang if err == nil && sameLang { return translated } if err != nil && sameLang && translated != "" { // See #8492 // TODO(bep) this needs to be improved/fixed upstream, // but currently we get an error even if the fallback to // "other" succeeds. if fmt.Sprintf("%T", err) == "i18n.pluralFormNotFoundError" { return translated } } if _, ok := err.(*i18n.MessageNotFoundErr); !ok { t.logger.Warnf("Failed to get translated string for language %q and ID %q: %s", currentLangStr, translationID, err) } if t.cfg.GetBool("logI18nWarnings") { i18nWarningLogger.Printf("i18n|MISSING_TRANSLATION|%s|%s", currentLangStr, translationID) } if enableMissingTranslationPlaceholders { return "[i18n] " + translationID } return translated } } } // intCount wraps the Count method. type intCount int func (c intCount) Count() int { return int(c) } const countFieldName = "Count" // getPluralCount gets the plural count as a string (floats) or an integer. // If v is nil, nil is returned. func getPluralCount(v interface{}) interface{} { if v == nil { // i18n called without any argument, make sure it does not // get any plural count. return nil } switch v := v.(type) { case map[string]interface{}: for k, vv := range v { if strings.EqualFold(k, countFieldName) { return toPluralCountValue(vv) } } default: vv := reflect.Indirect(reflect.ValueOf(v)) if vv.Kind() == reflect.Interface && !vv.IsNil() { vv = vv.Elem() } tp := vv.Type() if tp.Kind() == reflect.Struct { f := vv.FieldByName(countFieldName) if f.IsValid() { return toPluralCountValue(f.Interface()) } m := vv.MethodByName(countFieldName) if m.IsValid() && m.Type().NumIn() == 0 && m.Type().NumOut() == 1 { c := m.Call(nil) return toPluralCountValue(c[0].Interface()) } } } return toPluralCountValue(v) } // go-i18n expects floats to be represented by string. func toPluralCountValue(in interface{}) interface{} { k := reflect.TypeOf(in).Kind() switch { case hreflect.IsFloat(k): f := cast.ToString(in) if !strings.Contains(f, ".") { f += ".0" } return f case k == reflect.String: if _, err := cast.ToFloat64E(in); err == nil { return in } // A non-numeric value. return nil default: if i, err := cast.ToIntE(in); err == nil { return i } return nil } } hugo-0.92.2/langs/i18n/i18n_test.go000066400000000000000000000347501420147000300165760ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package i18n import ( "fmt" "path/filepath" "testing" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/modules" "github.com/gohugoio/hugo/tpl/tplimpl" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/resources/page" "github.com/spf13/afero" "github.com/gohugoio/hugo/deps" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/hugofs" ) var logger = loggers.NewErrorLogger() type i18nTest struct { name string data map[string][]byte args interface{} lang, id, expected, expectedFlag string } var i18nTests = []i18nTest{ // All translations present { name: "all-present", data: map[string][]byte{ "en.toml": []byte("[hello]\nother = \"Hello, World!\""), "es.toml": []byte("[hello]\nother = \"¡Hola, Mundo!\""), }, args: nil, lang: "es", id: "hello", expected: "¡Hola, Mundo!", expectedFlag: "¡Hola, Mundo!", }, // Translation missing in current language but present in default { name: "present-in-default", data: map[string][]byte{ "en.toml": []byte("[hello]\nother = \"Hello, World!\""), "es.toml": []byte("[goodbye]\nother = \"¡Adiós, Mundo!\""), }, args: nil, lang: "es", id: "hello", expected: "Hello, World!", expectedFlag: "[i18n] hello", }, // Translation missing in default language but present in current { name: "present-in-current", data: map[string][]byte{ "en.toml": []byte("[goodbye]\nother = \"Goodbye, World!\""), "es.toml": []byte("[hello]\nother = \"¡Hola, Mundo!\""), }, args: nil, lang: "es", id: "hello", expected: "¡Hola, Mundo!", expectedFlag: "¡Hola, Mundo!", }, // Translation missing in both default and current language { name: "missing", data: map[string][]byte{ "en.toml": []byte("[goodbye]\nother = \"Goodbye, World!\""), "es.toml": []byte("[goodbye]\nother = \"¡Adiós, Mundo!\""), }, args: nil, lang: "es", id: "hello", expected: "", expectedFlag: "[i18n] hello", }, // Default translation file missing or empty { name: "file-missing", data: map[string][]byte{ "en.toml": []byte(""), }, args: nil, lang: "es", id: "hello", expected: "", expectedFlag: "[i18n] hello", }, // Context provided { name: "context-provided", data: map[string][]byte{ "en.toml": []byte("[wordCount]\nother = \"Hello, {{.WordCount}} people!\""), "es.toml": []byte("[wordCount]\nother = \"¡Hola, {{.WordCount}} gente!\""), }, args: struct { WordCount int }{ 50, }, lang: "es", id: "wordCount", expected: "¡Hola, 50 gente!", expectedFlag: "¡Hola, 50 gente!", }, // https://github.com/gohugoio/hugo/issues/7787 { name: "readingTime-one", data: map[string][]byte{ "en.toml": []byte(`[readingTime] one = "One minute to read" other = "{{ .Count }} minutes to read" `), }, args: 1, lang: "en", id: "readingTime", expected: "One minute to read", expectedFlag: "One minute to read", }, { name: "readingTime-many-dot", data: map[string][]byte{ "en.toml": []byte(`[readingTime] one = "One minute to read" other = "{{ . }} minutes to read" `), }, args: 21, lang: "en", id: "readingTime", expected: "21 minutes to read", expectedFlag: "21 minutes to read", }, { name: "readingTime-many", data: map[string][]byte{ "en.toml": []byte(`[readingTime] one = "One minute to read" other = "{{ .Count }} minutes to read" `), }, args: 21, lang: "en", id: "readingTime", expected: "21 minutes to read", expectedFlag: "21 minutes to read", }, // Issue #8454 { name: "readingTime-map-one", data: map[string][]byte{ "en.toml": []byte(`[readingTime] one = "One minute to read" other = "{{ .Count }} minutes to read" `), }, args: map[string]interface{}{"Count": 1}, lang: "en", id: "readingTime", expected: "One minute to read", expectedFlag: "One minute to read", }, { name: "readingTime-string-one", data: map[string][]byte{ "en.toml": []byte(`[readingTime] one = "One minute to read" other = "{{ . }} minutes to read" `), }, args: "1", lang: "en", id: "readingTime", expected: "One minute to read", expectedFlag: "One minute to read", }, { name: "readingTime-map-many", data: map[string][]byte{ "en.toml": []byte(`[readingTime] one = "One minute to read" other = "{{ .Count }} minutes to read" `), }, args: map[string]interface{}{"Count": 21}, lang: "en", id: "readingTime", expected: "21 minutes to read", expectedFlag: "21 minutes to read", }, { name: "argument-float", data: map[string][]byte{ "en.toml": []byte(`[float] other = "Number is {{ . }}" `), }, args: 22.5, lang: "en", id: "float", expected: "Number is 22.5", expectedFlag: "Number is 22.5", }, // Same id and translation in current language // https://github.com/gohugoio/hugo/issues/2607 { name: "same-id-and-translation", data: map[string][]byte{ "es.toml": []byte("[hello]\nother = \"hello\""), "en.toml": []byte("[hello]\nother = \"hi\""), }, args: nil, lang: "es", id: "hello", expected: "hello", expectedFlag: "hello", }, // Translation missing in current language, but same id and translation in default { name: "same-id-and-translation-default", data: map[string][]byte{ "es.toml": []byte("[bye]\nother = \"bye\""), "en.toml": []byte("[hello]\nother = \"hello\""), }, args: nil, lang: "es", id: "hello", expected: "hello", expectedFlag: "[i18n] hello", }, // Unknown language code should get its plural spec from en { name: "unknown-language-code", data: map[string][]byte{ "en.toml": []byte(`[readingTime] one ="one minute read" other = "{{.Count}} minutes read"`), "klingon.toml": []byte(`[readingTime] one = "eitt minutt med lesing" other = "{{ .Count }} minuttar lesing"`), }, args: 3, lang: "klingon", id: "readingTime", expected: "3 minuttar lesing", expectedFlag: "3 minuttar lesing", }, // Issue #7838 { name: "unknown-language-codes", data: map[string][]byte{ "en.toml": []byte(`[readingTime] one ="en one" other = "en count {{.Count}}"`), "a1.toml": []byte(`[readingTime] one = "a1 one" other = "a1 count {{ .Count }}"`), "a2.toml": []byte(`[readingTime] one = "a2 one" other = "a2 count {{ .Count }}"`), }, args: 3, lang: "a2", id: "readingTime", expected: "a2 count 3", expectedFlag: "a2 count 3", }, // https://github.com/gohugoio/hugo/issues/7798 { name: "known-language-missing-plural", data: map[string][]byte{ "oc.toml": []byte(`[oc] one = "abc"`), }, args: 1, lang: "oc", id: "oc", expected: "abc", expectedFlag: "abc", }, // https://github.com/gohugoio/hugo/issues/7794 { name: "dotted-bare-key", data: map[string][]byte{ "en.toml": []byte(`"shop_nextPage.one" = "Show Me The Money" `), }, args: nil, lang: "en", id: "shop_nextPage.one", expected: "Show Me The Money", expectedFlag: "Show Me The Money", }, // https: //github.com/gohugoio/hugo/issues/7804 { name: "lang-with-hyphen", data: map[string][]byte{ "pt-br.toml": []byte(`foo.one = "abc"`), }, args: 1, lang: "pt-br", id: "foo", expected: "abc", expectedFlag: "abc", }, } func TestPlural(t *testing.T) { c := qt.New(t) for _, test := range []struct { name string lang string id string templ string variants []types.KeyValue }{ { name: "English", lang: "en", id: "hour", templ: ` [hour] one = "{{ . }} hour" other = "{{ . }} hours"`, variants: []types.KeyValue{ {Key: 1, Value: "1 hour"}, {Key: "1", Value: "1 hour"}, {Key: 1.5, Value: "1.5 hours"}, {Key: "1.5", Value: "1.5 hours"}, {Key: 2, Value: "2 hours"}, {Key: "2", Value: "2 hours"}, }, }, { name: "Other only", lang: "en", id: "hour", templ: ` [hour] other = "{{ with . }}{{ . }}{{ end }} hours"`, variants: []types.KeyValue{ {Key: 1, Value: "1 hours"}, {Key: "1", Value: "1 hours"}, {Key: 2, Value: "2 hours"}, {Key: nil, Value: " hours"}, }, }, { name: "Polish", lang: "pl", id: "day", templ: ` [day] one = "{{ . }} miesiąc" few = "{{ . }} miesiące" many = "{{ . }} miesięcy" other = "{{ . }} miesiąca" `, variants: []types.KeyValue{ {Key: 1, Value: "1 miesiąc"}, {Key: 2, Value: "2 miesiące"}, {Key: 100, Value: "100 miesięcy"}, {Key: "100.0", Value: "100.0 miesiąca"}, {Key: 100.0, Value: "100 miesiąca"}, }, }, } { c.Run(test.name, func(c *qt.C) { cfg := getConfig() cfg.Set("enableMissingTranslationPlaceholders", true) fs := hugofs.NewMem(cfg) err := afero.WriteFile(fs.Source, filepath.Join("i18n", test.lang+".toml"), []byte(test.templ), 0755) c.Assert(err, qt.IsNil) tp := NewTranslationProvider() depsCfg := newDepsConfig(tp, cfg, fs) depsCfg.Logger = loggers.NewWarningLogger() d, err := deps.New(depsCfg) c.Assert(err, qt.IsNil) c.Assert(d.LoadResources(), qt.IsNil) f := tp.t.Func(test.lang) for _, variant := range test.variants { c.Assert(f(test.id, variant.Key), qt.Equals, variant.Value, qt.Commentf("input: %v", variant.Key)) c.Assert(int(depsCfg.Logger.LogCounters().WarnCounter.Count()), qt.Equals, 0) } }) } } func doTestI18nTranslate(t testing.TB, test i18nTest, cfg config.Provider) string { tp := prepareTranslationProvider(t, test, cfg) f := tp.t.Func(test.lang) return f(test.id, test.args) } type countField struct { Count interface{} } type noCountField struct { Counts int } type countMethod struct { } func (c countMethod) Count() interface{} { return 32.5 } func TestGetPluralCount(t *testing.T) { c := qt.New(t) c.Assert(getPluralCount(map[string]interface{}{"Count": 32}), qt.Equals, 32) c.Assert(getPluralCount(map[string]interface{}{"Count": 1}), qt.Equals, 1) c.Assert(getPluralCount(map[string]interface{}{"Count": 1.5}), qt.Equals, "1.5") c.Assert(getPluralCount(map[string]interface{}{"Count": "32"}), qt.Equals, "32") c.Assert(getPluralCount(map[string]interface{}{"Count": "32.5"}), qt.Equals, "32.5") c.Assert(getPluralCount(map[string]interface{}{"count": 32}), qt.Equals, 32) c.Assert(getPluralCount(map[string]interface{}{"Count": "32"}), qt.Equals, "32") c.Assert(getPluralCount(map[string]interface{}{"Counts": 32}), qt.Equals, nil) c.Assert(getPluralCount("foo"), qt.Equals, nil) c.Assert(getPluralCount(countField{Count: 22}), qt.Equals, 22) c.Assert(getPluralCount(countField{Count: 1.5}), qt.Equals, "1.5") c.Assert(getPluralCount(&countField{Count: 22}), qt.Equals, 22) c.Assert(getPluralCount(noCountField{Counts: 23}), qt.Equals, nil) c.Assert(getPluralCount(countMethod{}), qt.Equals, "32.5") c.Assert(getPluralCount(&countMethod{}), qt.Equals, "32.5") c.Assert(getPluralCount(1234), qt.Equals, 1234) c.Assert(getPluralCount(1234.4), qt.Equals, "1234.4") c.Assert(getPluralCount(1234.0), qt.Equals, "1234.0") c.Assert(getPluralCount("1234"), qt.Equals, "1234") c.Assert(getPluralCount("0.5"), qt.Equals, "0.5") c.Assert(getPluralCount(nil), qt.Equals, nil) } func prepareTranslationProvider(t testing.TB, test i18nTest, cfg config.Provider) *TranslationProvider { c := qt.New(t) fs := hugofs.NewMem(cfg) for file, content := range test.data { err := afero.WriteFile(fs.Source, filepath.Join("i18n", file), []byte(content), 0755) c.Assert(err, qt.IsNil) } tp := NewTranslationProvider() depsCfg := newDepsConfig(tp, cfg, fs) d, err := deps.New(depsCfg) c.Assert(err, qt.IsNil) c.Assert(d.LoadResources(), qt.IsNil) return tp } func newDepsConfig(tp *TranslationProvider, cfg config.Provider, fs *hugofs.Fs) deps.DepsCfg { l := langs.NewLanguage("en", cfg) l.Set("i18nDir", "i18n") return deps.DepsCfg{ Language: l, Site: page.NewDummyHugoSite(cfg), Cfg: cfg, Fs: fs, Logger: logger, TemplateProvider: tplimpl.DefaultTemplateProvider, TranslationProvider: tp, } } func getConfig() config.Provider { v := config.New() v.Set("defaultContentLanguage", "en") v.Set("contentDir", "content") v.Set("dataDir", "data") v.Set("i18nDir", "i18n") v.Set("layoutDir", "layouts") v.Set("archetypeDir", "archetypes") v.Set("assetDir", "assets") v.Set("resourceDir", "resources") v.Set("publishDir", "public") langs.LoadLanguageSettings(v, nil) mod, err := modules.CreateProjectModule(v) if err != nil { panic(err) } v.Set("allModules", modules.Modules{mod}) return v } func TestI18nTranslate(t *testing.T) { c := qt.New(t) var actual, expected string v := getConfig() // Test without and with placeholders for _, enablePlaceholders := range []bool{false, true} { v.Set("enableMissingTranslationPlaceholders", enablePlaceholders) for _, test := range i18nTests { c.Run(fmt.Sprintf("%s-%t", test.name, enablePlaceholders), func(c *qt.C) { if enablePlaceholders { expected = test.expectedFlag } else { expected = test.expected } actual = doTestI18nTranslate(c, test, v) c.Assert(actual, qt.Equals, expected) }) } } } func BenchmarkI18nTranslate(b *testing.B) { v := getConfig() for _, test := range i18nTests { b.Run(test.name, func(b *testing.B) { tp := prepareTranslationProvider(b, test, v) b.ResetTimer() for i := 0; i < b.N; i++ { f := tp.t.Func(test.lang) actual := f(test.id, test.args) if actual != test.expected { b.Fatalf("expected %v got %v", test.expected, actual) } } }) } } hugo-0.92.2/langs/i18n/translationProvider.go000066400000000000000000000074451420147000300210320ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package i18n import ( "encoding/json" "strings" "github.com/gohugoio/hugo/common/paths" "github.com/gohugoio/hugo/common/herrors" "golang.org/x/text/language" yaml "gopkg.in/yaml.v2" "github.com/gohugoio/go-i18n/v2/i18n" "github.com/gohugoio/hugo/helpers" toml "github.com/pelletier/go-toml/v2" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/source" _errors "github.com/pkg/errors" ) // TranslationProvider provides translation handling, i.e. loading // of bundles etc. type TranslationProvider struct { t Translator } // NewTranslationProvider creates a new translation provider. func NewTranslationProvider() *TranslationProvider { return &TranslationProvider{} } // Update updates the i18n func in the provided Deps. func (tp *TranslationProvider) Update(d *deps.Deps) error { spec := source.NewSourceSpec(d.PathSpec, nil, nil) bundle := i18n.NewBundle(language.English) bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal) bundle.RegisterUnmarshalFunc("yml", yaml.Unmarshal) bundle.RegisterUnmarshalFunc("json", json.Unmarshal) // The source dirs are ordered so the most important comes first. Since this is a // last key win situation, we have to reverse the iteration order. dirs := d.BaseFs.I18n.Dirs for i := len(dirs) - 1; i >= 0; i-- { dir := dirs[i] src := spec.NewFilesystemFromFileMetaInfo(dir) files, err := src.Files() if err != nil { return err } for _, file := range files { if err := addTranslationFile(bundle, file); err != nil { return err } } } tp.t = NewTranslator(bundle, d.Cfg, d.Log) d.Translate = tp.t.Func(d.Language.Lang) return nil } const artificialLangTagPrefix = "art-x-" func addTranslationFile(bundle *i18n.Bundle, r source.File) error { f, err := r.FileInfo().Meta().Open() if err != nil { return _errors.Wrapf(err, "failed to open translations file %q:", r.LogicalName()) } b := helpers.ReaderToBytes(f) f.Close() name := r.LogicalName() lang := paths.Filename(name) tag := language.Make(lang) if tag == language.Und { try := artificialLangTagPrefix + lang _, err = language.Parse(try) if err != nil { return _errors.Errorf("%q %s.", try, err) } name = artificialLangTagPrefix + name } _, err = bundle.ParseMessageFileBytes(b, name) if err != nil { if strings.Contains(err.Error(), "no plural rule") { // https://github.com/gohugoio/hugo/issues/7798 name = artificialLangTagPrefix + name _, err = bundle.ParseMessageFileBytes(b, name) if err == nil { return nil } } return errWithFileContext(_errors.Wrapf(err, "failed to load translations"), r) } return nil } // Clone sets the language func for the new language. func (tp *TranslationProvider) Clone(d *deps.Deps) error { d.Translate = tp.t.Func(d.Language.Lang) return nil } func errWithFileContext(inerr error, r source.File) error { fim, ok := r.FileInfo().(hugofs.FileMetaInfo) if !ok { return inerr } meta := fim.Meta() realFilename := meta.Filename f, err := meta.Open() if err != nil { return inerr } defer f.Close() err, _ = herrors.WithFileContext( inerr, realFilename, f, herrors.SimpleLineMatcher) return err } hugo-0.92.2/langs/language.go000066400000000000000000000162361420147000300157630ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package langs import ( "sort" "strings" "sync" "time" "github.com/pkg/errors" translators "github.com/gohugoio/localescompressed" "github.com/gohugoio/locales" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/config" ) // These are the settings that should only be looked up in the global Viper // config and not per language. // This list may not be complete, but contains only settings that we know // will be looked up in both. // This isn't perfect, but it is ultimately the user who shoots him/herself in // the foot. // See the pathSpec. var globalOnlySettings = map[string]bool{ strings.ToLower("defaultContentLanguageInSubdir"): true, strings.ToLower("defaultContentLanguage"): true, strings.ToLower("multilingual"): true, strings.ToLower("assetDir"): true, strings.ToLower("resourceDir"): true, strings.ToLower("build"): true, } // Language manages specific-language configuration. type Language struct { Lang string LanguageName string LanguageDirection string Title string Weight int Disabled bool // If set per language, this tells Hugo that all content files without any // language indicator (e.g. my-page.en.md) is in this language. // This is usually a path relative to the working dir, but it can be an // absolute directory reference. It is what we get. ContentDir string // Global config. Cfg config.Provider // Language specific config. LocalCfg config.Provider // Composite config. config.Provider // These are params declared in the [params] section of the language merged with the // site's params, the most specific (language) wins on duplicate keys. params map[string]interface{} paramsMu sync.Mutex paramsSet bool // Used for date formatting etc. We don't want these exported to the // templates. // TODO(bep) do the same for some of the others. translator locales.Translator location *time.Location // Error during initialization. Will fail the buld. initErr error } func (l *Language) String() string { return l.Lang } // NewLanguage creates a new language. func NewLanguage(lang string, cfg config.Provider) *Language { // Note that language specific params will be overridden later. // We should improve that, but we need to make a copy: params := make(map[string]interface{}) for k, v := range cfg.GetStringMap("params") { params[k] = v } maps.PrepareParams(params) localCfg := config.New() compositeConfig := config.NewCompositeConfig(cfg, localCfg) translator := translators.GetTranslator(lang) if translator == nil { translator = translators.GetTranslator(cfg.GetString("defaultContentLanguage")) if translator == nil { translator = translators.GetTranslator("en") } } l := &Language{ Lang: lang, ContentDir: cfg.GetString("contentDir"), Cfg: cfg, LocalCfg: localCfg, Provider: compositeConfig, params: params, translator: translator, } if err := l.loadLocation(cfg.GetString("timeZone")); err != nil { l.initErr = err } return l } // NewDefaultLanguage creates the default language for a config.Provider. // If not otherwise specified the default is "en". func NewDefaultLanguage(cfg config.Provider) *Language { defaultLang := cfg.GetString("defaultContentLanguage") if defaultLang == "" { defaultLang = "en" } return NewLanguage(defaultLang, cfg) } // Languages is a sortable list of languages. type Languages []*Language // NewLanguages creates a sorted list of languages. // NOTE: function is currently unused. func NewLanguages(l ...*Language) Languages { languages := make(Languages, len(l)) for i := 0; i < len(l); i++ { languages[i] = l[i] } sort.Sort(languages) return languages } func (l Languages) Len() int { return len(l) } func (l Languages) Less(i, j int) bool { wi, wj := l[i].Weight, l[j].Weight if wi == wj { return l[i].Lang < l[j].Lang } return wj == 0 || wi < wj } func (l Languages) Swap(i, j int) { l[i], l[j] = l[j], l[i] } // Params returns language-specific params merged with the global params. func (l *Language) Params() maps.Params { // TODO(bep) this construct should not be needed. Create the // language params in one go. l.paramsMu.Lock() defer l.paramsMu.Unlock() if !l.paramsSet { maps.PrepareParams(l.params) l.paramsSet = true } return l.params } func (l Languages) AsSet() map[string]bool { m := make(map[string]bool) for _, lang := range l { m[lang.Lang] = true } return m } func (l Languages) AsOrdinalSet() map[string]int { m := make(map[string]int) for i, lang := range l { m[lang.Lang] = i } return m } // IsMultihost returns whether there are more than one language and at least one of // the languages has baseURL specificed on the language level. func (l Languages) IsMultihost() bool { if len(l) <= 1 { return false } for _, lang := range l { if lang.GetLocal("baseURL") != nil { return true } } return false } // SetParam sets a param with the given key and value. // SetParam is case-insensitive. func (l *Language) SetParam(k string, v interface{}) { l.paramsMu.Lock() defer l.paramsMu.Unlock() if l.paramsSet { panic("params cannot be changed once set") } l.params[k] = v } // GetLocal gets a configuration value set on language level. It will // not fall back to any global value. // It will return nil if a value with the given key cannot be found. func (l *Language) GetLocal(key string) interface{} { if l == nil { panic("language not set") } key = strings.ToLower(key) if !globalOnlySettings[key] { return l.LocalCfg.Get(key) } return nil } func (l *Language) Set(k string, v interface{}) { k = strings.ToLower(k) if globalOnlySettings[k] { return } l.Provider.Set(k, v) } // Merge is currently not supported for Language. func (l *Language) Merge(key string, value interface{}) { panic("Not supported") } // IsSet checks whether the key is set in the language or the related config store. func (l *Language) IsSet(key string) bool { key = strings.ToLower(key) if !globalOnlySettings[key] { return l.Provider.IsSet(key) } return l.Cfg.IsSet(key) } // Internal access to unexported Language fields. // This construct is to prevent them from leaking to the templates. func GetTranslator(l *Language) locales.Translator { return l.translator } func GetLocation(l *Language) *time.Location { return l.location } func (l *Language) loadLocation(tzStr string) error { location, err := time.LoadLocation(tzStr) if err != nil { return errors.Wrapf(err, "invalid timeZone for language %q", l.Lang) } l.location = location return nil } hugo-0.92.2/langs/language_test.go000066400000000000000000000026571420147000300170240ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package langs import ( "testing" "github.com/gohugoio/hugo/config" qt "github.com/frankban/quicktest" ) func TestGetGlobalOnlySetting(t *testing.T) { c := qt.New(t) v := config.New() v.Set("defaultContentLanguageInSubdir", true) v.Set("contentDir", "content") v.Set("paginatePath", "page") lang := NewDefaultLanguage(v) lang.Set("defaultContentLanguageInSubdir", false) lang.Set("paginatePath", "side") c.Assert(lang.GetBool("defaultContentLanguageInSubdir"), qt.Equals, true) c.Assert(lang.GetString("paginatePath"), qt.Equals, "side") } func TestLanguageParams(t *testing.T) { c := qt.New(t) v := config.New() v.Set("p1", "p1cfg") v.Set("contentDir", "content") lang := NewDefaultLanguage(v) lang.SetParam("p1", "p1p") c.Assert(lang.Params()["p1"], qt.Equals, "p1p") c.Assert(lang.Get("p1"), qt.Equals, "p1cfg") } hugo-0.92.2/lazy/000077500000000000000000000000001420147000300135145ustar00rootroot00000000000000hugo-0.92.2/lazy/init.go000066400000000000000000000111631420147000300150100ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package lazy import ( "context" "sync" "sync/atomic" "time" "github.com/pkg/errors" ) // New creates a new empty Init. func New() *Init { return &Init{} } // Init holds a graph of lazily initialized dependencies. type Init struct { // Used in tests initCount uint64 mu sync.Mutex prev *Init children []*Init init onceMore out interface{} err error f func() (interface{}, error) } // Add adds a func as a new child dependency. func (ini *Init) Add(initFn func() (interface{}, error)) *Init { if ini == nil { ini = New() } return ini.add(false, initFn) } // InitCount gets the number of this this Init has been initialized. func (ini *Init) InitCount() int { i := atomic.LoadUint64(&ini.initCount) return int(i) } // AddWithTimeout is same as Add, but with a timeout that aborts initialization. func (ini *Init) AddWithTimeout(timeout time.Duration, f func(ctx context.Context) (interface{}, error)) *Init { return ini.Add(func() (interface{}, error) { return ini.withTimeout(timeout, f) }) } // Branch creates a new dependency branch based on an existing and adds // the given dependency as a child. func (ini *Init) Branch(initFn func() (interface{}, error)) *Init { if ini == nil { ini = New() } return ini.add(true, initFn) } // BranchdWithTimeout is same as Branch, but with a timeout. func (ini *Init) BranchWithTimeout(timeout time.Duration, f func(ctx context.Context) (interface{}, error)) *Init { return ini.Branch(func() (interface{}, error) { return ini.withTimeout(timeout, f) }) } // Do initializes the entire dependency graph. func (ini *Init) Do() (interface{}, error) { if ini == nil { panic("init is nil") } ini.init.Do(func() { atomic.AddUint64(&ini.initCount, 1) prev := ini.prev if prev != nil { // A branch. Initialize the ancestors. if prev.shouldInitialize() { _, err := prev.Do() if err != nil { ini.err = err return } } else if prev.inProgress() { // Concurrent initialization. The following init func // may depend on earlier state, so wait. prev.wait() } } if ini.f != nil { ini.out, ini.err = ini.f() } for _, child := range ini.children { if child.shouldInitialize() { _, err := child.Do() if err != nil { ini.err = err return } } } }) ini.wait() return ini.out, ini.err } // TODO(bep) investigate if we can use sync.Cond for this. func (ini *Init) wait() { var counter time.Duration for !ini.init.Done() { counter += 10 if counter > 600000000 { panic("BUG: timed out in lazy init") } time.Sleep(counter * time.Microsecond) } } func (ini *Init) inProgress() bool { return ini != nil && ini.init.InProgress() } func (ini *Init) shouldInitialize() bool { return !(ini == nil || ini.init.Done() || ini.init.InProgress()) } // Reset resets the current and all its dependencies. func (ini *Init) Reset() { mu := ini.init.ResetWithLock() ini.err = nil defer mu.Unlock() for _, d := range ini.children { d.Reset() } } func (ini *Init) add(branch bool, initFn func() (interface{}, error)) *Init { ini.mu.Lock() defer ini.mu.Unlock() if branch { return &Init{ f: initFn, prev: ini, } } ini.checkDone() ini.children = append(ini.children, &Init{ f: initFn, }) return ini } func (ini *Init) checkDone() { if ini.init.Done() { panic("init cannot be added to after it has run") } } func (ini *Init) withTimeout(timeout time.Duration, f func(ctx context.Context) (interface{}, error)) (interface{}, error) { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() c := make(chan verr, 1) go func() { v, err := f(ctx) select { case <-ctx.Done(): return default: c <- verr{v: v, err: err} } }() select { case <-ctx.Done(): return nil, errors.New("timed out initializing value. You may have a circular loop in a shortcode, or your site may have resources that take longer to build than the `timeout` limit in your Hugo config file.") case ve := <-c: return ve.v, ve.err } } type verr struct { v interface{} err error } hugo-0.92.2/lazy/init_test.go000066400000000000000000000106701420147000300160510ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package lazy import ( "context" "errors" "math/rand" "strings" "sync" "testing" "time" qt "github.com/frankban/quicktest" ) var ( rnd = rand.New(rand.NewSource(time.Now().UnixNano())) bigOrSmall = func() int { if rnd.Intn(10) < 5 { return 10000 + rnd.Intn(100000) } return 1 + rnd.Intn(50) } ) func doWork() { doWorkOfSize(bigOrSmall()) } func doWorkOfSize(size int) { _ = strings.Repeat("Hugo Rocks! ", size) } func TestInit(t *testing.T) { c := qt.New(t) var result string f1 := func(name string) func() (interface{}, error) { return func() (interface{}, error) { result += name + "|" doWork() return name, nil } } f2 := func() func() (interface{}, error) { return func() (interface{}, error) { doWork() return nil, nil } } root := New() root.Add(f1("root(1)")) root.Add(f1("root(2)")) branch1 := root.Branch(f1("branch_1")) branch1.Add(f1("branch_1_1")) branch1_2 := branch1.Add(f1("branch_1_2")) branch1_2_1 := branch1_2.Add(f1("branch_1_2_1")) var wg sync.WaitGroup // Add some concurrency and randomness to verify thread safety and // init order. for i := 0; i < 100; i++ { wg.Add(1) go func(i int) { defer wg.Done() var err error if rnd.Intn(10) < 5 { _, err = root.Do() c.Assert(err, qt.IsNil) } // Add a new branch on the fly. if rnd.Intn(10) > 5 { branch := branch1_2.Branch(f2()) _, err = branch.Do() c.Assert(err, qt.IsNil) } else { _, err = branch1_2_1.Do() c.Assert(err, qt.IsNil) } _, err = branch1_2.Do() c.Assert(err, qt.IsNil) }(i) wg.Wait() c.Assert(result, qt.Equals, "root(1)|root(2)|branch_1|branch_1_1|branch_1_2|branch_1_2_1|") } } func TestInitAddWithTimeout(t *testing.T) { c := qt.New(t) init := New().AddWithTimeout(100*time.Millisecond, func(ctx context.Context) (interface{}, error) { return nil, nil }) _, err := init.Do() c.Assert(err, qt.IsNil) } func TestInitAddWithTimeoutTimeout(t *testing.T) { c := qt.New(t) init := New().AddWithTimeout(100*time.Millisecond, func(ctx context.Context) (interface{}, error) { time.Sleep(500 * time.Millisecond) select { case <-ctx.Done(): return nil, nil default: } t.Fatal("slept") return nil, nil }) _, err := init.Do() c.Assert(err, qt.Not(qt.IsNil)) c.Assert(err.Error(), qt.Contains, "timed out") time.Sleep(1 * time.Second) } func TestInitAddWithTimeoutError(t *testing.T) { c := qt.New(t) init := New().AddWithTimeout(100*time.Millisecond, func(ctx context.Context) (interface{}, error) { return nil, errors.New("failed") }) _, err := init.Do() c.Assert(err, qt.Not(qt.IsNil)) } type T struct { sync.Mutex V1 string V2 string } func (t *T) Add1(v string) { t.Lock() t.V1 += v t.Unlock() } func (t *T) Add2(v string) { t.Lock() t.V2 += v t.Unlock() } // https://github.com/gohugoio/hugo/issues/5901 func TestInitBranchOrder(t *testing.T) { c := qt.New(t) base := New() work := func(size int, f func()) func() (interface{}, error) { return func() (interface{}, error) { doWorkOfSize(size) if f != nil { f() } return nil, nil } } state := &T{} base = base.Add(work(10000, func() { state.Add1("A") })) inits := make([]*Init, 2) for i := range inits { inits[i] = base.Branch(work(i+1*100, func() { // V1 is A ab := state.V1 + "B" state.Add2(ab) })) } var wg sync.WaitGroup for _, v := range inits { v := v wg.Add(1) go func() { defer wg.Done() _, err := v.Do() c.Assert(err, qt.IsNil) }() } wg.Wait() c.Assert(state.V2, qt.Equals, "ABAB") } // See issue 7043 func TestResetError(t *testing.T) { c := qt.New(t) r := false i := New().Add(func() (interface{}, error) { if r { return nil, nil } return nil, errors.New("r is false") }) _, err := i.Do() c.Assert(err, qt.IsNotNil) i.Reset() r = true _, err = i.Do() c.Assert(err, qt.IsNil) } hugo-0.92.2/lazy/once.go000066400000000000000000000030471420147000300147730ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package lazy import ( "sync" "sync/atomic" ) // onceMore is similar to sync.Once. // // Additional features are: // * it can be reset, so the action can be repeated if needed // * it has methods to check if it's done or in progress // type onceMore struct { mu sync.Mutex lock uint32 done uint32 } func (t *onceMore) Do(f func()) { if atomic.LoadUint32(&t.done) == 1 { return } // f may call this Do and we would get a deadlock. locked := atomic.CompareAndSwapUint32(&t.lock, 0, 1) if !locked { return } defer atomic.StoreUint32(&t.lock, 0) t.mu.Lock() defer t.mu.Unlock() // Double check if t.done == 1 { return } defer atomic.StoreUint32(&t.done, 1) f() } func (t *onceMore) InProgress() bool { return atomic.LoadUint32(&t.lock) == 1 } func (t *onceMore) Done() bool { return atomic.LoadUint32(&t.done) == 1 } func (t *onceMore) ResetWithLock() *sync.Mutex { t.mu.Lock() defer atomic.StoreUint32(&t.done, 0) return &t.mu } hugo-0.92.2/livereload/000077500000000000000000000000001420147000300146635ustar00rootroot00000000000000hugo-0.92.2/livereload/connection.go000066400000000000000000000030551420147000300173540ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package livereload import ( "bytes" "sync" "github.com/gorilla/websocket" ) type connection struct { // The websocket connection. ws *websocket.Conn // Buffered channel of outbound messages. send chan []byte // There is a potential data race, especially visible with large files. // This is protected by synchronisation of the send channel's close. closer sync.Once } func (c *connection) close() { c.closer.Do(func() { close(c.send) }) } func (c *connection) reader() { for { _, message, err := c.ws.ReadMessage() if err != nil { break } if bytes.Contains(message, []byte(`"command":"hello"`)) { c.send <- []byte(`{ "command": "hello", "protocols": [ "http://livereload.com/protocols/official-7" ], "serverName": "Hugo" }`) } } c.ws.Close() } func (c *connection) writer() { for message := range c.send { err := c.ws.WriteMessage(websocket.TextMessage, message) if err != nil { break } } c.ws.Close() } hugo-0.92.2/livereload/hub.go000066400000000000000000000026261420147000300157760ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package livereload type hub struct { // Registered connections. connections map[*connection]bool // Inbound messages from the connections. broadcast chan []byte // Register requests from the connections. register chan *connection // Unregister requests from connections. unregister chan *connection } var wsHub = hub{ broadcast: make(chan []byte), register: make(chan *connection), unregister: make(chan *connection), connections: make(map[*connection]bool), } func (h *hub) run() { for { select { case c := <-h.register: h.connections[c] = true case c := <-h.unregister: delete(h.connections, c) c.close() case m := <-h.broadcast: for c := range h.connections { select { case c.send <- m: default: delete(h.connections, c) c.close() } } } } } hugo-0.92.2/livereload/livereload.go000066400000000000000000001077021420147000300173470ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Contains an embedded version of livereload.js // // Copyright (c) 2010-2015 Andrey Tarantsov // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package livereload import ( "fmt" "net" "net/http" "net/url" "path/filepath" "github.com/gorilla/websocket" ) // Prefix to signal to LiveReload that we need to navigate to another path. const hugoNavigatePrefix = "__hugo_navigate" var upgrader = &websocket.Upgrader{ // Hugo may potentially spin up multiple HTTP servers, so we need to exclude the // port when checking the origin. CheckOrigin: func(r *http.Request) bool { origin := r.Header["Origin"] if len(origin) == 0 { return true } u, err := url.Parse(origin[0]) if err != nil { return false } if u.Host == r.Host { return true } h1, _, err := net.SplitHostPort(u.Host) if err != nil { return false } h2, _, err := net.SplitHostPort(r.Host) if err != nil { return false } return h1 == h2 }, ReadBufferSize: 1024, WriteBufferSize: 1024, } // Handler is a HandlerFunc handling the livereload // Websocket interaction. func Handler(w http.ResponseWriter, r *http.Request) { ws, err := upgrader.Upgrade(w, r, nil) if err != nil { return } c := &connection{send: make(chan []byte, 256), ws: ws} wsHub.register <- c defer func() { wsHub.unregister <- c }() go c.writer() c.reader() } // Initialize starts the Websocket Hub handling live reloads. func Initialize() { go wsHub.run() } // ForceRefresh tells livereload to force a hard refresh. func ForceRefresh() { RefreshPath("/x.js") } // NavigateToPath tells livereload to navigate to the given path. // This translates to `window.location.href = path` in the client. func NavigateToPath(path string) { RefreshPath(hugoNavigatePrefix + path) } // NavigateToPathForPort is similar to NavigateToPath but will also // set window.location.port to the given port value. func NavigateToPathForPort(path string, port int) { refreshPathForPort(hugoNavigatePrefix+path, port) } // RefreshPath tells livereload to refresh only the given path. // If that path points to a CSS stylesheet or an image, only the changes // will be updated in the browser, not the entire page. func RefreshPath(s string) { refreshPathForPort(s, -1) } func refreshPathForPort(s string, port int) { // Tell livereload a file has changed - will force a hard refresh if not CSS or an image urlPath := filepath.ToSlash(s) portStr := "" if port > 0 { portStr = fmt.Sprintf(`, "overrideURL": %d`, port) } msg := fmt.Sprintf(`{"command":"reload","path":%q,"originalPath":"","liveCSS":true,"liveImg":true%s}`, urlPath, portStr) wsHub.broadcast <- []byte(msg) } // ServeJS serves the liverreload.js who's reference is injected into the page. func ServeJS(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/javascript") w.Write(liveReloadJS()) } func liveReloadJS() []byte { return []byte(livereloadJS + hugoLiveReloadPlugin) } var ( // This is a patched version, see https://github.com/livereload/livereload-js/pull/84 livereloadJS = `!function(){return function e(t,o,n){function r(s,c){if(!o[s]){if(!t[s]){var a="function"==typeof require&&require;if(!c&&a)return a(s,!0);if(i)return i(s,!0);var l=new Error("Cannot find module '"+s+"'");throw l.code="MODULE_NOT_FOUND",l}var h=o[s]={exports:{}};t[s][0].call(h.exports,function(e){return r(t[s][1][e]||e)},h,h.exports,e,t,o,n)}return o[s].exports}for(var i="function"==typeof require&&require,s=0;sh;)if((c=a[h++])!=c)return!0}else for(;l>h;h++)if((e||h in a)&&a[h]===o)return e||h||0;return!e&&-1}}},{"./_to-absolute-index":38,"./_to-iobject":40,"./_to-length":41}],5:[function(e,t,o){var n={}.toString;t.exports=function(e){return n.call(e).slice(8,-1)}},{}],6:[function(e,t,o){var n=t.exports={version:"2.6.5"};"number"==typeof __e&&(__e=n)},{}],7:[function(e,t,o){var n=e("./_a-function");t.exports=function(e,t,o){if(n(e),void 0===t)return e;switch(o){case 1:return function(o){return e.call(t,o)};case 2:return function(o,n){return e.call(t,o,n)};case 3:return function(o,n,r){return e.call(t,o,n,r)}}return function(){return e.apply(t,arguments)}}},{"./_a-function":1}],8:[function(e,t,o){t.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},{}],9:[function(e,t,o){t.exports=!e("./_fails")(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},{"./_fails":13}],10:[function(e,t,o){var n=e("./_is-object"),r=e("./_global").document,i=n(r)&&n(r.createElement);t.exports=function(e){return i?r.createElement(e):{}}},{"./_global":15,"./_is-object":21}],11:[function(e,t,o){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},{}],12:[function(e,t,o){var n=e("./_global"),r=e("./_core"),i=e("./_hide"),s=e("./_redefine"),c=e("./_ctx"),a=function(e,t,o){var l,h,u,d,f=e&a.F,p=e&a.G,_=e&a.S,m=e&a.P,g=e&a.B,y=p?n:_?n[t]||(n[t]={}):(n[t]||{}).prototype,v=p?r:r[t]||(r[t]={}),w=v.prototype||(v.prototype={});for(l in p&&(o=t),o)u=((h=!f&&y&&void 0!==y[l])?y:o)[l],d=g&&h?c(u,n):m&&"function"==typeof u?c(Function.call,u):u,y&&s(y,l,u,e&a.U),v[l]!=u&&i(v,l,d),m&&w[l]!=u&&(w[l]=u)};n.core=r,a.F=1,a.G=2,a.S=4,a.P=8,a.B=16,a.W=32,a.U=64,a.R=128,t.exports=a},{"./_core":6,"./_ctx":7,"./_global":15,"./_hide":17,"./_redefine":34}],13:[function(e,t,o){t.exports=function(e){try{return!!e()}catch(e){return!0}}},{}],14:[function(e,t,o){t.exports=e("./_shared")("native-function-to-string",Function.toString)},{"./_shared":37}],15:[function(e,t,o){var n=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},{}],16:[function(e,t,o){var n={}.hasOwnProperty;t.exports=function(e,t){return n.call(e,t)}},{}],17:[function(e,t,o){var n=e("./_object-dp"),r=e("./_property-desc");t.exports=e("./_descriptors")?function(e,t,o){return n.f(e,t,r(1,o))}:function(e,t,o){return e[t]=o,e}},{"./_descriptors":9,"./_object-dp":28,"./_property-desc":33}],18:[function(e,t,o){var n=e("./_global").document;t.exports=n&&n.documentElement},{"./_global":15}],19:[function(e,t,o){t.exports=!e("./_descriptors")&&!e("./_fails")(function(){return 7!=Object.defineProperty(e("./_dom-create")("div"),"a",{get:function(){return 7}}).a})},{"./_descriptors":9,"./_dom-create":10,"./_fails":13}],20:[function(e,t,o){var n=e("./_cof");t.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==n(e)?e.split(""):Object(e)}},{"./_cof":5}],21:[function(e,t,o){t.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},{}],22:[function(e,t,o){"use strict";var n=e("./_object-create"),r=e("./_property-desc"),i=e("./_set-to-string-tag"),s={};e("./_hide")(s,e("./_wks")("iterator"),function(){return this}),t.exports=function(e,t,o){e.prototype=n(s,{next:r(1,o)}),i(e,t+" Iterator")}},{"./_hide":17,"./_object-create":27,"./_property-desc":33,"./_set-to-string-tag":35,"./_wks":45}],23:[function(e,t,o){"use strict";var n=e("./_library"),r=e("./_export"),i=e("./_redefine"),s=e("./_hide"),c=e("./_iterators"),a=e("./_iter-create"),l=e("./_set-to-string-tag"),h=e("./_object-gpo"),u=e("./_wks")("iterator"),d=!([].keys&&"next"in[].keys()),f=function(){return this};t.exports=function(e,t,o,p,_,m,g){a(o,t,p);var y,v,w,b=function(e){if(!d&&e in L)return L[e];switch(e){case"keys":case"values":return function(){return new o(this,e)}}return function(){return new o(this,e)}},S=t+" Iterator",R="values"==_,k=!1,L=e.prototype,x=L[u]||L["@@iterator"]||_&&L[_],j=x||b(_),C=_?R?b("entries"):j:void 0,O="Array"==t&&L.entries||x;if(O&&(w=h(O.call(new e)))!==Object.prototype&&w.next&&(l(w,S,!0),n||"function"==typeof w[u]||s(w,u,f)),R&&x&&"values"!==x.name&&(k=!0,j=function(){return x.call(this)}),n&&!g||!d&&!k&&L[u]||s(L,u,j),c[t]=j,c[S]=f,_)if(y={values:R?j:b("values"),keys:m?j:b("keys"),entries:C},g)for(v in y)v in L||i(L,v,y[v]);else r(r.P+r.F*(d||k),t,y);return y}},{"./_export":12,"./_hide":17,"./_iter-create":22,"./_iterators":25,"./_library":26,"./_object-gpo":30,"./_redefine":34,"./_set-to-string-tag":35,"./_wks":45}],24:[function(e,t,o){t.exports=function(e,t){return{value:t,done:!!e}}},{}],25:[function(e,t,o){t.exports={}},{}],26:[function(e,t,o){t.exports=!1},{}],27:[function(e,t,o){var n=e("./_an-object"),r=e("./_object-dps"),i=e("./_enum-bug-keys"),s=e("./_shared-key")("IE_PROTO"),c=function(){},a=function(){var t,o=e("./_dom-create")("iframe"),n=i.length;for(o.style.display="none",e("./_html").appendChild(o),o.src="javascript:",(t=o.contentWindow.document).open(),t.write("
    `, f("div script", "foo", "")}, {"Style tags content should be skipped", `
    `, f("div style", "foo", "")}, {"Pre tags content should be skipped", `
    foobar
    `, f("div pre", "foo preclass", "")}, {"Textarea tags content should be skipped", `
    `, f("div textarea", "foo textareaclass", "")}, {"DOCTYPE should beskipped", ``, f("", "", "")}, {"Comments should be skipped", ``, f("", "", "")}, {"Comments with elements before and after", `
    `, f("div span", "", "")}, // Issue #8530 {"Comment with single quote", ``, f("i", "foo", "")}, {"Uppercase tags", `
    `, f("div", "", "")}, {"Predefined tags with distinct casing", `
    `, f("div script", "", "")}, // Issue #8417 {"Tabs inline", `
    d
    `, f("div hr", "bar foo", "a")}, {"Tabs on multiple rows", `
    d
    `, f("div form", "foo", "a b")}, {"Big input, multibyte runes", strings.Repeat(`神真美好 `, rnd.Intn(500)+1) + "
    " + strings.Repeat(`神真美好 `, rnd.Intn(100)+1) + " 神真美好", f("div span", "foo", "神真美好")}, } { for _, variant := range []struct { minify bool }{ {minify: false}, {minify: true}, } { c.Run(fmt.Sprintf("%s--minify-%t", test.name, variant.minify), func(c *qt.C) { w := newHTMLElementsCollectorWriter(newHTMLElementsCollector()) if variant.minify { if skipMinifyTest[test.name] { c.Skip("skip minify test") } v := config.New() m, _ := minifiers.New(media.DefaultTypes, output.DefaultFormats, v) m.Minify(media.HTMLType, w, strings.NewReader(test.html)) } else { var buff bytes.Buffer buff.WriteString(test.html) io.Copy(w, &buff) } got := w.collector.getHTMLElements() c.Assert(got, qt.DeepEquals, test.expect) }) } } } func BenchmarkElementsCollectorWriter(b *testing.B) { const benchHTML = ` title

    To force
    line breaks
    in a text,
    use the br
    element.


    Month Savings
    January $100
    February $200
    $300
    ` for i := 0; i < b.N; i++ { w := newHTMLElementsCollectorWriter(newHTMLElementsCollector()) fmt.Fprint(w, benchHTML) } } hugo-0.92.2/publisher/publisher.go000066400000000000000000000120721420147000300170600ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package publisher import ( "errors" "io" "net/url" "sync/atomic" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/minifiers" bp "github.com/gohugoio/hugo/bufferpool" "github.com/gohugoio/hugo/helpers" "github.com/spf13/afero" "github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/transform" "github.com/gohugoio/hugo/transform/livereloadinject" "github.com/gohugoio/hugo/transform/metainject" "github.com/gohugoio/hugo/transform/urlreplacers" ) // Descriptor describes the needed publishing chain for an item. type Descriptor struct { // The content to publish. Src io.Reader // The OutputFormat of the this content. OutputFormat output.Format // Where to publish this content. This is a filesystem-relative path. TargetPath string // Counter for the end build summary. StatCounter *uint64 // Configuration that trigger pre-processing. // LiveReload script will be injected if this is != nil LiveReloadBaseURL *url.URL // Enable to inject the Hugo generated tag in the header. Is currently only // injected on the home page for HTML type of output formats. AddHugoGeneratorTag bool // If set, will replace all relative URLs with this one. AbsURLPath string // Enable to minify the output using the OutputFormat defined above to // pick the correct minifier configuration. Minify bool } // DestinationPublisher is the default and currently only publisher in Hugo. This // publisher prepares and publishes an item to the defined destination, e.g. /public. type DestinationPublisher struct { fs afero.Fs min minifiers.Client htmlElementsCollector *htmlElementsCollector } // NewDestinationPublisher creates a new DestinationPublisher. func NewDestinationPublisher(rs *resources.Spec, outputFormats output.Formats, mediaTypes media.Types) (pub DestinationPublisher, err error) { fs := rs.BaseFs.PublishFs cfg := rs.Cfg var classCollector *htmlElementsCollector if rs.BuildConfig.WriteStats { classCollector = newHTMLElementsCollector() } pub = DestinationPublisher{fs: fs, htmlElementsCollector: classCollector} pub.min, err = minifiers.New(mediaTypes, outputFormats, cfg) return } // Publish applies any relevant transformations and writes the file // to its destination, e.g. /public. func (p DestinationPublisher) Publish(d Descriptor) error { if d.TargetPath == "" { return errors.New("Publish: must provide a TargetPath") } src := d.Src transformers := p.createTransformerChain(d) if len(transformers) != 0 { b := bp.GetBuffer() defer bp.PutBuffer(b) if err := transformers.Apply(b, d.Src); err != nil { return err } // This is now what we write to disk. src = b } f, err := helpers.OpenFileForWriting(p.fs, d.TargetPath) if err != nil { return err } defer f.Close() var w io.Writer = f if p.htmlElementsCollector != nil && d.OutputFormat.IsHTML { w = io.MultiWriter(w, newHTMLElementsCollectorWriter(p.htmlElementsCollector)) } _, err = io.Copy(w, src) if err == nil && d.StatCounter != nil { atomic.AddUint64(d.StatCounter, uint64(1)) } return err } func (p DestinationPublisher) PublishStats() PublishStats { if p.htmlElementsCollector == nil { return PublishStats{} } return PublishStats{ HTMLElements: p.htmlElementsCollector.getHTMLElements(), } } type PublishStats struct { HTMLElements HTMLElements `json:"htmlElements"` } // Publisher publishes a result file. type Publisher interface { Publish(d Descriptor) error PublishStats() PublishStats } // XML transformer := transform.New(urlreplacers.NewAbsURLInXMLTransformer(path)) func (p DestinationPublisher) createTransformerChain(f Descriptor) transform.Chain { transformers := transform.NewEmpty() isHTML := f.OutputFormat.IsHTML if f.AbsURLPath != "" { if isHTML { transformers = append(transformers, urlreplacers.NewAbsURLTransformer(f.AbsURLPath)) } else { // Assume XML. transformers = append(transformers, urlreplacers.NewAbsURLInXMLTransformer(f.AbsURLPath)) } } if isHTML { if f.LiveReloadBaseURL != nil { transformers = append(transformers, livereloadinject.New(*f.LiveReloadBaseURL)) } // This is only injected on the home page. if f.AddHugoGeneratorTag { transformers = append(transformers, metainject.HugoGenerator) } } if p.min.MinifyOutput { minifyTransformer := p.min.Transformer(f.OutputFormat.MediaType) if minifyTransformer != nil { transformers = append(transformers, minifyTransformer) } } return transformers } hugo-0.92.2/pull-docs.sh000077500000000000000000000004121420147000300147730ustar00rootroot00000000000000#!/bin/bash HUGO_DOCS_BRANCH="${HUGO_DOCS_BRANCH-master}" # We may extend this to also push changes in the other direction, but this is the most important step. git subtree pull --prefix=docs/ https://github.com/gohugoio/hugoDocs.git ${HUGO_DOCS_BRANCH} --squash hugo-0.92.2/related/000077500000000000000000000000001420147000300141555ustar00rootroot00000000000000hugo-0.92.2/related/inverted_index.go000066400000000000000000000261761420147000300175270ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package related holds code to help finding related content. package related import ( "errors" "fmt" "math" "sort" "strings" "time" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/types" "github.com/mitchellh/mapstructure" ) var ( _ Keyword = (*StringKeyword)(nil) zeroDate = time.Time{} // DefaultConfig is the default related config. DefaultConfig = Config{ Threshold: 80, Indices: IndexConfigs{ IndexConfig{Name: "keywords", Weight: 100}, IndexConfig{Name: "date", Weight: 10}, }, } ) /* Config is the top level configuration element used to configure how to retrieve related content in Hugo. An example site config.toml: [related] threshold = 1 [[related.indices]] name = "keywords" weight = 200 [[related.indices]] name = "tags" weight = 100 [[related.indices]] name = "date" weight = 1 pattern = "2006" */ type Config struct { // Only include matches >= threshold, a normalized rank between 0 and 100. Threshold int // To get stable "See also" sections we, by default, exclude newer related pages. IncludeNewer bool // Will lower case all string values and queries to the indices. // May get better results, but at a slight performance cost. ToLower bool Indices IndexConfigs } // Add adds a given index. func (c *Config) Add(index IndexConfig) { if c.ToLower { index.ToLower = true } c.Indices = append(c.Indices, index) } // IndexConfigs holds a set of index configurations. type IndexConfigs []IndexConfig // IndexConfig configures an index. type IndexConfig struct { // The index name. This directly maps to a field or Param name. Name string // Contextual pattern used to convert the Param value into a string. // Currently only used for dates. Can be used to, say, bump posts in the same // time frame when searching for related documents. // For dates it follows Go's time.Format patterns, i.e. // "2006" for YYYY and "200601" for YYYYMM. Pattern string // This field's weight when doing multi-index searches. Higher is "better". Weight int // Will lower case all string values in and queries tothis index. // May get better accurate results, but at a slight performance cost. ToLower bool } // Document is the interface an indexable document in Hugo must fulfill. type Document interface { // RelatedKeywords returns a list of keywords for the given index config. RelatedKeywords(cfg IndexConfig) ([]Keyword, error) // When this document was or will be published. PublishDate() time.Time // Name is used as an tiebreaker if both Weight and PublishDate are // the same. Name() string } // InvertedIndex holds an inverted index, also sometimes named posting list, which // lists, for every possible search term, the documents that contain that term. type InvertedIndex struct { cfg Config index map[string]map[Keyword][]Document minWeight int maxWeight int } func (idx *InvertedIndex) getIndexCfg(name string) (IndexConfig, bool) { for _, conf := range idx.cfg.Indices { if conf.Name == name { return conf, true } } return IndexConfig{}, false } // NewInvertedIndex creates a new InvertedIndex. // Documents to index must be added in Add. func NewInvertedIndex(cfg Config) *InvertedIndex { idx := &InvertedIndex{index: make(map[string]map[Keyword][]Document), cfg: cfg} for _, conf := range cfg.Indices { idx.index[conf.Name] = make(map[Keyword][]Document) if conf.Weight < idx.minWeight { // By default, the weight scale starts at 0, but we allow // negative weights. idx.minWeight = conf.Weight } if conf.Weight > idx.maxWeight { idx.maxWeight = conf.Weight } } return idx } // Add documents to the inverted index. // The value must support == and !=. func (idx *InvertedIndex) Add(docs ...Document) error { var err error for _, config := range idx.cfg.Indices { if config.Weight == 0 { // Disabled continue } setm := idx.index[config.Name] for _, doc := range docs { var words []Keyword words, err = doc.RelatedKeywords(config) if err != nil { continue } for _, keyword := range words { setm[keyword] = append(setm[keyword], doc) } } } return err } // queryElement holds the index name and keywords that can be used to compose a // search for related content. type queryElement struct { Index string Keywords []Keyword } func newQueryElement(index string, keywords ...Keyword) queryElement { return queryElement{Index: index, Keywords: keywords} } type ranks []*rank type rank struct { Doc Document Weight int Matches int } func (r *rank) addWeight(w int) { r.Weight += w r.Matches++ } func newRank(doc Document, weight int) *rank { return &rank{Doc: doc, Weight: weight, Matches: 1} } func (r ranks) Len() int { return len(r) } func (r ranks) Swap(i, j int) { r[i], r[j] = r[j], r[i] } func (r ranks) Less(i, j int) bool { if r[i].Weight == r[j].Weight { if r[i].Doc.PublishDate() == r[j].Doc.PublishDate() { return r[i].Doc.Name() < r[j].Doc.Name() } return r[i].Doc.PublishDate().After(r[j].Doc.PublishDate()) } return r[i].Weight > r[j].Weight } // SearchDoc finds the documents matching any of the keywords in the given indices // against the given document. // The resulting document set will be sorted according to number of matches // and the index weights, and any matches with a rank below the configured // threshold (normalize to 0..100) will be removed. // If an index name is provided, only that index will be queried. func (idx *InvertedIndex) SearchDoc(doc Document, indices ...string) ([]Document, error) { var q []queryElement var configs IndexConfigs if len(indices) == 0 { configs = idx.cfg.Indices } else { configs = make(IndexConfigs, len(indices)) for i, indexName := range indices { cfg, found := idx.getIndexCfg(indexName) if !found { return nil, fmt.Errorf("index %q not found", indexName) } configs[i] = cfg } } for _, cfg := range configs { keywords, err := doc.RelatedKeywords(cfg) if err != nil { return nil, err } q = append(q, newQueryElement(cfg.Name, keywords...)) } return idx.searchDate(doc.PublishDate(), q...) } // ToKeywords returns a Keyword slice of the given input. func (cfg IndexConfig) ToKeywords(v interface{}) ([]Keyword, error) { var ( keywords []Keyword toLower = cfg.ToLower ) switch vv := v.(type) { case string: if toLower { vv = strings.ToLower(vv) } keywords = append(keywords, StringKeyword(vv)) case []string: if toLower { vc := make([]string, len(vv)) copy(vc, vv) for i := 0; i < len(vc); i++ { vc[i] = strings.ToLower(vc[i]) } vv = vc } keywords = append(keywords, StringsToKeywords(vv...)...) case time.Time: layout := "2006" if cfg.Pattern != "" { layout = cfg.Pattern } keywords = append(keywords, StringKeyword(vv.Format(layout))) case nil: return keywords, nil default: return keywords, fmt.Errorf("indexing currently not supported for index %q and type %T", cfg.Name, vv) } return keywords, nil } // SearchKeyValues finds the documents matching any of the keywords in the given indices. // The resulting document set will be sorted according to number of matches // and the index weights, and any matches with a rank below the configured // threshold (normalize to 0..100) will be removed. func (idx *InvertedIndex) SearchKeyValues(args ...types.KeyValues) ([]Document, error) { q := make([]queryElement, len(args)) for i, arg := range args { var keywords []Keyword key := arg.KeyString() if key == "" { return nil, fmt.Errorf("index %q not valid", arg.Key) } conf, found := idx.getIndexCfg(key) if !found { return nil, fmt.Errorf("index %q not found", key) } for _, val := range arg.Values { k, err := conf.ToKeywords(val) if err != nil { return nil, err } keywords = append(keywords, k...) } q[i] = newQueryElement(conf.Name, keywords...) } return idx.search(q...) } func (idx *InvertedIndex) search(query ...queryElement) ([]Document, error) { return idx.searchDate(zeroDate, query...) } func (idx *InvertedIndex) searchDate(upperDate time.Time, query ...queryElement) ([]Document, error) { matchm := make(map[Document]*rank, 200) applyDateFilter := !idx.cfg.IncludeNewer && !upperDate.IsZero() for _, el := range query { setm, found := idx.index[el.Index] if !found { return []Document{}, fmt.Errorf("index for %q not found", el.Index) } config, found := idx.getIndexCfg(el.Index) if !found { return []Document{}, fmt.Errorf("index config for %q not found", el.Index) } for _, kw := range el.Keywords { if docs, found := setm[kw]; found { for _, doc := range docs { if applyDateFilter { // Exclude newer than the limit given if doc.PublishDate().After(upperDate) { continue } } r, found := matchm[doc] if !found { matchm[doc] = newRank(doc, config.Weight) } else { r.addWeight(config.Weight) } } } } } if len(matchm) == 0 { return []Document{}, nil } matches := make(ranks, 0, 100) for _, v := range matchm { avgWeight := v.Weight / v.Matches weight := norm(avgWeight, idx.minWeight, idx.maxWeight) threshold := idx.cfg.Threshold / v.Matches if weight >= threshold { matches = append(matches, v) } } sort.Stable(matches) result := make([]Document, len(matches)) for i, m := range matches { result[i] = m.Doc } return result, nil } // normalizes num to a number between 0 and 100. func norm(num, min, max int) int { if min > max { panic("min > max") } return int(math.Floor((float64(num-min) / float64(max-min) * 100) + 0.5)) } // DecodeConfig decodes a slice of map into Config. func DecodeConfig(m maps.Params) (Config, error) { if m == nil { return Config{}, errors.New("no related config provided") } if len(m) == 0 { return Config{}, errors.New("empty related config provided") } var c Config if err := mapstructure.WeakDecode(m, &c); err != nil { return c, err } if c.Threshold < 0 || c.Threshold > 100 { return Config{}, errors.New("related threshold must be between 0 and 100") } if c.ToLower { for i := range c.Indices { c.Indices[i].ToLower = true } } return c, nil } // StringKeyword is a string search keyword. type StringKeyword string func (s StringKeyword) String() string { return string(s) } // Keyword is the interface a keyword in the search index must implement. type Keyword interface { String() string } // StringsToKeywords converts the given slice of strings to a slice of Keyword. func StringsToKeywords(s ...string) []Keyword { kw := make([]Keyword, len(s)) for i := 0; i < len(s); i++ { kw[i] = StringKeyword(s[i]) } return kw } hugo-0.92.2/related/inverted_index_test.go000066400000000000000000000167601420147000300205640ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package related import ( "fmt" "math/rand" "testing" "time" qt "github.com/frankban/quicktest" ) type testDoc struct { keywords map[string][]Keyword date time.Time name string } func (d *testDoc) String() string { s := "\n" for k, v := range d.keywords { s += k + ":\t\t" for _, vv := range v { s += " " + vv.String() } s += "\n" } return s } func (d *testDoc) Name() string { return d.name } func newTestDoc(name string, keywords ...string) *testDoc { time.Sleep(1 * time.Millisecond) return newTestDocWithDate(name, time.Now(), keywords...) } func newTestDocWithDate(name string, date time.Time, keywords ...string) *testDoc { km := make(map[string][]Keyword) kw := &testDoc{keywords: km, date: date} kw.addKeywords(name, keywords...) return kw } func (d *testDoc) addKeywords(name string, keywords ...string) *testDoc { keywordm := createTestKeywords(name, keywords...) for k, v := range keywordm { keywords := make([]Keyword, len(v)) for i := 0; i < len(v); i++ { keywords[i] = StringKeyword(v[i]) } d.keywords[k] = keywords } return d } func createTestKeywords(name string, keywords ...string) map[string][]string { return map[string][]string{ name: keywords, } } func (d *testDoc) RelatedKeywords(cfg IndexConfig) ([]Keyword, error) { return d.keywords[cfg.Name], nil } func (d *testDoc) PublishDate() time.Time { return d.date } func TestSearch(t *testing.T) { config := Config{ Threshold: 90, IncludeNewer: false, Indices: IndexConfigs{ IndexConfig{Name: "tags", Weight: 50}, IndexConfig{Name: "keywords", Weight: 65}, }, } idx := NewInvertedIndex(config) // idx.debug = true docs := []Document{ newTestDoc("tags", "a", "b", "c", "d"), newTestDoc("tags", "b", "d", "g"), newTestDoc("tags", "b", "h").addKeywords("keywords", "a"), newTestDoc("tags", "g", "h").addKeywords("keywords", "a", "b"), } idx.Add(docs...) t.Run("count", func(t *testing.T) { c := qt.New(t) c.Assert(len(idx.index), qt.Equals, 2) set1, found := idx.index["tags"] c.Assert(found, qt.Equals, true) // 6 tags c.Assert(len(set1), qt.Equals, 6) set2, found := idx.index["keywords"] c.Assert(found, qt.Equals, true) c.Assert(len(set2), qt.Equals, 2) }) t.Run("search-tags", func(t *testing.T) { c := qt.New(t) m, err := idx.search(newQueryElement("tags", StringsToKeywords("a", "b", "d", "z")...)) c.Assert(err, qt.IsNil) c.Assert(len(m), qt.Equals, 2) c.Assert(m[0], qt.Equals, docs[0]) c.Assert(m[1], qt.Equals, docs[1]) }) t.Run("search-tags-and-keywords", func(t *testing.T) { c := qt.New(t) m, err := idx.search( newQueryElement("tags", StringsToKeywords("a", "b", "z")...), newQueryElement("keywords", StringsToKeywords("a", "b")...)) c.Assert(err, qt.IsNil) c.Assert(len(m), qt.Equals, 3) c.Assert(m[0], qt.Equals, docs[3]) c.Assert(m[1], qt.Equals, docs[2]) c.Assert(m[2], qt.Equals, docs[0]) }) t.Run("searchdoc-all", func(t *testing.T) { c := qt.New(t) doc := newTestDoc("tags", "a").addKeywords("keywords", "a") m, err := idx.SearchDoc(doc) c.Assert(err, qt.IsNil) c.Assert(len(m), qt.Equals, 2) c.Assert(m[0], qt.Equals, docs[3]) c.Assert(m[1], qt.Equals, docs[2]) }) t.Run("searchdoc-tags", func(t *testing.T) { c := qt.New(t) doc := newTestDoc("tags", "a", "b", "d", "z").addKeywords("keywords", "a", "b") m, err := idx.SearchDoc(doc, "tags") c.Assert(err, qt.IsNil) c.Assert(len(m), qt.Equals, 2) c.Assert(m[0], qt.Equals, docs[0]) c.Assert(m[1], qt.Equals, docs[1]) }) t.Run("searchdoc-keywords-date", func(t *testing.T) { c := qt.New(t) doc := newTestDoc("tags", "a", "b", "d", "z").addKeywords("keywords", "a", "b") // This will get a date newer than the others. newDoc := newTestDoc("keywords", "a", "b") idx.Add(newDoc) m, err := idx.SearchDoc(doc, "keywords") c.Assert(err, qt.IsNil) c.Assert(len(m), qt.Equals, 2) c.Assert(m[0], qt.Equals, docs[3]) }) t.Run("searchdoc-keywords-same-date", func(t *testing.T) { c := qt.New(t) idx := NewInvertedIndex(config) date := time.Now() doc := newTestDocWithDate("keywords", date, "a", "b") doc.name = "thedoc" for i := 0; i < 10; i++ { docc := *doc docc.name = fmt.Sprintf("doc%d", i) idx.Add(&docc) } m, err := idx.SearchDoc(doc, "keywords") c.Assert(err, qt.IsNil) c.Assert(len(m), qt.Equals, 10) for i := 0; i < 10; i++ { c.Assert(m[i].Name(), qt.Equals, fmt.Sprintf("doc%d", i)) } }) } func TestToKeywordsToLower(t *testing.T) { c := qt.New(t) slice := []string{"A", "B", "C"} config := IndexConfig{ToLower: true} keywords, err := config.ToKeywords(slice) c.Assert(err, qt.IsNil) c.Assert(slice, qt.DeepEquals, []string{"A", "B", "C"}) c.Assert(keywords, qt.DeepEquals, []Keyword{ StringKeyword("a"), StringKeyword("b"), StringKeyword("c"), }) } func BenchmarkRelatedNewIndex(b *testing.B) { pages := make([]*testDoc, 100) numkeywords := 30 allKeywords := make([]string, numkeywords) for i := 0; i < numkeywords; i++ { allKeywords[i] = fmt.Sprintf("keyword%d", i+1) } for i := 0; i < len(pages); i++ { start := rand.Intn(len(allKeywords)) end := start + 3 if end >= len(allKeywords) { end = start + 1 } kw := newTestDoc("tags", allKeywords[start:end]...) if i%5 == 0 { start := rand.Intn(len(allKeywords)) end := start + 3 if end >= len(allKeywords) { end = start + 1 } kw.addKeywords("keywords", allKeywords[start:end]...) } pages[i] = kw } cfg := Config{ Threshold: 50, Indices: IndexConfigs{ IndexConfig{Name: "tags", Weight: 100}, IndexConfig{Name: "keywords", Weight: 200}, }, } b.Run("singles", func(b *testing.B) { for i := 0; i < b.N; i++ { idx := NewInvertedIndex(cfg) for _, doc := range pages { idx.Add(doc) } } }) b.Run("all", func(b *testing.B) { for i := 0; i < b.N; i++ { idx := NewInvertedIndex(cfg) docs := make([]Document, len(pages)) for i := 0; i < len(pages); i++ { docs[i] = pages[i] } idx.Add(docs...) } }) } func BenchmarkRelatedMatchesIn(b *testing.B) { q1 := newQueryElement("tags", StringsToKeywords("keyword2", "keyword5", "keyword32", "asdf")...) q2 := newQueryElement("keywords", StringsToKeywords("keyword3", "keyword4")...) docs := make([]*testDoc, 1000) numkeywords := 20 allKeywords := make([]string, numkeywords) for i := 0; i < numkeywords; i++ { allKeywords[i] = fmt.Sprintf("keyword%d", i+1) } cfg := Config{ Threshold: 20, Indices: IndexConfigs{ IndexConfig{Name: "tags", Weight: 100}, IndexConfig{Name: "keywords", Weight: 200}, }, } idx := NewInvertedIndex(cfg) for i := 0; i < len(docs); i++ { start := rand.Intn(len(allKeywords)) end := start + 3 if end >= len(allKeywords) { end = start + 1 } index := "tags" if i%5 == 0 { index = "keywords" } idx.Add(newTestDoc(index, allKeywords[start:end]...)) } b.ResetTimer() for i := 0; i < b.N; i++ { if i%10 == 0 { idx.search(q2) } else { idx.search(q1) } } } hugo-0.92.2/releaser/000077500000000000000000000000001420147000300143375ustar00rootroot00000000000000hugo-0.92.2/releaser/git.go000066400000000000000000000126771420147000300154660ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package releaser import ( "fmt" "regexp" "sort" "strconv" "strings" "github.com/gohugoio/hugo/common/hexec" ) var issueRe = regexp.MustCompile(`(?i)(?:Updates?|Closes?|Fix.*|See) #(\d+)`) type changeLog struct { Version string Notes gitInfos All gitInfos Docs gitInfos // Overall stats Repo *gitHubRepo ContributorCount int ThemeCount int } func newChangeLog(infos, docInfos gitInfos) *changeLog { log := &changeLog{ Docs: docInfos, } for _, info := range infos { // TODO(bep) improve if regexp.MustCompile("(?i)deprecate|note").MatchString(info.Subject) { log.Notes = append(log.Notes, info) } log.All = append(log.All, info) info.Subject = strings.TrimSpace(info.Subject) } return log } type gitInfo struct { Hash string Author string Subject string Body string GitHubCommit *gitHubCommit } func (g gitInfo) Issues() []int { return extractIssues(g.Body) } func (g gitInfo) AuthorID() string { if g.GitHubCommit != nil { return g.GitHubCommit.Author.Login } return g.Author } func extractIssues(body string) []int { var i []int m := issueRe.FindAllStringSubmatch(body, -1) for _, mm := range m { issueID, err := strconv.Atoi(mm[1]) if err != nil { continue } i = append(i, issueID) } return i } type gitInfos []gitInfo func git(args ...string) (string, error) { cmd, _ := hexec.SafeCommand("git", args...) out, err := cmd.CombinedOutput() if err != nil { return "", fmt.Errorf("git failed: %q: %q (%q)", err, out, args) } return string(out), nil } func getGitInfos(tag, repo, repoPath string, remote bool) (gitInfos, error) { return getGitInfosBefore("HEAD", tag, repo, repoPath, remote) } type countribCount struct { Author string GitHubAuthor gitHubAuthor Count int } func (c countribCount) AuthorLink() string { if c.GitHubAuthor.HTMLURL != "" { return fmt.Sprintf("[@%s](%s)", c.GitHubAuthor.Login, c.GitHubAuthor.HTMLURL) } if !strings.Contains(c.Author, "@") { return c.Author } return c.Author[:strings.Index(c.Author, "@")] } type contribCounts []countribCount func (c contribCounts) Less(i, j int) bool { return c[i].Count > c[j].Count } func (c contribCounts) Len() int { return len(c) } func (c contribCounts) Swap(i, j int) { c[i], c[j] = c[j], c[i] } func (g gitInfos) ContribCountPerAuthor() contribCounts { var c contribCounts counters := make(map[string]countribCount) for _, gi := range g { authorID := gi.AuthorID() if count, ok := counters[authorID]; ok { count.Count = count.Count + 1 counters[authorID] = count } else { var ghA gitHubAuthor if gi.GitHubCommit != nil { ghA = gi.GitHubCommit.Author } authorCount := countribCount{Count: 1, Author: gi.Author, GitHubAuthor: ghA} counters[authorID] = authorCount } } for _, v := range counters { c = append(c, v) } sort.Sort(c) return c } func getGitInfosBefore(ref, tag, repo, repoPath string, remote bool) (gitInfos, error) { client := newGitHubAPI(repo) var g gitInfos log, err := gitLogBefore(ref, tag, repoPath) if err != nil { return g, err } log = strings.Trim(log, "\n\x1e'") entries := strings.Split(log, "\x1e") for _, entry := range entries { items := strings.Split(entry, "\x1f") gi := gitInfo{} if len(items) > 0 { gi.Hash = items[0] } if len(items) > 1 { gi.Author = items[1] } if len(items) > 2 { gi.Subject = items[2] } if len(items) > 3 { gi.Body = items[3] } if remote && gi.Hash != "" { gc, err := client.fetchCommit(gi.Hash) if err == nil { gi.GitHubCommit = &gc } } g = append(g, gi) } return g, nil } // Ignore autogenerated commits etc. in change log. This is a regexp. const ignoredCommits = "snapcraft:|Merge commit|Squashed" func gitLogBefore(ref, tag, repoPath string) (string, error) { var prevTag string var err error if tag != "" { prevTag = tag } else { prevTag, err = gitVersionTagBefore(ref) if err != nil { return "", err } } defaultArgs := []string{"log", "-E", fmt.Sprintf("--grep=%s", ignoredCommits), "--invert-grep", "--pretty=format:%x1e%h%x1f%aE%x1f%s%x1f%b", "--abbrev-commit", prevTag + ".." + ref} var args []string if repoPath != "" { args = append([]string{"-C", repoPath}, defaultArgs...) } else { args = defaultArgs } log, err := git(args...) if err != nil { return ",", err } return log, err } func gitVersionTagBefore(ref string) (string, error) { return gitShort("describe", "--tags", "--abbrev=0", "--always", "--match", "v[0-9]*", ref+"^") } func gitShort(args ...string) (output string, err error) { output, err = git(args...) return strings.Replace(strings.Split(output, "\n")[0], "'", "", -1), err } func tagExists(tag string) (bool, error) { out, err := git("tag", "-l", tag) if err != nil { return false, err } if strings.Contains(out, tag) { return true, nil } return false, nil } hugo-0.92.2/releaser/git_test.go000066400000000000000000000040661420147000300165160ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package releaser import ( "testing" qt "github.com/frankban/quicktest" ) func TestGitInfos(t *testing.T) { c := qt.New(t) skipIfCI(t) infos, err := getGitInfos("v0.20", "hugo", "", false) c.Assert(err, qt.IsNil) c.Assert(len(infos) > 0, qt.Equals, true) } func TestIssuesRe(t *testing.T) { c := qt.New(t) body := ` This is a commit message. Updates #123 Fix #345 closes #543 See #456 ` issues := extractIssues(body) c.Assert(len(issues), qt.Equals, 4) c.Assert(issues[0], qt.Equals, 123) c.Assert(issues[2], qt.Equals, 543) bodyNoIssues := ` This is a commit message without issue refs. But it has e #10 to make old regexp confused. Streets #20. ` emptyIssuesList := extractIssues(bodyNoIssues) c.Assert(len(emptyIssuesList), qt.Equals, 0) } func TestGitVersionTagBefore(t *testing.T) { skipIfCI(t) c := qt.New(t) v1, err := gitVersionTagBefore("v0.18") c.Assert(err, qt.IsNil) c.Assert(v1, qt.Equals, "v0.17") } func TestTagExists(t *testing.T) { skipIfCI(t) c := qt.New(t) b1, err := tagExists("v0.18") c.Assert(err, qt.IsNil) c.Assert(b1, qt.Equals, true) b2, err := tagExists("adfagdsfg") c.Assert(err, qt.IsNil) c.Assert(b2, qt.Equals, false) } func skipIfCI(t *testing.T) { if isCI() { // Travis has an ancient git with no --invert-grep: https://github.com/travis-ci/travis-ci/issues/6328 // Also Travis clones very shallowly, making some of the tests above shaky. t.Skip("Skip git test on Linux to make Travis happy.") } } hugo-0.92.2/releaser/github.go000066400000000000000000000061001420147000300161450ustar00rootroot00000000000000package releaser import ( "encoding/json" "fmt" "io/ioutil" "net/http" "os" "strings" ) var ( gitHubCommitsAPI = "https://api.github.com/repos/gohugoio/REPO/commits/%s" gitHubRepoAPI = "https://api.github.com/repos/gohugoio/REPO" gitHubContributorsAPI = "https://api.github.com/repos/gohugoio/REPO/contributors" ) type gitHubAPI struct { commitsAPITemplate string repoAPI string contributorsAPITemplate string } func newGitHubAPI(repo string) *gitHubAPI { return &gitHubAPI{ commitsAPITemplate: strings.Replace(gitHubCommitsAPI, "REPO", repo, -1), repoAPI: strings.Replace(gitHubRepoAPI, "REPO", repo, -1), contributorsAPITemplate: strings.Replace(gitHubContributorsAPI, "REPO", repo, -1), } } type gitHubCommit struct { Author gitHubAuthor `json:"author"` HTMLURL string `json:"html_url"` } type gitHubAuthor struct { ID int `json:"id"` Login string `json:"login"` HTMLURL string `json:"html_url"` AvatarURL string `json:"avatar_url"` } type gitHubRepo struct { ID int `json:"id"` Name string `json:"name"` Description string `json:"description"` HTMLURL string `json:"html_url"` Stars int `json:"stargazers_count"` Contributors []gitHubContributor } type gitHubContributor struct { ID int `json:"id"` Login string `json:"login"` HTMLURL string `json:"html_url"` Contributions int `json:"contributions"` } func (g *gitHubAPI) fetchCommit(ref string) (gitHubCommit, error) { var commit gitHubCommit u := fmt.Sprintf(g.commitsAPITemplate, ref) req, err := http.NewRequest("GET", u, nil) if err != nil { return commit, err } err = doGitHubRequest(req, &commit) return commit, err } func (g *gitHubAPI) fetchRepo() (gitHubRepo, error) { var repo gitHubRepo req, err := http.NewRequest("GET", g.repoAPI, nil) if err != nil { return repo, err } err = doGitHubRequest(req, &repo) if err != nil { return repo, err } var contributors []gitHubContributor page := 0 for { page++ var currPage []gitHubContributor url := fmt.Sprintf(g.contributorsAPITemplate+"?page=%d", page) req, err = http.NewRequest("GET", url, nil) if err != nil { return repo, err } err = doGitHubRequest(req, &currPage) if err != nil { return repo, err } if len(currPage) == 0 { break } contributors = append(contributors, currPage...) } repo.Contributors = contributors return repo, err } func doGitHubRequest(req *http.Request, v interface{}) error { addGitHubToken(req) resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() if isError(resp) { b, _ := ioutil.ReadAll(resp.Body) return fmt.Errorf("GitHub lookup failed: %s", string(b)) } return json.NewDecoder(resp.Body).Decode(v) } func isError(resp *http.Response) bool { return resp.StatusCode < 200 || resp.StatusCode > 299 } func addGitHubToken(req *http.Request) { gitHubToken := os.Getenv("GITHUB_TOKEN") if gitHubToken != "" { req.Header.Add("Authorization", "token "+gitHubToken) } } hugo-0.92.2/releaser/github_test.go000066400000000000000000000024121420147000300172060ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package releaser import ( "fmt" "os" "testing" qt "github.com/frankban/quicktest" ) func TestGitHubLookupCommit(t *testing.T) { skipIfNoToken(t) c := qt.New(t) client := newGitHubAPI("hugo") commit, err := client.fetchCommit("793554108763c0984f1a1b1a6ee5744b560d78d0") c.Assert(err, qt.IsNil) fmt.Println(commit) } func TestFetchRepo(t *testing.T) { skipIfNoToken(t) c := qt.New(t) client := newGitHubAPI("hugo") repo, err := client.fetchRepo() c.Assert(err, qt.IsNil) fmt.Println(">>", len(repo.Contributors)) } func skipIfNoToken(t *testing.T) { if os.Getenv("GITHUB_TOKEN") == "" { t.Skip("Skip test against GitHub as no GITHUB_TOKEN set.") } } hugo-0.92.2/releaser/releasenotes_writer.go000066400000000000000000000132571420147000300207630ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package releaser implements a set of utilities and a wrapper around Goreleaser // to help automate the Hugo release process. package releaser import ( "bytes" "fmt" "io" "io/ioutil" "net/http" "os" "path/filepath" "strings" "text/template" ) const ( issueLinkTemplate = "#%d" linkTemplate = "[%s](%s)" releaseNotesMarkdownTemplatePatchRelease = ` {{ if eq (len .All) 1 }} This is a bug-fix release with one important fix. {{ else }} This is a bug-fix release with a couple of important fixes. {{ end }} {{ range .All }} {{- if .GitHubCommit -}} * {{ .Subject }} {{ .Hash }} {{ . | authorURL }} {{ range .Issues }}{{ . | issue }} {{ end }} {{ else -}} * {{ .Subject }} {{ range .Issues }}{{ . | issue }} {{ end }} {{ end -}} {{- end }} ` releaseNotesMarkdownTemplate = ` {{- $contribsPerAuthor := .All.ContribCountPerAuthor -}} {{- $docsContribsPerAuthor := .Docs.ContribCountPerAuthor -}} This release represents **{{ len .All }} contributions by {{ len $contribsPerAuthor }} contributors** to the main Hugo code base. {{- if gt (len $contribsPerAuthor) 3 -}} {{- $u1 := index $contribsPerAuthor 0 -}} {{- $u2 := index $contribsPerAuthor 1 -}} {{- $u3 := index $contribsPerAuthor 2 -}} {{- $u4 := index $contribsPerAuthor 3 -}} {{- $u1.AuthorLink }} leads the Hugo development with a significant amount of contributions, but also a big shoutout to {{ $u2.AuthorLink }}, {{ $u3.AuthorLink }}, and {{ $u4.AuthorLink }} for their ongoing contributions. And thanks to [@digitalcraftsman](https://github.com/digitalcraftsman) for his ongoing work on keeping the themes site in pristine condition. {{ end }} Many have also been busy writing and fixing the documentation in [hugoDocs](https://github.com/gohugoio/hugoDocs), which has received **{{ len .Docs }} contributions by {{ len $docsContribsPerAuthor }} contributors**. {{- if gt (len $docsContribsPerAuthor) 3 -}} {{- $u1 := index $docsContribsPerAuthor 0 -}} {{- $u2 := index $docsContribsPerAuthor 1 -}} {{- $u3 := index $docsContribsPerAuthor 2 -}} {{- $u4 := index $docsContribsPerAuthor 3 }} A special thanks to {{ $u1.AuthorLink }}, {{ $u2.AuthorLink }}, {{ $u3.AuthorLink }}, and {{ $u4.AuthorLink }} for their work on the documentation site. {{ end }} Hugo now has: {{ with .Repo -}} * {{ .Stars }}+ [stars](https://github.com/gohugoio/hugo/stargazers) * {{ len .Contributors }}+ [contributors](https://github.com/gohugoio/hugo/graphs/contributors) {{- end -}} {{ with .ThemeCount }} * {{ . }}+ [themes](http://themes.gohugo.io/) {{ end }} {{ with .Notes }} ## Notes {{ template "change-section" . }} {{- end -}} {{ with .All }} ## Changes {{ template "change-section" . }} {{ end }} {{ define "change-section" }} {{ range . }} {{- if .GitHubCommit -}} * {{ .Subject }} {{ .Hash }} {{ . | authorURL }} {{ range .Issues }}{{ . | issue }} {{ end }} {{ else -}} * {{ .Subject }} {{ range .Issues }}{{ . | issue }} {{ end }} {{ end -}} {{- end }} {{ end }} ` ) var templateFuncs = template.FuncMap{ "isPatch": func(c changeLog) bool { return !strings.HasSuffix(c.Version, "0") }, "issue": func(id int) string { return fmt.Sprintf(issueLinkTemplate, id) }, "commitURL": func(info gitInfo) string { if info.GitHubCommit.HTMLURL == "" { return "" } return fmt.Sprintf(linkTemplate, info.Hash, info.GitHubCommit.HTMLURL) }, "authorURL": func(info gitInfo) string { if info.GitHubCommit.Author.Login == "" { return "" } return fmt.Sprintf(linkTemplate, "@"+info.GitHubCommit.Author.Login, info.GitHubCommit.Author.HTMLURL) }, } func writeReleaseNotes(version string, infosMain, infosDocs gitInfos, to io.Writer) error { client := newGitHubAPI("hugo") changes := newChangeLog(infosMain, infosDocs) changes.Version = version repo, err := client.fetchRepo() if err == nil { changes.Repo = &repo } themeCount, err := fetchThemeCount() if err == nil { changes.ThemeCount = themeCount } mtempl := releaseNotesMarkdownTemplate if !strings.HasSuffix(version, "0") { mtempl = releaseNotesMarkdownTemplatePatchRelease } tmpl, err := template.New("").Funcs(templateFuncs).Parse(mtempl) if err != nil { return err } err = tmpl.Execute(to, changes) if err != nil { return err } return nil } func fetchThemeCount() (int, error) { resp, err := http.Get("https://raw.githubusercontent.com/gohugoio/hugoThemesSiteBuilder/main/themes.txt") if err != nil { return 0, err } defer resp.Body.Close() b, _ := ioutil.ReadAll(resp.Body) return bytes.Count(b, []byte("\n")) - bytes.Count(b, []byte("#")), nil } func getReleaseNotesFilename(version string) string { return filepath.FromSlash(fmt.Sprintf("temp/%s-relnotes-ready.md", version)) } func (r *ReleaseHandler) writeReleaseNotesToTemp(version string, isPatch bool, infosMain, infosDocs gitInfos) (string, error) { filename := getReleaseNotesFilename(version) var w io.WriteCloser if !r.try { f, err := os.Create(filename) if err != nil { return "", err } defer f.Close() w = f } else { w = os.Stdout } if err := writeReleaseNotes(version, infosMain, infosDocs, w); err != nil { return "", err } return filename, nil } hugo-0.92.2/releaser/releasenotes_writer_test.go000066400000000000000000000026421420147000300220160ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package commands defines and implements command-line commands and flags // used by Hugo. Commands and flags are implemented using Cobra. package releaser import ( "bytes" "fmt" "os" "testing" qt "github.com/frankban/quicktest" ) func _TestReleaseNotesWriter(t *testing.T) { skipIfNoToken(t) if os.Getenv("CI") != "" { // Travis has an ancient git with no --invert-grep: https://github.com/travis-ci/travis-ci/issues/6328 t.Skip("Skip git test on CI to make Travis happy..") } c := qt.New(t) var b bytes.Buffer // TODO(bep) consider to query GitHub directly for the gitlog with author info, probably faster. infos, err := getGitInfosBefore("HEAD", "v0.89.0", "hugo", "", false) c.Assert(err, qt.IsNil) c.Assert(writeReleaseNotes("0.89.0", infos, infos, &b), qt.IsNil) fmt.Println(b.String()) } hugo-0.92.2/releaser/releaser.go000066400000000000000000000163661420147000300165040ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package releaser implements a set of utilities and a wrapper around Goreleaser // to help automate the Hugo release process. package releaser import ( "fmt" "io/ioutil" "log" "os" "path/filepath" "regexp" "strings" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/hugo" "github.com/pkg/errors" ) const commitPrefix = "releaser:" // ReleaseHandler provides functionality to release a new version of Hugo. // Test this locally without doing an actual release: // go run -tags release main.go release --skip-publish --try -r 0.90.0 // Or a variation of the above -- the skip-publish flag makes sure that any changes are performed to the local Git only. type ReleaseHandler struct { cliVersion string skipPublish bool // Just simulate, no actual changes. try bool git func(args ...string) (string, error) } func (r ReleaseHandler) calculateVersions() (hugo.Version, hugo.Version) { newVersion := hugo.MustParseVersion(r.cliVersion) finalVersion := newVersion.Next() finalVersion.PatchLevel = 0 if newVersion.Suffix != "-test" { newVersion.Suffix = "" } finalVersion.Suffix = "-DEV" return newVersion, finalVersion } // New initialises a ReleaseHandler. func New(version string, skipPublish, try bool) *ReleaseHandler { // When triggered from CI release branch version = strings.TrimPrefix(version, "release-") version = strings.TrimPrefix(version, "v") rh := &ReleaseHandler{cliVersion: version, skipPublish: skipPublish, try: try} if try { rh.git = func(args ...string) (string, error) { fmt.Println("git", strings.Join(args, " ")) return "", nil } } else { rh.git = git } return rh } // Run creates a new release. func (r *ReleaseHandler) Run() error { if os.Getenv("GITHUB_TOKEN") == "" { return errors.New("GITHUB_TOKEN not set, create one here with the repo scope selected: https://github.com/settings/tokens/new") } fmt.Printf("Start release from %q\n", wd()) newVersion, finalVersion := r.calculateVersions() version := newVersion.String() tag := "v" + version isPatch := newVersion.PatchLevel > 0 mainVersion := newVersion mainVersion.PatchLevel = 0 // Exit early if tag already exists exists, err := tagExists(tag) if err != nil { return err } if exists { return fmt.Errorf("tag %q already exists", tag) } var changeLogFromTag string if newVersion.PatchLevel == 0 { // There may have been patch releases between, so set the tag explicitly. changeLogFromTag = "v" + newVersion.Prev().String() exists, _ := tagExists(changeLogFromTag) if !exists { // fall back to one that exists. changeLogFromTag = "" } } var ( gitCommits gitInfos gitCommitsDocs gitInfos ) defer r.gitPush() // TODO(bep) gitCommits, err = getGitInfos(changeLogFromTag, "hugo", "", !r.try) if err != nil { return err } // TODO(bep) explicit tag? gitCommitsDocs, err = getGitInfos("", "hugoDocs", "../hugoDocs", !r.try) if err != nil { return err } releaseNotesFile, err := r.writeReleaseNotesToTemp(version, isPatch, gitCommits, gitCommitsDocs) if err != nil { return err } if _, err := r.git("add", releaseNotesFile); err != nil { return err } commitMsg := fmt.Sprintf("%s Add release notes for %s", commitPrefix, newVersion) commitMsg += "\n[ci skip]" if _, err := r.git("commit", "-m", commitMsg); err != nil { return err } if err := r.bumpVersions(newVersion); err != nil { return err } if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Bump versions for release of %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil { return err } if _, err := r.git("tag", "-a", tag, "-m", fmt.Sprintf("%s %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil { return err } if !r.skipPublish { if _, err := r.git("push", "origin", tag); err != nil { return err } } if err := r.release(releaseNotesFile); err != nil { return err } if err := r.bumpVersions(finalVersion); err != nil { return err } if !r.try { // No longer needed. if err := os.Remove(releaseNotesFile); err != nil { return err } } if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Prepare repository for %s\n\n[ci skip]", commitPrefix, finalVersion)); err != nil { return err } return nil } func (r *ReleaseHandler) gitPush() { if r.skipPublish { return } if _, err := r.git("push", "origin", "HEAD"); err != nil { log.Fatal("push failed:", err) } } func (r *ReleaseHandler) release(releaseNotesFile string) error { if r.try { fmt.Println("Skip goreleaser...") return nil } args := []string{"--parallelism", "3", "--timeout", "120m", "--rm-dist", "--release-notes", releaseNotesFile} if r.skipPublish { args = append(args, "--skip-publish") } cmd, _ := hexec.SafeCommand("goreleaser", args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { return errors.Wrap(err, "goreleaser failed") } return nil } func (r *ReleaseHandler) bumpVersions(ver hugo.Version) error { toDev := "" if ver.Suffix != "" { toDev = ver.Suffix } if err := r.replaceInFile("common/hugo/version_current.go", `Number:(\s{4,})(.*),`, fmt.Sprintf(`Number:${1}%.2f,`, ver.Number), `PatchLevel:(\s*)(.*),`, fmt.Sprintf(`PatchLevel:${1}%d,`, ver.PatchLevel), `Suffix:(\s{4,})".*",`, fmt.Sprintf(`Suffix:${1}"%s",`, toDev)); err != nil { return err } snapcraftGrade := "stable" if ver.Suffix != "" { snapcraftGrade = "devel" } if err := r.replaceInFile("snap/snapcraft.yaml", `version: "(.*)"`, fmt.Sprintf(`version: "%s"`, ver), `grade: (.*) #`, fmt.Sprintf(`grade: %s #`, snapcraftGrade)); err != nil { return err } var minVersion string if ver.Suffix != "" { // People use the DEV version in daily use, and we cannot create new themes // with the next version before it is released. minVersion = ver.Prev().String() } else { minVersion = ver.String() } if err := r.replaceInFile("commands/new.go", `min_version = "(.*)"`, fmt.Sprintf(`min_version = "%s"`, minVersion)); err != nil { return err } return nil } func (r *ReleaseHandler) replaceInFile(filename string, oldNew ...string) error { filename = filepath.FromSlash(filename) fi, err := os.Stat(filename) if err != nil { return err } if r.try { fmt.Printf("Replace in %q: %q\n", filename, oldNew) return nil } b, err := ioutil.ReadFile(filename) if err != nil { return err } newContent := string(b) for i := 0; i < len(oldNew); i += 2 { re := regexp.MustCompile(oldNew[i]) newContent = re.ReplaceAllString(newContent, oldNew[i+1]) } return ioutil.WriteFile(filename, []byte(newContent), fi.Mode()) } func isCI() bool { return os.Getenv("CI") != "" } func wd() string { p, err := os.Getwd() if err != nil { log.Fatal(err) } return p } hugo-0.92.2/resources/000077500000000000000000000000001420147000300145475ustar00rootroot00000000000000hugo-0.92.2/resources/errorResource.go000066400000000000000000000061241420147000300177420ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "image" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/images/exif" "github.com/gohugoio/hugo/resources/resource" ) var ( _ error = (*errorResource)(nil) // Imnage covers all current Resource implementations. _ resource.Image = (*errorResource)(nil) // The list of user facing and exported interfaces in resource.go // Note that if we're missing some interface here, the user will still // get an error, but not as pretty. _ resource.ContentResource = (*errorResource)(nil) _ resource.ReadSeekCloserResource = (*errorResource)(nil) _ resource.ResourcesLanguageMerger = (*resource.Resources)(nil) // Make sure it also fails when passed to a pipe function. _ ResourceTransformer = (*errorResource)(nil) ) // NewErrorResource wraps err in a Resource where all but the Err method will panic. func NewErrorResource(err error) resource.Resource { return &errorResource{error: err} } type errorResource struct { error } func (e *errorResource) Err() error { return e.error } func (e *errorResource) ReadSeekCloser() (hugio.ReadSeekCloser, error) { panic(e.error) } func (e *errorResource) Content() (interface{}, error) { panic(e.error) } func (e *errorResource) ResourceType() string { panic(e.error) } func (e *errorResource) MediaType() media.Type { panic(e.error) } func (e *errorResource) Permalink() string { panic(e.error) } func (e *errorResource) RelPermalink() string { panic(e.error) } func (e *errorResource) Name() string { panic(e.error) } func (e *errorResource) Title() string { panic(e.error) } func (e *errorResource) Params() maps.Params { panic(e.error) } func (e *errorResource) Data() interface{} { panic(e.error) } func (e *errorResource) Height() int { panic(e.error) } func (e *errorResource) Width() int { panic(e.error) } func (e *errorResource) Fill(spec string) (resource.Image, error) { panic(e.error) } func (e *errorResource) Fit(spec string) (resource.Image, error) { panic(e.error) } func (e *errorResource) Resize(spec string) (resource.Image, error) { panic(e.error) } func (e *errorResource) Filter(filters ...interface{}) (resource.Image, error) { panic(e.error) } func (e *errorResource) Exif() *exif.Exif { panic(e.error) } func (e *errorResource) DecodeImage() (image.Image, error) { panic(e.error) } func (e *errorResource) Transform(...ResourceTransformation) (ResourceTransformer, error) { panic(e.error) } hugo-0.92.2/resources/image.go000066400000000000000000000256371420147000300161750ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "encoding/json" "fmt" "image" "image/color" "image/draw" _ "image/gif" _ "image/png" "io" "io/ioutil" "os" "path" "path/filepath" "strings" "sync" "github.com/gohugoio/hugo/common/paths" "github.com/disintegration/gift" "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/resources/images/exif" "github.com/gohugoio/hugo/resources/resource" "github.com/pkg/errors" _errors "github.com/pkg/errors" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/resources/images" // Blind import for image.Decode _ "golang.org/x/image/webp" ) var ( _ resource.Image = (*imageResource)(nil) _ resource.Source = (*imageResource)(nil) _ resource.Cloner = (*imageResource)(nil) ) // ImageResource represents an image resource. type imageResource struct { *images.Image // When a image is processed in a chain, this holds the reference to the // original (first). root *imageResource metaInit sync.Once metaInitErr error meta *imageMeta baseResource } type imageMeta struct { Exif *exif.Exif } func (i *imageResource) Exif() *exif.Exif { return i.root.getExif() } func (i *imageResource) getExif() *exif.Exif { i.metaInit.Do(func() { supportsExif := i.Format == images.JPEG || i.Format == images.TIFF if !supportsExif { return } key := i.getImageMetaCacheTargetPath() read := func(info filecache.ItemInfo, r io.ReadSeeker) error { meta := &imageMeta{} data, err := ioutil.ReadAll(r) if err != nil { return err } if err = json.Unmarshal(data, &meta); err != nil { return err } i.meta = meta return nil } create := func(info filecache.ItemInfo, w io.WriteCloser) (err error) { f, err := i.root.ReadSeekCloser() if err != nil { i.metaInitErr = err return } defer f.Close() x, err := i.getSpec().imaging.DecodeExif(f) if err != nil { i.getSpec().Logger.Warnf("Unable to decode Exif metadata from image: %s", i.Key()) return nil } i.meta = &imageMeta{Exif: x} // Also write it to cache enc := json.NewEncoder(w) return enc.Encode(i.meta) } _, i.metaInitErr = i.getSpec().imageCache.fileCache.ReadOrCreate(key, read, create) }) if i.metaInitErr != nil { panic(fmt.Sprintf("metadata init failed: %s", i.metaInitErr)) } if i.meta == nil { return nil } return i.meta.Exif } func (i *imageResource) Clone() resource.Resource { gr := i.baseResource.Clone().(baseResource) return &imageResource{ root: i.root, Image: i.WithSpec(gr), baseResource: gr, } } func (i *imageResource) cloneWithUpdates(u *transformationUpdate) (baseResource, error) { base, err := i.baseResource.cloneWithUpdates(u) if err != nil { return nil, err } var img *images.Image if u.isContentChanged() { img = i.WithSpec(base) } else { img = i.Image } return &imageResource{ root: i.root, Image: img, baseResource: base, }, nil } // Resize resizes the image to the specified width and height using the specified resampling // filter and returns the transformed image. If one of width or height is 0, the image aspect // ratio is preserved. func (i *imageResource) Resize(spec string) (resource.Image, error) { conf, err := i.decodeImageConfig("resize", spec) if err != nil { return nil, err } return i.doWithImageConfig(conf, func(src image.Image) (image.Image, error) { return i.Proc.ApplyFiltersFromConfig(src, conf) }) } // Fit scales down the image using the specified resample filter to fit the specified // maximum width and height. func (i *imageResource) Fit(spec string) (resource.Image, error) { conf, err := i.decodeImageConfig("fit", spec) if err != nil { return nil, err } return i.doWithImageConfig(conf, func(src image.Image) (image.Image, error) { return i.Proc.ApplyFiltersFromConfig(src, conf) }) } // Fill scales the image to the smallest possible size that will cover the specified dimensions, // crops the resized image to the specified dimensions using the given anchor point. // Space delimited config: 200x300 TopLeft func (i *imageResource) Fill(spec string) (resource.Image, error) { conf, err := i.decodeImageConfig("fill", spec) if err != nil { return nil, err } img, err := i.doWithImageConfig(conf, func(src image.Image) (image.Image, error) { return i.Proc.ApplyFiltersFromConfig(src, conf) }) if err != nil { return nil, err } if conf.Anchor == 0 && img.Width() == 0 || img.Height() == 0 { // See https://github.com/gohugoio/hugo/issues/7955 // Smartcrop fails silently in some rare cases. // Fall back to a center fill. conf.Anchor = gift.CenterAnchor conf.AnchorStr = "center" return i.doWithImageConfig(conf, func(src image.Image) (image.Image, error) { return i.Proc.ApplyFiltersFromConfig(src, conf) }) } return img, err } func (i *imageResource) Filter(filters ...interface{}) (resource.Image, error) { conf := images.GetDefaultImageConfig("filter", i.Proc.Cfg) var gfilters []gift.Filter for _, f := range filters { gfilters = append(gfilters, images.ToFilters(f)...) } conf.Key = helpers.HashString(gfilters) conf.TargetFormat = i.Format return i.doWithImageConfig(conf, func(src image.Image) (image.Image, error) { return i.Proc.Filter(src, gfilters...) }) } // Serialize image processing. The imaging library spins up its own set of Go routines, // so there is not much to gain from adding more load to the mix. That // can even have negative effect in low resource scenarios. // Note that this only effects the non-cached scenario. Once the processed // image is written to disk, everything is fast, fast fast. const imageProcWorkers = 1 var imageProcSem = make(chan bool, imageProcWorkers) func (i *imageResource) doWithImageConfig(conf images.ImageConfig, f func(src image.Image) (image.Image, error)) (resource.Image, error) { img, err := i.getSpec().imageCache.getOrCreate(i, conf, func() (*imageResource, image.Image, error) { imageProcSem <- true defer func() { <-imageProcSem }() errOp := conf.Action errPath := i.getSourceFilename() src, err := i.DecodeImage() if err != nil { return nil, nil, &os.PathError{Op: errOp, Path: errPath, Err: err} } converted, err := f(src) if err != nil { return nil, nil, &os.PathError{Op: errOp, Path: errPath, Err: err} } hasAlpha := !images.IsOpaque(converted) shouldFill := conf.BgColor != nil && hasAlpha shouldFill = shouldFill || (!conf.TargetFormat.SupportsTransparency() && hasAlpha) var bgColor color.Color if shouldFill { bgColor = conf.BgColor if bgColor == nil { bgColor = i.Proc.Cfg.BgColor } tmp := image.NewRGBA(converted.Bounds()) draw.Draw(tmp, tmp.Bounds(), image.NewUniform(bgColor), image.Point{}, draw.Src) draw.Draw(tmp, tmp.Bounds(), converted, converted.Bounds().Min, draw.Over) converted = tmp } if conf.TargetFormat == images.PNG { // Apply the colour palette from the source if paletted, ok := src.(*image.Paletted); ok { palette := paletted.Palette if bgColor != nil && len(palette) < 256 { palette = images.AddColorToPalette(bgColor, palette) } else if bgColor != nil { images.ReplaceColorInPalette(bgColor, palette) } tmp := image.NewPaletted(converted.Bounds(), palette) draw.FloydSteinberg.Draw(tmp, tmp.Bounds(), converted, converted.Bounds().Min) converted = tmp } } ci := i.clone(converted) ci.setBasePath(conf) ci.Format = conf.TargetFormat ci.setMediaType(conf.TargetFormat.MediaType()) return ci, converted, nil }) if err != nil { if i.root != nil && i.root.getFileInfo() != nil { return nil, errors.Wrapf(err, "image %q", i.root.getFileInfo().Meta().Filename) } } return img, nil } func (i *imageResource) decodeImageConfig(action, spec string) (images.ImageConfig, error) { conf, err := images.DecodeImageConfig(action, spec, i.Proc.Cfg, i.Format) if err != nil { return conf, err } return conf, nil } // DecodeImage decodes the image source into an Image. // This an internal method and may change. func (i *imageResource) DecodeImage() (image.Image, error) { f, err := i.ReadSeekCloser() if err != nil { return nil, _errors.Wrap(err, "failed to open image for decode") } defer f.Close() img, _, err := image.Decode(f) return img, err } func (i *imageResource) clone(img image.Image) *imageResource { spec := i.baseResource.Clone().(baseResource) var image *images.Image if img != nil { image = i.WithImage(img) } else { image = i.WithSpec(spec) } return &imageResource{ Image: image, root: i.root, baseResource: spec, } } func (i *imageResource) setBasePath(conf images.ImageConfig) { i.getResourcePaths().relTargetDirFile = i.relTargetPathFromConfig(conf) } func (i *imageResource) getImageMetaCacheTargetPath() string { const imageMetaVersionNumber = 1 // Increment to invalidate the meta cache cfgHash := i.getSpec().imaging.Cfg.CfgHash df := i.getResourcePaths().relTargetDirFile if fi := i.getFileInfo(); fi != nil { df.dir = filepath.Dir(fi.Meta().Path) } p1, _ := paths.FileAndExt(df.file) h, _ := i.hash() idStr := helpers.HashString(h, i.size(), imageMetaVersionNumber, cfgHash) p := path.Join(df.dir, fmt.Sprintf("%s_%s.json", p1, idStr)) return p } func (i *imageResource) relTargetPathFromConfig(conf images.ImageConfig) dirFile { p1, p2 := paths.FileAndExt(i.getResourcePaths().relTargetDirFile.file) if conf.TargetFormat != i.Format { p2 = conf.TargetFormat.DefaultExtension() } h, _ := i.hash() idStr := fmt.Sprintf("_hu%s_%d", h, i.size()) // Do not change for no good reason. const md5Threshold = 100 key := conf.GetKey(i.Format) // It is useful to have the key in clear text, but when nesting transforms, it // can easily be too long to read, and maybe even too long // for the different OSes to handle. if len(p1)+len(idStr)+len(p2) > md5Threshold { key = helpers.MD5String(p1 + key + p2) huIdx := strings.Index(p1, "_hu") if huIdx != -1 { p1 = p1[:huIdx] } else { // This started out as a very long file name. Making it even longer // could melt ice in the Arctic. p1 = "" } } else if strings.Contains(p1, idStr) { // On scaling an already scaled image, we get the file info from the original. // Repeating the same info in the filename makes it stuttery for no good reason. idStr = "" } return dirFile{ dir: i.getResourcePaths().relTargetDirFile.dir, file: fmt.Sprintf("%s%s_%s%s", p1, idStr, key, p2), } } hugo-0.92.2/resources/image_cache.go000066400000000000000000000103161420147000300173040ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "image" "io" "path/filepath" "strings" "sync" "github.com/gohugoio/hugo/resources/images" "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/helpers" ) type imageCache struct { pathSpec *helpers.PathSpec fileCache *filecache.Cache mu sync.RWMutex store map[string]*resourceAdapter } func (c *imageCache) deleteIfContains(s string) { c.mu.Lock() defer c.mu.Unlock() s = c.normalizeKeyBase(s) for k := range c.store { if strings.Contains(k, s) { delete(c.store, k) } } } // The cache key is a lowercase path with Unix style slashes and it always starts with // a leading slash. func (c *imageCache) normalizeKey(key string) string { return "/" + c.normalizeKeyBase(key) } func (c *imageCache) normalizeKeyBase(key string) string { return strings.Trim(strings.ToLower(filepath.ToSlash(key)), "/") } func (c *imageCache) clear() { c.mu.Lock() defer c.mu.Unlock() c.store = make(map[string]*resourceAdapter) } func (c *imageCache) getOrCreate( parent *imageResource, conf images.ImageConfig, createImage func() (*imageResource, image.Image, error)) (*resourceAdapter, error) { relTarget := parent.relTargetPathFromConfig(conf) memKey := parent.relTargetPathForRel(relTarget.path(), false, false, false) memKey = c.normalizeKey(memKey) // For the file cache we want to generate and store it once if possible. fileKeyPath := relTarget if fi := parent.root.getFileInfo(); fi != nil { fileKeyPath.dir = filepath.ToSlash(filepath.Dir(fi.Meta().Path)) } fileKey := fileKeyPath.path() // First check the in-memory store, then the disk. c.mu.RLock() cachedImage, found := c.store[memKey] c.mu.RUnlock() if found { return cachedImage, nil } var img *imageResource // These funcs are protected by a named lock. // read clones the parent to its new name and copies // the content to the destinations. read := func(info filecache.ItemInfo, r io.ReadSeeker) error { img = parent.clone(nil) rp := img.getResourcePaths() rp.relTargetDirFile.file = relTarget.file img.setSourceFilename(info.Name) if err := img.InitConfig(r); err != nil { return err } r.Seek(0, 0) w, err := img.openDestinationsForWriting() if err != nil { return err } if w == nil { // Nothing to write. return nil } defer w.Close() _, err = io.Copy(w, r) return err } // create creates the image and encodes it to the cache (w). create := func(info filecache.ItemInfo, w io.WriteCloser) (err error) { defer w.Close() var conv image.Image img, conv, err = createImage() if err != nil { return } rp := img.getResourcePaths() rp.relTargetDirFile.file = relTarget.file img.setSourceFilename(info.Name) return img.EncodeTo(conf, conv, w) } // Now look in the file cache. // The definition of this counter is not that we have processed that amount // (e.g. resized etc.), it can be fetched from file cache, // but the count of processed image variations for this site. c.pathSpec.ProcessingStats.Incr(&c.pathSpec.ProcessingStats.ProcessedImages) _, err := c.fileCache.ReadOrCreate(fileKey, read, create) if err != nil { return nil, err } // The file is now stored in this cache. img.setSourceFs(c.fileCache.Fs) c.mu.Lock() if cachedImage, found = c.store[memKey]; found { c.mu.Unlock() return cachedImage, nil } imgAdapter := newResourceAdapter(parent.getSpec(), true, img) c.store[memKey] = imgAdapter c.mu.Unlock() return imgAdapter, nil } func newImageCache(fileCache *filecache.Cache, ps *helpers.PathSpec) *imageCache { return &imageCache{fileCache: fileCache, pathSpec: ps, store: make(map[string]*resourceAdapter)} } hugo-0.92.2/resources/image_extended_test.go000066400000000000000000000024761420147000300211100ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build extended package resources import ( "testing" "github.com/gohugoio/hugo/media" qt "github.com/frankban/quicktest" ) func TestImageResizeWebP(t *testing.T) { c := qt.New(t) image := fetchImage(c, "sunset.webp") c.Assert(image.MediaType(), qt.Equals, media.WEBPType) c.Assert(image.RelPermalink(), qt.Equals, "/a/sunset.webp") c.Assert(image.ResourceType(), qt.Equals, "image") c.Assert(image.Exif(), qt.IsNil) resized, err := image.Resize("123x") c.Assert(err, qt.IsNil) c.Assert(image.MediaType(), qt.Equals, media.WEBPType) c.Assert(resized.RelPermalink(), qt.Equals, "/a/sunset_hu36ee0b61ba924719ad36da960c273f96_59826_123x0_resize_q68_h2_linear_2.webp") c.Assert(resized.Width(), qt.Equals, 123) } hugo-0.92.2/resources/image_test.go000066400000000000000000000536511420147000300172310ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "fmt" "image" "io/ioutil" "math/big" "math/rand" "os" "path" "path/filepath" "runtime" "strconv" "sync" "testing" "time" "github.com/gohugoio/hugo/resources/images/webp" "github.com/gohugoio/hugo/common/paths" "github.com/spf13/afero" "github.com/disintegration/gift" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/images" "github.com/gohugoio/hugo/resources/resource" "github.com/google/go-cmp/cmp" "github.com/gohugoio/hugo/htesting/hqt" qt "github.com/frankban/quicktest" ) var eq = qt.CmpEquals( cmp.Comparer(func(p1, p2 *resourceAdapter) bool { return p1.resourceAdapterInner == p2.resourceAdapterInner }), cmp.Comparer(func(p1, p2 os.FileInfo) bool { return p1.Name() == p2.Name() && p1.Size() == p2.Size() && p1.IsDir() == p2.IsDir() }), cmp.Comparer(func(p1, p2 *genericResource) bool { return p1 == p2 }), cmp.Comparer(func(m1, m2 media.Type) bool { return m1.Type() == m2.Type() }), cmp.Comparer( func(v1, v2 *big.Rat) bool { return v1.RatString() == v2.RatString() }, ), cmp.Comparer(func(v1, v2 time.Time) bool { return v1.Unix() == v2.Unix() }), ) func TestImageTransformBasic(t *testing.T) { c := qt.New(t) image := fetchSunset(c) fileCache := image.(specProvider).getSpec().FileCaches.ImageCache().Fs assertWidthHeight := func(img resource.Image, w, h int) { c.Helper() c.Assert(img, qt.Not(qt.IsNil)) c.Assert(img.Width(), qt.Equals, w) c.Assert(img.Height(), qt.Equals, h) } c.Assert(image.RelPermalink(), qt.Equals, "/a/sunset.jpg") c.Assert(image.ResourceType(), qt.Equals, "image") assertWidthHeight(image, 900, 562) resized, err := image.Resize("300x200") c.Assert(err, qt.IsNil) c.Assert(image != resized, qt.Equals, true) c.Assert(image, qt.Not(eq), resized) assertWidthHeight(resized, 300, 200) assertWidthHeight(image, 900, 562) resized0x, err := image.Resize("x200") c.Assert(err, qt.IsNil) assertWidthHeight(resized0x, 320, 200) assertFileCache(c, fileCache, path.Base(resized0x.RelPermalink()), 320, 200) resizedx0, err := image.Resize("200x") c.Assert(err, qt.IsNil) assertWidthHeight(resizedx0, 200, 125) assertFileCache(c, fileCache, path.Base(resizedx0.RelPermalink()), 200, 125) resizedAndRotated, err := image.Resize("x200 r90") c.Assert(err, qt.IsNil) assertWidthHeight(resizedAndRotated, 125, 200) assertWidthHeight(resized, 300, 200) c.Assert(resized.RelPermalink(), qt.Equals, "/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_300x200_resize_q68_linear.jpg") fitted, err := resized.Fit("50x50") c.Assert(err, qt.IsNil) c.Assert(fitted.RelPermalink(), qt.Equals, "/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_625708021e2bb281c9f1002f88e4753f.jpg") assertWidthHeight(fitted, 50, 33) // Check the MD5 key threshold fittedAgain, _ := fitted.Fit("10x20") fittedAgain, err = fittedAgain.Fit("10x20") c.Assert(err, qt.IsNil) c.Assert(fittedAgain.RelPermalink(), qt.Equals, "/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_3f65ba24dc2b7fba0f56d7f104519157.jpg") assertWidthHeight(fittedAgain, 10, 7) filled, err := image.Fill("200x100 bottomLeft") c.Assert(err, qt.IsNil) c.Assert(filled.RelPermalink(), qt.Equals, "/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x100_fill_q68_linear_bottomleft.jpg") assertWidthHeight(filled, 200, 100) smart, err := image.Fill("200x100 smart") c.Assert(err, qt.IsNil) c.Assert(smart.RelPermalink(), qt.Equals, fmt.Sprintf("/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x100_fill_q68_linear_smart%d.jpg", 1)) assertWidthHeight(smart, 200, 100) // Check cache filledAgain, err := image.Fill("200x100 bottomLeft") c.Assert(err, qt.IsNil) c.Assert(filled, eq, filledAgain) } func TestImageTransformFormat(t *testing.T) { c := qt.New(t) image := fetchSunset(c) fileCache := image.(specProvider).getSpec().FileCaches.ImageCache().Fs assertExtWidthHeight := func(img resource.Image, ext string, w, h int) { c.Helper() c.Assert(img, qt.Not(qt.IsNil)) c.Assert(paths.Ext(img.RelPermalink()), qt.Equals, ext) c.Assert(img.Width(), qt.Equals, w) c.Assert(img.Height(), qt.Equals, h) } c.Assert(image.RelPermalink(), qt.Equals, "/a/sunset.jpg") c.Assert(image.ResourceType(), qt.Equals, "image") assertExtWidthHeight(image, ".jpg", 900, 562) imagePng, err := image.Resize("450x png") c.Assert(err, qt.IsNil) c.Assert(imagePng.RelPermalink(), qt.Equals, "/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_450x0_resize_linear.png") c.Assert(imagePng.ResourceType(), qt.Equals, "image") assertExtWidthHeight(imagePng, ".png", 450, 281) c.Assert(imagePng.Name(), qt.Equals, "sunset.jpg") c.Assert(imagePng.MediaType().String(), qt.Equals, "image/png") assertFileCache(c, fileCache, path.Base(imagePng.RelPermalink()), 450, 281) imageGif, err := image.Resize("225x gif") c.Assert(err, qt.IsNil) c.Assert(imageGif.RelPermalink(), qt.Equals, "/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_225x0_resize_linear.gif") c.Assert(imageGif.ResourceType(), qt.Equals, "image") assertExtWidthHeight(imageGif, ".gif", 225, 141) c.Assert(imageGif.Name(), qt.Equals, "sunset.jpg") c.Assert(imageGif.MediaType().String(), qt.Equals, "image/gif") assertFileCache(c, fileCache, path.Base(imageGif.RelPermalink()), 225, 141) } // https://github.com/gohugoio/hugo/issues/5730 func TestImagePermalinkPublishOrder(t *testing.T) { for _, checkOriginalFirst := range []bool{true, false} { name := "OriginalFirst" if !checkOriginalFirst { name = "ResizedFirst" } t.Run(name, func(t *testing.T) { c := qt.New(t) spec, workDir := newTestResourceOsFs(c) defer func() { os.Remove(workDir) }() check1 := func(img resource.Image) { resizedLink := "/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_100x50_resize_q75_box.jpg" c.Assert(img.RelPermalink(), qt.Equals, resizedLink) assertImageFile(c, spec.PublishFs, resizedLink, 100, 50) } check2 := func(img resource.Image) { c.Assert(img.RelPermalink(), qt.Equals, "/a/sunset.jpg") assertImageFile(c, spec.PublishFs, "a/sunset.jpg", 900, 562) } orignal := fetchImageForSpec(spec, c, "sunset.jpg") c.Assert(orignal, qt.Not(qt.IsNil)) if checkOriginalFirst { check2(orignal) } resized, err := orignal.Resize("100x50") c.Assert(err, qt.IsNil) check1(resized.(resource.Image)) if !checkOriginalFirst { check2(orignal) } }) } } func TestImageBugs(t *testing.T) { c := qt.New(t) // Issue #4261 c.Run("Transform long filename", func(c *qt.C) { image := fetchImage(c, "1234567890qwertyuiopasdfghjklzxcvbnm5to6eeeeee7via8eleph.jpg") c.Assert(image, qt.Not(qt.IsNil)) resized, err := image.Resize("200x") c.Assert(err, qt.IsNil) c.Assert(resized, qt.Not(qt.IsNil)) c.Assert(resized.Width(), qt.Equals, 200) c.Assert(resized.RelPermalink(), qt.Equals, "/a/_hu59e56ffff1bc1d8d122b1403d34e039f_90587_65b757a6e14debeae720fe8831f0a9bc.jpg") resized, err = resized.Resize("100x") c.Assert(err, qt.IsNil) c.Assert(resized, qt.Not(qt.IsNil)) c.Assert(resized.Width(), qt.Equals, 100) c.Assert(resized.RelPermalink(), qt.Equals, "/a/_hu59e56ffff1bc1d8d122b1403d34e039f_90587_c876768085288f41211f768147ba2647.jpg") }) // Issue #6137 c.Run("Transform upper case extension", func(c *qt.C) { image := fetchImage(c, "sunrise.JPG") resized, err := image.Resize("200x") c.Assert(err, qt.IsNil) c.Assert(resized, qt.Not(qt.IsNil)) c.Assert(resized.Width(), qt.Equals, 200) }) // Issue #7955 c.Run("Fill with smartcrop", func(c *qt.C) { sunset := fetchImage(c, "sunset.jpg") for _, test := range []struct { originalDimensions string targetWH int }{ {"408x403", 400}, {"425x403", 400}, {"459x429", 400}, {"476x442", 400}, {"544x403", 400}, {"476x468", 400}, {"578x585", 550}, {"578x598", 550}, } { c.Run(test.originalDimensions, func(c *qt.C) { image, err := sunset.Resize(test.originalDimensions) c.Assert(err, qt.IsNil) resized, err := image.Fill(fmt.Sprintf("%dx%d smart", test.targetWH, test.targetWH)) c.Assert(err, qt.IsNil) c.Assert(resized, qt.Not(qt.IsNil)) c.Assert(resized.Width(), qt.Equals, test.targetWH) c.Assert(resized.Height(), qt.Equals, test.targetWH) }) } }) } func TestImageTransformConcurrent(t *testing.T) { var wg sync.WaitGroup c := qt.New(t) spec, workDir := newTestResourceOsFs(c) defer func() { os.Remove(workDir) }() image := fetchImageForSpec(spec, c, "sunset.jpg") for i := 0; i < 4; i++ { wg.Add(1) go func(id int) { defer wg.Done() for j := 0; j < 5; j++ { img := image for k := 0; k < 2; k++ { r1, err := img.Resize(fmt.Sprintf("%dx", id-k)) if err != nil { t.Error(err) } if r1.Width() != id-k { t.Errorf("Width: %d:%d", r1.Width(), j) } r2, err := r1.Resize(fmt.Sprintf("%dx", id-k-1)) if err != nil { t.Error(err) } img = r2 } } }(i + 20) } wg.Wait() } func TestImageWithMetadata(t *testing.T) { c := qt.New(t) image := fetchSunset(c) meta := []map[string]interface{}{ { "title": "My Sunset", "name": "Sunset #:counter", "src": "*.jpg", }, } c.Assert(AssignMetadata(meta, image), qt.IsNil) c.Assert(image.Name(), qt.Equals, "Sunset #1") resized, err := image.Resize("200x") c.Assert(err, qt.IsNil) c.Assert(resized.Name(), qt.Equals, "Sunset #1") } func TestImageResize8BitPNG(t *testing.T) { c := qt.New(t) image := fetchImage(c, "gohugoio.png") c.Assert(image.MediaType().Type(), qt.Equals, "image/png") c.Assert(image.RelPermalink(), qt.Equals, "/a/gohugoio.png") c.Assert(image.ResourceType(), qt.Equals, "image") c.Assert(image.Exif(), qt.IsNil) resized, err := image.Resize("800x") c.Assert(err, qt.IsNil) c.Assert(resized.MediaType().Type(), qt.Equals, "image/png") c.Assert(resized.RelPermalink(), qt.Equals, "/a/gohugoio_hu0e1b9e4a4be4d6f86c7b37b9ccce3fbc_73886_800x0_resize_linear_3.png") c.Assert(resized.Width(), qt.Equals, 800) } func TestImageResizeInSubPath(t *testing.T) { c := qt.New(t) image := fetchImage(c, "sub/gohugoio2.png") c.Assert(image.MediaType(), eq, media.PNGType) c.Assert(image.RelPermalink(), qt.Equals, "/a/sub/gohugoio2.png") c.Assert(image.ResourceType(), qt.Equals, "image") c.Assert(image.Exif(), qt.IsNil) resized, err := image.Resize("101x101") c.Assert(err, qt.IsNil) c.Assert(resized.MediaType().Type(), qt.Equals, "image/png") c.Assert(resized.RelPermalink(), qt.Equals, "/a/sub/gohugoio2_hu0e1b9e4a4be4d6f86c7b37b9ccce3fbc_73886_101x101_resize_linear_3.png") c.Assert(resized.Width(), qt.Equals, 101) c.Assert(resized.Exif(), qt.IsNil) publishedImageFilename := filepath.Clean(resized.RelPermalink()) spec := image.(specProvider).getSpec() assertImageFile(c, spec.BaseFs.PublishFs, publishedImageFilename, 101, 101) c.Assert(spec.BaseFs.PublishFs.Remove(publishedImageFilename), qt.IsNil) // Clear mem cache to simulate reading from the file cache. spec.imageCache.clear() resizedAgain, err := image.Resize("101x101") c.Assert(err, qt.IsNil) c.Assert(resizedAgain.RelPermalink(), qt.Equals, "/a/sub/gohugoio2_hu0e1b9e4a4be4d6f86c7b37b9ccce3fbc_73886_101x101_resize_linear_3.png") c.Assert(resizedAgain.Width(), qt.Equals, 101) assertImageFile(c, image.(specProvider).getSpec().BaseFs.PublishFs, publishedImageFilename, 101, 101) } func TestSVGImage(t *testing.T) { c := qt.New(t) spec := newTestResourceSpec(specDescriptor{c: c}) svg := fetchResourceForSpec(spec, c, "circle.svg") c.Assert(svg, qt.Not(qt.IsNil)) } func TestSVGImageContent(t *testing.T) { c := qt.New(t) spec := newTestResourceSpec(specDescriptor{c: c}) svg := fetchResourceForSpec(spec, c, "circle.svg") c.Assert(svg, qt.Not(qt.IsNil)) content, err := svg.Content() c.Assert(err, qt.IsNil) c.Assert(content, hqt.IsSameType, "") c.Assert(content.(string), qt.Contains, ``) } func TestImageExif(t *testing.T) { c := qt.New(t) fs := afero.NewMemMapFs() spec := newTestResourceSpec(specDescriptor{fs: fs, c: c}) image := fetchResourceForSpec(spec, c, "sunset.jpg").(resource.Image) getAndCheckExif := func(c *qt.C, image resource.Image) { x := image.Exif() c.Assert(x, qt.Not(qt.IsNil)) c.Assert(x.Date.Format("2006-01-02"), qt.Equals, "2017-10-27") // Malaga: https://goo.gl/taazZy c.Assert(x.Lat, qt.Equals, float64(36.59744166666667)) c.Assert(x.Long, qt.Equals, float64(-4.50846)) v, found := x.Tags["LensModel"] c.Assert(found, qt.Equals, true) lensModel, ok := v.(string) c.Assert(ok, qt.Equals, true) c.Assert(lensModel, qt.Equals, "smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM") resized, _ := image.Resize("300x200") x2 := resized.Exif() c.Assert(x2, eq, x) } getAndCheckExif(c, image) image = fetchResourceForSpec(spec, c, "sunset.jpg").(resource.Image) // This will read from file cache. getAndCheckExif(c, image) } func BenchmarkImageExif(b *testing.B) { getImages := func(c *qt.C, b *testing.B, fs afero.Fs) []resource.Image { spec := newTestResourceSpec(specDescriptor{fs: fs, c: c}) images := make([]resource.Image, b.N) for i := 0; i < b.N; i++ { images[i] = fetchResourceForSpec(spec, c, "sunset.jpg", strconv.Itoa(i)).(resource.Image) } return images } getAndCheckExif := func(c *qt.C, image resource.Image) { x := image.Exif() c.Assert(x, qt.Not(qt.IsNil)) c.Assert(x.Long, qt.Equals, float64(-4.50846)) } b.Run("Cold cache", func(b *testing.B) { b.StopTimer() c := qt.New(b) images := getImages(c, b, afero.NewMemMapFs()) b.StartTimer() for i := 0; i < b.N; i++ { getAndCheckExif(c, images[i]) } }) b.Run("Cold cache, 10", func(b *testing.B) { b.StopTimer() c := qt.New(b) images := getImages(c, b, afero.NewMemMapFs()) b.StartTimer() for i := 0; i < b.N; i++ { for j := 0; j < 10; j++ { getAndCheckExif(c, images[i]) } } }) b.Run("Warm cache", func(b *testing.B) { b.StopTimer() c := qt.New(b) fs := afero.NewMemMapFs() images := getImages(c, b, fs) for i := 0; i < b.N; i++ { getAndCheckExif(c, images[i]) } images = getImages(c, b, fs) b.StartTimer() for i := 0; i < b.N; i++ { getAndCheckExif(c, images[i]) } }) } // usesFMA indicates whether "fused multiply and add" (FMA) instruction is // used. The command "grep FMADD go/test/codegen/floats.go" can help keep // the FMA-using architecture list updated. var usesFMA = runtime.GOARCH == "s390x" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "arm64" // goldenEqual compares two NRGBA images. It is used in golden tests only. // A small tolerance is allowed on architectures using "fused multiply and add" // (FMA) instruction to accommodate for floating-point rounding differences // with control golden images that were generated on amd64 architecture. // See https://golang.org/ref/spec#Floating_point_operators // and https://github.com/gohugoio/hugo/issues/6387 for more information. // // Borrowed from https://github.com/disintegration/gift/blob/a999ff8d5226e5ab14b64a94fca07c4ac3f357cf/gift_test.go#L598-L625 // Copyright (c) 2014-2019 Grigory Dryapak // Licensed under the MIT License. func goldenEqual(img1, img2 *image.NRGBA) bool { maxDiff := 0 if usesFMA { maxDiff = 1 } if !img1.Rect.Eq(img2.Rect) { return false } if len(img1.Pix) != len(img2.Pix) { return false } for i := 0; i < len(img1.Pix); i++ { diff := int(img1.Pix[i]) - int(img2.Pix[i]) if diff < 0 { diff = -diff } if diff > maxDiff { return false } } return true } // Issue #8729 func TestImageOperationsGoldenWebp(t *testing.T) { if !webp.Supports() { t.Skip("skip webp test") } c := qt.New(t) c.Parallel() devMode := false testImages := []string{"fuzzy-cirlcle.png"} spec, workDir := newTestResourceOsFs(c) defer func() { if !devMode { os.Remove(workDir) } }() if devMode { fmt.Println(workDir) } for _, imageName := range testImages { image := fetchImageForSpec(spec, c, imageName) imageWebp, err := image.Resize("200x webp") c.Assert(err, qt.IsNil) c.Assert(imageWebp.Width(), qt.Equals, 200) } if devMode { return } dir1 := filepath.Join(workDir, "resources/_gen/images") dir2 := filepath.FromSlash("testdata/golden_webp") assetGoldenDirs(c, dir1, dir2) } func TestImageOperationsGolden(t *testing.T) { c := qt.New(t) c.Parallel() // Note, if you're enabling this on a MacOS M1 (ARM) you need to run the test with GOARCH=amd64. // GOARCH=amd64 go test -timeout 30s -run "^TestImageOperationsGolden$" ./resources -v devMode := false testImages := []string{"sunset.jpg", "gohugoio8.png", "gohugoio24.png"} spec, workDir := newTestResourceOsFs(c) defer func() { if !devMode { os.Remove(workDir) } }() if devMode { fmt.Println(workDir) } gopher := fetchImageForSpec(spec, c, "gopher-hero8.png") var err error gopher, err = gopher.Resize("30x") c.Assert(err, qt.IsNil) // Test PNGs with alpha channel. for _, img := range []string{"gopher-hero8.png", "gradient-circle.png"} { orig := fetchImageForSpec(spec, c, img) for _, resizeSpec := range []string{"200x #e3e615", "200x jpg #e3e615"} { resized, err := orig.Resize(resizeSpec) c.Assert(err, qt.IsNil) rel := resized.RelPermalink() c.Log("resize", rel) c.Assert(rel, qt.Not(qt.Equals), "") } } for _, img := range testImages { orig := fetchImageForSpec(spec, c, img) for _, resizeSpec := range []string{"200x100", "600x", "200x r90 q50 Box"} { resized, err := orig.Resize(resizeSpec) c.Assert(err, qt.IsNil) rel := resized.RelPermalink() c.Log("resize", rel) c.Assert(rel, qt.Not(qt.Equals), "") } for _, fillSpec := range []string{"300x200 Gaussian Smart", "100x100 Center", "300x100 TopLeft NearestNeighbor", "400x200 BottomLeft"} { resized, err := orig.Fill(fillSpec) c.Assert(err, qt.IsNil) rel := resized.RelPermalink() c.Log("fill", rel) c.Assert(rel, qt.Not(qt.Equals), "") } for _, fitSpec := range []string{"300x200 Linear"} { resized, err := orig.Fit(fitSpec) c.Assert(err, qt.IsNil) rel := resized.RelPermalink() c.Log("fit", rel) c.Assert(rel, qt.Not(qt.Equals), "") } f := &images.Filters{} filters := []gift.Filter{ f.Grayscale(), f.GaussianBlur(6), f.Saturation(50), f.Sepia(100), f.Brightness(30), f.ColorBalance(10, -10, -10), f.Colorize(240, 50, 100), f.Gamma(1.5), f.UnsharpMask(1, 1, 0), f.Sigmoid(0.5, 7), f.Pixelate(5), f.Invert(), f.Hue(22), f.Contrast(32.5), f.Overlay(gopher.(images.ImageSource), 20, 30), f.Text("No options"), f.Text("This long text is to test line breaks. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."), f.Text("Hugo rocks!", map[string]interface{}{"x": 3, "y": 3, "size": 20, "color": "#fc03b1"}), } resized, err := orig.Fill("400x200 center") c.Assert(err, qt.IsNil) for _, filter := range filters { resized, err := resized.Filter(filter) c.Assert(err, qt.IsNil) rel := resized.RelPermalink() c.Logf("filter: %v %s", filter, rel) c.Assert(rel, qt.Not(qt.Equals), "") } resized, err = resized.Filter(filters[0:4]) c.Assert(err, qt.IsNil) rel := resized.RelPermalink() c.Log("filter all", rel) c.Assert(rel, qt.Not(qt.Equals), "") } if devMode { return } dir1 := filepath.Join(workDir, "resources/_gen/images") dir2 := filepath.FromSlash("testdata/golden") assetGoldenDirs(c, dir1, dir2) } func assetGoldenDirs(c *qt.C, dir1, dir2 string) { // The two dirs above should now be the same. dirinfos1, err := ioutil.ReadDir(dir1) c.Assert(err, qt.IsNil) dirinfos2, err := ioutil.ReadDir(dir2) c.Assert(err, qt.IsNil) c.Assert(len(dirinfos1), qt.Equals, len(dirinfos2)) for i, fi1 := range dirinfos1 { fi2 := dirinfos2[i] c.Assert(fi1.Name(), qt.Equals, fi2.Name()) f1, err := os.Open(filepath.Join(dir1, fi1.Name())) c.Assert(err, qt.IsNil) f2, err := os.Open(filepath.Join(dir2, fi2.Name())) c.Assert(err, qt.IsNil) img1, _, err := image.Decode(f1) c.Assert(err, qt.IsNil) img2, _, err := image.Decode(f2) c.Assert(err, qt.IsNil) nrgba1 := image.NewNRGBA(img1.Bounds()) gift.New().Draw(nrgba1, img1) nrgba2 := image.NewNRGBA(img2.Bounds()) gift.New().Draw(nrgba2, img2) if !goldenEqual(nrgba1, nrgba2) { switch fi1.Name() { case "gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_73c19c5f80881858a85aa23cd0ca400d.png", "gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_ae631e5252bb5d7b92bc766ad1a89069.png", "gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d1bbfa2629bffb90118cacce3fcfb924.png": c.Log("expectedly differs from golden due to dithering:", fi1.Name()) default: c.Errorf("resulting image differs from golden: %s", fi1.Name()) } } if !usesFMA { c.Assert(fi1, eq, fi2) _, err = f1.Seek(0, 0) c.Assert(err, qt.IsNil) _, err = f2.Seek(0, 0) c.Assert(err, qt.IsNil) hash1, err := helpers.MD5FromReader(f1) c.Assert(err, qt.IsNil) hash2, err := helpers.MD5FromReader(f2) c.Assert(err, qt.IsNil) c.Assert(hash1, qt.Equals, hash2) } f1.Close() f2.Close() } } func BenchmarkResizeParallel(b *testing.B) { c := qt.New(b) img := fetchSunset(c) b.RunParallel(func(pb *testing.PB) { for pb.Next() { w := rand.Intn(10) + 10 resized, err := img.Resize(strconv.Itoa(w) + "x") if err != nil { b.Fatal(err) } _, err = resized.Resize(strconv.Itoa(w-1) + "x") if err != nil { b.Fatal(err) } } }) } ���������������������������������������������������������������������������������������hugo-0.92.2/resources/images/�����������������������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0016014�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/color.go���������������������������������������������������������������0000664�0000000�0000000�00000003565�14201470003�0017472�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "encoding/hex" "image/color" "strings" "github.com/pkg/errors" ) // AddColorToPalette adds c as the first color in p if not already there. // Note that it does no additional checks, so callers must make sure // that the palette is valid for the relevant format. func AddColorToPalette(c color.Color, p color.Palette) color.Palette { var found bool for _, cc := range p { if c == cc { found = true break } } if !found { p = append(color.Palette{c}, p...) } return p } // ReplaceColorInPalette will replace the color in palette p closest to c in Euclidean // R,G,B,A space with c. func ReplaceColorInPalette(c color.Color, p color.Palette) { p[p.Index(c)] = c } func hexStringToColor(s string) (color.Color, error) { s = strings.TrimPrefix(s, "#") if len(s) != 3 && len(s) != 6 { return nil, errors.Errorf("invalid color code: %q", s) } s = strings.ToLower(s) if len(s) == 3 { var v string for _, r := range s { v += string(r) + string(r) } s = v } // Standard colors. if s == "ffffff" { return color.White, nil } if s == "000000" { return color.Black, nil } // Set Alfa to white. s += "ff" b, err := hex.DecodeString(s) if err != nil { return nil, err } return color.RGBA{b[0], b[1], b[2], b[3]}, nil } �������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/color_test.go����������������������������������������������������������0000664�0000000�0000000�00000004340�14201470003�0020521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "image/color" "testing" qt "github.com/frankban/quicktest" ) func TestHexStringToColor(t *testing.T) { c := qt.New(t) for _, test := range []struct { arg string expect interface{} }{ {"f", false}, {"#f", false}, {"#fffffff", false}, {"fffffff", false}, {"#fff", color.White}, {"fff", color.White}, {"FFF", color.White}, {"FfF", color.White}, {"#ffffff", color.White}, {"ffffff", color.White}, {"#000", color.Black}, {"#4287f5", color.RGBA{R: 0x42, G: 0x87, B: 0xf5, A: 0xff}}, {"777", color.RGBA{R: 0x77, G: 0x77, B: 0x77, A: 0xff}}, } { test := test c.Run(test.arg, func(c *qt.C) { c.Parallel() result, err := hexStringToColor(test.arg) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil)) return } c.Assert(err, qt.IsNil) c.Assert(result, qt.DeepEquals, test.expect) }) } } func TestAddColorToPalette(t *testing.T) { c := qt.New(t) palette := color.Palette{color.White, color.Black} c.Assert(AddColorToPalette(color.White, palette), qt.HasLen, 2) blue1, _ := hexStringToColor("34c3eb") blue2, _ := hexStringToColor("34c3eb") white, _ := hexStringToColor("fff") c.Assert(AddColorToPalette(white, palette), qt.HasLen, 2) c.Assert(AddColorToPalette(blue1, palette), qt.HasLen, 3) c.Assert(AddColorToPalette(blue2, palette), qt.HasLen, 3) } func TestReplaceColorInPalette(t *testing.T) { c := qt.New(t) palette := color.Palette{color.White, color.Black} offWhite, _ := hexStringToColor("fcfcfc") ReplaceColorInPalette(offWhite, palette) c.Assert(palette, qt.HasLen, 2) c.Assert(palette[0], qt.Equals, offWhite) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/config.go��������������������������������������������������������������0000664�0000000�0000000�00000030223�14201470003�0017610�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "fmt" "image/color" "strconv" "strings" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/media" "github.com/pkg/errors" "github.com/bep/gowebp/libwebp/webpoptions" "github.com/disintegration/gift" "github.com/mitchellh/mapstructure" ) var ( imageFormats = map[string]Format{ ".jpg": JPEG, ".jpeg": JPEG, ".jpe": JPEG, ".jif": JPEG, ".jfif": JPEG, ".png": PNG, ".tif": TIFF, ".tiff": TIFF, ".bmp": BMP, ".gif": GIF, ".webp": WEBP, } imageFormatsBySubType = map[string]Format{ media.JPEGType.SubType: JPEG, media.PNGType.SubType: PNG, media.TIFFType.SubType: TIFF, media.BMPType.SubType: BMP, media.GIFType.SubType: GIF, media.WEBPType.SubType: WEBP, } // Add or increment if changes to an image format's processing requires // re-generation. imageFormatsVersions = map[Format]int{ PNG: 3, // Fix transparency issue with 32 bit images. WEBP: 2, // Fix transparency issue with 32 bit images. } // Increment to mark all processed images as stale. Only use when absolutely needed. // See the finer grained smartCropVersionNumber and imageFormatsVersions. mainImageVersionNumber = 0 ) var anchorPositions = map[string]gift.Anchor{ strings.ToLower("Center"): gift.CenterAnchor, strings.ToLower("TopLeft"): gift.TopLeftAnchor, strings.ToLower("Top"): gift.TopAnchor, strings.ToLower("TopRight"): gift.TopRightAnchor, strings.ToLower("Left"): gift.LeftAnchor, strings.ToLower("Right"): gift.RightAnchor, strings.ToLower("BottomLeft"): gift.BottomLeftAnchor, strings.ToLower("Bottom"): gift.BottomAnchor, strings.ToLower("BottomRight"): gift.BottomRightAnchor, } // These encoding hints are currently only relevant for Webp. var hints = map[string]webpoptions.EncodingPreset{ "picture": webpoptions.EncodingPresetPicture, "photo": webpoptions.EncodingPresetPhoto, "drawing": webpoptions.EncodingPresetDrawing, "icon": webpoptions.EncodingPresetIcon, "text": webpoptions.EncodingPresetText, } var imageFilters = map[string]gift.Resampling{ strings.ToLower("NearestNeighbor"): gift.NearestNeighborResampling, strings.ToLower("Box"): gift.BoxResampling, strings.ToLower("Linear"): gift.LinearResampling, strings.ToLower("Hermite"): hermiteResampling, strings.ToLower("MitchellNetravali"): mitchellNetravaliResampling, strings.ToLower("CatmullRom"): catmullRomResampling, strings.ToLower("BSpline"): bSplineResampling, strings.ToLower("Gaussian"): gaussianResampling, strings.ToLower("Lanczos"): gift.LanczosResampling, strings.ToLower("Hann"): hannResampling, strings.ToLower("Hamming"): hammingResampling, strings.ToLower("Blackman"): blackmanResampling, strings.ToLower("Bartlett"): bartlettResampling, strings.ToLower("Welch"): welchResampling, strings.ToLower("Cosine"): cosineResampling, } func ImageFormatFromExt(ext string) (Format, bool) { f, found := imageFormats[ext] return f, found } func ImageFormatFromMediaSubType(sub string) (Format, bool) { f, found := imageFormatsBySubType[sub] return f, found } const ( defaultJPEGQuality = 75 defaultResampleFilter = "box" defaultBgColor = "ffffff" defaultHint = "photo" ) var defaultImaging = Imaging{ ResampleFilter: defaultResampleFilter, BgColor: defaultBgColor, Hint: defaultHint, Quality: defaultJPEGQuality, } func DecodeConfig(m map[string]interface{}) (ImagingConfig, error) { if m == nil { m = make(map[string]interface{}) } i := ImagingConfig{ Cfg: defaultImaging, CfgHash: helpers.HashString(m), } if err := mapstructure.WeakDecode(m, &i.Cfg); err != nil { return i, err } if err := i.Cfg.init(); err != nil { return i, err } var err error i.BgColor, err = hexStringToColor(i.Cfg.BgColor) if err != nil { return i, err } if i.Cfg.Anchor != "" && i.Cfg.Anchor != smartCropIdentifier { anchor, found := anchorPositions[i.Cfg.Anchor] if !found { return i, errors.Errorf("invalid anchor value %q in imaging config", i.Anchor) } i.Anchor = anchor } else { i.Cfg.Anchor = smartCropIdentifier } filter, found := imageFilters[i.Cfg.ResampleFilter] if !found { return i, fmt.Errorf("%q is not a valid resample filter", filter) } i.ResampleFilter = filter if strings.TrimSpace(i.Cfg.Exif.IncludeFields) == "" && strings.TrimSpace(i.Cfg.Exif.ExcludeFields) == "" { // Don't change this for no good reason. Please don't. i.Cfg.Exif.ExcludeFields = "GPS|Exif|Exposure[M|P|B]|Contrast|Resolution|Sharp|JPEG|Metering|Sensing|Saturation|ColorSpace|Flash|WhiteBalance" } return i, nil } func DecodeImageConfig(action, config string, defaults ImagingConfig, sourceFormat Format) (ImageConfig, error) { var ( c ImageConfig = GetDefaultImageConfig(action, defaults) err error ) c.Action = action if config == "" { return c, errors.New("image config cannot be empty") } parts := strings.Fields(config) for _, part := range parts { part = strings.ToLower(part) if part == smartCropIdentifier { c.AnchorStr = smartCropIdentifier } else if pos, ok := anchorPositions[part]; ok { c.Anchor = pos c.AnchorStr = part } else if filter, ok := imageFilters[part]; ok { c.Filter = filter c.FilterStr = part } else if hint, ok := hints[part]; ok { c.Hint = hint } else if part[0] == '#' { c.BgColorStr = part[1:] c.BgColor, err = hexStringToColor(c.BgColorStr) if err != nil { return c, err } } else if part[0] == 'q' { c.Quality, err = strconv.Atoi(part[1:]) if err != nil { return c, err } if c.Quality < 1 || c.Quality > 100 { return c, errors.New("quality ranges from 1 to 100 inclusive") } c.qualitySetForImage = true } else if part[0] == 'r' { c.Rotate, err = strconv.Atoi(part[1:]) if err != nil { return c, err } } else if strings.Contains(part, "x") { widthHeight := strings.Split(part, "x") if len(widthHeight) <= 2 { first := widthHeight[0] if first != "" { c.Width, err = strconv.Atoi(first) if err != nil { return c, err } } if len(widthHeight) == 2 { second := widthHeight[1] if second != "" { c.Height, err = strconv.Atoi(second) if err != nil { return c, err } } } } else { return c, errors.New("invalid image dimensions") } } else if f, ok := ImageFormatFromExt("." + part); ok { c.TargetFormat = f } } if c.Width == 0 && c.Height == 0 { return c, errors.New("must provide Width or Height") } if c.FilterStr == "" { c.FilterStr = defaults.Cfg.ResampleFilter c.Filter = defaults.ResampleFilter } if c.Hint == 0 { c.Hint = webpoptions.EncodingPresetPhoto } if c.AnchorStr == "" { c.AnchorStr = defaults.Cfg.Anchor c.Anchor = defaults.Anchor } // default to the source format if c.TargetFormat == 0 { c.TargetFormat = sourceFormat } if c.Quality <= 0 && c.TargetFormat.RequiresDefaultQuality() { // We need a quality setting for all JPEGs and WEBPs. c.Quality = defaults.Cfg.Quality } if c.BgColor == nil && c.TargetFormat != sourceFormat { if sourceFormat.SupportsTransparency() && !c.TargetFormat.SupportsTransparency() { c.BgColor = defaults.BgColor c.BgColorStr = defaults.Cfg.BgColor } } return c, nil } // ImageConfig holds configuration to create a new image from an existing one, resize etc. type ImageConfig struct { // This defines the output format of the output image. It defaults to the source format. TargetFormat Format Action string // If set, this will be used as the key in filenames etc. Key string // Quality ranges from 1 to 100 inclusive, higher is better. // This is only relevant for JPEG and WEBP images. // Default is 75. Quality int qualitySetForImage bool // Whether the above is set for this image. // Rotate rotates an image by the given angle counter-clockwise. // The rotation will be performed first. Rotate int // Used to fill any transparency. // When set in site config, it's used when converting to a format that does // not support transparency. // When set per image operation, it's used even for formats that does support // transparency. BgColor color.Color BgColorStr string // Hint about what type of picture this is. Used to optimize encoding // when target is set to webp. Hint webpoptions.EncodingPreset Width int Height int Filter gift.Resampling FilterStr string Anchor gift.Anchor AnchorStr string } func (i ImageConfig) GetKey(format Format) string { if i.Key != "" { return i.Action + "_" + i.Key } k := strconv.Itoa(i.Width) + "x" + strconv.Itoa(i.Height) if i.Action != "" { k += "_" + i.Action } // This slightly odd construct is here to preserve the old image keys. if i.qualitySetForImage || i.TargetFormat.RequiresDefaultQuality() { k += "_q" + strconv.Itoa(i.Quality) } if i.Rotate != 0 { k += "_r" + strconv.Itoa(i.Rotate) } if i.BgColorStr != "" { k += "_bg" + i.BgColorStr } if i.TargetFormat == WEBP { k += "_h" + strconv.Itoa(int(i.Hint)) } anchor := i.AnchorStr if anchor == smartCropIdentifier { anchor = anchor + strconv.Itoa(smartCropVersionNumber) } k += "_" + i.FilterStr if strings.EqualFold(i.Action, "fill") { k += "_" + anchor } if v, ok := imageFormatsVersions[format]; ok { k += "_" + strconv.Itoa(v) } if mainImageVersionNumber > 0 { k += "_" + strconv.Itoa(mainImageVersionNumber) } return k } type ImagingConfig struct { BgColor color.Color Hint webpoptions.EncodingPreset ResampleFilter gift.Resampling Anchor gift.Anchor // Config as provided by the user. Cfg Imaging // Hash of the config map provided by the user. CfgHash string } // Imaging contains default image processing configuration. This will be fetched // from site (or language) config. type Imaging struct { // Default image quality setting (1-100). Only used for JPEG images. Quality int // Resample filter to use in resize operations. ResampleFilter string // Hint about what type of image this is. // Currently only used when encoding to Webp. // Default is "photo". // Valid values are "picture", "photo", "drawing", "icon", or "text". Hint string // The anchor to use in Fill. Default is "smart", i.e. Smart Crop. Anchor string // Default color used in fill operations (e.g. "fff" for white). BgColor string Exif ExifConfig } func (cfg *Imaging) init() error { if cfg.Quality < 0 || cfg.Quality > 100 { return errors.New("image quality must be a number between 1 and 100") } cfg.BgColor = strings.ToLower(strings.TrimPrefix(cfg.BgColor, "#")) cfg.Anchor = strings.ToLower(cfg.Anchor) cfg.ResampleFilter = strings.ToLower(cfg.ResampleFilter) cfg.Hint = strings.ToLower(cfg.Hint) return nil } type ExifConfig struct { // Regexp matching the Exif fields you want from the (massive) set of Exif info // available. As we cache this info to disk, this is for performance and // disk space reasons more than anything. // If you want it all, put ".*" in this config setting. // Note that if neither this or ExcludeFields is set, Hugo will return a small // default set. IncludeFields string // Regexp matching the Exif fields you want to exclude. This may be easier to use // than IncludeFields above, depending on what you want. ExcludeFields string // Hugo extracts the "photo taken" date/time into .Date by default. // Set this to true to turn it off. DisableDate bool // Hugo extracts the "photo taken where" (GPS latitude and longitude) into // .Long and .Lat. Set this to true to turn it off. DisableLatLong bool } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/config_test.go���������������������������������������������������������0000664�0000000�0000000�00000010105�14201470003�0020644�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "fmt" "strings" "testing" qt "github.com/frankban/quicktest" ) func TestDecodeConfig(t *testing.T) { c := qt.New(t) m := map[string]interface{}{ "quality": 42, "resampleFilter": "NearestNeighbor", "anchor": "topLeft", } imagingConfig, err := DecodeConfig(m) c.Assert(err, qt.IsNil) imaging := imagingConfig.Cfg c.Assert(imaging.Quality, qt.Equals, 42) c.Assert(imaging.ResampleFilter, qt.Equals, "nearestneighbor") c.Assert(imaging.Anchor, qt.Equals, "topleft") m = map[string]interface{}{} imagingConfig, err = DecodeConfig(m) c.Assert(err, qt.IsNil) imaging = imagingConfig.Cfg c.Assert(imaging.ResampleFilter, qt.Equals, "box") c.Assert(imaging.Anchor, qt.Equals, "smart") _, err = DecodeConfig(map[string]interface{}{ "quality": 123, }) c.Assert(err, qt.Not(qt.IsNil)) _, err = DecodeConfig(map[string]interface{}{ "resampleFilter": "asdf", }) c.Assert(err, qt.Not(qt.IsNil)) _, err = DecodeConfig(map[string]interface{}{ "anchor": "asdf", }) c.Assert(err, qt.Not(qt.IsNil)) imagingConfig, err = DecodeConfig(map[string]interface{}{ "anchor": "Smart", }) imaging = imagingConfig.Cfg c.Assert(err, qt.IsNil) c.Assert(imaging.Anchor, qt.Equals, "smart") imagingConfig, err = DecodeConfig(map[string]interface{}{ "exif": map[string]interface{}{ "disableLatLong": true, }, }) c.Assert(err, qt.IsNil) imaging = imagingConfig.Cfg c.Assert(imaging.Exif.DisableLatLong, qt.Equals, true) c.Assert(imaging.Exif.ExcludeFields, qt.Equals, "GPS|Exif|Exposure[M|P|B]|Contrast|Resolution|Sharp|JPEG|Metering|Sensing|Saturation|ColorSpace|Flash|WhiteBalance") } func TestDecodeImageConfig(t *testing.T) { for i, this := range []struct { in string expect interface{} }{ {"300x400", newImageConfig(300, 400, 75, 0, "box", "smart", "")}, {"300x400 #fff", newImageConfig(300, 400, 75, 0, "box", "smart", "fff")}, {"100x200 bottomRight", newImageConfig(100, 200, 75, 0, "box", "BottomRight", "")}, {"10x20 topleft Lanczos", newImageConfig(10, 20, 75, 0, "Lanczos", "topleft", "")}, {"linear left 10x r180", newImageConfig(10, 0, 75, 180, "linear", "left", "")}, {"x20 riGht Cosine q95", newImageConfig(0, 20, 95, 0, "cosine", "right", "")}, {"", false}, {"foo", false}, } { cfg, err := DecodeConfig(nil) if err != nil { t.Fatal(err) } result, err := DecodeImageConfig("resize", this.in, cfg, PNG) if b, ok := this.expect.(bool); ok && !b { if err == nil { t.Errorf("[%d] parseImageConfig didn't return an expected error", i) } } else { if err != nil { t.Fatalf("[%d] err: %s", i, err) } if fmt.Sprint(result) != fmt.Sprint(this.expect) { t.Fatalf("[%d] got\n%v\n but expected\n%v", i, result, this.expect) } } } } func newImageConfig(width, height, quality, rotate int, filter, anchor, bgColor string) ImageConfig { var c ImageConfig = GetDefaultImageConfig("resize", ImagingConfig{}) c.TargetFormat = PNG c.Hint = 2 c.Width = width c.Height = height c.Quality = quality c.qualitySetForImage = quality != 75 c.Rotate = rotate c.BgColorStr = bgColor c.BgColor, _ = hexStringToColor(bgColor) if filter != "" { filter = strings.ToLower(filter) if v, ok := imageFilters[filter]; ok { c.Filter = v c.FilterStr = filter } } if anchor != "" { if anchor == smartCropIdentifier { c.AnchorStr = anchor } else { anchor = strings.ToLower(anchor) if v, ok := anchorPositions[anchor]; ok { c.Anchor = v c.AnchorStr = anchor } } } return c } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/exif/������������������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0016747�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/exif/exif.go�����������������������������������������������������������0000664�0000000�0000000�00000012273�14201470003�0020236�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package exif import ( "bytes" "fmt" "io" "math/big" "regexp" "strings" "time" "unicode" "unicode/utf8" "github.com/bep/tmc" _exif "github.com/rwcarlsen/goexif/exif" "github.com/rwcarlsen/goexif/tiff" ) const exifTimeLayout = "2006:01:02 15:04:05" type Exif struct { Lat float64 Long float64 Date time.Time Tags Tags } type Decoder struct { includeFieldsRe *regexp.Regexp excludeFieldsrRe *regexp.Regexp noDate bool noLatLong bool } func IncludeFields(expression string) func(*Decoder) error { return func(d *Decoder) error { re, err := compileRegexp(expression) if err != nil { return err } d.includeFieldsRe = re return nil } } func ExcludeFields(expression string) func(*Decoder) error { return func(d *Decoder) error { re, err := compileRegexp(expression) if err != nil { return err } d.excludeFieldsrRe = re return nil } } func WithLatLongDisabled(disabled bool) func(*Decoder) error { return func(d *Decoder) error { d.noLatLong = disabled return nil } } func WithDateDisabled(disabled bool) func(*Decoder) error { return func(d *Decoder) error { d.noDate = disabled return nil } } func compileRegexp(expression string) (*regexp.Regexp, error) { expression = strings.TrimSpace(expression) if expression == "" { return nil, nil } if !strings.HasPrefix(expression, "(") { // Make it case insensitive expression = "(?i)" + expression } return regexp.Compile(expression) } func NewDecoder(options ...func(*Decoder) error) (*Decoder, error) { d := &Decoder{} for _, opt := range options { if err := opt(d); err != nil { return nil, err } } return d, nil } func (d *Decoder) Decode(r io.Reader) (ex *Exif, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("Exif failed: %v", r) } }() var x *_exif.Exif x, err = _exif.Decode(r) if err != nil { if err.Error() == "EOF" { // Found no Exif return nil, nil } return } var tm time.Time var lat, long float64 if !d.noDate { tm, _ = x.DateTime() } if !d.noLatLong { lat, long, _ = x.LatLong() } walker := &exifWalker{x: x, vals: make(map[string]interface{}), includeMatcher: d.includeFieldsRe, excludeMatcher: d.excludeFieldsrRe} if err = x.Walk(walker); err != nil { return } ex = &Exif{Lat: lat, Long: long, Date: tm, Tags: walker.vals} return } func decodeTag(x *_exif.Exif, f _exif.FieldName, t *tiff.Tag) (interface{}, error) { switch t.Format() { case tiff.StringVal, tiff.UndefVal: s := nullString(t.Val) if strings.Contains(string(f), "DateTime") { if d, err := tryParseDate(x, s); err == nil { return d, nil } } return s, nil case tiff.OtherVal: return "unknown", nil } var rv []interface{} for i := 0; i < int(t.Count); i++ { switch t.Format() { case tiff.RatVal: n, d, _ := t.Rat2(i) rat := big.NewRat(n, d) if n == 1 { rv = append(rv, rat) } else { f, _ := rat.Float64() rv = append(rv, f) } case tiff.FloatVal: v, _ := t.Float(i) rv = append(rv, v) case tiff.IntVal: v, _ := t.Int(i) rv = append(rv, v) } } if t.Count == 1 { if len(rv) == 1 { return rv[0], nil } } return rv, nil } // Code borrowed from exif.DateTime and adjusted. func tryParseDate(x *_exif.Exif, s string) (time.Time, error) { dateStr := strings.TrimRight(s, "\x00") // TODO(bep): look for timezone offset, GPS time, etc. timeZone := time.Local if tz, _ := x.TimeZone(); tz != nil { timeZone = tz } return time.ParseInLocation(exifTimeLayout, dateStr, timeZone) } type exifWalker struct { x *_exif.Exif vals map[string]interface{} includeMatcher *regexp.Regexp excludeMatcher *regexp.Regexp } func (e *exifWalker) Walk(f _exif.FieldName, tag *tiff.Tag) error { name := string(f) if e.excludeMatcher != nil && e.excludeMatcher.MatchString(name) { return nil } if e.includeMatcher != nil && !e.includeMatcher.MatchString(name) { return nil } val, err := decodeTag(e.x, f, tag) if err != nil { return err } e.vals[name] = val return nil } func nullString(in []byte) string { var rv bytes.Buffer for len(in) > 0 { r, size := utf8.DecodeRune(in) if unicode.IsGraphic(r) { rv.WriteRune(r) } in = in[size:] } return rv.String() } var tcodec *tmc.Codec func init() { var err error tcodec, err = tmc.New() if err != nil { panic(err) } } type Tags map[string]interface{} func (v *Tags) UnmarshalJSON(b []byte) error { vv := make(map[string]interface{}) if err := tcodec.Unmarshal(b, &vv); err != nil { return err } *v = vv return nil } func (v Tags) MarshalJSON() ([]byte, error) { return tcodec.Marshal(v) } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/exif/exif_test.go������������������������������������������������������0000664�0000000�0000000�00000006360�14201470003�0021275�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package exif import ( "encoding/json" "math/big" "os" "path/filepath" "testing" "time" "github.com/gohugoio/hugo/htesting/hqt" "github.com/google/go-cmp/cmp" qt "github.com/frankban/quicktest" ) func TestExif(t *testing.T) { c := qt.New(t) f, err := os.Open(filepath.FromSlash("../../testdata/sunset.jpg")) c.Assert(err, qt.IsNil) defer f.Close() d, err := NewDecoder(IncludeFields("Lens|Date")) c.Assert(err, qt.IsNil) x, err := d.Decode(f) c.Assert(err, qt.IsNil) c.Assert(x.Date.Format("2006-01-02"), qt.Equals, "2017-10-27") // Malaga: https://goo.gl/taazZy c.Assert(x.Lat, qt.Equals, float64(36.59744166666667)) c.Assert(x.Long, qt.Equals, float64(-4.50846)) v, found := x.Tags["LensModel"] c.Assert(found, qt.Equals, true) lensModel, ok := v.(string) c.Assert(ok, qt.Equals, true) c.Assert(lensModel, qt.Equals, "smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM") v, found = x.Tags["DateTime"] c.Assert(found, qt.Equals, true) c.Assert(v, hqt.IsSameType, time.Time{}) // Verify that it survives a round-trip to JSON and back. data, err := json.Marshal(x) c.Assert(err, qt.IsNil) x2 := &Exif{} err = json.Unmarshal(data, x2) c.Assert(x2, eq, x) } func TestExifPNG(t *testing.T) { c := qt.New(t) f, err := os.Open(filepath.FromSlash("../../testdata/gohugoio.png")) c.Assert(err, qt.IsNil) defer f.Close() d, err := NewDecoder() c.Assert(err, qt.IsNil) _, err = d.Decode(f) c.Assert(err, qt.Not(qt.IsNil)) } func TestIssue8079(t *testing.T) { c := qt.New(t) f, err := os.Open(filepath.FromSlash("../../testdata/iss8079.jpg")) c.Assert(err, qt.IsNil) defer f.Close() d, err := NewDecoder() c.Assert(err, qt.IsNil) x, err := d.Decode(f) c.Assert(err, qt.IsNil) c.Assert(x.Tags["ImageDescription"], qt.Equals, "Città del Vaticano #nanoblock #vatican #vaticancity") } func TestNullString(t *testing.T) { c := qt.New(t) for _, test := range []struct { in string expect string }{ {"foo", "foo"}, {"\x20", "\x20"}, {"\xc4\x81", "\xc4\x81"}, // \u0101 {"\u0160", "\u0160"}, // non-breaking space } { res := nullString([]byte(test.in)) c.Assert(res, qt.Equals, test.expect) } } func BenchmarkDecodeExif(b *testing.B) { c := qt.New(b) f, err := os.Open(filepath.FromSlash("../../testdata/sunset.jpg")) c.Assert(err, qt.IsNil) defer f.Close() d, err := NewDecoder() c.Assert(err, qt.IsNil) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = d.Decode(f) c.Assert(err, qt.IsNil) f.Seek(0, 0) } } var eq = qt.CmpEquals( cmp.Comparer( func(v1, v2 *big.Rat) bool { return v1.RatString() == v2.RatString() }, ), cmp.Comparer(func(v1, v2 time.Time) bool { return v1.Unix() == v2.Unix() }), ) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/filters.go�������������������������������������������������������������0000664�0000000�0000000�00000016701�14201470003�0020020�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package images provides template functions for manipulating images. package images import ( "fmt" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/resources/resource" "github.com/disintegration/gift" "github.com/spf13/cast" ) // Increment for re-generation of images using these filters. const filterAPIVersion = 0 type Filters struct { } // Overlay creates a filter that overlays src at position x y. func (*Filters) Overlay(src ImageSource, x, y interface{}) gift.Filter { return filter{ Options: newFilterOpts(src.Key(), x, y), Filter: overlayFilter{src: src, x: cast.ToInt(x), y: cast.ToInt(y)}, } } // Text creates a filter that draws text with the given options. func (*Filters) Text(text string, options ...interface{}) gift.Filter { tf := textFilter{ text: text, color: "#ffffff", size: 20, x: 10, y: 10, linespacing: 2, } var opt maps.Params if len(options) > 0 { opt = maps.MustToParamsAndPrepare(options[0]) for option, v := range opt { switch option { case "color": tf.color = cast.ToString(v) case "size": tf.size = cast.ToFloat64(v) case "x": tf.x = cast.ToInt(v) case "y": tf.y = cast.ToInt(v) case "linespacing": tf.linespacing = cast.ToInt(v) case "font": if err, ok := v.(error); ok { panic(fmt.Sprintf("invalid font source: %s", err)) } fontSource, ok1 := v.(hugio.ReadSeekCloserProvider) identifier, ok2 := v.(resource.Identifier) if !(ok1 && ok2) { panic(fmt.Sprintf("invalid text font source: %T", v)) } tf.fontSource = fontSource // The input value isn't hashable and will not make a stable key. // Replace it with a string in the map used as basis for the // hash string. opt["font"] = identifier.Key() } } } return filter{ Options: newFilterOpts(text, opt), Filter: tf, } } // Brightness creates a filter that changes the brightness of an image. // The percentage parameter must be in range (-100, 100). func (*Filters) Brightness(percentage interface{}) gift.Filter { return filter{ Options: newFilterOpts(percentage), Filter: gift.Brightness(cast.ToFloat32(percentage)), } } // ColorBalance creates a filter that changes the color balance of an image. // The percentage parameters for each color channel (red, green, blue) must be in range (-100, 500). func (*Filters) ColorBalance(percentageRed, percentageGreen, percentageBlue interface{}) gift.Filter { return filter{ Options: newFilterOpts(percentageRed, percentageGreen, percentageBlue), Filter: gift.ColorBalance(cast.ToFloat32(percentageRed), cast.ToFloat32(percentageGreen), cast.ToFloat32(percentageBlue)), } } // Colorize creates a filter that produces a colorized version of an image. // The hue parameter is the angle on the color wheel, typically in range (0, 360). // The saturation parameter must be in range (0, 100). // The percentage parameter specifies the strength of the effect, it must be in range (0, 100). func (*Filters) Colorize(hue, saturation, percentage interface{}) gift.Filter { return filter{ Options: newFilterOpts(hue, saturation, percentage), Filter: gift.Colorize(cast.ToFloat32(hue), cast.ToFloat32(saturation), cast.ToFloat32(percentage)), } } // Contrast creates a filter that changes the contrast of an image. // The percentage parameter must be in range (-100, 100). func (*Filters) Contrast(percentage interface{}) gift.Filter { return filter{ Options: newFilterOpts(percentage), Filter: gift.Contrast(cast.ToFloat32(percentage)), } } // Gamma creates a filter that performs a gamma correction on an image. // The gamma parameter must be positive. Gamma = 1 gives the original image. // Gamma less than 1 darkens the image and gamma greater than 1 lightens it. func (*Filters) Gamma(gamma interface{}) gift.Filter { return filter{ Options: newFilterOpts(gamma), Filter: gift.Gamma(cast.ToFloat32(gamma)), } } // GaussianBlur creates a filter that applies a gaussian blur to an image. func (*Filters) GaussianBlur(sigma interface{}) gift.Filter { return filter{ Options: newFilterOpts(sigma), Filter: gift.GaussianBlur(cast.ToFloat32(sigma)), } } // Grayscale creates a filter that produces a grayscale version of an image. func (*Filters) Grayscale() gift.Filter { return filter{ Filter: gift.Grayscale(), } } // Hue creates a filter that rotates the hue of an image. // The hue angle shift is typically in range -180 to 180. func (*Filters) Hue(shift interface{}) gift.Filter { return filter{ Options: newFilterOpts(shift), Filter: gift.Hue(cast.ToFloat32(shift)), } } // Invert creates a filter that negates the colors of an image. func (*Filters) Invert() gift.Filter { return filter{ Filter: gift.Invert(), } } // Pixelate creates a filter that applies a pixelation effect to an image. func (*Filters) Pixelate(size interface{}) gift.Filter { return filter{ Options: newFilterOpts(size), Filter: gift.Pixelate(cast.ToInt(size)), } } // Saturation creates a filter that changes the saturation of an image. func (*Filters) Saturation(percentage interface{}) gift.Filter { return filter{ Options: newFilterOpts(percentage), Filter: gift.Saturation(cast.ToFloat32(percentage)), } } // Sepia creates a filter that produces a sepia-toned version of an image. func (*Filters) Sepia(percentage interface{}) gift.Filter { return filter{ Options: newFilterOpts(percentage), Filter: gift.Sepia(cast.ToFloat32(percentage)), } } // Sigmoid creates a filter that changes the contrast of an image using a sigmoidal function and returns the adjusted image. // It's a non-linear contrast change useful for photo adjustments as it preserves highlight and shadow detail. func (*Filters) Sigmoid(midpoint, factor interface{}) gift.Filter { return filter{ Options: newFilterOpts(midpoint, factor), Filter: gift.Sigmoid(cast.ToFloat32(midpoint), cast.ToFloat32(factor)), } } // UnsharpMask creates a filter that sharpens an image. // The sigma parameter is used in a gaussian function and affects the radius of effect. // Sigma must be positive. Sharpen radius roughly equals 3 * sigma. // The amount parameter controls how much darker and how much lighter the edge borders become. Typically between 0.5 and 1.5. // The threshold parameter controls the minimum brightness change that will be sharpened. Typically between 0 and 0.05. func (*Filters) UnsharpMask(sigma, amount, threshold interface{}) gift.Filter { return filter{ Options: newFilterOpts(sigma, amount, threshold), Filter: gift.UnsharpMask(cast.ToFloat32(sigma), cast.ToFloat32(amount), cast.ToFloat32(threshold)), } } type filter struct { Options filterOpts gift.Filter } // For cache-busting. type filterOpts struct { Version int Vals interface{} } func newFilterOpts(vals ...interface{}) filterOpts { return filterOpts{ Version: filterAPIVersion, Vals: vals, } } ���������������������������������������������������������������hugo-0.92.2/resources/images/filters_test.go��������������������������������������������������������0000664�0000000�0000000�00000002214�14201470003�0021051�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "testing" "github.com/gohugoio/hugo/helpers" qt "github.com/frankban/quicktest" ) func TestFilterHash(t *testing.T) { c := qt.New(t) f := &Filters{} c.Assert(helpers.HashString(f.Grayscale()), qt.Equals, helpers.HashString(f.Grayscale())) c.Assert(helpers.HashString(f.Grayscale()), qt.Not(qt.Equals), helpers.HashString(f.Invert())) c.Assert(helpers.HashString(f.Gamma(32)), qt.Not(qt.Equals), helpers.HashString(f.Gamma(33))) c.Assert(helpers.HashString(f.Gamma(32)), qt.Equals, helpers.HashString(f.Gamma(32))) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/image.go���������������������������������������������������������������0000664�0000000�0000000�00000017767�14201470003�0017447�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "fmt" "image" "image/color" "image/draw" "image/gif" "image/jpeg" "image/png" "io" "sync" "github.com/bep/gowebp/libwebp/webpoptions" "github.com/gohugoio/hugo/resources/images/webp" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/images/exif" "github.com/disintegration/gift" "golang.org/x/image/bmp" "golang.org/x/image/tiff" "github.com/gohugoio/hugo/common/hugio" "github.com/pkg/errors" ) func NewImage(f Format, proc *ImageProcessor, img image.Image, s Spec) *Image { if img != nil { return &Image{ Format: f, Proc: proc, Spec: s, imageConfig: &imageConfig{ config: imageConfigFromImage(img), configLoaded: true, }, } } return &Image{Format: f, Proc: proc, Spec: s, imageConfig: &imageConfig{}} } type Image struct { Format Format Proc *ImageProcessor Spec Spec *imageConfig } func (i *Image) EncodeTo(conf ImageConfig, img image.Image, w io.Writer) error { switch conf.TargetFormat { case JPEG: var rgba *image.RGBA quality := conf.Quality if nrgba, ok := img.(*image.NRGBA); ok { if nrgba.Opaque() { rgba = &image.RGBA{ Pix: nrgba.Pix, Stride: nrgba.Stride, Rect: nrgba.Rect, } } } if rgba != nil { return jpeg.Encode(w, rgba, &jpeg.Options{Quality: quality}) } return jpeg.Encode(w, img, &jpeg.Options{Quality: quality}) case PNG: encoder := png.Encoder{CompressionLevel: png.DefaultCompression} return encoder.Encode(w, img) case GIF: return gif.Encode(w, img, &gif.Options{ NumColors: 256, }) case TIFF: return tiff.Encode(w, img, &tiff.Options{Compression: tiff.Deflate, Predictor: true}) case BMP: return bmp.Encode(w, img) case WEBP: return webp.Encode( w, img, webpoptions.EncodingOptions{ Quality: conf.Quality, EncodingPreset: webpoptions.EncodingPreset(conf.Hint), UseSharpYuv: true, }, ) default: return errors.New("format not supported") } } // Height returns i's height. func (i *Image) Height() int { i.initConfig() return i.config.Height } // Width returns i's width. func (i *Image) Width() int { i.initConfig() return i.config.Width } func (i Image) WithImage(img image.Image) *Image { i.Spec = nil i.imageConfig = &imageConfig{ config: imageConfigFromImage(img), configLoaded: true, } return &i } func (i Image) WithSpec(s Spec) *Image { i.Spec = s i.imageConfig = &imageConfig{} return &i } // InitConfig reads the image config from the given reader. func (i *Image) InitConfig(r io.Reader) error { var err error i.configInit.Do(func() { i.config, _, err = image.DecodeConfig(r) }) return err } func (i *Image) initConfig() error { var err error i.configInit.Do(func() { if i.configLoaded { return } var f hugio.ReadSeekCloser f, err = i.Spec.ReadSeekCloser() if err != nil { return } defer f.Close() i.config, _, err = image.DecodeConfig(f) }) if err != nil { return errors.Wrap(err, "failed to load image config") } return nil } func NewImageProcessor(cfg ImagingConfig) (*ImageProcessor, error) { e := cfg.Cfg.Exif exifDecoder, err := exif.NewDecoder( exif.WithDateDisabled(e.DisableDate), exif.WithLatLongDisabled(e.DisableLatLong), exif.ExcludeFields(e.ExcludeFields), exif.IncludeFields(e.IncludeFields), ) if err != nil { return nil, err } return &ImageProcessor{ Cfg: cfg, exifDecoder: exifDecoder, }, nil } type ImageProcessor struct { Cfg ImagingConfig exifDecoder *exif.Decoder } func (p *ImageProcessor) DecodeExif(r io.Reader) (*exif.Exif, error) { return p.exifDecoder.Decode(r) } func (p *ImageProcessor) ApplyFiltersFromConfig(src image.Image, conf ImageConfig) (image.Image, error) { var filters []gift.Filter if conf.Rotate != 0 { // Apply any rotation before any resize. filters = append(filters, gift.Rotate(float32(conf.Rotate), color.Transparent, gift.NearestNeighborInterpolation)) } switch conf.Action { case "resize": filters = append(filters, gift.Resize(conf.Width, conf.Height, conf.Filter)) case "fill": if conf.AnchorStr == smartCropIdentifier { bounds, err := p.smartCrop(src, conf.Width, conf.Height, conf.Filter) if err != nil { return nil, err } // First crop it, then resize it. filters = append(filters, gift.Crop(bounds)) filters = append(filters, gift.Resize(conf.Width, conf.Height, conf.Filter)) } else { filters = append(filters, gift.ResizeToFill(conf.Width, conf.Height, conf.Filter, conf.Anchor)) } case "fit": filters = append(filters, gift.ResizeToFit(conf.Width, conf.Height, conf.Filter)) default: return nil, errors.Errorf("unsupported action: %q", conf.Action) } img, err := p.Filter(src, filters...) if err != nil { return nil, err } return img, nil } func (p *ImageProcessor) Filter(src image.Image, filters ...gift.Filter) (image.Image, error) { g := gift.New(filters...) bounds := g.Bounds(src.Bounds()) var dst draw.Image switch src.(type) { case *image.RGBA: dst = image.NewRGBA(bounds) case *image.NRGBA: dst = image.NewNRGBA(bounds) case *image.Gray: dst = image.NewGray(bounds) default: dst = image.NewNRGBA(bounds) } g.Draw(dst, src) return dst, nil } func GetDefaultImageConfig(action string, defaults ImagingConfig) ImageConfig { return ImageConfig{ Action: action, Hint: defaults.Hint, Quality: defaults.Cfg.Quality, } } type Spec interface { // Loads the image source. ReadSeekCloser() (hugio.ReadSeekCloser, error) } // Format is an image file format. type Format int const ( JPEG Format = iota + 1 PNG GIF TIFF BMP WEBP ) // RequiresDefaultQuality returns if the default quality needs to be applied to // images of this format. func (f Format) RequiresDefaultQuality() bool { return f == JPEG || f == WEBP } // SupportsTransparency reports whether it supports transparency in any form. func (f Format) SupportsTransparency() bool { return f != JPEG } // DefaultExtension returns the default file extension of this format, starting with a dot. // For example: .jpg for JPEG func (f Format) DefaultExtension() string { return f.MediaType().FirstSuffix.FullSuffix } // MediaType returns the media type of this image, e.g. image/jpeg for JPEG func (f Format) MediaType() media.Type { switch f { case JPEG: return media.JPEGType case PNG: return media.PNGType case GIF: return media.GIFType case TIFF: return media.TIFFType case BMP: return media.BMPType case WEBP: return media.WEBPType default: panic(fmt.Sprintf("%d is not a valid image format", f)) } } type imageConfig struct { config image.Config configInit sync.Once configLoaded bool } func imageConfigFromImage(img image.Image) image.Config { b := img.Bounds() return image.Config{Width: b.Max.X, Height: b.Max.Y} } func ToFilters(in interface{}) []gift.Filter { switch v := in.(type) { case []gift.Filter: return v case []filter: vv := make([]gift.Filter, len(v)) for i, f := range v { vv[i] = f } return vv case gift.Filter: return []gift.Filter{v} default: panic(fmt.Sprintf("%T is not an image filter", in)) } } // IsOpaque returns false if the image has alpha channel and there is at least 1 // pixel that is not (fully) opaque. func IsOpaque(img image.Image) bool { if oim, ok := img.(interface { Opaque() bool }); ok { return oim.Opaque() } return false } // ImageSource identifies and decodes an image. type ImageSource interface { DecodeImage() (image.Image, error) Key() string } ���������hugo-0.92.2/resources/images/overlay.go�������������������������������������������������������������0000664�0000000�0000000�00000002336�14201470003�0020030�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "fmt" "image" "image/draw" "github.com/disintegration/gift" ) var _ gift.Filter = (*overlayFilter)(nil) type overlayFilter struct { src ImageSource x, y int } func (f overlayFilter) Draw(dst draw.Image, src image.Image, options *gift.Options) { overlaySrc, err := f.src.DecodeImage() if err != nil { panic(fmt.Sprintf("failed to decode image: %s", err)) } gift.New().Draw(dst, src) gift.New().DrawAt(dst, overlaySrc, image.Pt(f.x, f.y), gift.OverOperator) } func (f overlayFilter) Bounds(srcBounds image.Rectangle) image.Rectangle { return image.Rect(0, 0, srcBounds.Dx(), srcBounds.Dy()) } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/resampling.go����������������������������������������������������������0000664�0000000�0000000�00000011411�14201470003�0020502�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import "math" // We moved from imaging to the gift package for image processing at some point. // That package had more, but also less resampling filters. So we add the missing // ones here. They are fairly exotic, but someone may use them, so keep them here // for now. // // The filters below are ported from https://github.com/disintegration/imaging/blob/9aab30e6aa535fe3337b489b76759ef97dfaf362/resize.go#L369 // MIT License. var ( // Hermite cubic spline filter (BC-spline; B=0; C=0). hermiteResampling = resamp{ name: "Hermite", support: 1.0, kernel: func(x float32) float32 { x = absf32(x) if x < 1.0 { return bcspline(x, 0.0, 0.0) } return 0 }, } // Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3). mitchellNetravaliResampling = resamp{ name: "MitchellNetravali", support: 2.0, kernel: func(x float32) float32 { x = absf32(x) if x < 2.0 { return bcspline(x, 1.0/3.0, 1.0/3.0) } return 0 }, } // Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5). catmullRomResampling = resamp{ name: "CatmullRomResampling", support: 2.0, kernel: func(x float32) float32 { x = absf32(x) if x < 2.0 { return bcspline(x, 0.0, 0.5) } return 0 }, } // BSpline is a smooth cubic filter (BC-spline; B=1; C=0). bSplineResampling = resamp{ name: "BSplineResampling", support: 2.0, kernel: func(x float32) float32 { x = absf32(x) if x < 2.0 { return bcspline(x, 1.0, 0.0) } return 0 }, } // Gaussian blurring filter. gaussianResampling = resamp{ name: "GaussianResampling", support: 2.0, kernel: func(x float32) float32 { x = absf32(x) if x < 2.0 { return float32(math.Exp(float64(-2 * x * x))) } return 0 }, } // Hann-windowed sinc filter (3 lobes). hannResampling = resamp{ name: "HannResampling", support: 3.0, kernel: func(x float32) float32 { x = absf32(x) if x < 3.0 { return sinc(x) * float32(0.5+0.5*math.Cos(math.Pi*float64(x)/3.0)) } return 0 }, } hammingResampling = resamp{ name: "HammingResampling", support: 3.0, kernel: func(x float32) float32 { x = absf32(x) if x < 3.0 { return sinc(x) * float32(0.54+0.46*math.Cos(math.Pi*float64(x)/3.0)) } return 0 }, } // Blackman-windowed sinc filter (3 lobes). blackmanResampling = resamp{ name: "BlackmanResampling", support: 3.0, kernel: func(x float32) float32 { x = absf32(x) if x < 3.0 { return sinc(x) * float32(0.42-0.5*math.Cos(math.Pi*float64(x)/3.0+math.Pi)+0.08*math.Cos(2.0*math.Pi*float64(x)/3.0)) } return 0 }, } bartlettResampling = resamp{ name: "BartlettResampling", support: 3.0, kernel: func(x float32) float32 { x = absf32(x) if x < 3.0 { return sinc(x) * (3.0 - x) / 3.0 } return 0 }, } // Welch-windowed sinc filter (parabolic window, 3 lobes). welchResampling = resamp{ name: "WelchResampling", support: 3.0, kernel: func(x float32) float32 { x = absf32(x) if x < 3.0 { return sinc(x) * (1.0 - (x * x / 9.0)) } return 0 }, } // Cosine-windowed sinc filter (3 lobes). cosineResampling = resamp{ name: "CosineResampling", support: 3.0, kernel: func(x float32) float32 { x = absf32(x) if x < 3.0 { return sinc(x) * float32(math.Cos((math.Pi/2.0)*(float64(x)/3.0))) } return 0 }, } ) // The following code is borrowed from https://raw.githubusercontent.com/disintegration/gift/master/resize.go // MIT licensed. type resamp struct { name string support float32 kernel func(float32) float32 } func (r resamp) String() string { return r.name } func (r resamp) Support() float32 { return r.support } func (r resamp) Kernel(x float32) float32 { return r.kernel(x) } func bcspline(x, b, c float32) float32 { if x < 0 { x = -x } if x < 1 { return ((12-9*b-6*c)*x*x*x + (-18+12*b+6*c)*x*x + (6 - 2*b)) / 6 } if x < 2 { return ((-b-6*c)*x*x*x + (6*b+30*c)*x*x + (-12*b-48*c)*x + (8*b + 24*c)) / 6 } return 0 } func absf32(x float32) float32 { if x < 0 { return -x } return x } func sinc(x float32) float32 { if x == 0 { return 1 } return float32(math.Sin(math.Pi*float64(x)) / (math.Pi * float64(x))) } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/smartcrop.go�����������������������������������������������������������0000664�0000000�0000000�00000005572�14201470003�0020366�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "image" "math" "github.com/disintegration/gift" "github.com/muesli/smartcrop" ) const ( // Do not change. smartCropIdentifier = "smart" // This is just a increment, starting on 1. If Smart Crop improves its cropping, we // need a way to trigger a re-generation of the crops in the wild, so increment this. smartCropVersionNumber = 1 ) func (p *ImageProcessor) newSmartCropAnalyzer(filter gift.Resampling) smartcrop.Analyzer { return smartcrop.NewAnalyzer(imagingResizer{p: p, filter: filter}) } // Needed by smartcrop type imagingResizer struct { p *ImageProcessor filter gift.Resampling } func (r imagingResizer) Resize(img image.Image, width, height uint) image.Image { // See https://github.com/gohugoio/hugo/issues/7955#issuecomment-861710681 scaleX, scaleY := calcFactorsNfnt(width, height, float64(img.Bounds().Dx()), float64(img.Bounds().Dy())) if width == 0 { width = uint(math.Ceil(float64(img.Bounds().Dx()) / scaleX)) } if height == 0 { height = uint(math.Ceil(float64(img.Bounds().Dy()) / scaleY)) } result, _ := r.p.Filter(img, gift.Resize(int(width), int(height), r.filter)) return result } func (p *ImageProcessor) smartCrop(img image.Image, width, height int, filter gift.Resampling) (image.Rectangle, error) { if width <= 0 || height <= 0 { return image.Rectangle{}, nil } srcBounds := img.Bounds() srcW := srcBounds.Dx() srcH := srcBounds.Dy() if srcW <= 0 || srcH <= 0 { return image.Rectangle{}, nil } if srcW == width && srcH == height { return srcBounds, nil } smart := p.newSmartCropAnalyzer(filter) rect, err := smart.FindBestCrop(img, width, height) if err != nil { return image.Rectangle{}, err } return img.Bounds().Intersect(rect), nil } // Calculates scaling factors using old and new image dimensions. // Code borrowed from https://github.com/nfnt/resize/blob/83c6a9932646f83e3267f353373d47347b6036b2/resize.go#L593 func calcFactorsNfnt(width, height uint, oldWidth, oldHeight float64) (scaleX, scaleY float64) { if width == 0 { if height == 0 { scaleX = 1.0 scaleY = 1.0 } else { scaleY = oldHeight / float64(height) scaleX = scaleY } } else { scaleX = oldWidth / float64(width) if height == 0 { scaleY = scaleX } else { scaleY = oldHeight / float64(height) } } return } ��������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/text.go����������������������������������������������������������������0000664�0000000�0000000�00000004731�14201470003�0017334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "image" "image/draw" "io" "strings" "github.com/disintegration/gift" "github.com/gohugoio/hugo/common/hugio" "golang.org/x/image/font" "golang.org/x/image/font/gofont/goregular" "golang.org/x/image/font/opentype" "golang.org/x/image/math/fixed" ) var _ gift.Filter = (*textFilter)(nil) type textFilter struct { text, color string x, y int size float64 linespacing int fontSource hugio.ReadSeekCloserProvider } func (f textFilter) Draw(dst draw.Image, src image.Image, options *gift.Options) { color, err := hexStringToColor(f.color) if err != nil { panic(err) } // Load and parse font ttf := goregular.TTF if f.fontSource != nil { rs, err := f.fontSource.ReadSeekCloser() if err != nil { panic(err) } defer rs.Close() ttf, err = io.ReadAll(rs) if err != nil { panic(err) } } otf, err := opentype.Parse(ttf) if err != nil { panic(err) } // Set font options face, err := opentype.NewFace(otf, &opentype.FaceOptions{ Size: f.size, DPI: 72, Hinting: font.HintingNone, }) if err != nil { panic(err) } d := font.Drawer{ Dst: dst, Src: image.NewUniform(color), Face: face, } gift.New().Draw(dst, src) // Draw text, consider and include linebreaks maxWidth := dst.Bounds().Dx() - 20 fontHeight := face.Metrics().Ascent.Ceil() // Correct y position based on font and size f.y = f.y + fontHeight // Start position y := f.y d.Dot = fixed.P(f.x, f.y) // Draw text and break line at max width parts := strings.Fields(f.text) for _, str := range parts { strWith := font.MeasureString(face, str) if (d.Dot.X.Ceil() + strWith.Ceil()) >= maxWidth { y = y + fontHeight + f.linespacing d.Dot = fixed.P(f.x, y) } d.DrawString(str + " ") } } func (f textFilter) Bounds(srcBounds image.Rectangle) image.Rectangle { return image.Rect(0, 0, srcBounds.Dx(), srcBounds.Dy()) } ���������������������������������������hugo-0.92.2/resources/images/webp/������������������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0016751�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/webp/webp.go�����������������������������������������������������������0000664�0000000�0000000�00000002027�14201470003�0020236�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build extended package webp import ( "image" "io" "github.com/bep/gowebp/libwebp" "github.com/bep/gowebp/libwebp/webpoptions" ) // Encode writes the Image m to w in Webp format with the given // options. func Encode(w io.Writer, m image.Image, o webpoptions.EncodingOptions) error { return libwebp.Encode(w, m, o) } // Supports returns whether webp encoding is supported in this build. func Supports() bool { return true } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/images/webp/webp_notavailable.go����������������������������������������������0000664�0000000�0000000�00000002024�14201470003�0022754�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build !extended package webp import ( "image" "io" "github.com/gohugoio/hugo/common/herrors" "github.com/bep/gowebp/libwebp/webpoptions" ) // Encode is only available in the extended version. func Encode(w io.Writer, m image.Image, o webpoptions.EncodingOptions) error { return herrors.ErrFeatureNotAvailable } // Supports returns whether webp encoding is supported in this build. func Supports() bool { return false } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/internal/���������������������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0016363�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/internal/key.go���������������������������������������������������������������0000664�0000000�0000000�00000003326�14201470003�0017506�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package internal import "github.com/gohugoio/hugo/helpers" // ResourceTransformationKey are provided by the different transformation implementations. // It identifies the transformation (name) and its configuration (elements). // We combine this in a chain with the rest of the transformations // with the target filename and a content hash of the origin to use as cache key. type ResourceTransformationKey struct { Name string elements []interface{} } // NewResourceTransformationKey creates a new ResourceTransformationKey from the transformation // name and elements. We will create a 64 bit FNV hash from the elements, which when combined // with the other key elements should be unique for all practical applications. func NewResourceTransformationKey(name string, elements ...interface{}) ResourceTransformationKey { return ResourceTransformationKey{Name: name, elements: elements} } // Value returns the Key as a string. // Do not change this without good reasons. func (k ResourceTransformationKey) Value() string { if len(k.elements) == 0 { return k.Name } return k.Name + "_" + helpers.HashString(k.elements...) } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/internal/key_test.go����������������������������������������������������������0000664�0000000�0000000�00000002106�14201470003�0020540�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package internal import ( "testing" qt "github.com/frankban/quicktest" ) type testStruct struct { Name string V1 int64 V2 int32 V3 int V4 uint64 } func TestResourceTransformationKey(t *testing.T) { // We really need this key to be portable across OSes. key := NewResourceTransformationKey("testing", testStruct{Name: "test", V1: int64(10), V2: int32(20), V3: 30, V4: uint64(40)}) c := qt.New(t) c.Assert(key.Value(), qt.Equals, "testing_518996646957295636") } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/jsconfig/���������������������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0016351�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/jsconfig/jsconfig.go����������������������������������������������������������0000664�0000000�0000000�00000004327�14201470003�0020510�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jsconfig import ( "path/filepath" "sort" "sync" ) // Builder builds a jsconfig.json file that, currently, is used only to assist // intellinsense in editors. type Builder struct { sourceRootsMu sync.RWMutex sourceRoots map[string]bool } // NewBuilder creates a new Builder. func NewBuilder() *Builder { return &Builder{sourceRoots: make(map[string]bool)} } // Build builds a new Config with paths relative to dir. // This method is thread safe. func (b *Builder) Build(dir string) *Config { b.sourceRootsMu.RLock() defer b.sourceRootsMu.RUnlock() if len(b.sourceRoots) == 0 { return nil } conf := newJSConfig() var roots []string for root := range b.sourceRoots { rel, err := filepath.Rel(dir, filepath.Join(root, "*")) if err == nil { roots = append(roots, rel) } } sort.Strings(roots) conf.CompilerOptions.Paths["*"] = roots return conf } // AddSourceRoot adds a new source root. // This method is thread safe. func (b *Builder) AddSourceRoot(root string) { b.sourceRootsMu.RLock() found := b.sourceRoots[root] b.sourceRootsMu.RUnlock() if found { return } b.sourceRootsMu.Lock() b.sourceRoots[root] = true b.sourceRootsMu.Unlock() } // CompilerOptions holds compilerOptions for jsonconfig.json. type CompilerOptions struct { BaseURL string `json:"baseUrl"` Paths map[string][]string `json:"paths"` } // Config holds the data for jsconfig.json. type Config struct { CompilerOptions CompilerOptions `json:"compilerOptions"` } func newJSConfig() *Config { return &Config{ CompilerOptions: CompilerOptions{ BaseURL: ".", Paths: make(map[string][]string), }, } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/jsconfig/jsconfig_test.go�����������������������������������������������������0000664�0000000�0000000�00000002142�14201470003�0021540�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jsconfig import ( "path/filepath" "testing" qt "github.com/frankban/quicktest" ) func TestJsConfigBuilder(t *testing.T) { c := qt.New(t) b := NewBuilder() b.AddSourceRoot("/c/assets") b.AddSourceRoot("/d/assets") conf := b.Build("/a/b") c.Assert(conf.CompilerOptions.BaseURL, qt.Equals, ".") c.Assert(conf.CompilerOptions.Paths["*"], qt.DeepEquals, []string{filepath.FromSlash("../../c/assets/*"), filepath.FromSlash("../../d/assets/*")}) c.Assert(NewBuilder().Build("/a/b"), qt.IsNil) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0015463�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page.go������������������������������������������������������������������0000664�0000000�0000000�00000026171�14201470003�0016735�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package page contains the core interfaces and types for the Page resource, // a core component in Hugo. package page import ( "html/template" "github.com/gohugoio/hugo/identity" "github.com/bep/gitmap" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/tpl" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/compare" "github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/navigation" "github.com/gohugoio/hugo/related" "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/source" ) // Clear clears any global package state. func Clear() error { spc.clear() return nil } // AlternativeOutputFormatsProvider provides alternative output formats for a // Page. type AlternativeOutputFormatsProvider interface { // AlternativeOutputFormats gives the alternative output formats for the // current output. // Note that we use the term "alternative" and not "alternate" here, as it // does not necessarily replace the other format, it is an alternative representation. AlternativeOutputFormats() OutputFormats } // AuthorProvider provides author information. type AuthorProvider interface { Author() Author Authors() AuthorList } // ChildCareProvider provides accessors to child resources. type ChildCareProvider interface { Pages() Pages // RegularPages returns a list of pages of kind 'Page'. // In Hugo 0.57 we changed the Pages method so it returns all page // kinds, even sections. If you want the old behaviour, you can // use RegularPages. RegularPages() Pages // RegularPagesRecursive returns all regular pages below the current // section. RegularPagesRecursive() Pages Resources() resource.Resources } // ContentProvider provides the content related values for a Page. type ContentProvider interface { Content() (interface{}, error) Plain() string PlainWords() []string Summary() template.HTML Truncated() bool FuzzyWordCount() int WordCount() int ReadingTime() int Len() int } // FileProvider provides the source file. type FileProvider interface { File() source.File } // GetPageProvider provides the GetPage method. type GetPageProvider interface { // GetPage looks up a page for the given ref. // {{ with .GetPage "blog" }}{{ .Title }}{{ end }} // // This will return nil when no page could be found, and will return // an error if the ref is ambiguous. GetPage(ref string) (Page, error) // GetPageWithTemplateInfo is for internal use only. GetPageWithTemplateInfo(info tpl.Info, ref string) (Page, error) } // GitInfoProvider provides Git info. type GitInfoProvider interface { GitInfo() *gitmap.GitInfo } // InSectionPositioner provides section navigation. type InSectionPositioner interface { NextInSection() Page PrevInSection() Page } // InternalDependencies is considered an internal interface. type InternalDependencies interface { GetRelatedDocsHandler() *RelatedDocsHandler } // OutputFormatsProvider provides the OutputFormats of a Page. type OutputFormatsProvider interface { OutputFormats() OutputFormats } // Page is the core interface in Hugo. type Page interface { ContentProvider TableOfContentsProvider PageWithoutContent } // PageMetaProvider provides page metadata, typically provided via front matter. type PageMetaProvider interface { // The 4 page dates resource.Dated // Aliases forms the base for redirects generation. Aliases() []string // BundleType returns the bundle type: "leaf", "branch" or an empty string if it is none. // See https://gohugo.io/content-management/page-bundles/ BundleType() files.ContentClass // A configured description. Description() string // Whether this is a draft. Will only be true if run with the --buildDrafts (-D) flag. Draft() bool // IsHome returns whether this is the home page. IsHome() bool // Configured keywords. Keywords() []string // The Page Kind. One of page, home, section, taxonomy, term. Kind() string // The configured layout to use to render this page. Typically set in front matter. Layout() string // The title used for links. LinkTitle() string // IsNode returns whether this is an item of one of the list types in Hugo, // i.e. not a regular content IsNode() bool // IsPage returns whether this is a regular content IsPage() bool // Param looks for a param in Page and then in Site config. Param(key interface{}) (interface{}, error) // Path gets the relative path, including file name and extension if relevant, // to the source of this Page. It will be relative to any content root. Path() string // This is just a temporary bridge method. Use Path in templates. Pathc() string // The slug, typically defined in front matter. Slug() string // This page's language code. Will be the same as the site's. Lang() string // IsSection returns whether this is a section IsSection() bool // Section returns the first path element below the content root. Section() string // Returns a slice of sections (directories if it's a file) to this // Page. SectionsEntries() []string // SectionsPath is SectionsEntries joined with a /. SectionsPath() string // Sitemap returns the sitemap configuration for this page. Sitemap() config.Sitemap // Type is a discriminator used to select layouts etc. It is typically set // in front matter, but will fall back to the root section. Type() string // The configured weight, used as the first sort value in the default // page sort if non-zero. Weight() int } // PageRenderProvider provides a way for a Page to render content. type PageRenderProvider interface { Render(layout ...string) (template.HTML, error) RenderString(args ...interface{}) (template.HTML, error) } // PageWithoutContent is the Page without any of the content methods. type PageWithoutContent interface { RawContentProvider resource.Resource PageMetaProvider resource.LanguageProvider // For pages backed by a file. FileProvider GitInfoProvider // Output formats OutputFormatsProvider AlternativeOutputFormatsProvider // Tree navigation ChildCareProvider TreeProvider // Horizontal navigation InSectionPositioner PageRenderProvider PaginatorProvider Positioner navigation.PageMenusProvider // TODO(bep) AuthorProvider // Page lookups/refs GetPageProvider RefProvider resource.TranslationKeyProvider TranslationsProvider SitesProvider // Helper methods ShortcodeInfoProvider compare.Eqer maps.Scratcher RelatedKeywordsProvider // GetTerms gets the terms of a given taxonomy, // e.g. GetTerms("categories") GetTerms(taxonomy string) Pages // Used in change/dependency tracking. identity.Provider DeprecatedWarningPageMethods } // Positioner provides next/prev navigation. type Positioner interface { Next() Page Prev() Page // Deprecated: Use Prev. Will be removed in Hugo 0.57 PrevPage() Page // Deprecated: Use Next. Will be removed in Hugo 0.57 NextPage() Page } // RawContentProvider provides the raw, unprocessed content of the page. type RawContentProvider interface { RawContent() string } // RefProvider provides the methods needed to create reflinks to pages. type RefProvider interface { Ref(argsm map[string]interface{}) (string, error) RefFrom(argsm map[string]interface{}, source interface{}) (string, error) RelRef(argsm map[string]interface{}) (string, error) RelRefFrom(argsm map[string]interface{}, source interface{}) (string, error) } // RelatedKeywordsProvider allows a Page to be indexed. type RelatedKeywordsProvider interface { // Make it indexable as a related.Document RelatedKeywords(cfg related.IndexConfig) ([]related.Keyword, error) } // ShortcodeInfoProvider provides info about the shortcodes in a Page. type ShortcodeInfoProvider interface { // HasShortcode return whether the page has a shortcode with the given name. // This method is mainly motivated with the Hugo Docs site's need for a list // of pages with the `todo` shortcode in it. HasShortcode(name string) bool } // SitesProvider provide accessors to get sites. type SitesProvider interface { Site() Site Sites() Sites } // TableOfContentsProvider provides the table of contents for a Page. type TableOfContentsProvider interface { TableOfContents() template.HTML } // TranslationsProvider provides access to any translations. type TranslationsProvider interface { // IsTranslated returns whether this content file is translated to // other language(s). IsTranslated() bool // AllTranslations returns all translations, including the current Page. AllTranslations() Pages // Translations returns the translations excluding the current Page. Translations() Pages } // TreeProvider provides section tree navigation. type TreeProvider interface { // IsAncestor returns whether the current page is an ancestor of the given // Note that this method is not relevant for taxonomy lists and taxonomy terms pages. IsAncestor(other interface{}) (bool, error) // CurrentSection returns the page's current section or the page itself if home or a section. // Note that this will return nil for pages that is not regular, home or section pages. CurrentSection() Page // IsDescendant returns whether the current page is a descendant of the given // Note that this method is not relevant for taxonomy lists and taxonomy terms pages. IsDescendant(other interface{}) (bool, error) // FirstSection returns the section on level 1 below home, e.g. "/docs". // For the home page, this will return itself. FirstSection() Page // InSection returns whether the given page is in the current section. // Note that this will always return false for pages that are // not either regular, home or section pages. InSection(other interface{}) (bool, error) // Parent returns a section's parent section or a page's section. // To get a section's subsections, see Page's Sections method. Parent() Page // Sections returns this section's subsections, if any. // Note that for non-sections, this method will always return an empty list. Sections() Pages // Page returns a reference to the Page itself, kept here mostly // for legacy reasons. Page() Page } // DeprecatedWarningPageMethods lists deprecated Page methods that will trigger // a WARNING if invoked. // This was added in Hugo 0.55. type DeprecatedWarningPageMethods interface { source.FileWithoutOverlap DeprecatedWarningPageMethods1 } type DeprecatedWarningPageMethods1 interface { IsDraft() bool Hugo() hugo.Info LanguagePrefix() string GetParam(key string) interface{} RSSLink() template.URL URL() string } // Move here to trigger ERROR instead of WARNING. // TODO(bep) create wrappers and put into the Page once it has some methods. type DeprecatedErrorPageMethods interface{} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_author.go�����������������������������������������������������������0000664�0000000�0000000�00000002462�14201470003�0020314�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page // AuthorList is a list of all authors and their metadata. type AuthorList map[string]Author // Author contains details about the author of a page. type Author struct { GivenName string FamilyName string DisplayName string Thumbnail string Image string ShortBio string LongBio string Email string Social AuthorSocial } // AuthorSocial is a place to put social details per author. These are the // standard keys that themes will expect to have available, but can be // expanded to any others on a per site basis // - website // - github // - facebook // - twitter // - pinterest // - instagram // - youtube // - linkedin // - skype type AuthorSocial map[string]string ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_data.go�������������������������������������������������������������0000664�0000000�0000000�00000002307�14201470003�0017721�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package page contains the core interfaces and types for the Page resource, // a core component in Hugo. package page import ( "fmt" ) // Data represents the .Data element in a Page in Hugo. We make this // a type so we can do lazy loading of .Data.Pages type Data map[string]interface{} // Pages returns the pages stored with key "pages". If this is a func, // it will be invoked. func (d Data) Pages() Pages { v, found := d["pages"] if !found { return nil } switch vv := v.(type) { case Pages: return vv case func() Pages: return vv() default: panic(fmt.Sprintf("%T is not Pages", v)) } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_data_test.go��������������������������������������������������������0000664�0000000�0000000�00000002341�14201470003�0020756�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "bytes" "testing" "text/template" qt "github.com/frankban/quicktest" ) func TestPageData(t *testing.T) { c := qt.New(t) data := make(Data) c.Assert(data.Pages(), qt.IsNil) pages := Pages{ &testPage{title: "a1"}, &testPage{title: "a2"}, } data["pages"] = pages c.Assert(data.Pages(), eq, pages) data["pages"] = func() Pages { return pages } c.Assert(data.Pages(), eq, pages) templ, err := template.New("").Parse(`Pages: {{ .Pages }}`) c.Assert(err, qt.IsNil) var buff bytes.Buffer c.Assert(templ.Execute(&buff, data), qt.IsNil) c.Assert(buff.String(), qt.Contains, "Pages(2)") } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_generate/�����������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0020251�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_generate/.gitignore�������������������������������������������������0000664�0000000�0000000�00000000010�14201470003�0022230�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������generate������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_generate/generate_page_wrappers.go����������������������������������0000664�0000000�0000000�00000016551�14201470003�0025321�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page_generate import ( "bytes" "fmt" "os" "path/filepath" "reflect" "github.com/pkg/errors" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/codegen" "github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/source" ) const header = `// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This file is autogenerated. ` var ( fileInterfaceDeprecated = reflect.TypeOf((*source.FileWithoutOverlap)(nil)).Elem() pageInterfaceDeprecated = reflect.TypeOf((*page.DeprecatedWarningPageMethods)(nil)).Elem() pageInterface = reflect.TypeOf((*page.Page)(nil)).Elem() packageDir = filepath.FromSlash("resources/page") ) func Generate(c *codegen.Inspector) error { if err := generateMarshalJSON(c); err != nil { return errors.Wrap(err, "failed to generate JSON marshaler") } if err := generateDeprecatedWrappers(c); err != nil { return errors.Wrap(err, "failed to generate deprecate wrappers") } if err := generateFileIsZeroWrappers(c); err != nil { return errors.Wrap(err, "failed to generate file wrappers") } return nil } func generateMarshalJSON(c *codegen.Inspector) error { filename := filepath.Join(c.ProjectRootDir, packageDir, "page_marshaljson.autogen.go") f, err := os.Create(filename) if err != nil { return err } defer f.Close() includes := []reflect.Type{pageInterface} // Exclude these methods excludes := []reflect.Type{ // We need to evaluate the deprecated vs JSON in the future, // but leave them out for now. pageInterfaceDeprecated, // Leave this out for now. We need to revisit the author issue. reflect.TypeOf((*page.AuthorProvider)(nil)).Elem(), reflect.TypeOf((*resource.ErrProvider)(nil)).Elem(), // navigation.PageMenus // Prevent loops. reflect.TypeOf((*page.SitesProvider)(nil)).Elem(), reflect.TypeOf((*page.Positioner)(nil)).Elem(), reflect.TypeOf((*page.ChildCareProvider)(nil)).Elem(), reflect.TypeOf((*page.TreeProvider)(nil)).Elem(), reflect.TypeOf((*page.InSectionPositioner)(nil)).Elem(), reflect.TypeOf((*page.PaginatorProvider)(nil)).Elem(), reflect.TypeOf((*maps.Scratcher)(nil)).Elem(), } methods := c.MethodsFromTypes( includes, excludes) if len(methods) == 0 { return errors.New("no methods found") } marshalJSON, pkgImports := methods.ToMarshalJSON( "Page", "github.com/gohugoio/hugo/resources/page", // Exclusion regexps. Matches method names. `\bPage\b`, ) fmt.Fprintf(f, `%s package page %s %s `, header, importsString(pkgImports), marshalJSON) return nil } func generateDeprecatedWrappers(c *codegen.Inspector) error { filename := filepath.Join(c.ProjectRootDir, packageDir, "page_wrappers.autogen.go") f, err := os.Create(filename) if err != nil { return err } defer f.Close() // Generate a wrapper for deprecated page methods reasons := map[string]string{ "IsDraft": "Use .Draft.", "Hugo": "Use the global hugo function.", "LanguagePrefix": "Use .Site.LanguagePrefix.", "GetParam": "Use .Param or .Params.myParam.", "RSSLink": `Use the Output Format's link, e.g. something like: {{ with .OutputFormats.Get "RSS" }}{{ .RelPermalink }}{{ end }}`, "URL": "Use .Permalink or .RelPermalink. If what you want is the front matter URL value, use .Params.url", } deprecated := func(name string, tp reflect.Type) string { var alternative string if tp == fileInterfaceDeprecated { alternative = "Use .File." + name } else { var found bool alternative, found = reasons[name] if !found { panic(fmt.Sprintf("no deprecated reason found for %q", name)) } } return fmt.Sprintf("helpers.Deprecated(%q, %q, true)", "Page."+name, alternative) } var buff bytes.Buffer methods := c.MethodsFromTypes([]reflect.Type{fileInterfaceDeprecated, pageInterfaceDeprecated}, nil) for _, m := range methods { fmt.Fprint(&buff, m.Declaration("*pageDeprecated")) fmt.Fprintln(&buff, " {") fmt.Fprintf(&buff, "\t%s\n", deprecated(m.Name, m.Owner)) fmt.Fprintf(&buff, "\t%s\n}\n", m.Delegate("p", "p")) } pkgImports := append(methods.Imports(), "github.com/gohugoio/hugo/helpers") fmt.Fprintf(f, `%s package page %s // NewDeprecatedWarningPage adds deprecation warnings to the given implementation. func NewDeprecatedWarningPage(p DeprecatedWarningPageMethods) DeprecatedWarningPageMethods { return &pageDeprecated{p: p} } type pageDeprecated struct { p DeprecatedWarningPageMethods } %s `, header, importsString(pkgImports), buff.String()) return nil } func generateFileIsZeroWrappers(c *codegen.Inspector) error { filename := filepath.Join(c.ProjectRootDir, packageDir, "zero_file.autogen.go") f, err := os.Create(filename) if err != nil { return err } defer f.Close() // Generate warnings for zero file access warning := func(name string, tp reflect.Type) string { msg := fmt.Sprintf(".File.%s on zero object. Wrap it in if or with: {{ with .File }}{{ .%s }}{{ end }}", name, name) // We made this a Warning in 0.92.0. // When we remove this construct in 0.93.0, people will get a nil pointer. return fmt.Sprintf("z.log.Warnln(%q)", msg) } var buff bytes.Buffer methods := c.MethodsFromTypes([]reflect.Type{reflect.TypeOf((*source.File)(nil)).Elem()}, nil) for _, m := range methods { if m.Name == "IsZero" { continue } fmt.Fprint(&buff, m.DeclarationNamed("zeroFile")) fmt.Fprintln(&buff, " {") fmt.Fprintf(&buff, "\t%s\n", warning(m.Name, m.Owner)) if len(m.Out) > 0 { fmt.Fprintln(&buff, "\treturn") } fmt.Fprintln(&buff, "}") } pkgImports := append(methods.Imports(), "github.com/gohugoio/hugo/common/loggers", "github.com/gohugoio/hugo/source") fmt.Fprintf(f, `%s package page %s // ZeroFile represents a zero value of source.File with warnings if invoked. type zeroFile struct { log loggers.Logger } func NewZeroFile(log loggers.Logger) source.File { return zeroFile{log: log} } func (zeroFile) IsZero() bool { return true } %s `, header, importsString(pkgImports), buff.String()) return nil } func importsString(imps []string) string { if len(imps) == 0 { return "" } if len(imps) == 1 { return fmt.Sprintf("import %q", imps[0]) } impsStr := "import (\n" for _, imp := range imps { impsStr += fmt.Sprintf("%q\n", imp) } return impsStr + ")" } �������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_kinds.go������������������������������������������������������������0000664�0000000�0000000�00000002554�14201470003�0020124�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import "strings" const ( KindPage = "page" // The rest are node types; home page, sections etc. KindHome = "home" KindSection = "section" // Note tha before Hugo 0.73 these were confusingly named // taxonomy (now: term) // taxonomyTerm (now: taxonomy) KindTaxonomy = "taxonomy" KindTerm = "term" ) var kindMap = map[string]string{ strings.ToLower(KindPage): KindPage, strings.ToLower(KindHome): KindHome, strings.ToLower(KindSection): KindSection, strings.ToLower(KindTaxonomy): KindTaxonomy, strings.ToLower(KindTerm): KindTerm, // Legacy, pre v0.53.0. "taxonomyterm": KindTaxonomy, } // GetKind gets the page kind given a string, empty if not found. func GetKind(s string) string { return kindMap[strings.ToLower(s)] } ����������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_kinds_test.go�������������������������������������������������������0000664�0000000�0000000�00000002406�14201470003�0021157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "testing" qt "github.com/frankban/quicktest" ) func TestKind(t *testing.T) { t.Parallel() c := qt.New(t) // Add tests for these constants to make sure they don't change c.Assert(KindPage, qt.Equals, "page") c.Assert(KindHome, qt.Equals, "home") c.Assert(KindSection, qt.Equals, "section") c.Assert(KindTaxonomy, qt.Equals, "taxonomy") c.Assert(KindTerm, qt.Equals, "term") c.Assert(GetKind("TAXONOMYTERM"), qt.Equals, KindTaxonomy) c.Assert(GetKind("Taxonomy"), qt.Equals, KindTaxonomy) c.Assert(GetKind("Page"), qt.Equals, KindPage) c.Assert(GetKind("Home"), qt.Equals, KindHome) c.Assert(GetKind("SEction"), qt.Equals, KindSection) } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_lazy_contentprovider.go���������������������������������������������0000664�0000000�0000000�00000006515�14201470003�0023301�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "html/template" "github.com/gohugoio/hugo/lazy" ) // OutputFormatContentProvider represents the method set that is "outputFormat aware" and that we // provide lazy initialization for in case they get invoked outside of their normal rendering context, e.g. via .Translations. // Note that this set is currently not complete, but should cover the most common use cases. // For the others, the implementation will be from the page.NoopPage. type OutputFormatContentProvider interface { ContentProvider TableOfContentsProvider PageRenderProvider } // LazyContentProvider initializes itself when read. Each method of the // ContentProvider interface initializes a content provider and shares it // with other methods. // // Used in cases where we cannot guarantee whether the content provider // will be needed. Must create via NewLazyContentProvider. type LazyContentProvider struct { init *lazy.Init cp OutputFormatContentProvider } // NewLazyContentProvider returns a LazyContentProvider initialized with // function f. The resulting LazyContentProvider calls f in order to // retrieve a ContentProvider func NewLazyContentProvider(f func() (OutputFormatContentProvider, error)) *LazyContentProvider { lcp := LazyContentProvider{ init: lazy.New(), cp: NopPage, } lcp.init.Add(func() (interface{}, error) { cp, err := f() if err != nil { return nil, err } lcp.cp = cp return nil, nil }) return &lcp } func (lcp *LazyContentProvider) Reset() { lcp.init.Reset() } func (lcp *LazyContentProvider) Content() (interface{}, error) { lcp.init.Do() return lcp.cp.Content() } func (lcp *LazyContentProvider) Plain() string { lcp.init.Do() return lcp.cp.Plain() } func (lcp *LazyContentProvider) PlainWords() []string { lcp.init.Do() return lcp.cp.PlainWords() } func (lcp *LazyContentProvider) Summary() template.HTML { lcp.init.Do() return lcp.cp.Summary() } func (lcp *LazyContentProvider) Truncated() bool { lcp.init.Do() return lcp.cp.Truncated() } func (lcp *LazyContentProvider) FuzzyWordCount() int { lcp.init.Do() return lcp.cp.FuzzyWordCount() } func (lcp *LazyContentProvider) WordCount() int { lcp.init.Do() return lcp.cp.WordCount() } func (lcp *LazyContentProvider) ReadingTime() int { lcp.init.Do() return lcp.cp.ReadingTime() } func (lcp *LazyContentProvider) Len() int { lcp.init.Do() return lcp.cp.Len() } func (lcp *LazyContentProvider) Render(layout ...string) (template.HTML, error) { lcp.init.Do() return lcp.cp.Render(layout...) } func (lcp *LazyContentProvider) RenderString(args ...interface{}) (template.HTML, error) { lcp.init.Do() return lcp.cp.RenderString(args...) } func (lcp *LazyContentProvider) TableOfContents() template.HTML { lcp.init.Do() return lcp.cp.TableOfContents() } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_marshaljson.autogen.go����������������������������������������������0000664�0000000�0000000�00000015144�14201470003�0022775�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This file is autogenerated. package page import ( "encoding/json" "html/template" "time" "github.com/bep/gitmap" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/identity" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/navigation" "github.com/gohugoio/hugo/source" ) func MarshalPageToJSON(p Page) ([]byte, error) { content, err := p.Content() if err != nil { return nil, err } plain := p.Plain() plainWords := p.PlainWords() summary := p.Summary() truncated := p.Truncated() fuzzyWordCount := p.FuzzyWordCount() wordCount := p.WordCount() readingTime := p.ReadingTime() length := p.Len() tableOfContents := p.TableOfContents() rawContent := p.RawContent() resourceType := p.ResourceType() mediaType := p.MediaType() permalink := p.Permalink() relPermalink := p.RelPermalink() name := p.Name() title := p.Title() params := p.Params() data := p.Data() date := p.Date() lastmod := p.Lastmod() publishDate := p.PublishDate() expiryDate := p.ExpiryDate() aliases := p.Aliases() bundleType := p.BundleType() description := p.Description() draft := p.Draft() isHome := p.IsHome() keywords := p.Keywords() kind := p.Kind() layout := p.Layout() linkTitle := p.LinkTitle() isNode := p.IsNode() isPage := p.IsPage() path := p.Pathc() slug := p.Slug() lang := p.Lang() isSection := p.IsSection() section := p.Section() sectionsEntries := p.SectionsEntries() sectionsPath := p.SectionsPath() sitemap := p.Sitemap() typ := p.Type() weight := p.Weight() language := p.Language() file := p.File() gitInfo := p.GitInfo() outputFormats := p.OutputFormats() alternativeOutputFormats := p.AlternativeOutputFormats() menus := p.Menus() translationKey := p.TranslationKey() isTranslated := p.IsTranslated() allTranslations := p.AllTranslations() translations := p.Translations() getIdentity := p.GetIdentity() s := struct { Content interface{} Plain string PlainWords []string Summary template.HTML Truncated bool FuzzyWordCount int WordCount int ReadingTime int Len int TableOfContents template.HTML RawContent string ResourceType string MediaType media.Type Permalink string RelPermalink string Name string Title string Params maps.Params Data interface{} Date time.Time Lastmod time.Time PublishDate time.Time ExpiryDate time.Time Aliases []string BundleType files.ContentClass Description string Draft bool IsHome bool Keywords []string Kind string Layout string LinkTitle string IsNode bool IsPage bool Path string Slug string Lang string IsSection bool Section string SectionsEntries []string SectionsPath string Sitemap config.Sitemap Type string Weight int Language *langs.Language File source.File GitInfo *gitmap.GitInfo OutputFormats OutputFormats AlternativeOutputFormats OutputFormats Menus navigation.PageMenus TranslationKey string IsTranslated bool AllTranslations Pages Translations Pages GetIdentity identity.Identity }{ Content: content, Plain: plain, PlainWords: plainWords, Summary: summary, Truncated: truncated, FuzzyWordCount: fuzzyWordCount, WordCount: wordCount, ReadingTime: readingTime, Len: length, TableOfContents: tableOfContents, RawContent: rawContent, ResourceType: resourceType, MediaType: mediaType, Permalink: permalink, RelPermalink: relPermalink, Name: name, Title: title, Params: params, Data: data, Date: date, Lastmod: lastmod, PublishDate: publishDate, ExpiryDate: expiryDate, Aliases: aliases, BundleType: bundleType, Description: description, Draft: draft, IsHome: isHome, Keywords: keywords, Kind: kind, Layout: layout, LinkTitle: linkTitle, IsNode: isNode, IsPage: isPage, Path: path, Slug: slug, Lang: lang, IsSection: isSection, Section: section, SectionsEntries: sectionsEntries, SectionsPath: sectionsPath, Sitemap: sitemap, Type: typ, Weight: weight, Language: language, File: file, GitInfo: gitInfo, OutputFormats: outputFormats, AlternativeOutputFormats: alternativeOutputFormats, Menus: menus, TranslationKey: translationKey, IsTranslated: isTranslated, AllTranslations: allTranslations, Translations: translations, GetIdentity: getIdentity, } return json.Marshal(&s) } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_matcher.go����������������������������������������������������������0000664�0000000�0000000�00000006111�14201470003�0020430�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "path/filepath" "strings" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/hugofs/glob" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) // A PageMatcher can be used to match a Page with Glob patterns. // Note that the pattern matching is case insensitive. type PageMatcher struct { // A Glob pattern matching the content path below /content. // Expects Unix-styled slashes. // Note that this is the virtual path, so it starts at the mount root // with a leading "/". Path string // A Glob pattern matching the Page's Kind(s), e.g. "{home,section}" Kind string // A Glob pattern matching the Page's language, e.g. "{en,sv}". Lang string } // Matches returns whether p matches this matcher. func (m PageMatcher) Matches(p Page) bool { if m.Kind != "" { g, err := glob.GetGlob(m.Kind) if err == nil && !g.Match(p.Kind()) { return false } } if m.Lang != "" { g, err := glob.GetGlob(m.Lang) if err == nil && !g.Match(p.Lang()) { return false } } if m.Path != "" { g, err := glob.GetGlob(m.Path) // TODO(bep) Path() vs filepath vs leading slash. p := strings.ToLower(filepath.ToSlash(p.Pathc())) if !(strings.HasPrefix(p, "/")) { p = "/" + p } if err == nil && !g.Match(p) { return false } } return true } // DecodeCascade decodes in which could be eiter a map or a slice of maps. func DecodeCascade(in interface{}) (map[PageMatcher]maps.Params, error) { m, err := maps.ToSliceStringMap(in) if err != nil { return map[PageMatcher]maps.Params{ {}: maps.ToStringMap(in), }, nil } cascade := make(map[PageMatcher]maps.Params) for _, vv := range m { var m PageMatcher if mv, found := vv["_target"]; found { err := DecodePageMatcher(mv, &m) if err != nil { return nil, err } } c, found := cascade[m] if found { // Merge for k, v := range vv { if _, found := c[k]; !found { c[k] = v } } } else { cascade[m] = vv } } return cascade, nil } // DecodePageMatcher decodes m into v. func DecodePageMatcher(m interface{}, v *PageMatcher) error { if err := mapstructure.WeakDecode(m, v); err != nil { return err } v.Kind = strings.ToLower(v.Kind) if v.Kind != "" { g, _ := glob.GetGlob(v.Kind) found := false for _, k := range kindMap { if g.Match(k) { found = true break } } if !found { return errors.Errorf("%q did not match a valid Page Kind", v.Kind) } } v.Path = filepath.ToSlash(strings.ToLower(v.Path)) return nil } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_matcher_test.go�����������������������������������������������������0000664�0000000�0000000�00000004756�14201470003�0021504�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "path/filepath" "testing" qt "github.com/frankban/quicktest" ) func TestPageMatcher(t *testing.T) { c := qt.New(t) p1, p2, p3 := &testPage{path: "/p1", kind: "section", lang: "en"}, &testPage{path: "p2", kind: "page", lang: "no"}, &testPage{path: "p3", kind: "page", lang: "en"} c.Run("Matches", func(c *qt.C) { m := PageMatcher{Kind: "section"} c.Assert(m.Matches(p1), qt.Equals, true) c.Assert(m.Matches(p2), qt.Equals, false) m = PageMatcher{Kind: "page"} c.Assert(m.Matches(p1), qt.Equals, false) c.Assert(m.Matches(p2), qt.Equals, true) c.Assert(m.Matches(p3), qt.Equals, true) m = PageMatcher{Kind: "page", Path: "/p2"} c.Assert(m.Matches(p1), qt.Equals, false) c.Assert(m.Matches(p2), qt.Equals, true) c.Assert(m.Matches(p3), qt.Equals, false) m = PageMatcher{Path: "/p*"} c.Assert(m.Matches(p1), qt.Equals, true) c.Assert(m.Matches(p2), qt.Equals, true) c.Assert(m.Matches(p3), qt.Equals, true) m = PageMatcher{Lang: "en"} c.Assert(m.Matches(p1), qt.Equals, true) c.Assert(m.Matches(p2), qt.Equals, false) c.Assert(m.Matches(p3), qt.Equals, true) }) c.Run("Decode", func(c *qt.C) { var v PageMatcher c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "foo"}, &v), qt.Not(qt.IsNil)) c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "{foo,bar}"}, &v), qt.Not(qt.IsNil)) c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "taxonomy"}, &v), qt.IsNil) c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "{taxonomy,foo}"}, &v), qt.IsNil) c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "{taxonomy,term}"}, &v), qt.IsNil) c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "*"}, &v), qt.IsNil) c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "home", "path": filepath.FromSlash("/a/b/**")}, &v), qt.IsNil) c.Assert(v, qt.Equals, PageMatcher{Kind: "home", Path: "/a/b/**"}) }) } ������������������hugo-0.92.2/resources/page/page_nop.go��������������������������������������������������������������0000664�0000000�0000000�00000020420�14201470003�0017600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package page contains the core interfaces and types for the Page resource, // a core component in Hugo. package page import ( "html/template" "time" "github.com/gohugoio/hugo/identity" "github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/tpl" "github.com/gohugoio/hugo/hugofs" "github.com/bep/gitmap" "github.com/gohugoio/hugo/navigation" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/related" "github.com/gohugoio/hugo/resources/resource" ) var ( NopPage Page = new(nopPage) NilPage *nopPage ) // PageNop implements Page, but does nothing. type nopPage int func (p *nopPage) Err() error { return nil } func (p *nopPage) Aliases() []string { return nil } func (p *nopPage) Sitemap() config.Sitemap { return config.Sitemap{} } func (p *nopPage) Layout() string { return "" } func (p *nopPage) RSSLink() template.URL { return "" } func (p *nopPage) Author() Author { return Author{} } func (p *nopPage) Authors() AuthorList { return nil } func (p *nopPage) AllTranslations() Pages { return nil } func (p *nopPage) LanguagePrefix() string { return "" } func (p *nopPage) AlternativeOutputFormats() OutputFormats { return nil } func (p *nopPage) BaseFileName() string { return "" } func (p *nopPage) BundleType() files.ContentClass { return "" } func (p *nopPage) Content() (interface{}, error) { return "", nil } func (p *nopPage) ContentBaseName() string { return "" } func (p *nopPage) CurrentSection() Page { return nil } func (p *nopPage) Data() interface{} { return nil } func (p *nopPage) Date() (t time.Time) { return } func (p *nopPage) Description() string { return "" } func (p *nopPage) RefFrom(argsm map[string]interface{}, source interface{}) (string, error) { return "", nil } func (p *nopPage) RelRefFrom(argsm map[string]interface{}, source interface{}) (string, error) { return "", nil } func (p *nopPage) Dir() string { return "" } func (p *nopPage) Draft() bool { return false } func (p *nopPage) Eq(other interface{}) bool { return p == other } func (p *nopPage) ExpiryDate() (t time.Time) { return } func (p *nopPage) Ext() string { return "" } func (p *nopPage) Extension() string { return "" } var nilFile *source.FileInfo func (p *nopPage) File() source.File { return nilFile } func (p *nopPage) FileInfo() hugofs.FileMetaInfo { return nil } func (p *nopPage) Filename() string { return "" } func (p *nopPage) FirstSection() Page { return nil } func (p *nopPage) FuzzyWordCount() int { return 0 } func (p *nopPage) GetPage(ref string) (Page, error) { return nil, nil } func (p *nopPage) GetPageWithTemplateInfo(info tpl.Info, ref string) (Page, error) { return nil, nil } func (p *nopPage) GetParam(key string) interface{} { return nil } func (p *nopPage) GetTerms(taxonomy string) Pages { return nil } func (p *nopPage) GitInfo() *gitmap.GitInfo { return nil } func (p *nopPage) HasMenuCurrent(menuID string, me *navigation.MenuEntry) bool { return false } func (p *nopPage) HasShortcode(name string) bool { return false } func (p *nopPage) Hugo() (h hugo.Info) { return } func (p *nopPage) InSection(other interface{}) (bool, error) { return false, nil } func (p *nopPage) IsAncestor(other interface{}) (bool, error) { return false, nil } func (p *nopPage) IsDescendant(other interface{}) (bool, error) { return false, nil } func (p *nopPage) IsDraft() bool { return false } func (p *nopPage) IsHome() bool { return false } func (p *nopPage) IsMenuCurrent(menuID string, inme *navigation.MenuEntry) bool { return false } func (p *nopPage) IsNode() bool { return false } func (p *nopPage) IsPage() bool { return false } func (p *nopPage) IsSection() bool { return false } func (p *nopPage) IsTranslated() bool { return false } func (p *nopPage) Keywords() []string { return nil } func (p *nopPage) Kind() string { return "" } func (p *nopPage) Lang() string { return "" } func (p *nopPage) Language() *langs.Language { return nil } func (p *nopPage) Lastmod() (t time.Time) { return } func (p *nopPage) Len() int { return 0 } func (p *nopPage) LinkTitle() string { return "" } func (p *nopPage) LogicalName() string { return "" } func (p *nopPage) MediaType() (m media.Type) { return } func (p *nopPage) Menus() (m navigation.PageMenus) { return } func (p *nopPage) Name() string { return "" } func (p *nopPage) Next() Page { return nil } func (p *nopPage) OutputFormats() OutputFormats { return nil } func (p *nopPage) Pages() Pages { return nil } func (p *nopPage) RegularPages() Pages { return nil } func (p *nopPage) RegularPagesRecursive() Pages { return nil } func (p *nopPage) Paginate(seq interface{}, options ...interface{}) (*Pager, error) { return nil, nil } func (p *nopPage) Paginator(options ...interface{}) (*Pager, error) { return nil, nil } func (p *nopPage) Param(key interface{}) (interface{}, error) { return nil, nil } func (p *nopPage) Params() maps.Params { return nil } func (p *nopPage) Page() Page { return p } func (p *nopPage) Parent() Page { return nil } func (p *nopPage) Path() string { return "" } func (p *nopPage) Pathc() string { return "" } func (p *nopPage) Permalink() string { return "" } func (p *nopPage) Plain() string { return "" } func (p *nopPage) PlainWords() []string { return nil } func (p *nopPage) Prev() Page { return nil } func (p *nopPage) PublishDate() (t time.Time) { return } func (p *nopPage) PrevInSection() Page { return nil } func (p *nopPage) NextInSection() Page { return nil } func (p *nopPage) PrevPage() Page { return nil } func (p *nopPage) NextPage() Page { return nil } func (p *nopPage) RawContent() string { return "" } func (p *nopPage) ReadingTime() int { return 0 } func (p *nopPage) Ref(argsm map[string]interface{}) (string, error) { return "", nil } func (p *nopPage) RelPermalink() string { return "" } func (p *nopPage) RelRef(argsm map[string]interface{}) (string, error) { return "", nil } func (p *nopPage) Render(layout ...string) (template.HTML, error) { return "", nil } func (p *nopPage) RenderString(args ...interface{}) (template.HTML, error) { return "", nil } func (p *nopPage) ResourceType() string { return "" } func (p *nopPage) Resources() resource.Resources { return nil } func (p *nopPage) Scratch() *maps.Scratch { return nil } func (p *nopPage) RelatedKeywords(cfg related.IndexConfig) ([]related.Keyword, error) { return nil, nil } func (p *nopPage) Section() string { return "" } func (p *nopPage) Sections() Pages { return nil } func (p *nopPage) SectionsEntries() []string { return nil } func (p *nopPage) SectionsPath() string { return "" } func (p *nopPage) Site() Site { return nil } func (p *nopPage) Sites() Sites { return nil } func (p *nopPage) Slug() string { return "" } func (p *nopPage) String() string { return "nopPage" } func (p *nopPage) Summary() template.HTML { return "" } func (p *nopPage) TableOfContents() template.HTML { return "" } func (p *nopPage) Title() string { return "" } func (p *nopPage) TranslationBaseName() string { return "" } func (p *nopPage) TranslationKey() string { return "" } func (p *nopPage) Translations() Pages { return nil } func (p *nopPage) Truncated() bool { return false } func (p *nopPage) Type() string { return "" } func (p *nopPage) URL() string { return "" } func (p *nopPage) UniqueID() string { return "" } func (p *nopPage) Weight() int { return 0 } func (p *nopPage) WordCount() int { return 0 } func (p *nopPage) GetIdentity() identity.Identity { return identity.NewPathIdentity("content", "foo/bar.md") } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_outputformat.go�����������������������������������������������������0000664�0000000�0000000�00000005716�14201470003�0021570�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package page contains the core interfaces and types for the Page resource, // a core component in Hugo. package page import ( "strings" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/output" ) // OutputFormats holds a list of the relevant output formats for a given page. type OutputFormats []OutputFormat // OutputFormat links to a representation of a resource. type OutputFormat struct { // Rel contains a value that can be used to construct a rel link. // This is value is fetched from the output format definition. // Note that for pages with only one output format, // this method will always return "canonical". // As an example, the AMP output format will, by default, return "amphtml". // // See: // https://www.ampproject.org/docs/guides/deploy/discovery // // Most other output formats will have "alternate" as value for this. Rel string Format output.Format relPermalink string permalink string } // Name returns this OutputFormat's name, i.e. HTML, AMP, JSON etc. func (o OutputFormat) Name() string { return o.Format.Name } // MediaType returns this OutputFormat's MediaType (MIME type). func (o OutputFormat) MediaType() media.Type { return o.Format.MediaType } // Permalink returns the absolute permalink to this output format. func (o OutputFormat) Permalink() string { return o.permalink } // RelPermalink returns the relative permalink to this output format. func (o OutputFormat) RelPermalink() string { return o.relPermalink } func NewOutputFormat(relPermalink, permalink string, isCanonical bool, f output.Format) OutputFormat { isUserConfigured := true for _, d := range output.DefaultFormats { if strings.EqualFold(d.Name, f.Name) { isUserConfigured = false } } rel := f.Rel // If the output format is the canonical format for the content, we want // to specify this in the "rel" attribute of an HTML "link" element. // However, for custom output formats, we don't want to surprise users by // overwriting "rel" if isCanonical && !isUserConfigured { rel = "canonical" } return OutputFormat{Rel: rel, Format: f, relPermalink: relPermalink, permalink: permalink} } // Get gets a OutputFormat given its name, i.e. json, html etc. // It returns nil if none found. func (o OutputFormats) Get(name string) *OutputFormat { for _, f := range o { if strings.EqualFold(f.Format.Name, name) { return &f } } return nil } ��������������������������������������������������hugo-0.92.2/resources/page/page_paths.go������������������������������������������������������������0000664�0000000�0000000�00000020414�14201470003�0020126�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "path" "path/filepath" "strings" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/output" ) const slash = "/" // TargetPathDescriptor describes how a file path for a given resource // should look like on the file system. The same descriptor is then later used to // create both the permalinks and the relative links, paginator URLs etc. // // The big motivating behind this is to have only one source of truth for URLs, // and by that also get rid of most of the fragile string parsing/encoding etc. // // type TargetPathDescriptor struct { PathSpec *helpers.PathSpec Type output.Format Kind string Sections []string // For regular content pages this is either // 1) the Slug, if set, // 2) the file base name (TranslationBaseName). BaseName string // Source directory. Dir string // Typically a language prefix added to file paths. PrefixFilePath string // Typically a language prefix added to links. PrefixLink string // If in multihost mode etc., every link/path needs to be prefixed, even // if set in URL. ForcePrefix bool // URL from front matter if set. Will override any Slug etc. URL string // Used to create paginator links. Addends string // The expanded permalink if defined for the section, ready to use. ExpandedPermalink string // Some types cannot have uglyURLs, even if globally enabled, RSS being one example. UglyURLs bool } // TODO(bep) move this type. type TargetPaths struct { // Where to store the file on disk relative to the publish dir. OS slashes. TargetFilename string // The directory to write sub-resources of the above. SubResourceBaseTarget string // The base for creating links to sub-resources of the above. SubResourceBaseLink string // The relative permalink to this resources. Unix slashes. Link string } func (p TargetPaths) RelPermalink(s *helpers.PathSpec) string { return s.PrependBasePath(p.Link, false) } func (p TargetPaths) PermalinkForOutputFormat(s *helpers.PathSpec, f output.Format) string { var baseURL string var err error if f.Protocol != "" { baseURL, err = s.BaseURL.WithProtocol(f.Protocol) if err != nil { return "" } } else { baseURL = s.BaseURL.String() } return s.PermalinkForBaseURL(p.Link, baseURL) } func isHtmlIndex(s string) bool { return strings.HasSuffix(s, "/index.html") } func CreateTargetPaths(d TargetPathDescriptor) (tp TargetPaths) { if d.Type.Name == "" { panic("CreateTargetPath: missing type") } // Normalize all file Windows paths to simplify what's next. if helpers.FilePathSeparator != slash { d.Dir = filepath.ToSlash(d.Dir) d.PrefixFilePath = filepath.ToSlash(d.PrefixFilePath) } if d.URL != "" && !strings.HasPrefix(d.URL, "/") { // Treat this as a context relative URL d.ForcePrefix = true } pagePath := slash fullSuffix := d.Type.MediaType.FirstSuffix.FullSuffix var ( pagePathDir string link string linkDir string ) // The top level index files, i.e. the home page etc., needs // the index base even when uglyURLs is enabled. needsBase := true isUgly := d.UglyURLs && !d.Type.NoUgly baseNameSameAsType := d.BaseName != "" && d.BaseName == d.Type.BaseName if d.ExpandedPermalink == "" && baseNameSameAsType { isUgly = true } if d.Kind != KindPage && d.URL == "" && len(d.Sections) > 0 { if d.ExpandedPermalink != "" { pagePath = pjoin(pagePath, d.ExpandedPermalink) } else { pagePath = pjoin(d.Sections...) } needsBase = false } if d.Type.Path != "" { pagePath = pjoin(pagePath, d.Type.Path) } if d.Kind != KindHome && d.URL != "" { pagePath = pjoin(pagePath, d.URL) if d.Addends != "" { pagePath = pjoin(pagePath, d.Addends) } pagePathDir = pagePath link = pagePath hasDot := strings.Contains(d.URL, ".") hasSlash := strings.HasSuffix(d.URL, slash) if hasSlash || !hasDot { pagePath = pjoin(pagePath, d.Type.BaseName+fullSuffix) } else if hasDot { pagePathDir = path.Dir(pagePathDir) } if !isHtmlIndex(pagePath) { link = pagePath } else if !hasSlash { link += slash } linkDir = pagePathDir if d.ForcePrefix { // Prepend language prefix if not already set in URL if d.PrefixFilePath != "" && !strings.HasPrefix(d.URL, slash+d.PrefixFilePath) { pagePath = pjoin(d.PrefixFilePath, pagePath) pagePathDir = pjoin(d.PrefixFilePath, pagePathDir) } if d.PrefixLink != "" && !strings.HasPrefix(d.URL, slash+d.PrefixLink) { link = pjoin(d.PrefixLink, link) linkDir = pjoin(d.PrefixLink, linkDir) } } } else if d.Kind == KindPage { if d.ExpandedPermalink != "" { pagePath = pjoin(pagePath, d.ExpandedPermalink) } else { if d.Dir != "" { pagePath = pjoin(pagePath, d.Dir) } if d.BaseName != "" { pagePath = pjoin(pagePath, d.BaseName) } } if d.Addends != "" { pagePath = pjoin(pagePath, d.Addends) } link = pagePath // TODO(bep) this should not happen after the fix in https://github.com/gohugoio/hugo/issues/4870 // but we may need some more testing before we can remove it. if baseNameSameAsType { link = strings.TrimSuffix(link, d.BaseName) } pagePathDir = link link = link + slash linkDir = pagePathDir if isUgly { pagePath = addSuffix(pagePath, fullSuffix) } else { pagePath = pjoin(pagePath, d.Type.BaseName+fullSuffix) } if !isHtmlIndex(pagePath) { link = pagePath } if d.PrefixFilePath != "" { pagePath = pjoin(d.PrefixFilePath, pagePath) pagePathDir = pjoin(d.PrefixFilePath, pagePathDir) } if d.PrefixLink != "" { link = pjoin(d.PrefixLink, link) linkDir = pjoin(d.PrefixLink, linkDir) } } else { if d.Addends != "" { pagePath = pjoin(pagePath, d.Addends) } needsBase = needsBase && d.Addends == "" // No permalink expansion etc. for node type pages (for now) base := "" if needsBase || !isUgly { base = d.Type.BaseName } pagePathDir = pagePath link = pagePath linkDir = pagePathDir if base != "" { pagePath = path.Join(pagePath, addSuffix(base, fullSuffix)) } else { pagePath = addSuffix(pagePath, fullSuffix) } if !isHtmlIndex(pagePath) { link = pagePath } else { link += slash } if d.PrefixFilePath != "" { pagePath = pjoin(d.PrefixFilePath, pagePath) pagePathDir = pjoin(d.PrefixFilePath, pagePathDir) } if d.PrefixLink != "" { link = pjoin(d.PrefixLink, link) linkDir = pjoin(d.PrefixLink, linkDir) } } pagePath = pjoin(slash, pagePath) pagePathDir = strings.TrimSuffix(path.Join(slash, pagePathDir), slash) hadSlash := strings.HasSuffix(link, slash) link = strings.Trim(link, slash) if hadSlash { link += slash } if !strings.HasPrefix(link, slash) { link = slash + link } linkDir = strings.TrimSuffix(path.Join(slash, linkDir), slash) // if page URL is explicitly set in frontmatter, // preserve its value without sanitization if d.Kind != KindPage || d.URL == "" { // Note: MakePathSanitized will lower case the path if // disablePathToLower isn't set. pagePath = d.PathSpec.MakePathSanitized(pagePath) pagePathDir = d.PathSpec.MakePathSanitized(pagePathDir) link = d.PathSpec.MakePathSanitized(link) linkDir = d.PathSpec.MakePathSanitized(linkDir) } tp.TargetFilename = filepath.FromSlash(pagePath) tp.SubResourceBaseTarget = filepath.FromSlash(pagePathDir) tp.SubResourceBaseLink = linkDir tp.Link = d.PathSpec.URLizeFilename(link) if tp.Link == "" { tp.Link = slash } return } func addSuffix(s, suffix string) string { return strings.Trim(s, slash) + suffix } // Like path.Join, but preserves one trailing slash if present. func pjoin(elem ...string) string { hadSlash := strings.HasSuffix(elem[len(elem)-1], slash) joined := path.Join(elem...) if hadSlash && !strings.HasSuffix(joined, slash) { return joined + slash } return joined } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/page_paths_test.go�������������������������������������������������������0000664�0000000�0000000�00000026732�14201470003�0021176�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "fmt" "path/filepath" "strings" "testing" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/output" ) func TestPageTargetPath(t *testing.T) { pathSpec := newTestPathSpec() noExtNoDelimMediaType := media.WithDelimiterAndSuffixes(media.TextType, "", "") noExtNoDelimMediaType.Delimiter = "" // Netlify style _redirects noExtDelimFormat := output.Format{ Name: "NER", MediaType: noExtNoDelimMediaType, BaseName: "_redirects", } for _, langPrefixPath := range []string{"", "no"} { for _, langPrefixLink := range []string{"", "no"} { for _, uglyURLs := range []bool{false, true} { tests := []struct { name string d TargetPathDescriptor expected TargetPaths }{ {"JSON home", TargetPathDescriptor{Kind: KindHome, Type: output.JSONFormat}, TargetPaths{TargetFilename: "/index.json", SubResourceBaseTarget: "", Link: "/index.json"}}, {"AMP home", TargetPathDescriptor{Kind: KindHome, Type: output.AMPFormat}, TargetPaths{TargetFilename: "/amp/index.html", SubResourceBaseTarget: "/amp", Link: "/amp/"}}, {"HTML home", TargetPathDescriptor{Kind: KindHome, BaseName: "_index", Type: output.HTMLFormat}, TargetPaths{TargetFilename: "/index.html", SubResourceBaseTarget: "", Link: "/"}}, {"Netlify redirects", TargetPathDescriptor{Kind: KindHome, BaseName: "_index", Type: noExtDelimFormat}, TargetPaths{TargetFilename: "/_redirects", SubResourceBaseTarget: "", Link: "/_redirects"}}, {"HTML section list", TargetPathDescriptor{ Kind: KindSection, Sections: []string{"sect1"}, BaseName: "_index", Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/sect1/index.html", SubResourceBaseTarget: "/sect1", Link: "/sect1/"}}, {"HTML taxonomy term", TargetPathDescriptor{ Kind: KindTerm, Sections: []string{"tags", "hugo"}, BaseName: "_index", Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/tags/hugo/index.html", SubResourceBaseTarget: "/tags/hugo", Link: "/tags/hugo/"}}, {"HTML taxonomy", TargetPathDescriptor{ Kind: KindTaxonomy, Sections: []string{"tags"}, BaseName: "_index", Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/tags/index.html", SubResourceBaseTarget: "/tags", Link: "/tags/"}}, { "HTML page", TargetPathDescriptor{ Kind: KindPage, Dir: "/a/b", BaseName: "mypage", Sections: []string{"a"}, Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/a/b/mypage/index.html", SubResourceBaseTarget: "/a/b/mypage", Link: "/a/b/mypage/"}, }, { "HTML page with index as base", TargetPathDescriptor{ Kind: KindPage, Dir: "/a/b", BaseName: "index", Sections: []string{"a"}, Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/a/b/index.html", SubResourceBaseTarget: "/a/b", Link: "/a/b/"}, }, { "HTML page with special chars", TargetPathDescriptor{ Kind: KindPage, Dir: "/a/b", BaseName: "My Page!", Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/a/b/my-page/index.html", SubResourceBaseTarget: "/a/b/my-page", Link: "/a/b/my-page/"}, }, {"RSS home", TargetPathDescriptor{Kind: "rss", Type: output.RSSFormat}, TargetPaths{TargetFilename: "/index.xml", SubResourceBaseTarget: "", Link: "/index.xml"}}, {"RSS section list", TargetPathDescriptor{ Kind: "rss", Sections: []string{"sect1"}, Type: output.RSSFormat, }, TargetPaths{TargetFilename: "/sect1/index.xml", SubResourceBaseTarget: "/sect1", Link: "/sect1/index.xml"}}, { "AMP page", TargetPathDescriptor{ Kind: KindPage, Dir: "/a/b/c", BaseName: "myamp", Type: output.AMPFormat, }, TargetPaths{TargetFilename: "/amp/a/b/c/myamp/index.html", SubResourceBaseTarget: "/amp/a/b/c/myamp", Link: "/amp/a/b/c/myamp/"}, }, { "AMP page with URL with suffix", TargetPathDescriptor{ Kind: KindPage, Dir: "/sect/", BaseName: "mypage", URL: "/some/other/url.xhtml", Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/some/other/url.xhtml", SubResourceBaseTarget: "/some/other", Link: "/some/other/url.xhtml"}, }, { "JSON page with URL without suffix", TargetPathDescriptor{ Kind: KindPage, Dir: "/sect/", BaseName: "mypage", URL: "/some/other/path/", Type: output.JSONFormat, }, TargetPaths{TargetFilename: "/some/other/path/index.json", SubResourceBaseTarget: "/some/other/path", Link: "/some/other/path/index.json"}, }, { "JSON page with URL without suffix and no trailing slash", TargetPathDescriptor{ Kind: KindPage, Dir: "/sect/", BaseName: "mypage", URL: "/some/other/path", Type: output.JSONFormat, }, TargetPaths{TargetFilename: "/some/other/path/index.json", SubResourceBaseTarget: "/some/other/path", Link: "/some/other/path/index.json"}, }, { "HTML page with URL without suffix and no trailing slash", TargetPathDescriptor{ Kind: KindPage, Dir: "/sect/", BaseName: "mypage", URL: "/some/other/path", Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/some/other/path/index.html", SubResourceBaseTarget: "/some/other/path", Link: "/some/other/path/"}, }, { "HTML page with URL containing double hyphen", TargetPathDescriptor{ Kind: KindPage, Dir: "/sect/", BaseName: "mypage", URL: "/some/other--url/", Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/some/other--url/index.html", SubResourceBaseTarget: "/some/other--url", Link: "/some/other--url/"}, }, { "HTML page with expanded permalink", TargetPathDescriptor{ Kind: KindPage, Dir: "/a/b", BaseName: "mypage", ExpandedPermalink: "/2017/10/my-title/", Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/2017/10/my-title/index.html", SubResourceBaseTarget: "/2017/10/my-title", Link: "/2017/10/my-title/"}, }, { "Paginated HTML home", TargetPathDescriptor{ Kind: KindHome, BaseName: "_index", Type: output.HTMLFormat, Addends: "page/3", }, TargetPaths{TargetFilename: "/page/3/index.html", SubResourceBaseTarget: "/page/3", Link: "/page/3/"}, }, { "Paginated Taxonomy terms list", TargetPathDescriptor{ Kind: KindTerm, BaseName: "_index", Sections: []string{"tags", "hugo"}, Type: output.HTMLFormat, Addends: "page/3", }, TargetPaths{TargetFilename: "/tags/hugo/page/3/index.html", SubResourceBaseTarget: "/tags/hugo/page/3", Link: "/tags/hugo/page/3/"}, }, { "Regular page with addend", TargetPathDescriptor{ Kind: KindPage, Dir: "/a/b", BaseName: "mypage", Addends: "c/d/e", Type: output.HTMLFormat, }, TargetPaths{TargetFilename: "/a/b/mypage/c/d/e/index.html", SubResourceBaseTarget: "/a/b/mypage/c/d/e", Link: "/a/b/mypage/c/d/e/"}, }, } for i, test := range tests { t.Run(fmt.Sprintf("langPrefixPath=%s,langPrefixLink=%s,uglyURLs=%t,name=%s", langPrefixPath, langPrefixLink, uglyURLs, test.name), func(t *testing.T) { test.d.ForcePrefix = true test.d.PathSpec = pathSpec test.d.UglyURLs = uglyURLs test.d.PrefixFilePath = langPrefixPath test.d.PrefixLink = langPrefixLink test.d.Dir = filepath.FromSlash(test.d.Dir) isUgly := uglyURLs && !test.d.Type.NoUgly expected := test.expected // TODO(bep) simplify if test.d.Kind == KindPage && test.d.BaseName == test.d.Type.BaseName { } else if test.d.Kind == KindHome && test.d.Type.Path != "" { } else if test.d.Type.MediaType.FirstSuffix.Suffix != "" && (!strings.HasPrefix(expected.TargetFilename, "/index") || test.d.Addends != "") && test.d.URL == "" && isUgly { expected.TargetFilename = strings.Replace(expected.TargetFilename, "/"+test.d.Type.BaseName+"."+test.d.Type.MediaType.FirstSuffix.Suffix, "."+test.d.Type.MediaType.FirstSuffix.Suffix, 1) expected.Link = strings.TrimSuffix(expected.Link, "/") + "." + test.d.Type.MediaType.FirstSuffix.Suffix } if test.d.PrefixFilePath != "" && !strings.HasPrefix(test.d.URL, "/"+test.d.PrefixFilePath) { expected.TargetFilename = "/" + test.d.PrefixFilePath + expected.TargetFilename expected.SubResourceBaseTarget = "/" + test.d.PrefixFilePath + expected.SubResourceBaseTarget } if test.d.PrefixLink != "" && !strings.HasPrefix(test.d.URL, "/"+test.d.PrefixLink) { expected.Link = "/" + test.d.PrefixLink + expected.Link } expected.TargetFilename = filepath.FromSlash(expected.TargetFilename) expected.SubResourceBaseTarget = filepath.FromSlash(expected.SubResourceBaseTarget) pagePath := CreateTargetPaths(test.d) if !eqTargetPaths(pagePath, expected) { t.Fatalf("[%d] [%s] targetPath expected\n%#v, got:\n%#v", i, test.name, expected, pagePath) } }) } } } } } func TestPageTargetPathPrefix(t *testing.T) { pathSpec := newTestPathSpec() tests := []struct { name string d TargetPathDescriptor expected TargetPaths }{ { "URL set, prefix both, no force", TargetPathDescriptor{Kind: KindPage, Type: output.JSONFormat, URL: "/mydir/my.json", ForcePrefix: false, PrefixFilePath: "pf", PrefixLink: "pl"}, TargetPaths{TargetFilename: "/mydir/my.json", SubResourceBaseTarget: "/mydir", SubResourceBaseLink: "/mydir", Link: "/mydir/my.json"}, }, { "URL set, prefix both, force", TargetPathDescriptor{Kind: KindPage, Type: output.JSONFormat, URL: "/mydir/my.json", ForcePrefix: true, PrefixFilePath: "pf", PrefixLink: "pl"}, TargetPaths{TargetFilename: "/pf/mydir/my.json", SubResourceBaseTarget: "/pf/mydir", SubResourceBaseLink: "/pl/mydir", Link: "/pl/mydir/my.json"}, }, } for i, test := range tests { t.Run(fmt.Sprintf(test.name), func(t *testing.T) { test.d.PathSpec = pathSpec expected := test.expected expected.TargetFilename = filepath.FromSlash(expected.TargetFilename) expected.SubResourceBaseTarget = filepath.FromSlash(expected.SubResourceBaseTarget) pagePath := CreateTargetPaths(test.d) if pagePath != expected { t.Fatalf("[%d] [%s] targetPath expected\n%#v, got:\n%#v", i, test.name, expected, pagePath) } }) } } func eqTargetPaths(p1, p2 TargetPaths) bool { if p1.Link != p2.Link { return false } if p1.SubResourceBaseTarget != p2.SubResourceBaseTarget { return false } if p1.TargetFilename != p2.TargetFilename { return false } return true } ��������������������������������������hugo-0.92.2/resources/page/page_wrappers.autogen.go�������������������������������������������������0000664�0000000�0000000�00000006701�14201470003�0022316�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This file is autogenerated. package page import ( "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "html/template" ) // NewDeprecatedWarningPage adds deprecation warnings to the given implementation. func NewDeprecatedWarningPage(p DeprecatedWarningPageMethods) DeprecatedWarningPageMethods { return &pageDeprecated{p: p} } type pageDeprecated struct { p DeprecatedWarningPageMethods } func (p *pageDeprecated) Filename() string { helpers.Deprecated("Page.Filename", "Use .File.Filename", true) return p.p.Filename() } func (p *pageDeprecated) Dir() string { helpers.Deprecated("Page.Dir", "Use .File.Dir", true) return p.p.Dir() } func (p *pageDeprecated) IsDraft() bool { helpers.Deprecated("Page.IsDraft", "Use .Draft.", true) return p.p.IsDraft() } func (p *pageDeprecated) Extension() string { helpers.Deprecated("Page.Extension", "Use .File.Extension", true) return p.p.Extension() } func (p *pageDeprecated) Hugo() hugo.Info { helpers.Deprecated("Page.Hugo", "Use the global hugo function.", true) return p.p.Hugo() } func (p *pageDeprecated) Ext() string { helpers.Deprecated("Page.Ext", "Use .File.Ext", true) return p.p.Ext() } func (p *pageDeprecated) LanguagePrefix() string { helpers.Deprecated("Page.LanguagePrefix", "Use .Site.LanguagePrefix.", true) return p.p.LanguagePrefix() } func (p *pageDeprecated) GetParam(arg0 string) interface{} { helpers.Deprecated("Page.GetParam", "Use .Param or .Params.myParam.", true) return p.p.GetParam(arg0) } func (p *pageDeprecated) LogicalName() string { helpers.Deprecated("Page.LogicalName", "Use .File.LogicalName", true) return p.p.LogicalName() } func (p *pageDeprecated) BaseFileName() string { helpers.Deprecated("Page.BaseFileName", "Use .File.BaseFileName", true) return p.p.BaseFileName() } func (p *pageDeprecated) RSSLink() template.URL { helpers.Deprecated("Page.RSSLink", "Use the Output Format's link, e.g. something like:\n {{ with .OutputFormats.Get \"RSS\" }}{{ .RelPermalink }}{{ end }}", true) return p.p.RSSLink() } func (p *pageDeprecated) TranslationBaseName() string { helpers.Deprecated("Page.TranslationBaseName", "Use .File.TranslationBaseName", true) return p.p.TranslationBaseName() } func (p *pageDeprecated) URL() string { helpers.Deprecated("Page.URL", "Use .Permalink or .RelPermalink. If what you want is the front matter URL value, use .Params.url", true) return p.p.URL() } func (p *pageDeprecated) ContentBaseName() string { helpers.Deprecated("Page.ContentBaseName", "Use .File.ContentBaseName", true) return p.p.ContentBaseName() } func (p *pageDeprecated) UniqueID() string { helpers.Deprecated("Page.UniqueID", "Use .File.UniqueID", true) return p.p.UniqueID() } func (p *pageDeprecated) FileInfo() hugofs.FileMetaInfo { helpers.Deprecated("Page.FileInfo", "Use .File.FileInfo", true) return p.p.FileInfo() } ���������������������������������������������������������������hugo-0.92.2/resources/page/pagegroup.go�������������������������������������������������������������0000664�0000000�0000000�00000026672�14201470003�0020020�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "errors" "fmt" "reflect" "sort" "strings" "time" "github.com/spf13/cast" "github.com/gohugoio/hugo/common/collections" "github.com/gohugoio/hugo/compare" "github.com/gohugoio/hugo/resources/resource" ) var ( _ collections.Slicer = PageGroup{} _ compare.ProbablyEqer = PageGroup{} _ compare.ProbablyEqer = PagesGroup{} ) // PageGroup represents a group of pages, grouped by the key. // The key is typically a year or similar. type PageGroup struct { Key interface{} Pages } type mapKeyValues []reflect.Value func (v mapKeyValues) Len() int { return len(v) } func (v mapKeyValues) Swap(i, j int) { v[i], v[j] = v[j], v[i] } type mapKeyByInt struct{ mapKeyValues } func (s mapKeyByInt) Less(i, j int) bool { return s.mapKeyValues[i].Int() < s.mapKeyValues[j].Int() } type mapKeyByStr struct{ mapKeyValues } func (s mapKeyByStr) Less(i, j int) bool { return compare.LessStrings(s.mapKeyValues[i].String(), s.mapKeyValues[j].String()) } func sortKeys(v []reflect.Value, order string) []reflect.Value { if len(v) <= 1 { return v } switch v[0].Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if order == "desc" { sort.Sort(sort.Reverse(mapKeyByInt{v})) } else { sort.Sort(mapKeyByInt{v}) } case reflect.String: if order == "desc" { sort.Sort(sort.Reverse(mapKeyByStr{v})) } else { sort.Sort(mapKeyByStr{v}) } } return v } // PagesGroup represents a list of page groups. // This is what you get when doing page grouping in the templates. type PagesGroup []PageGroup // Reverse reverses the order of this list of page groups. func (p PagesGroup) Reverse() PagesGroup { for i, j := 0, len(p)-1; i < j; i, j = i+1, j-1 { p[i], p[j] = p[j], p[i] } return p } var ( errorType = reflect.TypeOf((*error)(nil)).Elem() pagePtrType = reflect.TypeOf((*Page)(nil)).Elem() pagesType = reflect.TypeOf(Pages{}) ) // GroupBy groups by the value in the given field or method name and with the given order. // Valid values for order is asc, desc, rev and reverse. func (p Pages) GroupBy(key string, order ...string) (PagesGroup, error) { if len(p) < 1 { return nil, nil } direction := "asc" if len(order) > 0 && (strings.ToLower(order[0]) == "desc" || strings.ToLower(order[0]) == "rev" || strings.ToLower(order[0]) == "reverse") { direction = "desc" } var ft interface{} m, ok := pagePtrType.MethodByName(key) if ok { if m.Type.NumOut() == 0 || m.Type.NumOut() > 2 { return nil, errors.New(key + " is a Page method but you can't use it with GroupBy") } if m.Type.NumOut() == 1 && m.Type.Out(0).Implements(errorType) { return nil, errors.New(key + " is a Page method but you can't use it with GroupBy") } if m.Type.NumOut() == 2 && !m.Type.Out(1).Implements(errorType) { return nil, errors.New(key + " is a Page method but you can't use it with GroupBy") } ft = m } else { ft, ok = pagePtrType.Elem().FieldByName(key) if !ok { return nil, errors.New(key + " is neither a field nor a method of Page") } } var tmp reflect.Value switch e := ft.(type) { case reflect.StructField: tmp = reflect.MakeMap(reflect.MapOf(e.Type, pagesType)) case reflect.Method: tmp = reflect.MakeMap(reflect.MapOf(e.Type.Out(0), pagesType)) } for _, e := range p { ppv := reflect.ValueOf(e) var fv reflect.Value switch ft.(type) { case reflect.StructField: fv = ppv.Elem().FieldByName(key) case reflect.Method: fv = ppv.MethodByName(key).Call([]reflect.Value{})[0] } if !fv.IsValid() { continue } if !tmp.MapIndex(fv).IsValid() { tmp.SetMapIndex(fv, reflect.MakeSlice(pagesType, 0, 0)) } tmp.SetMapIndex(fv, reflect.Append(tmp.MapIndex(fv), ppv)) } sortedKeys := sortKeys(tmp.MapKeys(), direction) r := make([]PageGroup, len(sortedKeys)) for i, k := range sortedKeys { r[i] = PageGroup{Key: k.Interface(), Pages: tmp.MapIndex(k).Interface().(Pages)} } return r, nil } // GroupByParam groups by the given page parameter key's value and with the given order. // Valid values for order is asc, desc, rev and reverse. func (p Pages) GroupByParam(key string, order ...string) (PagesGroup, error) { if len(p) < 1 { return nil, nil } direction := "asc" if len(order) > 0 && (strings.ToLower(order[0]) == "desc" || strings.ToLower(order[0]) == "rev" || strings.ToLower(order[0]) == "reverse") { direction = "desc" } var tmp reflect.Value var keyt reflect.Type for _, e := range p { param := resource.GetParamToLower(e, key) if param != nil { if _, ok := param.([]string); !ok { keyt = reflect.TypeOf(param) tmp = reflect.MakeMap(reflect.MapOf(keyt, pagesType)) break } } } if !tmp.IsValid() { return nil, errors.New("there is no such a param") } for _, e := range p { param := resource.GetParam(e, key) if param == nil || reflect.TypeOf(param) != keyt { continue } v := reflect.ValueOf(param) if !tmp.MapIndex(v).IsValid() { tmp.SetMapIndex(v, reflect.MakeSlice(pagesType, 0, 0)) } tmp.SetMapIndex(v, reflect.Append(tmp.MapIndex(v), reflect.ValueOf(e))) } var r []PageGroup for _, k := range sortKeys(tmp.MapKeys(), direction) { r = append(r, PageGroup{Key: k.Interface(), Pages: tmp.MapIndex(k).Interface().(Pages)}) } return r, nil } func (p Pages) groupByDateField(sorter func(p Pages) Pages, formatter func(p Page) string, order ...string) (PagesGroup, error) { if len(p) < 1 { return nil, nil } sp := sorter(p) if !(len(order) > 0 && (strings.ToLower(order[0]) == "asc" || strings.ToLower(order[0]) == "rev" || strings.ToLower(order[0]) == "reverse")) { sp = sp.Reverse() } if sp == nil { return nil, nil } date := formatter(sp[0].(Page)) var r []PageGroup r = append(r, PageGroup{Key: date, Pages: make(Pages, 0)}) r[0].Pages = append(r[0].Pages, sp[0]) i := 0 for _, e := range sp[1:] { date = formatter(e.(Page)) if r[i].Key.(string) != date { r = append(r, PageGroup{Key: date}) i++ } r[i].Pages = append(r[i].Pages, e) } return r, nil } // GroupByDate groups by the given page's Date value in // the given format and with the given order. // Valid values for order is asc, desc, rev and reverse. // For valid format strings, see https://golang.org/pkg/time/#Time.Format func (p Pages) GroupByDate(format string, order ...string) (PagesGroup, error) { sorter := func(p Pages) Pages { return p.ByDate() } formatter := func(p Page) string { return p.Date().Format(format) } return p.groupByDateField(sorter, formatter, order...) } // GroupByPublishDate groups by the given page's PublishDate value in // the given format and with the given order. // Valid values for order is asc, desc, rev and reverse. // For valid format strings, see https://golang.org/pkg/time/#Time.Format func (p Pages) GroupByPublishDate(format string, order ...string) (PagesGroup, error) { sorter := func(p Pages) Pages { return p.ByPublishDate() } formatter := func(p Page) string { return p.PublishDate().Format(format) } return p.groupByDateField(sorter, formatter, order...) } // GroupByExpiryDate groups by the given page's ExpireDate value in // the given format and with the given order. // Valid values for order is asc, desc, rev and reverse. // For valid format strings, see https://golang.org/pkg/time/#Time.Format func (p Pages) GroupByExpiryDate(format string, order ...string) (PagesGroup, error) { sorter := func(p Pages) Pages { return p.ByExpiryDate() } formatter := func(p Page) string { return p.ExpiryDate().Format(format) } return p.groupByDateField(sorter, formatter, order...) } // GroupByLastmod groups by the given page's Lastmod value in // the given format and with the given order. // Valid values for order is asc, desc, rev and reverse. // For valid format strings, see https://golang.org/pkg/time/#Time.Format func (p Pages) GroupByLastmod(format string, order ...string) (PagesGroup, error) { sorter := func(p Pages) Pages { return p.ByLastmod() } formatter := func(p Page) string { return p.Lastmod().Format(format) } return p.groupByDateField(sorter, formatter, order...) } // GroupByParamDate groups by a date set as a param on the page in // the given format and with the given order. // Valid values for order is asc, desc, rev and reverse. // For valid format strings, see https://golang.org/pkg/time/#Time.Format func (p Pages) GroupByParamDate(key string, format string, order ...string) (PagesGroup, error) { // Cache the dates. dates := make(map[Page]time.Time) sorter := func(pages Pages) Pages { var r Pages for _, p := range pages { param := resource.GetParam(p, key) var t time.Time if param != nil { var ok bool if t, ok = param.(time.Time); !ok { // Probably a string. Try to convert it to time.Time. t = cast.ToTime(param) } } dates[p] = t r = append(r, p) } pdate := func(p1, p2 Page) bool { return dates[p1].Unix() < dates[p2].Unix() } pageBy(pdate).Sort(r) return r } formatter := func(p Page) string { return dates[p].Format(format) } return p.groupByDateField(sorter, formatter, order...) } // ProbablyEq wraps compare.ProbablyEqer func (p PageGroup) ProbablyEq(other interface{}) bool { otherP, ok := other.(PageGroup) if !ok { return false } if p.Key != otherP.Key { return false } return p.Pages.ProbablyEq(otherP.Pages) } // Slice is not meant to be used externally. It's a bridge function // for the template functions. See collections.Slice. func (p PageGroup) Slice(in interface{}) (interface{}, error) { switch items := in.(type) { case PageGroup: return items, nil case []interface{}: groups := make(PagesGroup, len(items)) for i, v := range items { g, ok := v.(PageGroup) if !ok { return nil, fmt.Errorf("type %T is not a PageGroup", v) } groups[i] = g } return groups, nil default: return nil, fmt.Errorf("invalid slice type %T", items) } } // Len returns the number of pages in the page group. func (psg PagesGroup) Len() int { l := 0 for _, pg := range psg { l += len(pg.Pages) } return l } // ProbablyEq wraps compare.ProbablyEqer func (psg PagesGroup) ProbablyEq(other interface{}) bool { otherPsg, ok := other.(PagesGroup) if !ok { return false } if len(psg) != len(otherPsg) { return false } for i := range psg { if !psg[i].ProbablyEq(otherPsg[i]) { return false } } return true } // ToPagesGroup tries to convert seq into a PagesGroup. func ToPagesGroup(seq interface{}) (PagesGroup, error) { switch v := seq.(type) { case nil: return nil, nil case PagesGroup: return v, nil case []PageGroup: return PagesGroup(v), nil case []interface{}: l := len(v) if l == 0 { break } switch v[0].(type) { case PageGroup: pagesGroup := make(PagesGroup, l) for i, ipg := range v { if pg, ok := ipg.(PageGroup); ok { pagesGroup[i] = pg } else { return nil, fmt.Errorf("unsupported type in paginate from slice, got %T instead of PageGroup", ipg) } } return pagesGroup, nil } } return nil, nil } ����������������������������������������������������������������������hugo-0.92.2/resources/page/pagegroup_test.go��������������������������������������������������������0000664�0000000�0000000�00000032450�14201470003�0021046�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "reflect" "strings" "testing" qt "github.com/frankban/quicktest" "github.com/spf13/cast" ) type pageGroupTestObject struct { path string weight int date string param string } var pageGroupTestSources = []pageGroupTestObject{ {"/section1/testpage1.md", 3, "2012-04-06", "foo"}, {"/section1/testpage2.md", 3, "2012-01-01", "bar"}, {"/section1/testpage3.md", 2, "2012-04-06", "foo"}, {"/section2/testpage4.md", 1, "2012-03-02", "bar"}, // date might also be a full datetime: {"/section2/testpage5.md", 1, "2012-04-06T00:00:00Z", "baz"}, } func preparePageGroupTestPages(t *testing.T) Pages { var pages Pages for _, src := range pageGroupTestSources { p := newTestPage() p.path = src.path if p.path != "" { p.section = strings.Split(strings.TrimPrefix(p.path, "/"), "/")[0] } p.weight = src.weight p.date = cast.ToTime(src.date) p.pubDate = cast.ToTime(src.date) p.expiryDate = cast.ToTime(src.date) p.lastMod = cast.ToTime(src.date).AddDate(3, 0, 0) p.params["custom_param"] = src.param p.params["custom_date"] = cast.ToTime(src.date) p.params["custom_string_date"] = src.date pages = append(pages, p) } return pages } func TestGroupByWithFieldNameArg(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: 1, Pages: Pages{pages[3], pages[4]}}, {Key: 2, Pages: Pages{pages[2]}}, {Key: 3, Pages: Pages{pages[0], pages[1]}}, } groups, err := pages.GroupBy("Weight") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByWithMethodNameArg(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "section1", Pages: Pages{pages[0], pages[1], pages[2]}}, {Key: "section2", Pages: Pages{pages[3], pages[4]}}, } groups, err := pages.GroupBy("Type") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByWithSectionArg(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "section1", Pages: Pages{pages[0], pages[1], pages[2]}}, {Key: "section2", Pages: Pages{pages[3], pages[4]}}, } groups, err := pages.GroupBy("Section") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be\n%#v, got\n%#v", expect, groups) } } func TestGroupByInReverseOrder(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: 3, Pages: Pages{pages[0], pages[1]}}, {Key: 2, Pages: Pages{pages[2]}}, {Key: 1, Pages: Pages{pages[3], pages[4]}}, } groups, err := pages.GroupBy("Weight", "desc") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByCalledWithEmptyPages(t *testing.T) { t.Parallel() var pages Pages groups, err := pages.GroupBy("Weight") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if groups != nil { t.Errorf("PagesGroup isn't empty. It should be %#v, got %#v", nil, groups) } } func TestGroupByParamCalledWithUnavailableKey(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) _, err := pages.GroupByParam("UnavailableKey") if err == nil { t.Errorf("GroupByParam should return an error but didn't") } } func TestReverse(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) groups1, err := pages.GroupBy("Weight", "desc") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } groups2, err := pages.GroupBy("Weight") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } groups2 = groups2.Reverse() if !reflect.DeepEqual(groups2, groups1) { t.Errorf("PagesGroup is sorted in unexpected order. It should be %#v, got %#v", groups2, groups1) } } func TestGroupByParam(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "bar", Pages: Pages{pages[1], pages[3]}}, {Key: "baz", Pages: Pages{pages[4]}}, {Key: "foo", Pages: Pages{pages[0], pages[2]}}, } groups, err := pages.GroupByParam("custom_param") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByParamInReverseOrder(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "foo", Pages: Pages{pages[0], pages[2]}}, {Key: "baz", Pages: Pages{pages[4]}}, {Key: "bar", Pages: Pages{pages[1], pages[3]}}, } groups, err := pages.GroupByParam("custom_param", "desc") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByParamCalledWithCapitalLetterString(t *testing.T) { c := qt.New(t) testStr := "TestString" p := newTestPage() p.params["custom_param"] = testStr pages := Pages{p} groups, err := pages.GroupByParam("custom_param") c.Assert(err, qt.IsNil) c.Assert(groups[0].Key, qt.Equals, testStr) } func TestGroupByParamCalledWithSomeUnavailableParams(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) delete(pages[1].Params(), "custom_param") delete(pages[3].Params(), "custom_param") delete(pages[4].Params(), "custom_param") expect := PagesGroup{ {Key: "foo", Pages: Pages{pages[0], pages[2]}}, } groups, err := pages.GroupByParam("custom_param") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByParamCalledWithEmptyPages(t *testing.T) { t.Parallel() var pages Pages groups, err := pages.GroupByParam("custom_param") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if groups != nil { t.Errorf("PagesGroup isn't empty. It should be %#v, got %#v", nil, groups) } } func TestGroupByParamCalledWithUnavailableParam(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) _, err := pages.GroupByParam("unavailable_param") if err == nil { t.Errorf("GroupByParam should return an error but didn't") } } func TestGroupByDate(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "2012-04", Pages: Pages{pages[4], pages[2], pages[0]}}, {Key: "2012-03", Pages: Pages{pages[3]}}, {Key: "2012-01", Pages: Pages{pages[1]}}, } groups, err := pages.GroupByDate("2006-01") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByDateInReverseOrder(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "2012-01", Pages: Pages{pages[1]}}, {Key: "2012-03", Pages: Pages{pages[3]}}, {Key: "2012-04", Pages: Pages{pages[0], pages[2], pages[4]}}, } groups, err := pages.GroupByDate("2006-01", "asc") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByPublishDate(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "2012-04", Pages: Pages{pages[4], pages[2], pages[0]}}, {Key: "2012-03", Pages: Pages{pages[3]}}, {Key: "2012-01", Pages: Pages{pages[1]}}, } groups, err := pages.GroupByPublishDate("2006-01") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByPublishDateInReverseOrder(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "2012-01", Pages: Pages{pages[1]}}, {Key: "2012-03", Pages: Pages{pages[3]}}, {Key: "2012-04", Pages: Pages{pages[0], pages[2], pages[4]}}, } groups, err := pages.GroupByDate("2006-01", "asc") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByPublishDateWithEmptyPages(t *testing.T) { t.Parallel() var pages Pages groups, err := pages.GroupByPublishDate("2006-01") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if groups != nil { t.Errorf("PagesGroup isn't empty. It should be %#v, got %#v", nil, groups) } } func TestGroupByExpiryDate(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "2012-04", Pages: Pages{pages[4], pages[2], pages[0]}}, {Key: "2012-03", Pages: Pages{pages[3]}}, {Key: "2012-01", Pages: Pages{pages[1]}}, } groups, err := pages.GroupByExpiryDate("2006-01") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByParamDate(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "2012-04", Pages: Pages{pages[4], pages[2], pages[0]}}, {Key: "2012-03", Pages: Pages{pages[3]}}, {Key: "2012-01", Pages: Pages{pages[1]}}, } groups, err := pages.GroupByParamDate("custom_date", "2006-01") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } // https://github.com/gohugoio/hugo/issues/3983 func TestGroupByParamDateWithStringParams(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "2012-04", Pages: Pages{pages[4], pages[2], pages[0]}}, {Key: "2012-03", Pages: Pages{pages[3]}}, {Key: "2012-01", Pages: Pages{pages[1]}}, } groups, err := pages.GroupByParamDate("custom_string_date", "2006-01") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByLastmod(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "2015-04", Pages: Pages{pages[4], pages[2], pages[0]}}, {Key: "2015-03", Pages: Pages{pages[3]}}, {Key: "2015-01", Pages: Pages{pages[1]}}, } groups, err := pages.GroupByLastmod("2006-01") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByLastmodInReverseOrder(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "2015-01", Pages: Pages{pages[1]}}, {Key: "2015-03", Pages: Pages{pages[3]}}, {Key: "2015-04", Pages: Pages{pages[0], pages[2], pages[4]}}, } groups, err := pages.GroupByLastmod("2006-01", "asc") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be\n%#v, got\n%#v", expect, groups) } } func TestGroupByParamDateInReverseOrder(t *testing.T) { t.Parallel() pages := preparePageGroupTestPages(t) expect := PagesGroup{ {Key: "2012-01", Pages: Pages{pages[1]}}, {Key: "2012-03", Pages: Pages{pages[3]}}, {Key: "2012-04", Pages: Pages{pages[0], pages[2], pages[4]}}, } groups, err := pages.GroupByParamDate("custom_date", "2006-01", "asc") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if !reflect.DeepEqual(groups, expect) { t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups) } } func TestGroupByParamDateWithEmptyPages(t *testing.T) { t.Parallel() var pages Pages groups, err := pages.GroupByParamDate("custom_date", "2006-01") if err != nil { t.Fatalf("Unable to make PagesGroup array: %s", err) } if groups != nil { t.Errorf("PagesGroup isn't empty. It should be %#v, got %#v", nil, groups) } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pagemeta/����������������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0017246�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pagemeta/page_frontmatter.go���������������������������������������������0000664�0000000�0000000�00000026164�14201470003�0023147�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package pagemeta import ( "strings" "time" "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/paths" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/config" "github.com/spf13/cast" ) // FrontMatterHandler maps front matter into Page fields and .Params. // Note that we currently have only extracted the date logic. type FrontMatterHandler struct { fmConfig frontmatterConfig dateHandler frontMatterFieldHandler lastModHandler frontMatterFieldHandler publishDateHandler frontMatterFieldHandler expiryDateHandler frontMatterFieldHandler // A map of all date keys configured, including any custom. allDateKeys map[string]bool logger loggers.Logger } // FrontMatterDescriptor describes how to handle front matter for a given Page. // It has pointers to values in the receiving page which gets updated. type FrontMatterDescriptor struct { // This the Page's front matter. Frontmatter map[string]interface{} // This is the Page's base filename (BaseFilename), e.g. page.md., or // if page is a leaf bundle, the bundle folder name (ContentBaseName). BaseFilename string // The content file's mod time. ModTime time.Time // May be set from the author date in Git. GitAuthorDate time.Time // The below are pointers to values on Page and will be modified. // This is the Page's params. Params map[string]interface{} // This is the Page's dates. Dates *resource.Dates // This is the Page's Slug etc. PageURLs *URLPath // The Location to use to parse dates without time zone info. Location *time.Location } var dateFieldAliases = map[string][]string{ fmDate: {}, fmLastmod: {"modified"}, fmPubDate: {"pubdate", "published"}, fmExpiryDate: {"unpublishdate"}, } // HandleDates updates all the dates given the current configuration and the // supplied front matter params. Note that this requires all lower-case keys // in the params map. func (f FrontMatterHandler) HandleDates(d *FrontMatterDescriptor) error { if d.Dates == nil { panic("missing dates") } if f.dateHandler == nil { panic("missing date handler") } if _, err := f.dateHandler(d); err != nil { return err } if _, err := f.lastModHandler(d); err != nil { return err } if _, err := f.publishDateHandler(d); err != nil { return err } if _, err := f.expiryDateHandler(d); err != nil { return err } return nil } // IsDateKey returns whether the given front matter key is considered a date by the current // configuration. func (f FrontMatterHandler) IsDateKey(key string) bool { return f.allDateKeys[key] } // A Zero date is a signal that the name can not be parsed. // This follows the format as outlined in Jekyll, https://jekyllrb.com/docs/posts/: // "Where YEAR is a four-digit number, MONTH and DAY are both two-digit numbers" func dateAndSlugFromBaseFilename(location *time.Location, name string) (time.Time, string) { withoutExt, _ := paths.FileAndExt(name) if len(withoutExt) < 10 { // This can not be a date. return time.Time{}, "" } d, err := htime.ToTimeInDefaultLocationE(withoutExt[:10], location) if err != nil { return time.Time{}, "" } // Be a little lenient with the format here. slug := strings.Trim(withoutExt[10:], " -_") return d, slug } type frontMatterFieldHandler func(d *FrontMatterDescriptor) (bool, error) func (f FrontMatterHandler) newChainedFrontMatterFieldHandler(handlers ...frontMatterFieldHandler) frontMatterFieldHandler { return func(d *FrontMatterDescriptor) (bool, error) { for _, h := range handlers { // First successful handler wins. success, err := h(d) if err != nil { f.logger.Errorln(err) } else if success { return true, nil } } return false, nil } } type frontmatterConfig struct { date []string lastmod []string publishDate []string expiryDate []string } const ( // These are all the date handler identifiers // All identifiers not starting with a ":" maps to a front matter parameter. fmDate = "date" fmPubDate = "publishdate" fmLastmod = "lastmod" fmExpiryDate = "expirydate" // Gets date from filename, e.g 218-02-22-mypage.md fmFilename = ":filename" // Gets date from file OS mod time. fmModTime = ":filemodtime" // Gets date from Git fmGitAuthorDate = ":git" ) // This is the config you get when doing nothing. func newDefaultFrontmatterConfig() frontmatterConfig { return frontmatterConfig{ date: []string{fmDate, fmPubDate, fmLastmod}, lastmod: []string{fmGitAuthorDate, fmLastmod, fmDate, fmPubDate}, publishDate: []string{fmPubDate, fmDate}, expiryDate: []string{fmExpiryDate}, } } func newFrontmatterConfig(cfg config.Provider) (frontmatterConfig, error) { c := newDefaultFrontmatterConfig() defaultConfig := c if cfg.IsSet("frontmatter") { fm := cfg.GetStringMap("frontmatter") for k, v := range fm { loki := strings.ToLower(k) switch loki { case fmDate: c.date = toLowerSlice(v) case fmPubDate: c.publishDate = toLowerSlice(v) case fmLastmod: c.lastmod = toLowerSlice(v) case fmExpiryDate: c.expiryDate = toLowerSlice(v) } } } expander := func(c, d []string) []string { out := expandDefaultValues(c, d) out = addDateFieldAliases(out) return out } c.date = expander(c.date, defaultConfig.date) c.publishDate = expander(c.publishDate, defaultConfig.publishDate) c.lastmod = expander(c.lastmod, defaultConfig.lastmod) c.expiryDate = expander(c.expiryDate, defaultConfig.expiryDate) return c, nil } func addDateFieldAliases(values []string) []string { var complete []string for _, v := range values { complete = append(complete, v) if aliases, found := dateFieldAliases[v]; found { complete = append(complete, aliases...) } } return helpers.UniqueStringsReuse(complete) } func expandDefaultValues(values []string, defaults []string) []string { var out []string for _, v := range values { if v == ":default" { out = append(out, defaults...) } else { out = append(out, v) } } return out } func toLowerSlice(in interface{}) []string { out := cast.ToStringSlice(in) for i := 0; i < len(out); i++ { out[i] = strings.ToLower(out[i]) } return out } // NewFrontmatterHandler creates a new FrontMatterHandler with the given logger and configuration. // If no logger is provided, one will be created. func NewFrontmatterHandler(logger loggers.Logger, cfg config.Provider) (FrontMatterHandler, error) { if logger == nil { logger = loggers.NewErrorLogger() } frontMatterConfig, err := newFrontmatterConfig(cfg) if err != nil { return FrontMatterHandler{}, err } allDateKeys := make(map[string]bool) addKeys := func(vals []string) { for _, k := range vals { if !strings.HasPrefix(k, ":") { allDateKeys[k] = true } } } addKeys(frontMatterConfig.date) addKeys(frontMatterConfig.expiryDate) addKeys(frontMatterConfig.lastmod) addKeys(frontMatterConfig.publishDate) f := FrontMatterHandler{logger: logger, fmConfig: frontMatterConfig, allDateKeys: allDateKeys} if err := f.createHandlers(); err != nil { return f, err } return f, nil } func (f *FrontMatterHandler) createHandlers() error { var err error if f.dateHandler, err = f.createDateHandler(f.fmConfig.date, func(d *FrontMatterDescriptor, t time.Time) { d.Dates.FDate = t setParamIfNotSet(fmDate, t, d) }); err != nil { return err } if f.lastModHandler, err = f.createDateHandler(f.fmConfig.lastmod, func(d *FrontMatterDescriptor, t time.Time) { setParamIfNotSet(fmLastmod, t, d) d.Dates.FLastmod = t }); err != nil { return err } if f.publishDateHandler, err = f.createDateHandler(f.fmConfig.publishDate, func(d *FrontMatterDescriptor, t time.Time) { setParamIfNotSet(fmPubDate, t, d) d.Dates.FPublishDate = t }); err != nil { return err } if f.expiryDateHandler, err = f.createDateHandler(f.fmConfig.expiryDate, func(d *FrontMatterDescriptor, t time.Time) { setParamIfNotSet(fmExpiryDate, t, d) d.Dates.FExpiryDate = t }); err != nil { return err } return nil } func setParamIfNotSet(key string, value interface{}, d *FrontMatterDescriptor) { if _, found := d.Params[key]; found { return } d.Params[key] = value } func (f FrontMatterHandler) createDateHandler(identifiers []string, setter func(d *FrontMatterDescriptor, t time.Time)) (frontMatterFieldHandler, error) { var h *frontmatterFieldHandlers var handlers []frontMatterFieldHandler for _, identifier := range identifiers { switch identifier { case fmFilename: handlers = append(handlers, h.newDateFilenameHandler(setter)) case fmModTime: handlers = append(handlers, h.newDateModTimeHandler(setter)) case fmGitAuthorDate: handlers = append(handlers, h.newDateGitAuthorDateHandler(setter)) default: handlers = append(handlers, h.newDateFieldHandler(identifier, setter)) } } return f.newChainedFrontMatterFieldHandler(handlers...), nil } type frontmatterFieldHandlers int func (f *frontmatterFieldHandlers) newDateFieldHandler(key string, setter func(d *FrontMatterDescriptor, t time.Time)) frontMatterFieldHandler { return func(d *FrontMatterDescriptor) (bool, error) { v, found := d.Frontmatter[key] if !found { return false, nil } date, err := htime.ToTimeInDefaultLocationE(v, d.Location) if err != nil { return false, nil } // We map several date keys to one, so, for example, // "expirydate", "unpublishdate" will all set .ExpiryDate (first found). setter(d, date) // This is the params key as set in front matter. d.Params[key] = date return true, nil } } func (f *frontmatterFieldHandlers) newDateFilenameHandler(setter func(d *FrontMatterDescriptor, t time.Time)) frontMatterFieldHandler { return func(d *FrontMatterDescriptor) (bool, error) { date, slug := dateAndSlugFromBaseFilename(d.Location, d.BaseFilename) if date.IsZero() { return false, nil } setter(d, date) if _, found := d.Frontmatter["slug"]; !found { // Use slug from filename d.PageURLs.Slug = slug } return true, nil } } func (f *frontmatterFieldHandlers) newDateModTimeHandler(setter func(d *FrontMatterDescriptor, t time.Time)) frontMatterFieldHandler { return func(d *FrontMatterDescriptor) (bool, error) { if d.ModTime.IsZero() { return false, nil } setter(d, d.ModTime) return true, nil } } func (f *frontmatterFieldHandlers) newDateGitAuthorDateHandler(setter func(d *FrontMatterDescriptor, t time.Time)) frontMatterFieldHandler { return func(d *FrontMatterDescriptor) (bool, error) { if d.GitAuthorDate.IsZero() { return false, nil } setter(d, d.GitAuthorDate) return true, nil } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pagemeta/page_frontmatter_test.go����������������������������������������0000664�0000000�0000000�00000020222�14201470003�0024173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package pagemeta import ( "strings" "testing" "time" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/resources/resource" qt "github.com/frankban/quicktest" ) func TestDateAndSlugFromBaseFilename(t *testing.T) { t.Parallel() c := qt.New(t) tests := []struct { name string date string slug string }{ {"page.md", "0001-01-01", ""}, {"2012-09-12-page.md", "2012-09-12", "page"}, {"2018-02-28-page.md", "2018-02-28", "page"}, {"2018-02-28_page.md", "2018-02-28", "page"}, {"2018-02-28 page.md", "2018-02-28", "page"}, {"2018-02-28page.md", "2018-02-28", "page"}, {"2018-02-28-.md", "2018-02-28", ""}, {"2018-02-28-.md", "2018-02-28", ""}, {"2018-02-28.md", "2018-02-28", ""}, {"2018-02-28-page", "2018-02-28", "page"}, {"2012-9-12-page.md", "0001-01-01", ""}, {"asdfasdf.md", "0001-01-01", ""}, } for _, test := range tests { expecteFDate, err := time.Parse("2006-01-02", test.date) c.Assert(err, qt.IsNil) gotDate, gotSlug := dateAndSlugFromBaseFilename(time.UTC, test.name) c.Assert(gotDate, qt.Equals, expecteFDate) c.Assert(gotSlug, qt.Equals, test.slug) } } func newTestFd() *FrontMatterDescriptor { return &FrontMatterDescriptor{ Frontmatter: make(map[string]interface{}), Params: make(map[string]interface{}), Dates: &resource.Dates{}, PageURLs: &URLPath{}, Location: time.UTC, } } func TestFrontMatterNewConfig(t *testing.T) { c := qt.New(t) cfg := config.New() cfg.Set("frontmatter", map[string]interface{}{ "date": []string{"publishDate", "LastMod"}, "Lastmod": []string{"publishDate"}, "expiryDate": []string{"lastMod"}, "publishDate": []string{"date"}, }) fc, err := newFrontmatterConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(fc.date, qt.DeepEquals, []string{"publishdate", "pubdate", "published", "lastmod", "modified"}) c.Assert(fc.lastmod, qt.DeepEquals, []string{"publishdate", "pubdate", "published"}) c.Assert(fc.expiryDate, qt.DeepEquals, []string{"lastmod", "modified"}) c.Assert(fc.publishDate, qt.DeepEquals, []string{"date"}) // Default cfg = config.New() fc, err = newFrontmatterConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(fc.date, qt.DeepEquals, []string{"date", "publishdate", "pubdate", "published", "lastmod", "modified"}) c.Assert(fc.lastmod, qt.DeepEquals, []string{":git", "lastmod", "modified", "date", "publishdate", "pubdate", "published"}) c.Assert(fc.expiryDate, qt.DeepEquals, []string{"expirydate", "unpublishdate"}) c.Assert(fc.publishDate, qt.DeepEquals, []string{"publishdate", "pubdate", "published", "date"}) // :default keyword cfg.Set("frontmatter", map[string]interface{}{ "date": []string{"d1", ":default"}, "lastmod": []string{"d2", ":default"}, "expiryDate": []string{"d3", ":default"}, "publishDate": []string{"d4", ":default"}, }) fc, err = newFrontmatterConfig(cfg) c.Assert(err, qt.IsNil) c.Assert(fc.date, qt.DeepEquals, []string{"d1", "date", "publishdate", "pubdate", "published", "lastmod", "modified"}) c.Assert(fc.lastmod, qt.DeepEquals, []string{"d2", ":git", "lastmod", "modified", "date", "publishdate", "pubdate", "published"}) c.Assert(fc.expiryDate, qt.DeepEquals, []string{"d3", "expirydate", "unpublishdate"}) c.Assert(fc.publishDate, qt.DeepEquals, []string{"d4", "publishdate", "pubdate", "published", "date"}) } func TestFrontMatterDatesHandlers(t *testing.T) { c := qt.New(t) for _, handlerID := range []string{":filename", ":fileModTime", ":git"} { cfg := config.New() cfg.Set("frontmatter", map[string]interface{}{ "date": []string{handlerID, "date"}, }) handler, err := NewFrontmatterHandler(nil, cfg) c.Assert(err, qt.IsNil) d1, _ := time.Parse("2006-01-02", "2018-02-01") d2, _ := time.Parse("2006-01-02", "2018-02-02") d := newTestFd() switch strings.ToLower(handlerID) { case ":filename": d.BaseFilename = "2018-02-01-page.md" case ":filemodtime": d.ModTime = d1 case ":git": d.GitAuthorDate = d1 } d.Frontmatter["date"] = d2 c.Assert(handler.HandleDates(d), qt.IsNil) c.Assert(d.Dates.FDate, qt.Equals, d1) c.Assert(d.Params["date"], qt.Equals, d2) d = newTestFd() d.Frontmatter["date"] = d2 c.Assert(handler.HandleDates(d), qt.IsNil) c.Assert(d.Dates.FDate, qt.Equals, d2) c.Assert(d.Params["date"], qt.Equals, d2) } } func TestFrontMatterDatesCustomConfig(t *testing.T) { t.Parallel() c := qt.New(t) cfg := config.New() cfg.Set("frontmatter", map[string]interface{}{ "date": []string{"mydate"}, "lastmod": []string{"publishdate"}, "publishdate": []string{"publishdate"}, }) handler, err := NewFrontmatterHandler(nil, cfg) c.Assert(err, qt.IsNil) testDate, err := time.Parse("2006-01-02", "2018-02-01") c.Assert(err, qt.IsNil) d := newTestFd() d.Frontmatter["mydate"] = testDate testDate = testDate.Add(24 * time.Hour) d.Frontmatter["date"] = testDate testDate = testDate.Add(24 * time.Hour) d.Frontmatter["lastmod"] = testDate testDate = testDate.Add(24 * time.Hour) d.Frontmatter["publishdate"] = testDate testDate = testDate.Add(24 * time.Hour) d.Frontmatter["expirydate"] = testDate c.Assert(handler.HandleDates(d), qt.IsNil) c.Assert(d.Dates.FDate.Day(), qt.Equals, 1) c.Assert(d.Dates.FLastmod.Day(), qt.Equals, 4) c.Assert(d.Dates.FPublishDate.Day(), qt.Equals, 4) c.Assert(d.Dates.FExpiryDate.Day(), qt.Equals, 5) c.Assert(d.Params["date"], qt.Equals, d.Dates.FDate) c.Assert(d.Params["mydate"], qt.Equals, d.Dates.FDate) c.Assert(d.Params["publishdate"], qt.Equals, d.Dates.FPublishDate) c.Assert(d.Params["expirydate"], qt.Equals, d.Dates.FExpiryDate) c.Assert(handler.IsDateKey("date"), qt.Equals, false) // This looks odd, but is configured like this. c.Assert(handler.IsDateKey("mydate"), qt.Equals, true) c.Assert(handler.IsDateKey("publishdate"), qt.Equals, true) c.Assert(handler.IsDateKey("pubdate"), qt.Equals, true) } func TestFrontMatterDatesDefaultKeyword(t *testing.T) { t.Parallel() c := qt.New(t) cfg := config.New() cfg.Set("frontmatter", map[string]interface{}{ "date": []string{"mydate", ":default"}, "publishdate": []string{":default", "mypubdate"}, }) handler, err := NewFrontmatterHandler(nil, cfg) c.Assert(err, qt.IsNil) testDate, _ := time.Parse("2006-01-02", "2018-02-01") d := newTestFd() d.Frontmatter["mydate"] = testDate d.Frontmatter["date"] = testDate.Add(1 * 24 * time.Hour) d.Frontmatter["mypubdate"] = testDate.Add(2 * 24 * time.Hour) d.Frontmatter["publishdate"] = testDate.Add(3 * 24 * time.Hour) c.Assert(handler.HandleDates(d), qt.IsNil) c.Assert(d.Dates.FDate.Day(), qt.Equals, 1) c.Assert(d.Dates.FLastmod.Day(), qt.Equals, 2) c.Assert(d.Dates.FPublishDate.Day(), qt.Equals, 4) c.Assert(d.Dates.FExpiryDate.IsZero(), qt.Equals, true) } func TestExpandDefaultValues(t *testing.T) { c := qt.New(t) c.Assert(expandDefaultValues([]string{"a", ":default", "d"}, []string{"b", "c"}), qt.DeepEquals, []string{"a", "b", "c", "d"}) c.Assert(expandDefaultValues([]string{"a", "b", "c"}, []string{"a", "b", "c"}), qt.DeepEquals, []string{"a", "b", "c"}) c.Assert(expandDefaultValues([]string{":default", "a", ":default", "d"}, []string{"b", "c"}), qt.DeepEquals, []string{"b", "c", "a", "b", "c", "d"}) } func TestFrontMatterDateFieldHandler(t *testing.T) { t.Parallel() c := qt.New(t) handlers := new(frontmatterFieldHandlers) fd := newTestFd() d, _ := time.Parse("2006-01-02", "2018-02-01") fd.Frontmatter["date"] = d h := handlers.newDateFieldHandler("date", func(d *FrontMatterDescriptor, t time.Time) { d.Dates.FDate = t }) handled, err := h(fd) c.Assert(handled, qt.Equals, true) c.Assert(err, qt.IsNil) c.Assert(fd.Dates.FDate, qt.Equals, d) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pagemeta/pagemeta.go�����������������������������������������������������0000664�0000000�0000000�00000005420�14201470003�0021361�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package pagemeta import ( "github.com/mitchellh/mapstructure" ) type URLPath struct { URL string Permalink string Slug string Section string } const ( Never = "never" Always = "always" ListLocally = "local" Link = "link" ) var defaultBuildConfig = BuildConfig{ List: Always, Render: Always, PublishResources: true, set: true, } // BuildConfig holds configuration options about how to handle a Page in Hugo's // build process. type BuildConfig struct { // Whether to add it to any of the page collections. // Note that the page can always be found with .Site.GetPage. // Valid values: never, always, local. // Setting it to 'local' means they will be available via the local // page collections, e.g. $section.Pages. // Note: before 0.57.2 this was a bool, so we accept those too. List string // Whether to render it. // Valid values: never, always, link. // The value link means it will not be rendered, but it will get a RelPermalink/Permalink. // Note that before 0.76.0 this was a bool, so we accept those too. Render string // Whether to publish its resources. These will still be published on demand, // but enabling this can be useful if the originals (e.g. images) are // never used. PublishResources bool set bool // BuildCfg is non-zero if this is set to true. } // Disable sets all options to their off value. func (b *BuildConfig) Disable() { b.List = Never b.Render = Never b.PublishResources = false b.set = true } func (b BuildConfig) IsZero() bool { return !b.set } func DecodeBuildConfig(m interface{}) (BuildConfig, error) { b := defaultBuildConfig if m == nil { return b, nil } err := mapstructure.WeakDecode(m, &b) // In 0.67.1 we changed the list attribute from a bool to a string (enum). // Bool values will become 0 or 1. switch b.List { case "0": b.List = Never case "1": b.List = Always case Always, Never, ListLocally: default: b.List = Always } // In 0.76.0 we changed the Render from bool to a string. switch b.Render { case "0": b.Render = Never case "1": b.Render = Always case Always, Never, Link: default: b.Render = Always } return b, err } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pagemeta/pagemeta_test.go������������������������������������������������0000664�0000000�0000000�00000004440�14201470003�0022421�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package pagemeta import ( "fmt" "testing" "github.com/gohugoio/hugo/htesting/hqt" "github.com/gohugoio/hugo/config" qt "github.com/frankban/quicktest" ) func TestDecodeBuildConfig(t *testing.T) { t.Parallel() c := qt.New(t) configTempl := ` [_build] render = %s list = %s publishResources = true` for _, test := range []struct { args []interface{} expect BuildConfig }{ { []interface{}{"true", "true"}, BuildConfig{ Render: Always, List: Always, PublishResources: true, set: true, }, }, {[]interface{}{"true", "false"}, BuildConfig{ Render: Always, List: Never, PublishResources: true, set: true, }}, {[]interface{}{`"always"`, `"always"`}, BuildConfig{ Render: Always, List: Always, PublishResources: true, set: true, }}, {[]interface{}{`"never"`, `"never"`}, BuildConfig{ Render: Never, List: Never, PublishResources: true, set: true, }}, {[]interface{}{`"link"`, `"local"`}, BuildConfig{ Render: Link, List: ListLocally, PublishResources: true, set: true, }}, {[]interface{}{`"always"`, `"asdfadf"`}, BuildConfig{ Render: Always, List: Always, PublishResources: true, set: true, }}, } { cfg, err := config.FromConfigString(fmt.Sprintf(configTempl, test.args...), "toml") c.Assert(err, qt.IsNil) bcfg, err := DecodeBuildConfig(cfg.Get("_build")) c.Assert(err, qt.IsNil) eq := qt.CmpEquals(hqt.DeepAllowUnexported(BuildConfig{})) c.Assert(bcfg, eq, test.expect) } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages.go�����������������������������������������������������������������0000664�0000000�0000000�00000006011�14201470003�0017107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "fmt" "math/rand" "github.com/gohugoio/hugo/compare" "github.com/gohugoio/hugo/resources/resource" ) var ( _ resource.ResourcesConverter = Pages{} _ compare.ProbablyEqer = Pages{} ) // Pages is a slice of pages. This is the most common list type in Hugo. type Pages []Page func (ps Pages) String() string { return fmt.Sprintf("Pages(%d)", len(ps)) } // Used in tests. func (ps Pages) shuffle() { for i := range ps { j := rand.Intn(i + 1) ps[i], ps[j] = ps[j], ps[i] } } // ToResources wraps resource.ResourcesConverter func (pages Pages) ToResources() resource.Resources { r := make(resource.Resources, len(pages)) for i, p := range pages { r[i] = p } return r } // ToPages tries to convert seq into Pages. func ToPages(seq interface{}) (Pages, error) { if seq == nil { return Pages{}, nil } switch v := seq.(type) { case Pages: return v, nil case *Pages: return *(v), nil case WeightedPages: return v.Pages(), nil case PageGroup: return v.Pages, nil case []Page: pages := make(Pages, len(v)) for i, vv := range v { pages[i] = vv } return pages, nil case []interface{}: pages := make(Pages, len(v)) success := true for i, vv := range v { p, ok := vv.(Page) if !ok { success = false break } pages[i] = p } if success { return pages, nil } } return nil, fmt.Errorf("cannot convert type %T to Pages", seq) } func (p Pages) Group(key interface{}, in interface{}) (interface{}, error) { pages, err := ToPages(in) if err != nil { return nil, err } return PageGroup{Key: key, Pages: pages}, nil } // Len returns the number of pages in the list. func (p Pages) Len() int { return len(p) } // ProbablyEq wraps compare.ProbablyEqer func (pages Pages) ProbablyEq(other interface{}) bool { otherPages, ok := other.(Pages) if !ok { return false } if len(pages) != len(otherPages) { return false } step := 1 for i := 0; i < len(pages); i += step { if !pages[i].Eq(otherPages[i]) { return false } if i > 50 { // This is most likely the same. step = 50 } } return true } func (ps Pages) removeFirstIfFound(p Page) Pages { ii := -1 for i, pp := range ps { if p.Eq(pp) { ii = i break } } if ii != -1 { ps = append(ps[:ii], ps[ii+1:]...) } return ps } // PagesFactory somehow creates some Pages. // We do a lot of lazy Pages initialization in Hugo, so we need a type. type PagesFactory func() Pages �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages_cache.go�����������������������������������������������������������0000664�0000000�0000000�00000005507�14201470003�0020243�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "sync" ) type pageCacheEntry struct { in []Pages out Pages } func (entry pageCacheEntry) matches(pageLists []Pages) bool { if len(entry.in) != len(pageLists) { return false } for i, p := range pageLists { if !pagesEqual(p, entry.in[i]) { return false } } return true } type pageCache struct { sync.RWMutex m map[string][]pageCacheEntry } func newPageCache() *pageCache { return &pageCache{m: make(map[string][]pageCacheEntry)} } func (c *pageCache) clear() { c.Lock() defer c.Unlock() c.m = make(map[string][]pageCacheEntry) } // get/getP gets a Pages slice from the cache matching the given key and // all the provided Pages slices. // If none found in cache, a copy of the first slice is created. // // If an apply func is provided, that func is applied to the newly created copy. // // The getP variant' apply func takes a pointer to Pages. // // The cache and the execution of the apply func is protected by a RWMutex. func (c *pageCache) get(key string, apply func(p Pages), pageLists ...Pages) (Pages, bool) { return c.getP(key, func(p *Pages) { if apply != nil { apply(*p) } }, pageLists...) } func (c *pageCache) getP(key string, apply func(p *Pages), pageLists ...Pages) (Pages, bool) { c.RLock() if cached, ok := c.m[key]; ok { for _, entry := range cached { if entry.matches(pageLists) { c.RUnlock() return entry.out, true } } } c.RUnlock() c.Lock() defer c.Unlock() // double-check if cached, ok := c.m[key]; ok { for _, entry := range cached { if entry.matches(pageLists) { return entry.out, true } } } p := pageLists[0] pagesCopy := append(Pages(nil), p...) if apply != nil { apply(&pagesCopy) } entry := pageCacheEntry{in: pageLists, out: pagesCopy} if v, ok := c.m[key]; ok { c.m[key] = append(v, entry) } else { c.m[key] = []pageCacheEntry{entry} } return pagesCopy, false } // pagesEqual returns whether p1 and p2 are equal. func pagesEqual(p1, p2 Pages) bool { if p1 == nil && p2 == nil { return true } if p1 == nil || p2 == nil { return false } if p1.Len() != p2.Len() { return false } if p1.Len() == 0 { return true } for i := 0; i < len(p1); i++ { if p1[i] != p2[i] { return false } } return true } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages_cache_test.go������������������������������������������������������0000664�0000000�0000000�00000004126�14201470003�0021276�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "strconv" "sync" "sync/atomic" "testing" qt "github.com/frankban/quicktest" ) func TestPageCache(t *testing.T) { t.Parallel() c := qt.New(t) c1 := newPageCache() changeFirst := func(p Pages) { p[0].(*testPage).description = "changed" } var o1 uint64 var o2 uint64 var wg sync.WaitGroup var l1 sync.Mutex var l2 sync.Mutex var testPageSets []Pages for i := 0; i < 50; i++ { testPageSets = append(testPageSets, createSortTestPages(i+1)) } for j := 0; j < 100; j++ { wg.Add(1) go func() { defer wg.Done() for k, pages := range testPageSets { l1.Lock() p, ca := c1.get("k1", nil, pages) c.Assert(ca, qt.Equals, !atomic.CompareAndSwapUint64(&o1, uint64(k), uint64(k+1))) l1.Unlock() p2, c2 := c1.get("k1", nil, p) c.Assert(c2, qt.Equals, true) c.Assert(pagesEqual(p, p2), qt.Equals, true) c.Assert(pagesEqual(p, pages), qt.Equals, true) c.Assert(p, qt.Not(qt.IsNil)) l2.Lock() p3, c3 := c1.get("k2", changeFirst, pages) c.Assert(c3, qt.Equals, !atomic.CompareAndSwapUint64(&o2, uint64(k), uint64(k+1))) l2.Unlock() c.Assert(p3, qt.Not(qt.IsNil)) c.Assert("changed", qt.Equals, p3[0].(*testPage).description) } }() } wg.Wait() } func BenchmarkPageCache(b *testing.B) { cache := newPageCache() pages := make(Pages, 30) for i := 0; i < 30; i++ { pages[i] = &testPage{title: "p" + strconv.Itoa(i)} } key := "key" b.ResetTimer() for i := 0; i < b.N; i++ { cache.getP(key, nil, pages) } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages_language_merge.go��������������������������������������������������0000664�0000000�0000000�00000003402�14201470003�0022132�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "fmt" ) var _ pagesLanguageMerger = (*Pages)(nil) type pagesLanguageMerger interface { MergeByLanguage(other Pages) Pages // Needed for integration with the tpl package. MergeByLanguageInterface(other interface{}) (interface{}, error) } // MergeByLanguage supplies missing translations in p1 with values from p2. // The result is sorted by the default sort order for pages. func (p1 Pages) MergeByLanguage(p2 Pages) Pages { merge := func(pages *Pages) { m := make(map[string]bool) for _, p := range *pages { m[p.TranslationKey()] = true } for _, p := range p2 { if _, found := m[p.TranslationKey()]; !found { *pages = append(*pages, p) } } SortByDefault(*pages) } out, _ := spc.getP("pages.MergeByLanguage", merge, p1, p2) return out } // MergeByLanguageInterface is the generic version of MergeByLanguage. It // is here just so it can be called from the tpl package. func (p1 Pages) MergeByLanguageInterface(in interface{}) (interface{}, error) { if in == nil { return p1, nil } p2, ok := in.(Pages) if !ok { return nil, fmt.Errorf("%T cannot be merged by language", in) } return p1.MergeByLanguage(p2), nil } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages_prev_next.go�������������������������������������������������������0000664�0000000�0000000�00000001707�14201470003�0021210�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page // Next returns the next page relative to the given func (p Pages) Next(cur Page) Page { x := searchPage(cur, p) if x <= 0 { return nil } return p[x-1] } // Prev returns the previous page reletive to the given func (p Pages) Prev(cur Page) Page { x := searchPage(cur, p) if x == -1 || len(p)-x < 2 { return nil } return p[x+1] } ���������������������������������������������������������hugo-0.92.2/resources/page/pages_prev_next_test.go��������������������������������������������������0000664�0000000�0000000�00000004564�14201470003�0022253�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "testing" qt "github.com/frankban/quicktest" "github.com/spf13/cast" ) type pagePNTestObject struct { path string weight int date string } var pagePNTestSources = []pagePNTestObject{ {"/section1/testpage1.md", 5, "2012-04-06"}, {"/section1/testpage2.md", 4, "2012-01-01"}, {"/section1/testpage3.md", 3, "2012-04-06"}, {"/section2/testpage4.md", 2, "2012-03-02"}, {"/section2/testpage5.md", 1, "2012-04-06"}, } func TestPrev(t *testing.T) { t.Parallel() c := qt.New(t) pages := preparePageGroupTestPages(t) c.Assert(pages.Prev(pages[3]), qt.Equals, pages[4]) c.Assert(pages.Prev(pages[1]), qt.Equals, pages[2]) c.Assert(pages.Prev(pages[4]), qt.IsNil) } func TestNext(t *testing.T) { t.Parallel() c := qt.New(t) pages := preparePageGroupTestPages(t) c.Assert(pages.Next(pages[0]), qt.IsNil) c.Assert(pages.Next(pages[1]), qt.Equals, pages[0]) c.Assert(pages.Next(pages[4]), qt.Equals, pages[3]) } func prepareWeightedPagesPrevNext(t *testing.T) WeightedPages { w := WeightedPages{} for _, src := range pagePNTestSources { p := newTestPage() p.path = src.path p.weight = src.weight p.date = cast.ToTime(src.date) p.pubDate = cast.ToTime(src.date) w = append(w, WeightedPage{Weight: p.weight, Page: p}) } w.Sort() return w } func TestWeightedPagesPrev(t *testing.T) { t.Parallel() c := qt.New(t) w := prepareWeightedPagesPrevNext(t) c.Assert(w.Prev(w[0].Page), qt.Equals, w[1].Page) c.Assert(w.Prev(w[1].Page), qt.Equals, w[2].Page) c.Assert(w.Prev(w[4].Page), qt.IsNil) } func TestWeightedPagesNext(t *testing.T) { t.Parallel() c := qt.New(t) w := prepareWeightedPagesPrevNext(t) c.Assert(w.Next(w[0].Page), qt.IsNil) c.Assert(w.Next(w[1].Page), qt.Equals, w[0].Page) c.Assert(w.Next(w[4].Page), qt.Equals, w[3].Page) } ��������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages_related.go���������������������������������������������������������0000664�0000000�0000000�00000011510�14201470003�0020607�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "sync" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/related" "github.com/pkg/errors" "github.com/spf13/cast" ) var ( // Assert that Pages and PageGroup implements the PageGenealogist interface. _ PageGenealogist = (Pages)(nil) _ PageGenealogist = PageGroup{} ) // A PageGenealogist finds related pages in a page collection. This interface is implemented // by Pages and PageGroup, which makes it available as `{{ .RegularRelated . }}` etc. type PageGenealogist interface { // Template example: // {{ $related := .RegularPages.Related . }} Related(doc related.Document) (Pages, error) // Template example: // {{ $related := .RegularPages.RelatedIndices . "tags" "date" }} RelatedIndices(doc related.Document, indices ...interface{}) (Pages, error) // Template example: // {{ $related := .RegularPages.RelatedTo ( keyVals "tags" "hugo", "rocks") ( keyVals "date" .Date ) }} RelatedTo(args ...types.KeyValues) (Pages, error) } // Related searches all the configured indices with the search keywords from the // supplied document. func (p Pages) Related(doc related.Document) (Pages, error) { result, err := p.searchDoc(doc) if err != nil { return nil, err } if page, ok := doc.(Page); ok { return result.removeFirstIfFound(page), nil } return result, nil } // RelatedIndices searches the given indices with the search keywords from the // supplied document. func (p Pages) RelatedIndices(doc related.Document, indices ...interface{}) (Pages, error) { indicesStr, err := cast.ToStringSliceE(indices) if err != nil { return nil, err } result, err := p.searchDoc(doc, indicesStr...) if err != nil { return nil, err } if page, ok := doc.(Page); ok { return result.removeFirstIfFound(page), nil } return result, nil } // RelatedTo searches the given indices with the corresponding values. func (p Pages) RelatedTo(args ...types.KeyValues) (Pages, error) { if len(p) == 0 { return nil, nil } return p.search(args...) } func (p Pages) search(args ...types.KeyValues) (Pages, error) { return p.withInvertedIndex(func(idx *related.InvertedIndex) ([]related.Document, error) { return idx.SearchKeyValues(args...) }) } func (p Pages) searchDoc(doc related.Document, indices ...string) (Pages, error) { return p.withInvertedIndex(func(idx *related.InvertedIndex) ([]related.Document, error) { return idx.SearchDoc(doc, indices...) }) } func (p Pages) withInvertedIndex(search func(idx *related.InvertedIndex) ([]related.Document, error)) (Pages, error) { if len(p) == 0 { return nil, nil } d, ok := p[0].(InternalDependencies) if !ok { return nil, errors.Errorf("invalid type %T in related search", p[0]) } cache := d.GetRelatedDocsHandler() searchIndex, err := cache.getOrCreateIndex(p) if err != nil { return nil, err } result, err := search(searchIndex) if err != nil { return nil, err } if len(result) > 0 { mp := make(Pages, len(result)) for i, match := range result { mp[i] = match.(Page) } return mp, nil } return nil, nil } type cachedPostingList struct { p Pages postingList *related.InvertedIndex } type RelatedDocsHandler struct { cfg related.Config postingLists []*cachedPostingList mu sync.RWMutex } func NewRelatedDocsHandler(cfg related.Config) *RelatedDocsHandler { return &RelatedDocsHandler{cfg: cfg} } func (s *RelatedDocsHandler) Clone() *RelatedDocsHandler { return NewRelatedDocsHandler(s.cfg) } // This assumes that a lock has been acquired. func (s *RelatedDocsHandler) getIndex(p Pages) *related.InvertedIndex { for _, ci := range s.postingLists { if pagesEqual(p, ci.p) { return ci.postingList } } return nil } func (s *RelatedDocsHandler) getOrCreateIndex(p Pages) (*related.InvertedIndex, error) { s.mu.RLock() cachedIndex := s.getIndex(p) if cachedIndex != nil { s.mu.RUnlock() return cachedIndex, nil } s.mu.RUnlock() s.mu.Lock() defer s.mu.Unlock() if cachedIndex := s.getIndex(p); cachedIndex != nil { return cachedIndex, nil } searchIndex := related.NewInvertedIndex(s.cfg) for _, page := range p { if err := searchIndex.Add(page); err != nil { return nil, err } } s.postingLists = append(s.postingLists, &cachedPostingList{p: p, postingList: searchIndex}) return searchIndex, nil } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages_related_test.go����������������������������������������������������0000664�0000000�0000000�00000004472�14201470003�0021657�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "testing" "time" "github.com/gohugoio/hugo/common/types" qt "github.com/frankban/quicktest" ) func TestRelated(t *testing.T) { c := qt.New(t) t.Parallel() pages := Pages{ &testPage{ title: "Page 1", pubDate: mustParseDate("2017-01-03"), params: map[string]interface{}{ "keywords": []string{"hugo", "says"}, }, }, &testPage{ title: "Page 2", pubDate: mustParseDate("2017-01-02"), params: map[string]interface{}{ "keywords": []string{"hugo", "rocks"}, }, }, &testPage{ title: "Page 3", pubDate: mustParseDate("2017-01-01"), params: map[string]interface{}{ "keywords": []string{"bep", "says"}, }, }, } result, err := pages.RelatedTo(types.NewKeyValuesStrings("keywords", "hugo", "rocks")) c.Assert(err, qt.IsNil) c.Assert(len(result), qt.Equals, 2) c.Assert(result[0].Title(), qt.Equals, "Page 2") c.Assert(result[1].Title(), qt.Equals, "Page 1") result, err = pages.Related(pages[0]) c.Assert(err, qt.IsNil) c.Assert(len(result), qt.Equals, 2) c.Assert(result[0].Title(), qt.Equals, "Page 2") c.Assert(result[1].Title(), qt.Equals, "Page 3") result, err = pages.RelatedIndices(pages[0], "keywords") c.Assert(err, qt.IsNil) c.Assert(len(result), qt.Equals, 2) c.Assert(result[0].Title(), qt.Equals, "Page 2") c.Assert(result[1].Title(), qt.Equals, "Page 3") result, err = pages.RelatedTo(types.NewKeyValuesStrings("keywords", "bep", "rocks")) c.Assert(err, qt.IsNil) c.Assert(len(result), qt.Equals, 2) c.Assert(result[0].Title(), qt.Equals, "Page 2") c.Assert(result[1].Title(), qt.Equals, "Page 3") } func mustParseDate(s string) time.Time { d, err := time.Parse("2006-01-02", s) if err != nil { panic(err) } return d } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages_sort.go������������������������������������������������������������0000664�0000000�0000000�00000021374�14201470003�0020167�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "sort" "github.com/gohugoio/hugo/common/collections" "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/compare" "github.com/spf13/cast" ) var spc = newPageCache() /* * Implementation of a custom sorter for Pages */ // A pageSorter implements the sort interface for Pages type pageSorter struct { pages Pages by pageBy } // pageBy is a closure used in the Sort.Less method. type pageBy func(p1, p2 Page) bool func getOrdinals(p1, p2 Page) (int, int) { p1o, ok1 := p1.(collections.Order) if !ok1 { return -1, -1 } p2o, ok2 := p2.(collections.Order) if !ok2 { return -1, -1 } return p1o.Ordinal(), p2o.Ordinal() } // Sort stable sorts the pages given the receiver's sort order. func (by pageBy) Sort(pages Pages) { ps := &pageSorter{ pages: pages, by: by, // The Sort method's receiver is the function (closure) that defines the sort order. } sort.Stable(ps) } var ( // DefaultPageSort is the default sort func for pages in Hugo: // Order by Ordinal, Weight, Date, LinkTitle and then full file path. DefaultPageSort = func(p1, p2 Page) bool { o1, o2 := getOrdinals(p1, p2) if o1 != o2 && o1 != -1 && o2 != -1 { return o1 < o2 } if p1.Weight() == p2.Weight() { if p1.Date().Unix() == p2.Date().Unix() { c := compare.Strings(p1.LinkTitle(), p2.LinkTitle()) if c == 0 { if p1.File().IsZero() || p2.File().IsZero() { return p1.File().IsZero() } return compare.LessStrings(p1.File().Filename(), p2.File().Filename()) } return c < 0 } return p1.Date().Unix() > p2.Date().Unix() } if p2.Weight() == 0 { return true } if p1.Weight() == 0 { return false } return p1.Weight() < p2.Weight() } lessPageLanguage = func(p1, p2 Page) bool { if p1.Language().Weight == p2.Language().Weight { if p1.Date().Unix() == p2.Date().Unix() { c := compare.Strings(p1.LinkTitle(), p2.LinkTitle()) if c == 0 { if !p1.File().IsZero() && !p2.File().IsZero() { return compare.LessStrings(p1.File().Filename(), p2.File().Filename()) } } return c < 0 } return p1.Date().Unix() > p2.Date().Unix() } if p2.Language().Weight == 0 { return true } if p1.Language().Weight == 0 { return false } return p1.Language().Weight < p2.Language().Weight } lessPageTitle = func(p1, p2 Page) bool { return compare.LessStrings(p1.Title(), p2.Title()) } lessPageLinkTitle = func(p1, p2 Page) bool { return compare.LessStrings(p1.LinkTitle(), p2.LinkTitle()) } lessPageDate = func(p1, p2 Page) bool { return p1.Date().Unix() < p2.Date().Unix() } lessPagePubDate = func(p1, p2 Page) bool { return p1.PublishDate().Unix() < p2.PublishDate().Unix() } ) func (ps *pageSorter) Len() int { return len(ps.pages) } func (ps *pageSorter) Swap(i, j int) { ps.pages[i], ps.pages[j] = ps.pages[j], ps.pages[i] } // Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter. func (ps *pageSorter) Less(i, j int) bool { return ps.by(ps.pages[i], ps.pages[j]) } // Limit limits the number of pages returned to n. func (p Pages) Limit(n int) Pages { if len(p) > n { return p[0:n] } return p } // ByWeight sorts the Pages by weight and returns a copy. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByWeight() Pages { const key = "pageSort.ByWeight" pages, _ := spc.get(key, pageBy(DefaultPageSort).Sort, p) return pages } // SortByDefault sorts pages by the default sort. func SortByDefault(pages Pages) { pageBy(DefaultPageSort).Sort(pages) } // ByTitle sorts the Pages by title and returns a copy. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByTitle() Pages { const key = "pageSort.ByTitle" pages, _ := spc.get(key, pageBy(lessPageTitle).Sort, p) return pages } // ByLinkTitle sorts the Pages by link title and returns a copy. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByLinkTitle() Pages { const key = "pageSort.ByLinkTitle" pages, _ := spc.get(key, pageBy(lessPageLinkTitle).Sort, p) return pages } // ByDate sorts the Pages by date and returns a copy. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByDate() Pages { const key = "pageSort.ByDate" pages, _ := spc.get(key, pageBy(lessPageDate).Sort, p) return pages } // ByPublishDate sorts the Pages by publish date and returns a copy. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByPublishDate() Pages { const key = "pageSort.ByPublishDate" pages, _ := spc.get(key, pageBy(lessPagePubDate).Sort, p) return pages } // ByExpiryDate sorts the Pages by publish date and returns a copy. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByExpiryDate() Pages { const key = "pageSort.ByExpiryDate" expDate := func(p1, p2 Page) bool { return p1.ExpiryDate().Unix() < p2.ExpiryDate().Unix() } pages, _ := spc.get(key, pageBy(expDate).Sort, p) return pages } // ByLastmod sorts the Pages by the last modification date and returns a copy. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByLastmod() Pages { const key = "pageSort.ByLastmod" date := func(p1, p2 Page) bool { return p1.Lastmod().Unix() < p2.Lastmod().Unix() } pages, _ := spc.get(key, pageBy(date).Sort, p) return pages } // ByLength sorts the Pages by length and returns a copy. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByLength() Pages { const key = "pageSort.ByLength" length := func(p1, p2 Page) bool { p1l, ok1 := p1.(resource.LengthProvider) p2l, ok2 := p2.(resource.LengthProvider) if !ok1 { return true } if !ok2 { return false } return p1l.Len() < p2l.Len() } pages, _ := spc.get(key, pageBy(length).Sort, p) return pages } // ByLanguage sorts the Pages by the language's Weight. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByLanguage() Pages { const key = "pageSort.ByLanguage" pages, _ := spc.get(key, pageBy(lessPageLanguage).Sort, p) return pages } // SortByLanguage sorts the pages by language. func SortByLanguage(pages Pages) { pageBy(lessPageLanguage).Sort(pages) } // Reverse reverses the order in Pages and returns a copy. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) Reverse() Pages { const key = "pageSort.Reverse" reverseFunc := func(pages Pages) { for i, j := 0, len(pages)-1; i < j; i, j = i+1, j-1 { pages[i], pages[j] = pages[j], pages[i] } } pages, _ := spc.get(key, reverseFunc, p) return pages } // ByParam sorts the pages according to the given page Params key. // // Adjacent invocations on the same receiver with the same paramsKey will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByParam(paramsKey interface{}) Pages { paramsKeyStr := cast.ToString(paramsKey) key := "pageSort.ByParam." + paramsKeyStr paramsKeyComparator := func(p1, p2 Page) bool { v1, _ := p1.Param(paramsKeyStr) v2, _ := p2.Param(paramsKeyStr) if v1 == nil { return false } if v2 == nil { return true } isNumeric := func(v interface{}) bool { switch v.(type) { case uint8, uint16, uint32, uint64, int, int8, int16, int32, int64, float32, float64: return true default: return false } } if isNumeric(v1) && isNumeric(v2) { return cast.ToFloat64(v1) < cast.ToFloat64(v2) } s1 := cast.ToString(v1) s2 := cast.ToString(v2) return compare.LessStrings(s1, s2) } pages, _ := spc.get(key, pageBy(paramsKeyComparator).Sort, p) return pages } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages_sort_search.go�����������������������������������������������������0000664�0000000�0000000�00000005032�14201470003�0021505�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import "sort" // Used in page binary search, the most common in front. var pageLessFunctions = []func(p1, p2 Page) bool{ DefaultPageSort, lessPageDate, lessPagePubDate, lessPageTitle, lessPageLinkTitle, } func searchPage(p Page, pages Pages) int { if len(pages) < 1000 { // For smaller data sets, doing a linear search is faster. return searchPageLinear(p, pages, 0) } less := isPagesProbablySorted(pages, pageLessFunctions...) if less == nil { return searchPageLinear(p, pages, 0) } i := searchPageBinary(p, pages, less) if i != -1 { return i } return searchPageLinear(p, pages, 0) } func searchPageLinear(p Page, pages Pages, start int) int { for i := start; i < len(pages); i++ { c := pages[i] if c.Eq(p) { return i } } return -1 } func searchPageBinary(p Page, pages Pages, less func(p1, p2 Page) bool) int { n := len(pages) f := func(i int) bool { c := pages[i] isLess := less(c, p) return !isLess || c.Eq(p) } i := sort.Search(n, f) if i == n { return -1 } return searchPageLinear(p, pages, i) } // isProbablySorted tests if the pages slice is probably sorted. func isPagesProbablySorted(pages Pages, lessFuncs ...func(p1, p2 Page) bool) func(p1, p2 Page) bool { n := len(pages) step := 1 if n > 500 { step = 50 } is := func(less func(p1, p2 Page) bool) bool { samples := 0 for i := n - 1; i > 0; i = i - step { if less(pages[i], pages[i-1]) { return false } samples++ if samples >= 15 { return true } } return samples > 0 } isReverse := func(less func(p1, p2 Page) bool) bool { samples := 0 for i := 0; i < n-1; i = i + step { if less(pages[i], pages[i+1]) { return false } samples++ if samples > 15 { return true } } return samples > 0 } for _, less := range lessFuncs { if is(less) { return less } if isReverse(less) { return func(p1, p2 Page) bool { return less(p2, p1) } } } return nil } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages_sort_search_test.go������������������������������������������������0000664�0000000�0000000�00000006773�14201470003�0022561�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "fmt" "math/rand" "testing" "time" qt "github.com/frankban/quicktest" ) func TestSearchPage(t *testing.T) { t.Parallel() c := qt.New(t) pages := createSortTestPages(10) for i, p := range pages { p.(*testPage).title = fmt.Sprintf("Title %d", i%2) } for _, pages := range []Pages{pages.ByTitle(), pages.ByTitle().Reverse()} { less := isPagesProbablySorted(pages, lessPageTitle) c.Assert(less, qt.Not(qt.IsNil)) for i, p := range pages { idx := searchPageBinary(p, pages, less) c.Assert(idx, qt.Equals, i) } } } func BenchmarkSearchPage(b *testing.B) { type Variant struct { name string preparePages func(pages Pages) Pages search func(p Page, pages Pages) int } shufflePages := func(pages Pages) Pages { rand.Shuffle(len(pages), func(i, j int) { pages[i], pages[j] = pages[j], pages[i] }) return pages } linearSearch := func(p Page, pages Pages) int { return searchPageLinear(p, pages, 0) } createPages := func(num int) Pages { pages := createSortTestPages(num) for _, p := range pages { tp := p.(*testPage) tp.weight = rand.Intn(len(pages)) tp.title = fmt.Sprintf("Title %d", rand.Intn(len(pages))) tp.pubDate = time.Now().Add(time.Duration(rand.Intn(len(pages)/5)) * time.Hour) tp.date = time.Now().Add(time.Duration(rand.Intn(len(pages)/5)) * time.Hour) } return pages } for _, variant := range []Variant{ {"Shuffled", shufflePages, searchPage}, {"ByWeight", func(pages Pages) Pages { return pages.ByWeight() }, searchPage}, {"ByWeight.Reverse", func(pages Pages) Pages { return pages.ByWeight().Reverse() }, searchPage}, {"ByDate", func(pages Pages) Pages { return pages.ByDate() }, searchPage}, {"ByPublishDate", func(pages Pages) Pages { return pages.ByPublishDate() }, searchPage}, {"ByTitle", func(pages Pages) Pages { return pages.ByTitle() }, searchPage}, {"ByTitle Linear", func(pages Pages) Pages { return pages.ByTitle() }, linearSearch}, } { for _, numPages := range []int{100, 500, 1000, 5000} { b.Run(fmt.Sprintf("%s-%d", variant.name, numPages), func(b *testing.B) { b.StopTimer() pages := createPages(numPages) if variant.preparePages != nil { pages = variant.preparePages(pages) } b.StartTimer() for i := 0; i < b.N; i++ { j := rand.Intn(numPages) k := variant.search(pages[j], pages) if k != j { b.Fatalf("%d != %d", k, j) } } }) } } } func TestIsPagesProbablySorted(t *testing.T) { t.Parallel() c := qt.New(t) c.Assert(isPagesProbablySorted(createSortTestPages(6).ByWeight(), DefaultPageSort), qt.Not(qt.IsNil)) c.Assert(isPagesProbablySorted(createSortTestPages(300).ByWeight(), DefaultPageSort), qt.Not(qt.IsNil)) c.Assert(isPagesProbablySorted(createSortTestPages(6), DefaultPageSort), qt.IsNil) c.Assert(isPagesProbablySorted(createSortTestPages(300).ByTitle(), pageLessFunctions...), qt.Not(qt.IsNil)) } �����hugo-0.92.2/resources/page/pages_sort_test.go�������������������������������������������������������0000664�0000000�0000000�00000017314�14201470003�0021225�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "fmt" "testing" "time" "github.com/gohugoio/hugo/htesting/hqt" "github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/resources/resource" qt "github.com/frankban/quicktest" ) var eq = qt.CmpEquals(hqt.DeepAllowUnexported( &testPage{}, &source.FileInfo{}, )) func TestDefaultSort(t *testing.T) { t.Parallel() c := qt.New(t) d1 := time.Now() d2 := d1.Add(-1 * time.Hour) d3 := d1.Add(-2 * time.Hour) d4 := d1.Add(-3 * time.Hour) p := createSortTestPages(4) // first by weight setSortVals([4]time.Time{d1, d2, d3, d4}, [4]string{"b", "a", "c", "d"}, [4]int{4, 3, 2, 1}, p) SortByDefault(p) c.Assert(p[0].Weight(), qt.Equals, 1) // Consider zero weight, issue #2673 setSortVals([4]time.Time{d1, d2, d3, d4}, [4]string{"b", "a", "d", "c"}, [4]int{0, 0, 0, 1}, p) SortByDefault(p) c.Assert(p[0].Weight(), qt.Equals, 1) // next by date setSortVals([4]time.Time{d3, d4, d1, d2}, [4]string{"a", "b", "c", "d"}, [4]int{1, 1, 1, 1}, p) SortByDefault(p) c.Assert(p[0].Date(), qt.Equals, d1) // finally by link title setSortVals([4]time.Time{d3, d3, d3, d3}, [4]string{"b", "c", "a", "d"}, [4]int{1, 1, 1, 1}, p) SortByDefault(p) c.Assert(p[0].LinkTitle(), qt.Equals, "al") c.Assert(p[1].LinkTitle(), qt.Equals, "bl") c.Assert(p[2].LinkTitle(), qt.Equals, "cl") } // https://github.com/gohugoio/hugo/issues/4953 func TestSortByLinkTitle(t *testing.T) { t.Parallel() c := qt.New(t) pages := createSortTestPages(6) for i, p := range pages { pp := p.(*testPage) if i < 5 { pp.title = fmt.Sprintf("title%d", i) } if i > 2 { pp.linkTitle = fmt.Sprintf("linkTitle%d", i) } } pages.shuffle() bylt := pages.ByLinkTitle() for i, p := range bylt { if i < 3 { c.Assert(p.LinkTitle(), qt.Equals, fmt.Sprintf("linkTitle%d", i+3)) } else { c.Assert(p.LinkTitle(), qt.Equals, fmt.Sprintf("title%d", i-3)) } } } func TestSortByN(t *testing.T) { t.Parallel() d1 := time.Now() d2 := d1.Add(-2 * time.Hour) d3 := d1.Add(-10 * time.Hour) d4 := d1.Add(-20 * time.Hour) p := createSortTestPages(4) for i, this := range []struct { sortFunc func(p Pages) Pages assertFunc func(p Pages) bool }{ {(Pages).ByWeight, func(p Pages) bool { return p[0].Weight() == 1 }}, {(Pages).ByTitle, func(p Pages) bool { return p[0].Title() == "ab" }}, {(Pages).ByLinkTitle, func(p Pages) bool { return p[0].LinkTitle() == "abl" }}, {(Pages).ByDate, func(p Pages) bool { return p[0].Date() == d4 }}, {(Pages).ByPublishDate, func(p Pages) bool { return p[0].PublishDate() == d4 }}, {(Pages).ByExpiryDate, func(p Pages) bool { return p[0].ExpiryDate() == d4 }}, {(Pages).ByLastmod, func(p Pages) bool { return p[1].Lastmod() == d3 }}, {(Pages).ByLength, func(p Pages) bool { return p[0].(resource.LengthProvider).Len() == len(p[0].(*testPage).content) }}, } { setSortVals([4]time.Time{d1, d2, d3, d4}, [4]string{"b", "ab", "cde", "fg"}, [4]int{0, 3, 2, 1}, p) sorted := this.sortFunc(p) if !this.assertFunc(sorted) { t.Errorf("[%d] sort error", i) } } } func TestLimit(t *testing.T) { t.Parallel() c := qt.New(t) p := createSortTestPages(10) firstFive := p.Limit(5) c.Assert(len(firstFive), qt.Equals, 5) for i := 0; i < 5; i++ { c.Assert(firstFive[i], qt.Equals, p[i]) } c.Assert(p.Limit(10), eq, p) c.Assert(p.Limit(11), eq, p) } func TestPageSortReverse(t *testing.T) { t.Parallel() c := qt.New(t) p1 := createSortTestPages(10) c.Assert(p1[0].(*testPage).fuzzyWordCount, qt.Equals, 0) c.Assert(p1[9].(*testPage).fuzzyWordCount, qt.Equals, 9) p2 := p1.Reverse() c.Assert(p2[0].(*testPage).fuzzyWordCount, qt.Equals, 9) c.Assert(p2[9].(*testPage).fuzzyWordCount, qt.Equals, 0) // cached c.Assert(pagesEqual(p2, p1.Reverse()), qt.Equals, true) } func TestPageSortByParam(t *testing.T) { t.Parallel() c := qt.New(t) var k interface{} = "arbitrarily.nested" unsorted := createSortTestPages(10) delete(unsorted[9].Params(), "arbitrarily") firstSetValue, _ := unsorted[0].Param(k) secondSetValue, _ := unsorted[1].Param(k) lastSetValue, _ := unsorted[8].Param(k) unsetValue, _ := unsorted[9].Param(k) c.Assert(firstSetValue, qt.Equals, "xyz100") c.Assert(secondSetValue, qt.Equals, "xyz99") c.Assert(lastSetValue, qt.Equals, "xyz92") c.Assert(unsetValue, qt.Equals, nil) sorted := unsorted.ByParam("arbitrarily.nested") firstSetSortedValue, _ := sorted[0].Param(k) secondSetSortedValue, _ := sorted[1].Param(k) lastSetSortedValue, _ := sorted[8].Param(k) unsetSortedValue, _ := sorted[9].Param(k) c.Assert(firstSetSortedValue, qt.Equals, firstSetValue) c.Assert(lastSetSortedValue, qt.Equals, secondSetValue) c.Assert(secondSetSortedValue, qt.Equals, lastSetValue) c.Assert(unsetSortedValue, qt.Equals, unsetValue) } func TestPageSortByParamNumeric(t *testing.T) { t.Parallel() c := qt.New(t) var k interface{} = "arbitrarily.nested" n := 10 unsorted := createSortTestPages(n) for i := 0; i < n; i++ { v := 100 - i if i%2 == 0 { v = 100.0 - i } unsorted[i].(*testPage).params = map[string]interface{}{ "arbitrarily": map[string]interface{}{ "nested": v, }, } } delete(unsorted[9].Params(), "arbitrarily") firstSetValue, _ := unsorted[0].Param(k) secondSetValue, _ := unsorted[1].Param(k) lastSetValue, _ := unsorted[8].Param(k) unsetValue, _ := unsorted[9].Param(k) c.Assert(firstSetValue, qt.Equals, 100) c.Assert(secondSetValue, qt.Equals, 99) c.Assert(lastSetValue, qt.Equals, 92) c.Assert(unsetValue, qt.Equals, nil) sorted := unsorted.ByParam("arbitrarily.nested") firstSetSortedValue, _ := sorted[0].Param(k) secondSetSortedValue, _ := sorted[1].Param(k) lastSetSortedValue, _ := sorted[8].Param(k) unsetSortedValue, _ := sorted[9].Param(k) c.Assert(firstSetSortedValue, qt.Equals, 92) c.Assert(secondSetSortedValue, qt.Equals, 93) c.Assert(lastSetSortedValue, qt.Equals, 100) c.Assert(unsetSortedValue, qt.Equals, unsetValue) } func BenchmarkSortByWeightAndReverse(b *testing.B) { p := createSortTestPages(300) b.ResetTimer() for i := 0; i < b.N; i++ { p = p.ByWeight().Reverse() } } func setSortVals(dates [4]time.Time, titles [4]string, weights [4]int, pages Pages) { for i := range dates { this := pages[i].(*testPage) other := pages[len(dates)-1-i].(*testPage) this.date = dates[i] this.lastMod = dates[i] this.weight = weights[i] this.title = titles[i] // make sure we compare apples and ... apples ... other.linkTitle = this.Title() + "l" other.pubDate = dates[i] other.expiryDate = dates[i] other.content = titles[i] + "_content" } lastLastMod := pages[2].Lastmod() pages[2].(*testPage).lastMod = pages[1].Lastmod() pages[1].(*testPage).lastMod = lastLastMod for _, p := range pages { p.(*testPage).content = "" } } func createSortTestPages(num int) Pages { pages := make(Pages, num) for i := 0; i < num; i++ { p := newTestPage() p.path = fmt.Sprintf("/x/y/p%d.md", i) p.title = fmt.Sprintf("Title %d", i%(num+1/2)) p.params = map[string]interface{}{ "arbitrarily": map[string]interface{}{ "nested": ("xyz" + fmt.Sprintf("%v", 100-i)), }, } w := 5 if i%2 == 0 { w = 10 } p.fuzzyWordCount = i p.weight = w p.description = "initial" pages[i] = p } return pages } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pages_test.go������������������������������������������������������������0000664�0000000�0000000�00000004310�14201470003�0020146�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "testing" qt "github.com/frankban/quicktest" ) func TestProbablyEq(t *testing.T) { p1, p2, p3 := &testPage{title: "p1"}, &testPage{title: "p2"}, &testPage{title: "p3"} pages12 := Pages{p1, p2} pages21 := Pages{p2, p1} pages123 := Pages{p1, p2, p3} t.Run("Pages", func(t *testing.T) { c := qt.New(t) c.Assert(pages12.ProbablyEq(pages12), qt.Equals, true) c.Assert(pages123.ProbablyEq(pages12), qt.Equals, false) c.Assert(pages12.ProbablyEq(pages21), qt.Equals, false) }) t.Run("PageGroup", func(t *testing.T) { c := qt.New(t) c.Assert(PageGroup{Key: "a", Pages: pages12}.ProbablyEq(PageGroup{Key: "a", Pages: pages12}), qt.Equals, true) c.Assert(PageGroup{Key: "a", Pages: pages12}.ProbablyEq(PageGroup{Key: "b", Pages: pages12}), qt.Equals, false) }) t.Run("PagesGroup", func(t *testing.T) { c := qt.New(t) pg1, pg2 := PageGroup{Key: "a", Pages: pages12}, PageGroup{Key: "b", Pages: pages123} c.Assert(PagesGroup{pg1, pg2}.ProbablyEq(PagesGroup{pg1, pg2}), qt.Equals, true) c.Assert(PagesGroup{pg1, pg2}.ProbablyEq(PagesGroup{pg2, pg1}), qt.Equals, false) }) } func TestToPages(t *testing.T) { c := qt.New(t) p1, p2 := &testPage{title: "p1"}, &testPage{title: "p2"} pages12 := Pages{p1, p2} mustToPages := func(in interface{}) Pages { p, err := ToPages(in) c.Assert(err, qt.IsNil) return p } c.Assert(mustToPages(nil), eq, Pages{}) c.Assert(mustToPages(pages12), eq, pages12) c.Assert(mustToPages([]Page{p1, p2}), eq, pages12) c.Assert(mustToPages([]interface{}{p1, p2}), eq, pages12) _, err := ToPages("not a page") c.Assert(err, qt.Not(qt.IsNil)) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pagination.go������������������������������������������������������������0000664�0000000�0000000�00000021640�14201470003�0020146�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "errors" "fmt" "html/template" "math" "reflect" "github.com/gohugoio/hugo/config" "github.com/spf13/cast" ) // PaginatorProvider provides two ways to create a page paginator. type PaginatorProvider interface { Paginator(options ...interface{}) (*Pager, error) Paginate(seq interface{}, options ...interface{}) (*Pager, error) } // Pager represents one of the elements in a paginator. // The number, starting on 1, represents its place. type Pager struct { number int *Paginator } func (p Pager) String() string { return fmt.Sprintf("Pager %d", p.number) } type paginatedElement interface { Len() int } type pagers []*Pager var ( paginatorEmptyPages Pages paginatorEmptyPageGroups PagesGroup ) type Paginator struct { paginatedElements []paginatedElement pagers paginationURLFactory total int size int } type paginationURLFactory func(int) string // PageNumber returns the current page's number in the pager sequence. func (p *Pager) PageNumber() int { return p.number } // URL returns the URL to the current page. func (p *Pager) URL() template.HTML { return template.HTML(p.paginationURLFactory(p.PageNumber())) } // Pages returns the Pages on this page. // Note: If this return a non-empty result, then PageGroups() will return empty. func (p *Pager) Pages() Pages { if len(p.paginatedElements) == 0 { return paginatorEmptyPages } if pages, ok := p.element().(Pages); ok { return pages } return paginatorEmptyPages } // PageGroups return Page groups for this page. // Note: If this return non-empty result, then Pages() will return empty. func (p *Pager) PageGroups() PagesGroup { if len(p.paginatedElements) == 0 { return paginatorEmptyPageGroups } if groups, ok := p.element().(PagesGroup); ok { return groups } return paginatorEmptyPageGroups } func (p *Pager) element() paginatedElement { if len(p.paginatedElements) == 0 { return paginatorEmptyPages } return p.paginatedElements[p.PageNumber()-1] } // page returns the Page with the given index func (p *Pager) page(index int) (Page, error) { if pages, ok := p.element().(Pages); ok { if pages != nil && len(pages) > index { return pages[index], nil } return nil, nil } // must be PagesGroup // this construction looks clumsy, but ... // ... it is the difference between 99.5% and 100% test coverage :-) groups := p.element().(PagesGroup) i := 0 for _, v := range groups { for _, page := range v.Pages { if i == index { return page, nil } i++ } } return nil, nil } // NumberOfElements gets the number of elements on this page. func (p *Pager) NumberOfElements() int { return p.element().Len() } // HasPrev tests whether there are page(s) before the current. func (p *Pager) HasPrev() bool { return p.PageNumber() > 1 } // Prev returns the pager for the previous page. func (p *Pager) Prev() *Pager { if !p.HasPrev() { return nil } return p.pagers[p.PageNumber()-2] } // HasNext tests whether there are page(s) after the current. func (p *Pager) HasNext() bool { return p.PageNumber() < len(p.paginatedElements) } // Next returns the pager for the next page. func (p *Pager) Next() *Pager { if !p.HasNext() { return nil } return p.pagers[p.PageNumber()] } // First returns the pager for the first page. func (p *Pager) First() *Pager { return p.pagers[0] } // Last returns the pager for the last page. func (p *Pager) Last() *Pager { return p.pagers[len(p.pagers)-1] } // Pagers returns a list of pagers that can be used to build a pagination menu. func (p *Paginator) Pagers() pagers { return p.pagers } // PageSize returns the size of each paginator page. func (p *Paginator) PageSize() int { return p.size } // TotalPages returns the number of pages in the paginator. func (p *Paginator) TotalPages() int { return len(p.paginatedElements) } // TotalNumberOfElements returns the number of elements on all pages in this paginator. func (p *Paginator) TotalNumberOfElements() int { return p.total } func splitPages(pages Pages, size int) []paginatedElement { var split []paginatedElement for low, j := 0, len(pages); low < j; low += size { high := int(math.Min(float64(low+size), float64(len(pages)))) split = append(split, pages[low:high]) } return split } func splitPageGroups(pageGroups PagesGroup, size int) []paginatedElement { type keyPage struct { key interface{} page Page } var ( split []paginatedElement flattened []keyPage ) for _, g := range pageGroups { for _, p := range g.Pages { flattened = append(flattened, keyPage{g.Key, p}) } } numPages := len(flattened) for low, j := 0, numPages; low < j; low += size { high := int(math.Min(float64(low+size), float64(numPages))) var ( pg PagesGroup key interface{} groupIndex = -1 ) for k := low; k < high; k++ { kp := flattened[k] if key == nil || key != kp.key { key = kp.key pg = append(pg, PageGroup{Key: key}) groupIndex++ } pg[groupIndex].Pages = append(pg[groupIndex].Pages, kp.page) } split = append(split, pg) } return split } func ResolvePagerSize(cfg config.Provider, options ...interface{}) (int, error) { if len(options) == 0 { return cfg.GetInt("paginate"), nil } if len(options) > 1 { return -1, errors.New("too many arguments, 'pager size' is currently the only option") } pas, err := cast.ToIntE(options[0]) if err != nil || pas <= 0 { return -1, errors.New(("'pager size' must be a positive integer")) } return pas, nil } func Paginate(td TargetPathDescriptor, seq interface{}, pagerSize int) (*Paginator, error) { if pagerSize <= 0 { return nil, errors.New("'paginate' configuration setting must be positive to paginate") } urlFactory := newPaginationURLFactory(td) var paginator *Paginator groups, err := ToPagesGroup(seq) if err != nil { return nil, err } if groups != nil { paginator, _ = newPaginatorFromPageGroups(groups, pagerSize, urlFactory) } else { pages, err := ToPages(seq) if err != nil { return nil, err } paginator, _ = newPaginatorFromPages(pages, pagerSize, urlFactory) } return paginator, nil } // probablyEqual checks page lists for probable equality. // It may return false positives. // The motivation behind this is to avoid potential costly reflect.DeepEqual // when "probably" is good enough. func probablyEqualPageLists(a1 interface{}, a2 interface{}) bool { if a1 == nil || a2 == nil { return a1 == a2 } t1 := reflect.TypeOf(a1) t2 := reflect.TypeOf(a2) if t1 != t2 { return false } if g1, ok := a1.(PagesGroup); ok { g2 := a2.(PagesGroup) if len(g1) != len(g2) { return false } if len(g1) == 0 { return true } if g1.Len() != g2.Len() { return false } return g1[0].Pages[0] == g2[0].Pages[0] } p1, err1 := ToPages(a1) p2, err2 := ToPages(a2) // probably the same wrong type if err1 != nil && err2 != nil { return true } if len(p1) != len(p2) { return false } if len(p1) == 0 { return true } return p1[0] == p2[0] } func newPaginatorFromPages(pages Pages, size int, urlFactory paginationURLFactory) (*Paginator, error) { if size <= 0 { return nil, errors.New("Paginator size must be positive") } split := splitPages(pages, size) return newPaginator(split, len(pages), size, urlFactory) } func newPaginatorFromPageGroups(pageGroups PagesGroup, size int, urlFactory paginationURLFactory) (*Paginator, error) { if size <= 0 { return nil, errors.New("Paginator size must be positive") } split := splitPageGroups(pageGroups, size) return newPaginator(split, pageGroups.Len(), size, urlFactory) } func newPaginator(elements []paginatedElement, total, size int, urlFactory paginationURLFactory) (*Paginator, error) { p := &Paginator{total: total, paginatedElements: elements, size: size, paginationURLFactory: urlFactory} var ps pagers if len(elements) > 0 { ps = make(pagers, len(elements)) for i := range p.paginatedElements { ps[i] = &Pager{number: (i + 1), Paginator: p} } } else { ps = make(pagers, 1) ps[0] = &Pager{number: 1, Paginator: p} } p.pagers = ps return p, nil } func newPaginationURLFactory(d TargetPathDescriptor) paginationURLFactory { return func(pageNumber int) string { pathDescriptor := d var rel string if pageNumber > 1 { rel = fmt.Sprintf("/%s/%d/", d.PathSpec.PaginatePath, pageNumber) pathDescriptor.Addends = rel } return CreateTargetPaths(pathDescriptor).RelPermalink(d.PathSpec) } } ������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/pagination_test.go�������������������������������������������������������0000664�0000000�0000000�00000021135�14201470003�0021204�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "fmt" "html/template" "testing" "github.com/gohugoio/hugo/config" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/output" ) func TestSplitPages(t *testing.T) { t.Parallel() c := qt.New(t) pages := createTestPages(21) chunks := splitPages(pages, 5) c.Assert(len(chunks), qt.Equals, 5) for i := 0; i < 4; i++ { c.Assert(chunks[i].Len(), qt.Equals, 5) } lastChunk := chunks[4] c.Assert(lastChunk.Len(), qt.Equals, 1) } func TestSplitPageGroups(t *testing.T) { t.Parallel() c := qt.New(t) pages := createTestPages(21) groups, _ := pages.GroupBy("Weight", "desc") chunks := splitPageGroups(groups, 5) c.Assert(len(chunks), qt.Equals, 5) firstChunk := chunks[0] // alternate weight 5 and 10 if groups, ok := firstChunk.(PagesGroup); ok { c.Assert(groups.Len(), qt.Equals, 5) for _, pg := range groups { // first group 10 in weight c.Assert(pg.Key, qt.Equals, 10) for _, p := range pg.Pages { c.Assert(p.FuzzyWordCount()%2 == 0, qt.Equals, true) // magic test } } } else { t.Fatal("Excepted PageGroup") } lastChunk := chunks[4] if groups, ok := lastChunk.(PagesGroup); ok { c.Assert(groups.Len(), qt.Equals, 1) for _, pg := range groups { // last should have 5 in weight c.Assert(pg.Key, qt.Equals, 5) for _, p := range pg.Pages { c.Assert(p.FuzzyWordCount()%2 != 0, qt.Equals, true) // magic test } } } else { t.Fatal("Excepted PageGroup") } } func TestPager(t *testing.T) { t.Parallel() c := qt.New(t) pages := createTestPages(21) groups, _ := pages.GroupBy("Weight", "desc") urlFactory := func(page int) string { return fmt.Sprintf("page/%d/", page) } _, err := newPaginatorFromPages(pages, -1, urlFactory) c.Assert(err, qt.Not(qt.IsNil)) _, err = newPaginatorFromPageGroups(groups, -1, urlFactory) c.Assert(err, qt.Not(qt.IsNil)) pag, err := newPaginatorFromPages(pages, 5, urlFactory) c.Assert(err, qt.IsNil) doTestPages(t, pag) first := pag.Pagers()[0].First() c.Assert(first.String(), qt.Equals, "Pager 1") c.Assert(first.Pages(), qt.Not(qt.HasLen), 0) c.Assert(first.PageGroups(), qt.HasLen, 0) pag, err = newPaginatorFromPageGroups(groups, 5, urlFactory) c.Assert(err, qt.IsNil) doTestPages(t, pag) first = pag.Pagers()[0].First() c.Assert(first.PageGroups(), qt.Not(qt.HasLen), 0) c.Assert(first.Pages(), qt.HasLen, 0) } func doTestPages(t *testing.T, paginator *Paginator) { c := qt.New(t) paginatorPages := paginator.Pagers() c.Assert(len(paginatorPages), qt.Equals, 5) c.Assert(paginator.TotalNumberOfElements(), qt.Equals, 21) c.Assert(paginator.PageSize(), qt.Equals, 5) c.Assert(paginator.TotalPages(), qt.Equals, 5) first := paginatorPages[0] c.Assert(first.URL(), qt.Equals, template.HTML("page/1/")) c.Assert(first.First(), qt.Equals, first) c.Assert(first.HasNext(), qt.Equals, true) c.Assert(first.Next(), qt.Equals, paginatorPages[1]) c.Assert(first.HasPrev(), qt.Equals, false) c.Assert(first.Prev(), qt.IsNil) c.Assert(first.NumberOfElements(), qt.Equals, 5) c.Assert(first.PageNumber(), qt.Equals, 1) third := paginatorPages[2] c.Assert(third.HasNext(), qt.Equals, true) c.Assert(third.HasPrev(), qt.Equals, true) c.Assert(third.Prev(), qt.Equals, paginatorPages[1]) last := paginatorPages[4] c.Assert(last.URL(), qt.Equals, template.HTML("page/5/")) c.Assert(last.Last(), qt.Equals, last) c.Assert(last.HasNext(), qt.Equals, false) c.Assert(last.Next(), qt.IsNil) c.Assert(last.HasPrev(), qt.Equals, true) c.Assert(last.NumberOfElements(), qt.Equals, 1) c.Assert(last.PageNumber(), qt.Equals, 5) } func TestPagerNoPages(t *testing.T) { t.Parallel() c := qt.New(t) pages := createTestPages(0) groups, _ := pages.GroupBy("Weight", "desc") urlFactory := func(page int) string { return fmt.Sprintf("page/%d/", page) } paginator, _ := newPaginatorFromPages(pages, 5, urlFactory) doTestPagerNoPages(t, paginator) first := paginator.Pagers()[0].First() c.Assert(first.PageGroups(), qt.HasLen, 0) c.Assert(first.Pages(), qt.HasLen, 0) paginator, _ = newPaginatorFromPageGroups(groups, 5, urlFactory) doTestPagerNoPages(t, paginator) first = paginator.Pagers()[0].First() c.Assert(first.PageGroups(), qt.HasLen, 0) c.Assert(first.Pages(), qt.HasLen, 0) } func doTestPagerNoPages(t *testing.T, paginator *Paginator) { paginatorPages := paginator.Pagers() c := qt.New(t) c.Assert(len(paginatorPages), qt.Equals, 1) c.Assert(paginator.TotalNumberOfElements(), qt.Equals, 0) c.Assert(paginator.PageSize(), qt.Equals, 5) c.Assert(paginator.TotalPages(), qt.Equals, 0) // pageOne should be nothing but the first pageOne := paginatorPages[0] c.Assert(pageOne.First(), qt.Not(qt.IsNil)) c.Assert(pageOne.HasNext(), qt.Equals, false) c.Assert(pageOne.HasPrev(), qt.Equals, false) c.Assert(pageOne.Next(), qt.IsNil) c.Assert(len(pageOne.Pagers()), qt.Equals, 1) c.Assert(pageOne.Pages().Len(), qt.Equals, 0) c.Assert(pageOne.NumberOfElements(), qt.Equals, 0) c.Assert(pageOne.TotalNumberOfElements(), qt.Equals, 0) c.Assert(pageOne.TotalPages(), qt.Equals, 0) c.Assert(pageOne.PageNumber(), qt.Equals, 1) c.Assert(pageOne.PageSize(), qt.Equals, 5) } func TestPaginationURLFactory(t *testing.T) { t.Parallel() c := qt.New(t) cfg := config.New() cfg.Set("paginatePath", "zoo") for _, uglyURLs := range []bool{false, true} { c.Run(fmt.Sprintf("uglyURLs=%t", uglyURLs), func(c *qt.C) { tests := []struct { name string d TargetPathDescriptor baseURL string page int expected string expectedUgly string }{ { "HTML home page 32", TargetPathDescriptor{Kind: KindHome, Type: output.HTMLFormat}, "http://example.com/", 32, "/zoo/32/", "/zoo/32.html", }, { "JSON home page 42", TargetPathDescriptor{Kind: KindHome, Type: output.JSONFormat}, "http://example.com/", 42, "/zoo/42/index.json", "/zoo/42.json", }, } for _, test := range tests { d := test.d cfg.Set("baseURL", test.baseURL) cfg.Set("uglyURLs", uglyURLs) d.UglyURLs = uglyURLs pathSpec := newTestPathSpecFor(cfg) d.PathSpec = pathSpec factory := newPaginationURLFactory(d) got := factory(test.page) if uglyURLs { c.Assert(got, qt.Equals, test.expectedUgly) } else { c.Assert(got, qt.Equals, test.expected) } } }) } } func TestProbablyEqualPageLists(t *testing.T) { t.Parallel() fivePages := createTestPages(5) zeroPages := createTestPages(0) zeroPagesByWeight, _ := createTestPages(0).GroupBy("Weight", "asc") fivePagesByWeight, _ := createTestPages(5).GroupBy("Weight", "asc") ninePagesByWeight, _ := createTestPages(9).GroupBy("Weight", "asc") for i, this := range []struct { v1 interface{} v2 interface{} expect bool }{ {nil, nil, true}, {"a", "b", true}, {"a", fivePages, false}, {fivePages, "a", false}, {fivePages, createTestPages(2), false}, {fivePages, fivePages, true}, {zeroPages, zeroPages, true}, {fivePagesByWeight, fivePagesByWeight, true}, {zeroPagesByWeight, fivePagesByWeight, false}, {zeroPagesByWeight, zeroPagesByWeight, true}, {fivePagesByWeight, fivePages, false}, {fivePagesByWeight, ninePagesByWeight, false}, } { result := probablyEqualPageLists(this.v1, this.v2) if result != this.expect { t.Errorf("[%d] got %t but expected %t", i, result, this.expect) } } } func TestPaginationPage(t *testing.T) { t.Parallel() c := qt.New(t) urlFactory := func(page int) string { return fmt.Sprintf("page/%d/", page) } fivePages := createTestPages(7) fivePagesFuzzyWordCount, _ := createTestPages(7).GroupBy("FuzzyWordCount", "asc") p1, _ := newPaginatorFromPages(fivePages, 2, urlFactory) p2, _ := newPaginatorFromPageGroups(fivePagesFuzzyWordCount, 2, urlFactory) f1 := p1.pagers[0].First() f2 := p2.pagers[0].First() page11, _ := f1.page(1) page1Nil, _ := f1.page(3) page21, _ := f2.page(1) page2Nil, _ := f2.page(3) c.Assert(page11.FuzzyWordCount(), qt.Equals, 3) c.Assert(page1Nil, qt.IsNil) c.Assert(page21, qt.Not(qt.IsNil)) c.Assert(page21.FuzzyWordCount(), qt.Equals, 3) c.Assert(page2Nil, qt.IsNil) } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/permalinks.go������������������������������������������������������������0000664�0000000�0000000�00000022733�14201470003�0020166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "fmt" "os" "path" "path/filepath" "regexp" "strconv" "strings" "time" "github.com/pkg/errors" "github.com/gohugoio/hugo/helpers" ) // PermalinkExpander holds permalin mappings per section. type PermalinkExpander struct { // knownPermalinkAttributes maps :tags in a permalink specification to a // function which, given a page and the tag, returns the resulting string // to be used to replace that tag. knownPermalinkAttributes map[string]pageToPermaAttribute expanders map[string]func(Page) (string, error) ps *helpers.PathSpec } // Time for checking date formats. Every field is different than the // Go reference time for date formatting. This ensures that formatting this date // with a Go time format always has a different output than the format itself. var referenceTime = time.Date(2019, time.November, 9, 23, 1, 42, 1, time.UTC) // Return the callback for the given permalink attribute and a boolean indicating if the attribute is valid or not. func (p PermalinkExpander) callback(attr string) (pageToPermaAttribute, bool) { if callback, ok := p.knownPermalinkAttributes[attr]; ok { return callback, true } if strings.HasPrefix(attr, "sections[") { fn := p.toSliceFunc(strings.TrimPrefix(attr, "sections")) return func(p Page, s string) (string, error) { return path.Join(fn(p.CurrentSection().SectionsEntries())...), nil }, true } // Make sure this comes after all the other checks. if referenceTime.Format(attr) != attr { return p.pageToPermalinkDate, true } return nil, false } // NewPermalinkExpander creates a new PermalinkExpander configured by the given // PathSpec. func NewPermalinkExpander(ps *helpers.PathSpec) (PermalinkExpander, error) { p := PermalinkExpander{ps: ps} p.knownPermalinkAttributes = map[string]pageToPermaAttribute{ "year": p.pageToPermalinkDate, "month": p.pageToPermalinkDate, "monthname": p.pageToPermalinkDate, "day": p.pageToPermalinkDate, "weekday": p.pageToPermalinkDate, "weekdayname": p.pageToPermalinkDate, "yearday": p.pageToPermalinkDate, "section": p.pageToPermalinkSection, "sections": p.pageToPermalinkSections, "title": p.pageToPermalinkTitle, "slug": p.pageToPermalinkSlugElseTitle, "filename": p.pageToPermalinkFilename, } patterns := ps.Cfg.GetStringMapString("permalinks") if patterns == nil { return p, nil } e, err := p.parse(patterns) if err != nil { return p, err } p.expanders = e return p, nil } // Expand expands the path in p according to the rules defined for the given key. // If no rules are found for the given key, an empty string is returned. func (l PermalinkExpander) Expand(key string, p Page) (string, error) { expand, found := l.expanders[key] if !found { return "", nil } return expand(p) } func (l PermalinkExpander) parse(patterns map[string]string) (map[string]func(Page) (string, error), error) { expanders := make(map[string]func(Page) (string, error)) // Allow " " and / to represent the root section. const sectionCutSet = " /" + string(os.PathSeparator) for k, pattern := range patterns { k = strings.Trim(k, sectionCutSet) if !l.validate(pattern) { return nil, &permalinkExpandError{pattern: pattern, err: errPermalinkIllFormed} } pattern := pattern matches := attributeRegexp.FindAllStringSubmatch(pattern, -1) callbacks := make([]pageToPermaAttribute, len(matches)) replacements := make([]string, len(matches)) for i, m := range matches { replacement := m[0] attr := replacement[1:] replacements[i] = replacement callback, ok := l.callback(attr) if !ok { return nil, &permalinkExpandError{pattern: pattern, err: errPermalinkAttributeUnknown} } callbacks[i] = callback } expanders[k] = func(p Page) (string, error) { if matches == nil { return pattern, nil } newField := pattern for i, replacement := range replacements { attr := replacement[1:] callback := callbacks[i] newAttr, err := callback(p, attr) if err != nil { return "", &permalinkExpandError{pattern: pattern, err: err} } newField = strings.Replace(newField, replacement, newAttr, 1) } return newField, nil } } return expanders, nil } // pageToPermaAttribute is the type of a function which, given a page and a tag // can return a string to go in that position in the page (or an error) type pageToPermaAttribute func(Page, string) (string, error) var attributeRegexp = regexp.MustCompile(`:\w+(\[.+\])?`) // validate determines if a PathPattern is well-formed func (l PermalinkExpander) validate(pp string) bool { fragments := strings.Split(pp[1:], "/") bail := false for i := range fragments { if bail { return false } if len(fragments[i]) == 0 { bail = true continue } matches := attributeRegexp.FindAllStringSubmatch(fragments[i], -1) if matches == nil { continue } for _, match := range matches { k := match[0][1:] if _, ok := l.callback(k); !ok { return false } } } return true } type permalinkExpandError struct { pattern string err error } func (pee *permalinkExpandError) Error() string { return fmt.Sprintf("error expanding %q: %s", pee.pattern, pee.err) } var ( errPermalinkIllFormed = errors.New("permalink ill-formed") errPermalinkAttributeUnknown = errors.New("permalink attribute not recognised") ) func (l PermalinkExpander) pageToPermalinkDate(p Page, dateField string) (string, error) { // a Page contains a Node which provides a field Date, time.Time switch dateField { case "year": return strconv.Itoa(p.Date().Year()), nil case "month": return fmt.Sprintf("%02d", int(p.Date().Month())), nil case "monthname": return p.Date().Month().String(), nil case "day": return fmt.Sprintf("%02d", p.Date().Day()), nil case "weekday": return strconv.Itoa(int(p.Date().Weekday())), nil case "weekdayname": return p.Date().Weekday().String(), nil case "yearday": return strconv.Itoa(p.Date().YearDay()), nil } return p.Date().Format(dateField), nil } // pageToPermalinkTitle returns the URL-safe form of the title func (l PermalinkExpander) pageToPermalinkTitle(p Page, _ string) (string, error) { return l.ps.URLize(p.Title()), nil } // pageToPermalinkFilename returns the URL-safe form of the filename func (l PermalinkExpander) pageToPermalinkFilename(p Page, _ string) (string, error) { name := p.File().TranslationBaseName() if name == "index" { // Page bundles; the directory name will hopefully have a better name. dir := strings.TrimSuffix(p.File().Dir(), helpers.FilePathSeparator) _, name = filepath.Split(dir) } return l.ps.URLize(name), nil } // if the page has a slug, return the slug, else return the title func (l PermalinkExpander) pageToPermalinkSlugElseTitle(p Page, a string) (string, error) { if p.Slug() != "" { return l.ps.URLize(p.Slug()), nil } return l.pageToPermalinkTitle(p, a) } func (l PermalinkExpander) pageToPermalinkSection(p Page, _ string) (string, error) { return p.Section(), nil } func (l PermalinkExpander) pageToPermalinkSections(p Page, _ string) (string, error) { return p.CurrentSection().SectionsPath(), nil } var ( nilSliceFunc = func(s []string) []string { return nil } allSliceFunc = func(s []string) []string { return s } ) // toSliceFunc returns a slice func that slices s according to the cut spec. // The cut spec must be on form [low:high] (one or both can be omitted), // also allowing single slice indices (e.g. [2]) and the special [last] keyword // giving the last element of the slice. // The returned function will be lenient and not panic in out of bounds situation. // // The current use case for this is to use parts of the sections path in permalinks. func (l PermalinkExpander) toSliceFunc(cut string) func(s []string) []string { cut = strings.ToLower(strings.TrimSpace(cut)) if cut == "" { return allSliceFunc } if len(cut) < 3 || (cut[0] != '[' || cut[len(cut)-1] != ']') { return nilSliceFunc } toNFunc := func(s string, low bool) func(ss []string) int { if s == "" { if low { return func(ss []string) int { return 0 } } else { return func(ss []string) int { return len(ss) } } } if s == "last" { return func(ss []string) int { return len(ss) - 1 } } n, _ := strconv.Atoi(s) if n < 0 { n = 0 } return func(ss []string) int { // Prevent out of bound situations. It would not make // much sense to panic here. if n > len(ss) { return len(ss) } return n } } opsStr := cut[1 : len(cut)-1] opts := strings.Split(opsStr, ":") if !strings.Contains(opsStr, ":") { toN := toNFunc(opts[0], true) return func(s []string) []string { if len(s) == 0 { return nil } v := s[toN(s)] if v == "" { return nil } return []string{v} } } toN1, toN2 := toNFunc(opts[0], true), toNFunc(opts[1], false) return func(s []string) []string { if len(s) == 0 { return nil } return s[toN1(s):toN2(s)] } } �������������������������������������hugo-0.92.2/resources/page/permalinks_test.go�������������������������������������������������������0000664�0000000�0000000�00000014303�14201470003�0021217�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "fmt" "regexp" "sync" "testing" "time" qt "github.com/frankban/quicktest" ) // testdataPermalinks is used by a couple of tests; the expandsTo content is // subject to the data in simplePageJSON. var testdataPermalinks = []struct { spec string valid bool expandsTo string }{ {":title", true, "spf13-vim-3.0-release-and-new-website"}, {"/:year-:month-:title", true, "/2012-04-spf13-vim-3.0-release-and-new-website"}, {"/:year/:yearday/:month/:monthname/:day/:weekday/:weekdayname/", true, "/2012/97/04/April/06/5/Friday/"}, // Dates {"/:section/", true, "/blue/"}, // Section {"/:title/", true, "/spf13-vim-3.0-release-and-new-website/"}, // Title {"/:slug/", true, "/the-slug/"}, // Slug {"/:filename/", true, "/test-page/"}, // Filename {"/:06-:1-:2-:Monday", true, "/12-4-6-Friday"}, // Dates with Go formatting {"/:2006_01_02_15_04_05.000", true, "/2012_04_06_03_01_59.000"}, // Complicated custom date format {"/:sections/", true, "/a/b/c/"}, // Sections {"/:sections[last]/", true, "/c/"}, // Sections // Failures {"/blog/:fred", false, ""}, {"/:year//:title", false, ""}, {"/:TITLE", false, ""}, // case is not normalized {"/:2017", false, ""}, // invalid date format {"/:2006-01-02", false, ""}, // valid date format but invalid attribute name } func TestPermalinkExpansion(t *testing.T) { t.Parallel() c := qt.New(t) page := newTestPageWithFile("/test-page/index.md") page.title = "Spf13 Vim 3.0 Release and new website" d, _ := time.Parse("2006-01-02 15:04:05", "2012-04-06 03:01:59") page.date = d page.section = "blue" page.slug = "The Slug" for _, item := range testdataPermalinks { if !item.valid { continue } specNameCleaner := regexp.MustCompile(`[\:\/\[\]]`) name := specNameCleaner.ReplaceAllString(item.spec, "") c.Run(name, func(c *qt.C) { permalinksConfig := map[string]string{ "posts": item.spec, } ps := newTestPathSpec() ps.Cfg.Set("permalinks", permalinksConfig) expander, err := NewPermalinkExpander(ps) c.Assert(err, qt.IsNil) expanded, err := expander.Expand("posts", page) c.Assert(err, qt.IsNil) c.Assert(expanded, qt.Equals, item.expandsTo) }) } } func TestPermalinkExpansionMultiSection(t *testing.T) { t.Parallel() c := qt.New(t) page := newTestPage() page.title = "Page Title" d, _ := time.Parse("2006-01-02", "2012-04-06") page.date = d page.section = "blue" page.slug = "The Slug" permalinksConfig := map[string]string{ "posts": "/:slug", "blog": "/:section/:year", } ps := newTestPathSpec() ps.Cfg.Set("permalinks", permalinksConfig) expander, err := NewPermalinkExpander(ps) c.Assert(err, qt.IsNil) expanded, err := expander.Expand("posts", page) c.Assert(err, qt.IsNil) c.Assert(expanded, qt.Equals, "/the-slug") expanded, err = expander.Expand("blog", page) c.Assert(err, qt.IsNil) c.Assert(expanded, qt.Equals, "/blue/2012") } func TestPermalinkExpansionConcurrent(t *testing.T) { t.Parallel() c := qt.New(t) permalinksConfig := map[string]string{ "posts": "/:slug/", } ps := newTestPathSpec() ps.Cfg.Set("permalinks", permalinksConfig) expander, err := NewPermalinkExpander(ps) c.Assert(err, qt.IsNil) var wg sync.WaitGroup for i := 1; i < 20; i++ { wg.Add(1) go func(i int) { defer wg.Done() page := newTestPage() for j := 1; j < 20; j++ { page.slug = fmt.Sprintf("slug%d", i+j) expanded, err := expander.Expand("posts", page) c.Assert(err, qt.IsNil) c.Assert(expanded, qt.Equals, fmt.Sprintf("/%s/", page.slug)) } }(i) } wg.Wait() } func TestPermalinkExpansionSliceSyntax(t *testing.T) { t.Parallel() c := qt.New(t) exp, _ := NewPermalinkExpander(newTestPathSpec()) slice := []string{"a", "b", "c", "d"} fn := func(s string) []string { return exp.toSliceFunc(s)(slice) } c.Run("Basic", func(c *qt.C) { c.Assert(fn("[1:3]"), qt.DeepEquals, []string{"b", "c"}) c.Assert(fn("[1:]"), qt.DeepEquals, []string{"b", "c", "d"}) c.Assert(fn("[:2]"), qt.DeepEquals, []string{"a", "b"}) c.Assert(fn("[0:2]"), qt.DeepEquals, []string{"a", "b"}) c.Assert(fn("[:]"), qt.DeepEquals, []string{"a", "b", "c", "d"}) c.Assert(fn(""), qt.DeepEquals, []string{"a", "b", "c", "d"}) c.Assert(fn("[last]"), qt.DeepEquals, []string{"d"}) c.Assert(fn("[:last]"), qt.DeepEquals, []string{"a", "b", "c"}) }) c.Run("Out of bounds", func(c *qt.C) { c.Assert(fn("[1:5]"), qt.DeepEquals, []string{"b", "c", "d"}) c.Assert(fn("[-1:5]"), qt.DeepEquals, []string{"a", "b", "c", "d"}) c.Assert(fn("[5:]"), qt.DeepEquals, []string{}) c.Assert(fn("[5:]"), qt.DeepEquals, []string{}) c.Assert(fn("[5:32]"), qt.DeepEquals, []string{}) c.Assert(exp.toSliceFunc("[:1]")(nil), qt.DeepEquals, []string(nil)) c.Assert(exp.toSliceFunc("[:1]")([]string{}), qt.DeepEquals, []string(nil)) // These all return nil c.Assert(fn("[]"), qt.IsNil) c.Assert(fn("[1:}"), qt.IsNil) c.Assert(fn("foo"), qt.IsNil) }) } func BenchmarkPermalinkExpand(b *testing.B) { page := newTestPage() page.title = "Hugo Rocks" d, _ := time.Parse("2006-01-02", "2019-02-28") page.date = d permalinksConfig := map[string]string{ "posts": "/:year-:month-:title", } ps := newTestPathSpec() ps.Cfg.Set("permalinks", permalinksConfig) expander, err := NewPermalinkExpander(ps) if err != nil { b.Fatal(err) } b.ResetTimer() for i := 0; i < b.N; i++ { s, err := expander.Expand("posts", page) if err != nil { b.Fatal(err) } if s != "/2019-02-hugo-rocks" { b.Fatal(s) } } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/site.go������������������������������������������������������������������0000664�0000000�0000000�00000005074�14201470003�0016764�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "html/template" "time" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/navigation" ) // Site represents a site in the build. This is currently a very narrow interface, // but the actual implementation will be richer, see hugolib.SiteInfo. type Site interface { Language() *langs.Language RegularPages() Pages Pages() Pages IsServer() bool ServerPort() int Title() string Sites() Sites Hugo() hugo.Info BaseURL() template.URL Taxonomies() interface{} LastChange() time.Time Menus() navigation.Menus Params() maps.Params Data() map[string]interface{} } // Sites represents an ordered list of sites (languages). type Sites []Site // First is a convenience method to get the first Site, i.e. the main language. func (s Sites) First() Site { if len(s) == 0 { return nil } return s[0] } type testSite struct { h hugo.Info l *langs.Language } func (t testSite) Hugo() hugo.Info { return t.h } func (t testSite) ServerPort() int { return 1313 } func (testSite) LastChange() (t time.Time) { return } func (t testSite) Title() string { return "foo" } func (t testSite) Sites() Sites { return nil } func (t testSite) IsServer() bool { return false } func (t testSite) Language() *langs.Language { return t.l } func (t testSite) Pages() Pages { return nil } func (t testSite) RegularPages() Pages { return nil } func (t testSite) Menus() navigation.Menus { return nil } func (t testSite) Taxonomies() interface{} { return nil } func (t testSite) BaseURL() template.URL { return "" } func (t testSite) Params() maps.Params { return nil } func (t testSite) Data() map[string]interface{} { return nil } // NewDummyHugoSite creates a new minimal test site. func NewDummyHugoSite(cfg config.Provider) Site { return testSite{ h: hugo.NewInfo(hugo.EnvironmentProduction, nil), l: langs.NewLanguage("en", cfg), } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/testhelpers_test.go������������������������������������������������������0000664�0000000�0000000�00000026362�14201470003�0021424�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "fmt" "html/template" "path" "path/filepath" "time" "github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/identity" "github.com/gohugoio/hugo/tpl" "github.com/gohugoio/hugo/modules" "github.com/bep/gitmap" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/navigation" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/related" "github.com/gohugoio/hugo/source" ) var ( _ resource.LengthProvider = (*testPage)(nil) _ Page = (*testPage)(nil) ) var relatedDocsHandler = NewRelatedDocsHandler(related.DefaultConfig) func newTestPage() *testPage { return newTestPageWithFile("/a/b/c.md") } func newTestPageWithFile(filename string) *testPage { filename = filepath.FromSlash(filename) file := source.NewTestFile(filename) return &testPage{ params: make(map[string]interface{}), data: make(map[string]interface{}), file: file, currentSection: &testPage{ sectionEntries: []string{"a", "b", "c"}, }, } } func newTestPathSpec() *helpers.PathSpec { return newTestPathSpecFor(config.New()) } func newTestPathSpecFor(cfg config.Provider) *helpers.PathSpec { config.SetBaseTestDefaults(cfg) langs.LoadLanguageSettings(cfg, nil) mod, err := modules.CreateProjectModule(cfg) if err != nil { panic(err) } cfg.Set("allModules", modules.Modules{mod}) fs := hugofs.NewMem(cfg) s, err := helpers.NewPathSpec(fs, cfg, nil) if err != nil { panic(err) } return s } type testPage struct { kind string description string title string linkTitle string lang string section string content string fuzzyWordCount int path string slug string // Dates date time.Time lastMod time.Time expiryDate time.Time pubDate time.Time weight int params map[string]interface{} data map[string]interface{} file source.File currentSection *testPage sectionEntries []string } func (p *testPage) Err() error { return nil } func (p *testPage) Aliases() []string { panic("not implemented") } func (p *testPage) AllTranslations() Pages { panic("not implemented") } func (p *testPage) AlternativeOutputFormats() OutputFormats { panic("not implemented") } func (p *testPage) Author() Author { return Author{} } func (p *testPage) Authors() AuthorList { return nil } func (p *testPage) BaseFileName() string { panic("not implemented") } func (p *testPage) BundleType() files.ContentClass { panic("not implemented") } func (p *testPage) Content() (interface{}, error) { panic("not implemented") } func (p *testPage) ContentBaseName() string { panic("not implemented") } func (p *testPage) CurrentSection() Page { return p.currentSection } func (p *testPage) Data() interface{} { return p.data } func (p *testPage) Sitemap() config.Sitemap { return config.Sitemap{} } func (p *testPage) Layout() string { return "" } func (p *testPage) Date() time.Time { return p.date } func (p *testPage) Description() string { return "" } func (p *testPage) Dir() string { panic("not implemented") } func (p *testPage) Draft() bool { panic("not implemented") } func (p *testPage) Eq(other interface{}) bool { return p == other } func (p *testPage) ExpiryDate() time.Time { return p.expiryDate } func (p *testPage) Ext() string { panic("not implemented") } func (p *testPage) Extension() string { panic("not implemented") } func (p *testPage) File() source.File { return p.file } func (p *testPage) FileInfo() hugofs.FileMetaInfo { panic("not implemented") } func (p *testPage) Filename() string { panic("not implemented") } func (p *testPage) FirstSection() Page { panic("not implemented") } func (p *testPage) FuzzyWordCount() int { return p.fuzzyWordCount } func (p *testPage) GetPage(ref string) (Page, error) { panic("not implemented") } func (p *testPage) GetPageWithTemplateInfo(info tpl.Info, ref string) (Page, error) { panic("not implemented") } func (p *testPage) GetParam(key string) interface{} { panic("not implemented") } func (p *testPage) GetTerms(taxonomy string) Pages { panic("not implemented") } func (p *testPage) GetRelatedDocsHandler() *RelatedDocsHandler { return relatedDocsHandler } func (p *testPage) GitInfo() *gitmap.GitInfo { return nil } func (p *testPage) HasMenuCurrent(menuID string, me *navigation.MenuEntry) bool { panic("not implemented") } func (p *testPage) HasShortcode(name string) bool { panic("not implemented") } func (p *testPage) Hugo() hugo.Info { panic("not implemented") } func (p *testPage) InSection(other interface{}) (bool, error) { panic("not implemented") } func (p *testPage) IsAncestor(other interface{}) (bool, error) { panic("not implemented") } func (p *testPage) IsDescendant(other interface{}) (bool, error) { panic("not implemented") } func (p *testPage) IsDraft() bool { return false } func (p *testPage) IsHome() bool { panic("not implemented") } func (p *testPage) IsMenuCurrent(menuID string, inme *navigation.MenuEntry) bool { panic("not implemented") } func (p *testPage) IsNode() bool { panic("not implemented") } func (p *testPage) IsPage() bool { panic("not implemented") } func (p *testPage) IsSection() bool { panic("not implemented") } func (p *testPage) IsTranslated() bool { panic("not implemented") } func (p *testPage) Keywords() []string { return nil } func (p *testPage) Kind() string { return p.kind } func (p *testPage) Lang() string { return p.lang } func (p *testPage) Language() *langs.Language { panic("not implemented") } func (p *testPage) LanguagePrefix() string { return "" } func (p *testPage) Lastmod() time.Time { return p.lastMod } func (p *testPage) Len() int { return len(p.content) } func (p *testPage) LinkTitle() string { if p.linkTitle == "" { if p.title == "" { return p.path } return p.title } return p.linkTitle } func (p *testPage) LogicalName() string { panic("not implemented") } func (p *testPage) MediaType() media.Type { panic("not implemented") } func (p *testPage) Menus() navigation.PageMenus { return navigation.PageMenus{} } func (p *testPage) Name() string { panic("not implemented") } func (p *testPage) Next() Page { panic("not implemented") } func (p *testPage) NextInSection() Page { return nil } func (p *testPage) NextPage() Page { return nil } func (p *testPage) OutputFormats() OutputFormats { panic("not implemented") } func (p *testPage) Pages() Pages { panic("not implemented") } func (p *testPage) RegularPages() Pages { panic("not implemented") } func (p *testPage) RegularPagesRecursive() Pages { panic("not implemented") } func (p *testPage) Paginate(seq interface{}, options ...interface{}) (*Pager, error) { return nil, nil } func (p *testPage) Paginator(options ...interface{}) (*Pager, error) { return nil, nil } func (p *testPage) Param(key interface{}) (interface{}, error) { return resource.Param(p, nil, key) } func (p *testPage) Params() maps.Params { return p.params } func (p *testPage) Page() Page { return p } func (p *testPage) Parent() Page { panic("not implemented") } func (p *testPage) Path() string { return p.path } func (p *testPage) Pathc() string { return p.path } func (p *testPage) Permalink() string { panic("not implemented") } func (p *testPage) Plain() string { panic("not implemented") } func (p *testPage) PlainWords() []string { panic("not implemented") } func (p *testPage) Prev() Page { panic("not implemented") } func (p *testPage) PrevInSection() Page { return nil } func (p *testPage) PrevPage() Page { return nil } func (p *testPage) PublishDate() time.Time { return p.pubDate } func (p *testPage) RSSLink() template.URL { return "" } func (p *testPage) RawContent() string { panic("not implemented") } func (p *testPage) ReadingTime() int { panic("not implemented") } func (p *testPage) Ref(argsm map[string]interface{}) (string, error) { panic("not implemented") } func (p *testPage) RefFrom(argsm map[string]interface{}, source interface{}) (string, error) { return "", nil } func (p *testPage) RelPermalink() string { panic("not implemented") } func (p *testPage) RelRef(argsm map[string]interface{}) (string, error) { panic("not implemented") } func (p *testPage) RelRefFrom(argsm map[string]interface{}, source interface{}) (string, error) { return "", nil } func (p *testPage) Render(layout ...string) (template.HTML, error) { panic("not implemented") } func (p *testPage) RenderString(args ...interface{}) (template.HTML, error) { panic("not implemented") } func (p *testPage) ResourceType() string { panic("not implemented") } func (p *testPage) Resources() resource.Resources { panic("not implemented") } func (p *testPage) Scratch() *maps.Scratch { panic("not implemented") } func (p *testPage) RelatedKeywords(cfg related.IndexConfig) ([]related.Keyword, error) { v, err := p.Param(cfg.Name) if err != nil { return nil, err } return cfg.ToKeywords(v) } func (p *testPage) Section() string { return p.section } func (p *testPage) Sections() Pages { panic("not implemented") } func (p *testPage) SectionsEntries() []string { return p.sectionEntries } func (p *testPage) SectionsPath() string { return path.Join(p.sectionEntries...) } func (p *testPage) Site() Site { panic("not implemented") } func (p *testPage) Sites() Sites { panic("not implemented") } func (p *testPage) Slug() string { return p.slug } func (p *testPage) String() string { return p.path } func (p *testPage) Summary() template.HTML { panic("not implemented") } func (p *testPage) TableOfContents() template.HTML { panic("not implemented") } func (p *testPage) Title() string { return p.title } func (p *testPage) TranslationBaseName() string { panic("not implemented") } func (p *testPage) TranslationKey() string { return p.path } func (p *testPage) Translations() Pages { panic("not implemented") } func (p *testPage) Truncated() bool { panic("not implemented") } func (p *testPage) Type() string { return p.section } func (p *testPage) URL() string { return "" } func (p *testPage) UniqueID() string { panic("not implemented") } func (p *testPage) Weight() int { return p.weight } func (p *testPage) WordCount() int { panic("not implemented") } func (p *testPage) GetIdentity() identity.Identity { panic("not implemented") } func createTestPages(num int) Pages { pages := make(Pages, num) for i := 0; i < num; i++ { m := &testPage{ path: fmt.Sprintf("/x/y/z/p%d.md", i), weight: 5, fuzzyWordCount: i + 2, // magic } if i%2 == 0 { m.weight = 10 } pages[i] = m } return pages } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/weighted.go��������������������������������������������������������������0000664�0000000�0000000�00000007150�14201470003�0017615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package page import ( "fmt" "sort" "github.com/gohugoio/hugo/common/collections" ) var _ collections.Slicer = WeightedPage{} // WeightedPages is a list of Pages with their corresponding (and relative) weight // [{Weight: 30, Page: *1}, {Weight: 40, Page: *2}] type WeightedPages []WeightedPage // Page will return the Page (of Kind taxonomyList) that represents this set // of pages. This method will panic if p is empty, as that should never happen. func (p WeightedPages) Page() Page { if len(p) == 0 { panic("WeightedPages is empty") } first := p[0] // TODO(bep) fix tests if first.owner == nil { return nil } return first.owner } // A WeightedPage is a Page with a weight. type WeightedPage struct { Weight int Page // Reference to the owning Page. This avoids having to do // manual .Site.GetPage lookups. It is implemented in this roundabout way // because we cannot add additional state to the WeightedPages slice // without breaking lots of templates in the wild. owner Page } func NewWeightedPage(weight int, p Page, owner Page) WeightedPage { return WeightedPage{Weight: weight, Page: p, owner: owner} } func (w WeightedPage) String() string { return fmt.Sprintf("WeightedPage(%d,%q)", w.Weight, w.Page.Title()) } // Slice is not meant to be used externally. It's a bridge function // for the template functions. See collections.Slice. func (p WeightedPage) Slice(in interface{}) (interface{}, error) { switch items := in.(type) { case WeightedPages: return items, nil case []interface{}: weighted := make(WeightedPages, len(items)) for i, v := range items { g, ok := v.(WeightedPage) if !ok { return nil, fmt.Errorf("type %T is not a WeightedPage", v) } weighted[i] = g } return weighted, nil default: return nil, fmt.Errorf("invalid slice type %T", items) } } // Pages returns the Pages in this weighted page set. func (wp WeightedPages) Pages() Pages { pages := make(Pages, len(wp)) for i := range wp { pages[i] = wp[i].Page } return pages } // Next returns the next Page relative to the given Page in // this weighted page set. func (wp WeightedPages) Next(cur Page) Page { for x, c := range wp { if c.Page.Eq(cur) { if x == 0 { return nil } return wp[x-1].Page } } return nil } // Prev returns the previous Page relative to the given Page in // this weighted page set. func (wp WeightedPages) Prev(cur Page) Page { for x, c := range wp { if c.Page.Eq(cur) { if x < len(wp)-1 { return wp[x+1].Page } return nil } } return nil } func (wp WeightedPages) Len() int { return len(wp) } func (wp WeightedPages) Swap(i, j int) { wp[i], wp[j] = wp[j], wp[i] } // Sort stable sorts this weighted page set. func (wp WeightedPages) Sort() { sort.Stable(wp) } // Count returns the number of pages in this weighted page set. func (wp WeightedPages) Count() int { return len(wp) } func (wp WeightedPages) Less(i, j int) bool { if wp[i].Weight == wp[j].Weight { return DefaultPageSort(wp[i].Page, wp[j].Page) } return wp[i].Weight < wp[j].Weight } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/page/zero_file.autogen.go�����������������������������������������������������0000664�0000000�0000000�00000006213�14201470003�0021433�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This file is autogenerated. package page import ( "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/source" ) // ZeroFile represents a zero value of source.File with warnings if invoked. type zeroFile struct { log loggers.Logger } func NewZeroFile(log loggers.Logger) source.File { return zeroFile{log: log} } func (zeroFile) IsZero() bool { return true } func (z zeroFile) Path() (o0 string) { z.log.Warnln(".File.Path on zero object. Wrap it in if or with: {{ with .File }}{{ .Path }}{{ end }}") return } func (z zeroFile) Section() (o0 string) { z.log.Warnln(".File.Section on zero object. Wrap it in if or with: {{ with .File }}{{ .Section }}{{ end }}") return } func (z zeroFile) Lang() (o0 string) { z.log.Warnln(".File.Lang on zero object. Wrap it in if or with: {{ with .File }}{{ .Lang }}{{ end }}") return } func (z zeroFile) Filename() (o0 string) { z.log.Warnln(".File.Filename on zero object. Wrap it in if or with: {{ with .File }}{{ .Filename }}{{ end }}") return } func (z zeroFile) Dir() (o0 string) { z.log.Warnln(".File.Dir on zero object. Wrap it in if or with: {{ with .File }}{{ .Dir }}{{ end }}") return } func (z zeroFile) Extension() (o0 string) { z.log.Warnln(".File.Extension on zero object. Wrap it in if or with: {{ with .File }}{{ .Extension }}{{ end }}") return } func (z zeroFile) Ext() (o0 string) { z.log.Warnln(".File.Ext on zero object. Wrap it in if or with: {{ with .File }}{{ .Ext }}{{ end }}") return } func (z zeroFile) LogicalName() (o0 string) { z.log.Warnln(".File.LogicalName on zero object. Wrap it in if or with: {{ with .File }}{{ .LogicalName }}{{ end }}") return } func (z zeroFile) BaseFileName() (o0 string) { z.log.Warnln(".File.BaseFileName on zero object. Wrap it in if or with: {{ with .File }}{{ .BaseFileName }}{{ end }}") return } func (z zeroFile) TranslationBaseName() (o0 string) { z.log.Warnln(".File.TranslationBaseName on zero object. Wrap it in if or with: {{ with .File }}{{ .TranslationBaseName }}{{ end }}") return } func (z zeroFile) ContentBaseName() (o0 string) { z.log.Warnln(".File.ContentBaseName on zero object. Wrap it in if or with: {{ with .File }}{{ .ContentBaseName }}{{ end }}") return } func (z zeroFile) UniqueID() (o0 string) { z.log.Warnln(".File.UniqueID on zero object. Wrap it in if or with: {{ with .File }}{{ .UniqueID }}{{ end }}") return } func (z zeroFile) FileInfo() (o0 hugofs.FileMetaInfo) { z.log.Warnln(".File.FileInfo on zero object. Wrap it in if or with: {{ with .File }}{{ .FileInfo }}{{ end }}") return } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/post_publish.go���������������������������������������������������������������0000664�0000000�0000000�00000002723�14201470003�0017615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "github.com/gohugoio/hugo/resources/postpub" "github.com/gohugoio/hugo/resources/resource" ) type transformationKeyer interface { TransformationKey() string } // PostProcess wraps the given Resource for later processing. func (spec *Spec) PostProcess(r resource.Resource) (postpub.PostPublishedResource, error) { key := r.(transformationKeyer).TransformationKey() spec.postProcessMu.RLock() result, found := spec.PostProcessResources[key] spec.postProcessMu.RUnlock() if found { return result, nil } spec.postProcessMu.Lock() defer spec.postProcessMu.Unlock() // Double check result, found = spec.PostProcessResources[key] if found { return result, nil } result = postpub.NewPostPublishResource(spec.incr.Incr(), r) if result == nil { panic("got nil result") } spec.PostProcessResources[key] = result return result, nil } ���������������������������������������������hugo-0.92.2/resources/postpub/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0016243�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/postpub/fields.go�������������������������������������������������������������0000664�0000000�0000000�00000003072�14201470003�0020042�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package postpub import ( "reflect" ) const ( FieldNotSupported = "__field_not_supported" ) func structToMapWithPlaceholders(root string, in interface{}, createPlaceholder func(s string) string) map[string]interface{} { m := structToMap(in) insertFieldPlaceholders(root, m, createPlaceholder) return m } func structToMap(s interface{}) map[string]interface{} { m := make(map[string]interface{}) t := reflect.TypeOf(s) for i := 0; i < t.NumMethod(); i++ { method := t.Method(i) if method.PkgPath != "" { continue } if method.Type.NumIn() == 1 { m[method.Name] = "" } } for i := 0; i < t.NumField(); i++ { field := t.Field(i) if field.PkgPath != "" { continue } m[field.Name] = "" } return m } // insert placeholder for the templates. Do it very shallow for now. func insertFieldPlaceholders(root string, m map[string]interface{}, createPlaceholder func(s string) string) { for k := range m { m[k] = createPlaceholder(root + "." + k) } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/postpub/fields_test.go��������������������������������������������������������0000664�0000000�0000000�00000002550�14201470003�0021101�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package postpub import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/media" ) func TestCreatePlaceholders(t *testing.T) { c := qt.New(t) m := structToMap(media.CSSType) insertFieldPlaceholders("foo", m, func(s string) string { return "pre_" + s + "_post" }) c.Assert(m, qt.DeepEquals, map[string]interface{}{ "IsZero": "pre_foo.IsZero_post", "MarshalJSON": "pre_foo.MarshalJSON_post", "Suffixes": "pre_foo.Suffixes_post", "Delimiter": "pre_foo.Delimiter_post", "FirstSuffix": "pre_foo.FirstSuffix_post", "IsText": "pre_foo.IsText_post", "String": "pre_foo.String_post", "Type": "pre_foo.Type_post", "MainType": "pre_foo.MainType_post", "SubType": "pre_foo.SubType_post", }) } ��������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/postpub/postpub.go������������������������������������������������������������0000664�0000000�0000000�00000011157�14201470003�0020273�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package postpub import ( "fmt" "reflect" "strconv" "strings" "github.com/spf13/cast" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/resource" ) type PostPublishedResource interface { resource.ResourceTypeProvider resource.ResourceLinksProvider resource.ResourceMetaProvider resource.ResourceParamsProvider resource.ResourceDataProvider resource.OriginProvider MediaType() map[string]interface{} } const ( PostProcessPrefix = "__h_pp_l1" // The suffix has an '=' in it to prevent the minifier to remove any enclosing // quoutes around the attribute values. // See issue #8884. PostProcessSuffix = "__e=" ) func NewPostPublishResource(id int, r resource.Resource) PostPublishedResource { return &PostPublishResource{ prefix: PostProcessPrefix + "_" + strconv.Itoa(id) + "_", delegate: r, } } // postPublishResource holds a Resource to be transformed post publishing. type PostPublishResource struct { prefix string delegate resource.Resource } func (r *PostPublishResource) field(name string) string { return r.prefix + name + PostProcessSuffix } func (r *PostPublishResource) Permalink() string { return r.field("Permalink") } func (r *PostPublishResource) RelPermalink() string { return r.field("RelPermalink") } func (r *PostPublishResource) Origin() resource.Resource { return r.delegate } func (r *PostPublishResource) GetFieldString(pattern string) (string, bool) { if r == nil { panic("resource is nil") } prefixIdx := strings.Index(pattern, r.prefix) if prefixIdx == -1 { // Not a method on this resource. return "", false } fieldAccessor := pattern[prefixIdx+len(r.prefix) : strings.Index(pattern, PostProcessSuffix)] d := r.delegate switch { case fieldAccessor == "RelPermalink": return d.RelPermalink(), true case fieldAccessor == "Permalink": return d.Permalink(), true case fieldAccessor == "Name": return d.Name(), true case fieldAccessor == "Title": return d.Title(), true case fieldAccessor == "ResourceType": return d.ResourceType(), true case fieldAccessor == "Content": content, err := d.(resource.ContentProvider).Content() if err != nil { return "", true } return cast.ToString(content), true case strings.HasPrefix(fieldAccessor, "MediaType"): return r.fieldToString(d.MediaType(), fieldAccessor), true case fieldAccessor == "Data.Integrity": return cast.ToString((d.Data().(map[string]interface{})["Integrity"])), true default: panic(fmt.Sprintf("unknown field accessor %q", fieldAccessor)) } } func (r *PostPublishResource) fieldToString(receiver interface{}, path string) string { fieldname := strings.Split(path, ".")[1] receiverv := reflect.ValueOf(receiver) switch receiverv.Kind() { case reflect.Map: v := receiverv.MapIndex(reflect.ValueOf(fieldname)) return cast.ToString(v.Interface()) default: v := receiverv.FieldByName(fieldname) if !v.IsValid() { method := receiverv.MethodByName(fieldname) if method.IsValid() { vals := method.Call(nil) if len(vals) > 0 { v = vals[0] } } } if v.IsValid() { return cast.ToString(v.Interface()) } return "" } } func (r *PostPublishResource) Data() interface{} { m := map[string]interface{}{ "Integrity": "", } insertFieldPlaceholders("Data", m, r.field) return m } func (r *PostPublishResource) MediaType() map[string]interface{} { m := structToMapWithPlaceholders("MediaType", media.Type{}, r.field) return m } func (r *PostPublishResource) ResourceType() string { return r.field("ResourceType") } func (r *PostPublishResource) Name() string { return r.field("Name") } func (r *PostPublishResource) Title() string { return r.field("Title") } func (r *PostPublishResource) Params() maps.Params { panic(r.fieldNotSupported("Params")) } func (r *PostPublishResource) Content() (interface{}, error) { return r.field("Content"), nil } func (r *PostPublishResource) fieldNotSupported(name string) string { return fmt.Sprintf("method .%s is currently not supported in post-publish transformations.", name) } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource.go�������������������������������������������������������������������0000664�0000000�0000000�00000037530�14201470003�0016735�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "fmt" "io" "io/ioutil" "os" "path" "path/filepath" "sync" "github.com/gohugoio/hugo/resources/internal" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/source" "github.com/pkg/errors" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/resources/resource" "github.com/spf13/afero" "github.com/gohugoio/hugo/helpers" ) var ( _ resource.ContentResource = (*genericResource)(nil) _ resource.ReadSeekCloserResource = (*genericResource)(nil) _ resource.Resource = (*genericResource)(nil) _ resource.Source = (*genericResource)(nil) _ resource.Cloner = (*genericResource)(nil) _ resource.ResourcesLanguageMerger = (*resource.Resources)(nil) _ permalinker = (*genericResource)(nil) _ resource.Identifier = (*genericResource)(nil) _ fileInfo = (*genericResource)(nil) ) type ResourceSourceDescriptor struct { // TargetPaths is a callback to fetch paths's relative to its owner. TargetPaths func() page.TargetPaths // Need one of these to load the resource content. SourceFile source.File OpenReadSeekCloser resource.OpenReadSeekCloser FileInfo os.FileInfo // If OpenReadSeekerCloser is not set, we use this to open the file. SourceFilename string Fs afero.Fs // Set when its known up front, else it's resolved from the target filename. MediaType media.Type // The relative target filename without any language code. RelTargetFilename string // Any base paths prepended to the target path. This will also typically be the // language code, but setting it here means that it should not have any effect on // the permalink. // This may be several values. In multihost mode we may publish the same resources to // multiple targets. TargetBasePaths []string // Delay publishing until either Permalink or RelPermalink is called. Maybe never. LazyPublish bool } func (r ResourceSourceDescriptor) Filename() string { if r.SourceFile != nil { return r.SourceFile.Filename() } return r.SourceFilename } type ResourceTransformer interface { resource.Resource Transformer } type Transformer interface { Transform(...ResourceTransformation) (ResourceTransformer, error) } func NewFeatureNotAvailableTransformer(key string, elements ...interface{}) ResourceTransformation { return transformerNotAvailable{ key: internal.NewResourceTransformationKey(key, elements...), } } type transformerNotAvailable struct { key internal.ResourceTransformationKey } func (t transformerNotAvailable) Transform(ctx *ResourceTransformationCtx) error { return herrors.ErrFeatureNotAvailable } func (t transformerNotAvailable) Key() internal.ResourceTransformationKey { return t.key } type baseResourceResource interface { resource.Cloner resource.ContentProvider resource.Resource resource.Identifier } type baseResourceInternal interface { resource.Source fileInfo metaAssigner targetPather ReadSeekCloser() (hugio.ReadSeekCloser, error) // Internal cloneWithUpdates(*transformationUpdate) (baseResource, error) tryTransformedFileCache(key string, u *transformationUpdate) io.ReadCloser specProvider getResourcePaths() *resourcePathDescriptor getTargetFilenames() []string openDestinationsForWriting() (io.WriteCloser, error) openPublishFileForWriting(relTargetPath string) (io.WriteCloser, error) relTargetPathForRel(rel string, addBaseTargetPath, isAbs, isURL bool) string } type specProvider interface { getSpec() *Spec } type baseResource interface { baseResourceResource baseResourceInternal } type commonResource struct { } // Slice is not meant to be used externally. It's a bridge function // for the template functions. See collections.Slice. func (commonResource) Slice(in interface{}) (interface{}, error) { switch items := in.(type) { case resource.Resources: return items, nil case []interface{}: groups := make(resource.Resources, len(items)) for i, v := range items { g, ok := v.(resource.Resource) if !ok { return nil, fmt.Errorf("type %T is not a Resource", v) } groups[i] = g { } } return groups, nil default: return nil, fmt.Errorf("invalid slice type %T", items) } } type dirFile struct { // This is the directory component with Unix-style slashes. dir string // This is the file component. file string } func (d dirFile) path() string { return path.Join(d.dir, d.file) } type fileInfo interface { getSourceFilename() string setSourceFilename(string) setSourceFs(afero.Fs) getFileInfo() hugofs.FileMetaInfo hash() (string, error) size() int } // genericResource represents a generic linkable resource. type genericResource struct { *resourcePathDescriptor *resourceFileInfo *resourceContent spec *Spec title string name string params map[string]interface{} data map[string]interface{} resourceType string mediaType media.Type } func (l *genericResource) Clone() resource.Resource { return l.clone() } func (l *genericResource) Content() (interface{}, error) { if err := l.initContent(); err != nil { return nil, err } return l.content, nil } func (r *genericResource) Err() error { return nil } func (l *genericResource) Data() interface{} { return l.data } func (l *genericResource) Key() string { return l.RelPermalink() } func (l *genericResource) MediaType() media.Type { return l.mediaType } func (l *genericResource) setMediaType(mediaType media.Type) { l.mediaType = mediaType } func (l *genericResource) Name() string { return l.name } func (l *genericResource) Params() maps.Params { return l.params } func (l *genericResource) Permalink() string { return l.spec.PermalinkForBaseURL(l.relPermalinkForRel(l.relTargetDirFile.path(), true), l.spec.BaseURL.HostURL()) } func (l *genericResource) Publish() error { var err error l.publishInit.Do(func() { var fr hugio.ReadSeekCloser fr, err = l.ReadSeekCloser() if err != nil { return } defer fr.Close() var fw io.WriteCloser fw, err = helpers.OpenFilesForWriting(l.spec.BaseFs.PublishFs, l.getTargetFilenames()...) if err != nil { return } defer fw.Close() _, err = io.Copy(fw, fr) }) return err } func (l *genericResource) RelPermalink() string { return l.relPermalinkFor(l.relTargetDirFile.path()) } func (l *genericResource) ResourceType() string { return l.resourceType } func (l *genericResource) String() string { return fmt.Sprintf("Resource(%s: %s)", l.resourceType, l.name) } // Path is stored with Unix style slashes. func (l *genericResource) TargetPath() string { return l.relTargetDirFile.path() } func (l *genericResource) Title() string { return l.title } func (l *genericResource) createBasePath(rel string, isURL bool) string { if l.targetPathBuilder == nil { return rel } tp := l.targetPathBuilder() if isURL { return path.Join(tp.SubResourceBaseLink, rel) } // TODO(bep) path return path.Join(filepath.ToSlash(tp.SubResourceBaseTarget), rel) } func (l *genericResource) initContent() error { var err error l.contentInit.Do(func() { var r hugio.ReadSeekCloser r, err = l.ReadSeekCloser() if err != nil { return } defer r.Close() var b []byte b, err = ioutil.ReadAll(r) if err != nil { return } l.content = string(b) }) return err } func (l *genericResource) setName(name string) { l.name = name } func (l *genericResource) getResourcePaths() *resourcePathDescriptor { return l.resourcePathDescriptor } func (l *genericResource) getSpec() *Spec { return l.spec } func (l *genericResource) getTargetFilenames() []string { paths := l.relTargetPaths() for i, p := range paths { paths[i] = filepath.Clean(p) } return paths } func (l *genericResource) setTitle(title string) { l.title = title } func (r *genericResource) tryTransformedFileCache(key string, u *transformationUpdate) io.ReadCloser { fi, f, meta, found := r.spec.ResourceCache.getFromFile(key) if !found { return nil } u.sourceFilename = &fi.Name mt, _ := r.spec.MediaTypes.GetByType(meta.MediaTypeV) u.mediaType = mt u.data = meta.MetaData u.targetPath = meta.Target return f } func (r *genericResource) mergeData(in map[string]interface{}) { if len(in) == 0 { return } if r.data == nil { r.data = make(map[string]interface{}) } for k, v := range in { if _, found := r.data[k]; !found { r.data[k] = v } } } func (rc *genericResource) cloneWithUpdates(u *transformationUpdate) (baseResource, error) { r := rc.clone() if u.content != nil { r.contentInit.Do(func() { r.content = *u.content r.openReadSeekerCloser = func() (hugio.ReadSeekCloser, error) { return hugio.NewReadSeekerNoOpCloserFromString(r.content), nil } }) } r.mediaType = u.mediaType if u.sourceFilename != nil { r.setSourceFilename(*u.sourceFilename) } if u.sourceFs != nil { r.setSourceFs(u.sourceFs) } if u.targetPath == "" { return nil, errors.New("missing targetPath") } fpath, fname := path.Split(u.targetPath) r.resourcePathDescriptor.relTargetDirFile = dirFile{dir: fpath, file: fname} r.mergeData(u.data) return r, nil } func (l genericResource) clone() *genericResource { gi := *l.resourceFileInfo rp := *l.resourcePathDescriptor l.resourceFileInfo = &gi l.resourcePathDescriptor = &rp l.resourceContent = &resourceContent{} return &l } // returns an opened file or nil if nothing to write (it may already be published). func (l *genericResource) openDestinationsForWriting() (w io.WriteCloser, err error) { l.publishInit.Do(func() { targetFilenames := l.getTargetFilenames() var changedFilenames []string // Fast path: // This is a processed version of the original; // check if it already exists at the destination. for _, targetFilename := range targetFilenames { if _, err := l.getSpec().BaseFs.PublishFs.Stat(targetFilename); err == nil { continue } changedFilenames = append(changedFilenames, targetFilename) } if len(changedFilenames) == 0 { return } w, err = helpers.OpenFilesForWriting(l.getSpec().BaseFs.PublishFs, changedFilenames...) }) return } func (r *genericResource) openPublishFileForWriting(relTargetPath string) (io.WriteCloser, error) { return helpers.OpenFilesForWriting(r.spec.BaseFs.PublishFs, r.relTargetPathsFor(relTargetPath)...) } func (l *genericResource) permalinkFor(target string) string { return l.spec.PermalinkForBaseURL(l.relPermalinkForRel(target, true), l.spec.BaseURL.HostURL()) } func (l *genericResource) relPermalinkFor(target string) string { return l.relPermalinkForRel(target, false) } func (l *genericResource) relPermalinkForRel(rel string, isAbs bool) string { return l.spec.PathSpec.URLizeFilename(l.relTargetPathForRel(rel, false, isAbs, true)) } func (l *genericResource) relTargetPathForRel(rel string, addBaseTargetPath, isAbs, isURL bool) string { if addBaseTargetPath && len(l.baseTargetPathDirs) > 1 { panic("multiple baseTargetPathDirs") } var basePath string if addBaseTargetPath && len(l.baseTargetPathDirs) > 0 { basePath = l.baseTargetPathDirs[0] } return l.relTargetPathForRelAndBasePath(rel, basePath, isAbs, isURL) } func (l *genericResource) relTargetPathForRelAndBasePath(rel, basePath string, isAbs, isURL bool) string { rel = l.createBasePath(rel, isURL) if basePath != "" { rel = path.Join(basePath, rel) } if l.baseOffset != "" { rel = path.Join(l.baseOffset, rel) } if isURL { bp := l.spec.PathSpec.GetBasePath(!isAbs) if bp != "" { rel = path.Join(bp, rel) } } if len(rel) == 0 || rel[0] != '/' { rel = "/" + rel } return rel } func (l *genericResource) relTargetPaths() []string { return l.relTargetPathsForRel(l.TargetPath()) } func (l *genericResource) relTargetPathsFor(target string) []string { return l.relTargetPathsForRel(target) } func (l *genericResource) relTargetPathsForRel(rel string) []string { if len(l.baseTargetPathDirs) == 0 { return []string{l.relTargetPathForRelAndBasePath(rel, "", false, false)} } targetPaths := make([]string, len(l.baseTargetPathDirs)) for i, dir := range l.baseTargetPathDirs { targetPaths[i] = l.relTargetPathForRelAndBasePath(rel, dir, false, false) } return targetPaths } func (l *genericResource) updateParams(params map[string]interface{}) { if l.params == nil { l.params = params return } // Sets the params not already set for k, v := range params { if _, found := l.params[k]; !found { l.params[k] = v } } } type targetPather interface { TargetPath() string } type permalinker interface { targetPather permalinkFor(target string) string relPermalinkFor(target string) string relTargetPaths() []string relTargetPathsFor(target string) []string } type resourceContent struct { content string contentInit sync.Once publishInit sync.Once } type resourceFileInfo struct { // Will be set if this resource is backed by something other than a file. openReadSeekerCloser resource.OpenReadSeekCloser // This may be set to tell us to look in another filesystem for this resource. // We, by default, use the sourceFs filesystem in the spec below. sourceFs afero.Fs // Absolute filename to the source, including any content folder path. // Note that this is absolute in relation to the filesystem it is stored in. // It can be a base path filesystem, and then this filename will not match // the path to the file on the real filesystem. sourceFilename string fi hugofs.FileMetaInfo // A hash of the source content. Is only calculated in caching situations. h *resourceHash } func (fi *resourceFileInfo) ReadSeekCloser() (hugio.ReadSeekCloser, error) { if fi.openReadSeekerCloser != nil { return fi.openReadSeekerCloser() } f, err := fi.getSourceFs().Open(fi.getSourceFilename()) if err != nil { return nil, err } return f, nil } func (fi *resourceFileInfo) getFileInfo() hugofs.FileMetaInfo { return fi.fi } func (fi *resourceFileInfo) getSourceFilename() string { return fi.sourceFilename } func (fi *resourceFileInfo) setSourceFilename(s string) { // Make sure it's always loaded by sourceFilename. fi.openReadSeekerCloser = nil fi.sourceFilename = s } func (fi *resourceFileInfo) getSourceFs() afero.Fs { return fi.sourceFs } func (fi *resourceFileInfo) setSourceFs(fs afero.Fs) { fi.sourceFs = fs } func (fi *resourceFileInfo) hash() (string, error) { var err error fi.h.init.Do(func() { var hash string var f hugio.ReadSeekCloser f, err = fi.ReadSeekCloser() if err != nil { err = errors.Wrap(err, "failed to open source file") return } defer f.Close() hash, err = helpers.MD5FromFileFast(f) if err != nil { return } fi.h.value = hash }) return fi.h.value, err } func (fi *resourceFileInfo) size() int { if fi.fi == nil { return 0 } return int(fi.fi.Size()) } type resourceHash struct { value string init sync.Once } type resourcePathDescriptor struct { // The relative target directory and filename. relTargetDirFile dirFile // Callback used to construct a target path relative to its owner. targetPathBuilder func() page.TargetPaths // This will normally be the same as above, but this will only apply to publishing // of resources. It may be multiple values when in multihost mode. baseTargetPathDirs []string // baseOffset is set when the output format's path has a offset, e.g. for AMP. baseOffset string } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource/���������������������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0016376�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource/dates.go�������������������������������������������������������������0000664�0000000�0000000�00000003743�14201470003�0020034�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resource import "time" var _ Dated = Dates{} // Dated wraps a "dated resource". These are the 4 dates that makes // the date logic in Hugo. type Dated interface { Date() time.Time Lastmod() time.Time PublishDate() time.Time ExpiryDate() time.Time } // Dates holds the 4 Hugo dates. type Dates struct { FDate time.Time FLastmod time.Time FPublishDate time.Time FExpiryDate time.Time } func (d *Dates) UpdateDateAndLastmodIfAfter(in Dated) { if in.Date().After(d.Date()) { d.FDate = in.Date() } if in.Lastmod().After(d.Lastmod()) { d.FLastmod = in.Lastmod() } } // IsFuture returns whether the argument represents the future. func IsFuture(d Dated) bool { if d.PublishDate().IsZero() { return false } return d.PublishDate().After(time.Now()) } // IsExpired returns whether the argument is expired. func IsExpired(d Dated) bool { if d.ExpiryDate().IsZero() { return false } return d.ExpiryDate().Before(time.Now()) } // IsZeroDates returns true if all of the dates are zero. func IsZeroDates(d Dated) bool { return d.Date().IsZero() && d.Lastmod().IsZero() && d.ExpiryDate().IsZero() && d.PublishDate().IsZero() } func (p Dates) Date() time.Time { return p.FDate } func (p Dates) Lastmod() time.Time { return p.FLastmod } func (p Dates) PublishDate() time.Time { return p.FPublishDate } func (p Dates) ExpiryDate() time.Time { return p.FExpiryDate } �����������������������������hugo-0.92.2/resources/resource/params.go������������������������������������������������������������0000664�0000000�0000000�00000002000�14201470003�0020200�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resource import ( "github.com/gohugoio/hugo/common/maps" "github.com/spf13/cast" ) func Param(r ResourceParamsProvider, fallback maps.Params, key interface{}) (interface{}, error) { keyStr, err := cast.ToStringE(key) if err != nil { return nil, err } if fallback == nil { return maps.GetNestedParam(keyStr, ".", r.Params()) } return maps.GetNestedParam(keyStr, ".", r.Params(), fallback) } hugo-0.92.2/resources/resource/resource_helpers.go��������������������������������������������������0000664�0000000�0000000�00000003321�14201470003�0022275�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resource import ( "strings" "time" "github.com/gohugoio/hugo/helpers" "github.com/spf13/cast" ) // GetParam will return the param with the given key from the Resource, // nil if not found. func GetParam(r Resource, key string) interface{} { return getParam(r, key, false) } // GetParamToLower is the same as GetParam but it will lower case any string // result, including string slices. func GetParamToLower(r Resource, key string) interface{} { return getParam(r, key, true) } func getParam(r Resource, key string, stringToLower bool) interface{} { v := r.Params()[strings.ToLower(key)] if v == nil { return nil } switch val := v.(type) { case bool: return val case string: if stringToLower { return strings.ToLower(val) } return val case int64, int32, int16, int8, int: return cast.ToInt(v) case float64, float32: return cast.ToFloat64(v) case time.Time: return val case []string: if stringToLower { return helpers.SliceToLower(val) } return v case map[string]interface{}: // JSON and TOML return v case map[interface{}]interface{}: // YAML return v } return nil } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource/resources.go���������������������������������������������������������0000664�0000000�0000000�00000007240�14201470003�0020742�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resource import ( "fmt" "strings" "github.com/gohugoio/hugo/hugofs/glob" ) // Resources represents a slice of resources, which can be a mix of different types. // I.e. both pages and images etc. type Resources []Resource // ResourcesConverter converts a given slice of Resource objects to Resources. type ResourcesConverter interface { ToResources() Resources } // ByType returns resources of a given resource type (ie. "image"). func (r Resources) ByType(tp string) Resources { var filtered Resources for _, resource := range r { if resource.ResourceType() == tp { filtered = append(filtered, resource) } } return filtered } // GetMatch finds the first Resource matching the given pattern, or nil if none found. // See Match for a more complete explanation about the rules used. func (r Resources) GetMatch(pattern string) Resource { g, err := glob.GetGlob(pattern) if err != nil { return nil } for _, resource := range r { if g.Match(strings.ToLower(resource.Name())) { return resource } } return nil } // Match gets all resources matching the given base filename prefix, e.g // "*.png" will match all png files. The "*" does not match path delimiters (/), // so if you organize your resources in sub-folders, you need to be explicit about it, e.g.: // "images/*.png". To match any PNG image anywhere in the bundle you can do "**.png", and // to match all PNG images below the images folder, use "images/**.jpg". // The matching is case insensitive. // Match matches by using the value of Resource.Name, which, by default, is a filename with // path relative to the bundle root with Unix style slashes (/) and no leading slash, e.g. "images/logo.png". // See https://github.com/gobwas/glob for the full rules set. func (r Resources) Match(pattern string) Resources { g, err := glob.GetGlob(pattern) if err != nil { return nil } var matches Resources for _, resource := range r { if g.Match(strings.ToLower(resource.Name())) { matches = append(matches, resource) } } return matches } type translatedResource interface { TranslationKey() string } // MergeByLanguage adds missing translations in r1 from r2. func (r Resources) MergeByLanguage(r2 Resources) Resources { result := append(Resources(nil), r...) m := make(map[string]bool) for _, rr := range r { if translated, ok := rr.(translatedResource); ok { m[translated.TranslationKey()] = true } } for _, rr := range r2 { if translated, ok := rr.(translatedResource); ok { if _, found := m[translated.TranslationKey()]; !found { result = append(result, rr) } } } return result } // MergeByLanguageInterface is the generic version of MergeByLanguage. It // is here just so it can be called from the tpl package. func (r Resources) MergeByLanguageInterface(in interface{}) (interface{}, error) { r2, ok := in.(Resources) if !ok { return nil, fmt.Errorf("%T cannot be merged by language", in) } return r.MergeByLanguage(r2), nil } // Source is an internal template and not meant for use in the templates. It // may change without notice. type Source interface { Publish() error } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource/resourcetypes.go�����������������������������������������������������0000664�0000000�0000000�00000014030�14201470003�0021637�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resource import ( "image" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/images/exif" "github.com/gohugoio/hugo/common/hugio" ) // Cloner is an internal template and not meant for use in the templates. It // may change without notice. type Cloner interface { Clone() Resource } // OriginProvider provides the original Resource if this is wrapped. // This is an internal Hugo interface and not meant for use in the templates. type OriginProvider interface { Origin() Resource GetFieldString(pattern string) (string, bool) } // ErrProvider provides an Err. type ErrProvider interface { Err() error } // Resource represents a linkable resource, i.e. a content page, image etc. type Resource interface { ResourceTypeProvider MediaTypeProvider ResourceLinksProvider ResourceMetaProvider ResourceParamsProvider ResourceDataProvider ErrProvider } // Image represents an image resource. type Image interface { Resource ImageOps } type ImageOps interface { Height() int Width() int Fill(spec string) (Image, error) Fit(spec string) (Image, error) Resize(spec string) (Image, error) Filter(filters ...interface{}) (Image, error) Exif() *exif.Exif // Internal DecodeImage() (image.Image, error) } type ResourceTypeProvider interface { // ResourceType is the resource type. For most file types, this is the main // part of the MIME type, e.g. "image", "application", "text" etc. // For content pages, this value is "page". ResourceType() string } type ResourceTypesProvider interface { ResourceTypeProvider MediaTypeProvider } type MediaTypeProvider interface { // MediaType is this resource's MIME type. MediaType() media.Type } type ResourceLinksProvider interface { // Permalink represents the absolute link to this resource. Permalink() string // RelPermalink represents the host relative link to this resource. RelPermalink() string } type ResourceMetaProvider interface { // Name is the logical name of this resource. This can be set in the front matter // metadata for this resource. If not set, Hugo will assign a value. // This will in most cases be the base filename. // So, for the image "/some/path/sunset.jpg" this will be "sunset.jpg". // The value returned by this method will be used in the GetByPrefix and ByPrefix methods // on Resources. Name() string // Title returns the title if set in front matter. For content pages, this will be the expected value. Title() string } type ResourceParamsProvider interface { // Params set in front matter for this resource. Params() maps.Params } type ResourceDataProvider interface { // Resource specific data set by Hugo. // One example would be.Data.Digest for fingerprinted resources. Data() interface{} } // ResourcesLanguageMerger describes an interface for merging resources from a // different language. type ResourcesLanguageMerger interface { MergeByLanguage(other Resources) Resources // Needed for integration with the tpl package. MergeByLanguageInterface(other interface{}) (interface{}, error) } // Identifier identifies a resource. type Identifier interface { Key() string } // ContentResource represents a Resource that provides a way to get to its content. // Most Resource types in Hugo implements this interface, including Page. type ContentResource interface { MediaType() media.Type ContentProvider } // ContentProvider provides Content. // This should be used with care, as it will read the file content into memory, but it // should be cached as effectively as possible by the implementation. type ContentProvider interface { // Content returns this resource's content. It will be equivalent to reading the content // that RelPermalink points to in the published folder. // The return type will be contextual, and should be what you would expect: // * Page: template.HTML // * JSON: String // * Etc. Content() (interface{}, error) } // OpenReadSeekCloser allows setting some other way (than reading from a filesystem) // to open or create a ReadSeekCloser. type OpenReadSeekCloser func() (hugio.ReadSeekCloser, error) // ReadSeekCloserResource is a Resource that supports loading its content. type ReadSeekCloserResource interface { MediaType() media.Type hugio.ReadSeekCloserProvider } // LengthProvider is a Resource that provides a length // (typically the length of the content). type LengthProvider interface { Len() int } // LanguageProvider is a Resource in a language. type LanguageProvider interface { Language() *langs.Language } // TranslationKeyProvider connects translations of the same Resource. type TranslationKeyProvider interface { TranslationKey() string } // UnmarshableResource represents a Resource that can be unmarshaled to some other format. type UnmarshableResource interface { ReadSeekCloserResource Identifier } type resourceTypesHolder struct { mediaType media.Type resourceType string } func (r resourceTypesHolder) MediaType() media.Type { return r.mediaType } func (r resourceTypesHolder) ResourceType() string { return r.resourceType } func NewResourceTypesProvider(mediaType media.Type, resourceType string) ResourceTypesProvider { return resourceTypesHolder{mediaType: mediaType, resourceType: resourceType} } type languageHolder struct { lang *langs.Language } func (l languageHolder) Language() *langs.Language { return l.lang } func NewLanguageProvider(lang *langs.Language) LanguageProvider { return languageHolder{lang: lang} } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_cache.go�������������������������������������������������������������0000664�0000000�0000000�00000016065�14201470003�0020060�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "encoding/json" "io" "path" "path/filepath" "regexp" "strings" "sync" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs/glob" "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/cache/filecache" "github.com/BurntSushi/locker" ) const ( CACHE_CLEAR_ALL = "clear_all" CACHE_OTHER = "other" ) type ResourceCache struct { rs *Spec sync.RWMutex // Either resource.Resource or resource.Resources. cache map[string]interface{} fileCache *filecache.Cache // Provides named resource locks. nlocker *locker.Locker } // ResourceCacheKey converts the filename into the format used in the resource // cache. func ResourceCacheKey(filename string) string { filename = filepath.ToSlash(filename) return path.Join(resourceKeyPartition(filename), filename) } func resourceKeyPartition(filename string) string { ext := strings.TrimPrefix(path.Ext(filepath.ToSlash(filename)), ".") if ext == "" { ext = CACHE_OTHER } return ext } // Commonly used aliases and directory names used for some types. var extAliasKeywords = map[string][]string{ "sass": {"scss"}, "scss": {"sass"}, } // ResourceKeyPartitions resolves a ordered slice of partitions that is // used to do resource cache invalidations. // // We use the first directory path element and the extension, so: // a/b.json => "a", "json" // b.json => "json" // // For some of the extensions we will also map to closely related types, // e.g. "scss" will also return "sass". // func ResourceKeyPartitions(filename string) []string { var partitions []string filename = glob.NormalizePath(filename) dir, name := path.Split(filename) ext := strings.TrimPrefix(path.Ext(filepath.ToSlash(name)), ".") if dir != "" { partitions = append(partitions, strings.Split(dir, "/")[0]) } if ext != "" { partitions = append(partitions, ext) } if aliases, found := extAliasKeywords[ext]; found { partitions = append(partitions, aliases...) } if len(partitions) == 0 { partitions = []string{CACHE_OTHER} } return helpers.UniqueStringsSorted(partitions) } // ResourceKeyContainsAny returns whether the key is a member of any of the // given partitions. // // This is used for resource cache invalidation. func ResourceKeyContainsAny(key string, partitions []string) bool { parts := strings.Split(key, "/") for _, p1 := range partitions { for _, p2 := range parts { if p1 == p2 { return true } } } return false } func newResourceCache(rs *Spec) *ResourceCache { return &ResourceCache{ rs: rs, fileCache: rs.FileCaches.AssetsCache(), cache: make(map[string]interface{}), nlocker: locker.NewLocker(), } } func (c *ResourceCache) clear() { c.Lock() defer c.Unlock() c.cache = make(map[string]interface{}) c.nlocker = locker.NewLocker() } func (c *ResourceCache) Contains(key string) bool { key = c.cleanKey(filepath.ToSlash(key)) _, found := c.get(key) return found } func (c *ResourceCache) cleanKey(key string) string { return strings.TrimPrefix(path.Clean(strings.ToLower(key)), "/") } func (c *ResourceCache) get(key string) (interface{}, bool) { c.RLock() defer c.RUnlock() r, found := c.cache[key] return r, found } func (c *ResourceCache) GetOrCreate(key string, f func() (resource.Resource, error)) (resource.Resource, error) { r, err := c.getOrCreate(key, func() (interface{}, error) { return f() }) if r == nil || err != nil { return nil, err } return r.(resource.Resource), nil } func (c *ResourceCache) GetOrCreateResources(key string, f func() (resource.Resources, error)) (resource.Resources, error) { r, err := c.getOrCreate(key, func() (interface{}, error) { return f() }) if r == nil || err != nil { return nil, err } return r.(resource.Resources), nil } func (c *ResourceCache) getOrCreate(key string, f func() (interface{}, error)) (interface{}, error) { key = c.cleanKey(key) // First check in-memory cache. r, found := c.get(key) if found { return r, nil } // This is a potentially long running operation, so get a named lock. c.nlocker.Lock(key) // Double check in-memory cache. r, found = c.get(key) if found { c.nlocker.Unlock(key) return r, nil } defer c.nlocker.Unlock(key) r, err := f() if err != nil { return nil, err } c.set(key, r) return r, nil } func (c *ResourceCache) getFilenames(key string) (string, string) { filenameMeta := key + ".json" filenameContent := key + ".content" return filenameMeta, filenameContent } func (c *ResourceCache) getFromFile(key string) (filecache.ItemInfo, io.ReadCloser, transformedResourceMetadata, bool) { c.RLock() defer c.RUnlock() var meta transformedResourceMetadata filenameMeta, filenameContent := c.getFilenames(key) _, jsonContent, _ := c.fileCache.GetBytes(filenameMeta) if jsonContent == nil { return filecache.ItemInfo{}, nil, meta, false } if err := json.Unmarshal(jsonContent, &meta); err != nil { return filecache.ItemInfo{}, nil, meta, false } fi, rc, _ := c.fileCache.Get(filenameContent) return fi, rc, meta, rc != nil } // writeMeta writes the metadata to file and returns a writer for the content part. func (c *ResourceCache) writeMeta(key string, meta transformedResourceMetadata) (filecache.ItemInfo, io.WriteCloser, error) { filenameMeta, filenameContent := c.getFilenames(key) raw, err := json.Marshal(meta) if err != nil { return filecache.ItemInfo{}, nil, err } _, fm, err := c.fileCache.WriteCloser(filenameMeta) if err != nil { return filecache.ItemInfo{}, nil, err } defer fm.Close() if _, err := fm.Write(raw); err != nil { return filecache.ItemInfo{}, nil, err } fi, fc, err := c.fileCache.WriteCloser(filenameContent) return fi, fc, err } func (c *ResourceCache) set(key string, r interface{}) { c.Lock() defer c.Unlock() c.cache[key] = r } func (c *ResourceCache) DeletePartitions(partitions ...string) { partitionsSet := map[string]bool{ // Always clear out the resources not matching any partition. "other": true, } for _, p := range partitions { partitionsSet[p] = true } if partitionsSet[CACHE_CLEAR_ALL] { c.clear() return } c.Lock() defer c.Unlock() for k := range c.cache { clear := false for p := range partitionsSet { if strings.Contains(k, p) { // There will be some false positive, but that's fine. clear = true break } } if clear { delete(c.cache, k) } } } func (c *ResourceCache) DeleteMatches(re *regexp.Regexp) { c.Lock() defer c.Unlock() for k := range c.cache { if re.MatchString(k) { delete(c.cache, k) } } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_cache_test.go��������������������������������������������������������0000664�0000000�0000000�00000003237�14201470003�0021114�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "path/filepath" "testing" qt "github.com/frankban/quicktest" ) func TestResourceKeyPartitions(t *testing.T) { c := qt.New(t) for _, test := range []struct { input string expected []string }{ {"a.js", []string{"js"}}, {"a.scss", []string{"sass", "scss"}}, {"a.sass", []string{"sass", "scss"}}, {"d/a.js", []string{"d", "js"}}, {"js/a.js", []string{"js"}}, {"D/a.JS", []string{"d", "js"}}, {"d/a", []string{"d"}}, {filepath.FromSlash("/d/a.js"), []string{"d", "js"}}, {filepath.FromSlash("/d/e/a.js"), []string{"d", "js"}}, } { c.Assert(ResourceKeyPartitions(test.input), qt.DeepEquals, test.expected, qt.Commentf(test.input)) } } func TestResourceKeyContainsAny(t *testing.T) { c := qt.New(t) for _, test := range []struct { key string filename string expected bool }{ {"styles/css", "asdf.css", true}, {"styles/css", "styles/asdf.scss", true}, {"js/foo.bar", "asdf.css", false}, } { c.Assert(ResourceKeyContainsAny(test.key, ResourceKeyPartitions(test.filename)), qt.Equals, test.expected) } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_factories/�����������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0020435�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_factories/bundler/���������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0022070�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_factories/bundler/bundler.go�����������������������������������������0000664�0000000�0000000�00000010500�14201470003�0024046�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package bundler contains functions for concatenation etc. of Resource objects. package bundler import ( "fmt" "io" "path" "path/filepath" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/resource" ) // Client contains methods perform concatenation and other bundling related // tasks to Resource objects. type Client struct { rs *resources.Spec } // New creates a new Client with the given specification. func New(rs *resources.Spec) *Client { return &Client{rs: rs} } type multiReadSeekCloser struct { mr io.Reader sources []hugio.ReadSeekCloser } func toReaders(sources []hugio.ReadSeekCloser) []io.Reader { readers := make([]io.Reader, len(sources)) for i, r := range sources { readers[i] = r } return readers } func newMultiReadSeekCloser(sources ...hugio.ReadSeekCloser) *multiReadSeekCloser { mr := io.MultiReader(toReaders(sources)...) return &multiReadSeekCloser{mr, sources} } func (r *multiReadSeekCloser) Read(p []byte) (n int, err error) { return r.mr.Read(p) } func (r *multiReadSeekCloser) Seek(offset int64, whence int) (newOffset int64, err error) { for _, s := range r.sources { newOffset, err = s.Seek(offset, whence) if err != nil { return } } r.mr = io.MultiReader(toReaders(r.sources)...) return } func (r *multiReadSeekCloser) Close() error { for _, s := range r.sources { s.Close() } return nil } // Concat concatenates the list of Resource objects. func (c *Client) Concat(targetPath string, r resource.Resources) (resource.Resource, error) { // The CACHE_OTHER will make sure this will be re-created and published on rebuilds. return c.rs.ResourceCache.GetOrCreate(path.Join(resources.CACHE_OTHER, targetPath), func() (resource.Resource, error) { var resolvedm media.Type // The given set of resources must be of the same Media Type. // We may improve on that in the future, but then we need to know more. for i, r := range r { if i > 0 && r.MediaType().Type() != resolvedm.Type() { return nil, fmt.Errorf("resources in Concat must be of the same Media Type, got %q and %q", r.MediaType().Type(), resolvedm.Type()) } resolvedm = r.MediaType() } concatr := func() (hugio.ReadSeekCloser, error) { var rcsources []hugio.ReadSeekCloser for _, s := range r { rcr, ok := s.(resource.ReadSeekCloserResource) if !ok { return nil, fmt.Errorf("resource %T does not implement resource.ReadSeekerCloserResource", s) } rc, err := rcr.ReadSeekCloser() if err != nil { // Close the already opened. for _, rcs := range rcsources { rcs.Close() } return nil, err } rcsources = append(rcsources, rc) } // Arbitrary JavaScript files require a barrier between them to be safely concatenated together. // Without this, the last line of one file can affect the first line of the next file and change how both files are interpreted. if resolvedm.MainType == media.JavascriptType.MainType && resolvedm.SubType == media.JavascriptType.SubType { readers := make([]hugio.ReadSeekCloser, 2*len(rcsources)-1) j := 0 for i := 0; i < len(rcsources); i++ { if i > 0 { readers[j] = hugio.NewReadSeekerNoOpCloserFromString("\n;\n") j++ } readers[j] = rcsources[i] j++ } return newMultiReadSeekCloser(readers...), nil } return newMultiReadSeekCloser(rcsources...), nil } composite, err := c.rs.New( resources.ResourceSourceDescriptor{ Fs: c.rs.FileCaches.AssetsCache().Fs, LazyPublish: true, OpenReadSeekCloser: concatr, RelTargetFilename: filepath.Clean(targetPath), }) if err != nil { return nil, err } return composite, nil }) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_factories/bundler/bundler_test.go������������������������������������0000664�0000000�0000000�00000002204�14201470003�0025107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package bundler import ( "testing" "github.com/gohugoio/hugo/helpers" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/common/hugio" ) func TestMultiReadSeekCloser(t *testing.T) { c := qt.New(t) rc := newMultiReadSeekCloser( hugio.NewReadSeekerNoOpCloserFromString("A"), hugio.NewReadSeekerNoOpCloserFromString("B"), hugio.NewReadSeekerNoOpCloserFromString("C"), ) for i := 0; i < 3; i++ { s1 := helpers.ReaderToString(rc) c.Assert(s1, qt.Equals, "ABC") _, err := rc.Seek(0, 0) c.Assert(err, qt.IsNil) } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_factories/create/����������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0021700�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_factories/create/create.go�������������������������������������������0000664�0000000�0000000�00000010072�14201470003�0023472�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package create contains functions for to create Resource objects. This will // typically non-files. package create import ( "net/http" "path" "path/filepath" "strings" "time" "github.com/gohugoio/hugo/hugofs/glob" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/resource" ) // Client contains methods to create Resource objects. // tasks to Resource objects. type Client struct { rs *resources.Spec httpClient *http.Client cacheGetResource *filecache.Cache } // New creates a new Client with the given specification. func New(rs *resources.Spec) *Client { return &Client{ rs: rs, httpClient: &http.Client{ Timeout: 10 * time.Second, }, cacheGetResource: rs.FileCaches.GetResourceCache(), } } // Get creates a new Resource by opening the given filename in the assets filesystem. func (c *Client) Get(filename string) (resource.Resource, error) { filename = filepath.Clean(filename) return c.rs.ResourceCache.GetOrCreate(resources.ResourceCacheKey(filename), func() (resource.Resource, error) { return c.rs.New(resources.ResourceSourceDescriptor{ Fs: c.rs.BaseFs.Assets.Fs, LazyPublish: true, SourceFilename: filename, }) }) } // Match gets the resources matching the given pattern from the assets filesystem. func (c *Client) Match(pattern string) (resource.Resources, error) { return c.match(pattern, false) } // GetMatch gets first resource matching the given pattern from the assets filesystem. func (c *Client) GetMatch(pattern string) (resource.Resource, error) { res, err := c.match(pattern, true) if err != nil || len(res) == 0 { return nil, err } return res[0], err } func (c *Client) match(pattern string, firstOnly bool) (resource.Resources, error) { var name string if firstOnly { name = "__get-match" } else { name = "__match" } pattern = glob.NormalizePath(pattern) partitions := glob.FilterGlobParts(strings.Split(pattern, "/")) if len(partitions) == 0 { partitions = []string{resources.CACHE_OTHER} } key := path.Join(name, path.Join(partitions...)) key = path.Join(key, pattern) return c.rs.ResourceCache.GetOrCreateResources(key, func() (resource.Resources, error) { var res resource.Resources handle := func(info hugofs.FileMetaInfo) (bool, error) { meta := info.Meta() r, err := c.rs.New(resources.ResourceSourceDescriptor{ LazyPublish: true, FileInfo: info, OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) { return meta.Open() }, RelTargetFilename: meta.Path, }) if err != nil { return true, err } res = append(res, r) return firstOnly, nil } if err := hugofs.Glob(c.rs.BaseFs.Assets.Fs, pattern, handle); err != nil { return nil, err } return res, nil }) } // FromString creates a new Resource from a string with the given relative target path. func (c *Client) FromString(targetPath, content string) (resource.Resource, error) { return c.rs.ResourceCache.GetOrCreate(path.Join(resources.CACHE_OTHER, targetPath), func() (resource.Resource, error) { return c.rs.New( resources.ResourceSourceDescriptor{ Fs: c.rs.FileCaches.AssetsCache().Fs, LazyPublish: true, OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) { return hugio.NewReadSeekerNoOpCloserFromString(content), nil }, RelTargetFilename: filepath.Clean(targetPath), }) }) } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_factories/create/remote.go�������������������������������������������0000664�0000000�0000000�00000014005�14201470003�0023522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package create import ( "bufio" "bytes" "io" "io/ioutil" "mime" "net/http" "net/http/httputil" "net/url" "path" "path/filepath" "strings" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/resource" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) // FromRemote expects one or n-parts of a URL to a resource // If you provide multiple parts they will be joined together to the final URL. func (c *Client) FromRemote(uri string, optionsm map[string]interface{}) (resource.Resource, error) { rURL, err := url.Parse(uri) if err != nil { return nil, errors.Wrapf(err, "failed to parse URL for resource %s", uri) } resourceID := helpers.HashString(uri, optionsm) _, httpResponse, err := c.cacheGetResource.GetOrCreate(resourceID, func() (io.ReadCloser, error) { options, err := decodeRemoteOptions(optionsm) if err != nil { return nil, errors.Wrapf(err, "failed to decode options for resource %s", uri) } if err := c.validateFromRemoteArgs(uri, options); err != nil { return nil, err } req, err := http.NewRequest(options.Method, uri, options.BodyReader()) if err != nil { return nil, errors.Wrapf(err, "failed to create request for resource %s", uri) } addDefaultHeaders(req) if options.Headers != nil { addUserProvidedHeaders(options.Headers, req) } res, err := c.httpClient.Do(req) if err != nil { return nil, err } if res.StatusCode != http.StatusNotFound { if res.StatusCode < 200 || res.StatusCode > 299 { return nil, errors.Errorf("failed to fetch remote resource: %s", http.StatusText(res.StatusCode)) } } httpResponse, err := httputil.DumpResponse(res, true) if err != nil { return nil, err } return hugio.ToReadCloser(bytes.NewReader(httpResponse)), nil }) if err != nil { return nil, err } defer httpResponse.Close() res, err := http.ReadResponse(bufio.NewReader(httpResponse), nil) if err != nil { return nil, err } if res.StatusCode == http.StatusNotFound { // Not found. This matches how looksup for local resources work. return nil, nil } body, err := ioutil.ReadAll(res.Body) if err != nil { return nil, errors.Wrapf(err, "failed to read remote resource %q", uri) } filename := path.Base(rURL.Path) if _, params, _ := mime.ParseMediaType(res.Header.Get("Content-Disposition")); params != nil { if _, ok := params["filename"]; ok { filename = params["filename"] } } var extensionHints []string contentType := res.Header.Get("Content-Type") // mime.ExtensionsByType gives a long list of extensions for text/plain, // just use ".txt". if strings.HasPrefix(contentType, "text/plain") { extensionHints = []string{".txt"} } else { exts, _ := mime.ExtensionsByType(contentType) if exts != nil { extensionHints = exts } } // Look for a file extention. If it's .txt, look for a more specific. if extensionHints == nil || extensionHints[0] == ".txt" { if ext := path.Ext(filename); ext != "" { extensionHints = []string{ext} } } // Now resolve the media type primarily using the content. mediaType := media.FromContent(c.rs.MediaTypes, extensionHints, body) if mediaType.IsZero() { return nil, errors.Errorf("failed to resolve media type for remote resource %q", uri) } resourceID = filename[:len(filename)-len(path.Ext(filename))] + "_" + resourceID + mediaType.FirstSuffix.FullSuffix return c.rs.New( resources.ResourceSourceDescriptor{ MediaType: mediaType, LazyPublish: true, OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) { return hugio.NewReadSeekerNoOpCloser(bytes.NewReader(body)), nil }, RelTargetFilename: filepath.Clean(resourceID), }) } func (c *Client) validateFromRemoteArgs(uri string, options fromRemoteOptions) error { if err := c.rs.ExecHelper.Sec().CheckAllowedHTTPURL(uri); err != nil { return err } if err := c.rs.ExecHelper.Sec().CheckAllowedHTTPMethod(options.Method); err != nil { return err } return nil } func addDefaultHeaders(req *http.Request, accepts ...string) { for _, accept := range accepts { if !hasHeaderValue(req.Header, "Accept", accept) { req.Header.Add("Accept", accept) } } if !hasHeaderKey(req.Header, "User-Agent") { req.Header.Add("User-Agent", "Hugo Static Site Generator") } } func addUserProvidedHeaders(headers map[string]interface{}, req *http.Request) { if headers == nil { return } for key, val := range headers { vals := types.ToStringSlicePreserveString(val) for _, s := range vals { req.Header.Add(key, s) } } } func hasHeaderValue(m http.Header, key, value string) bool { var s []string var ok bool if s, ok = m[key]; !ok { return false } for _, v := range s { if v == value { return true } } return false } func hasHeaderKey(m http.Header, key string) bool { _, ok := m[key] return ok } type fromRemoteOptions struct { Method string Headers map[string]interface{} Body []byte } func (o fromRemoteOptions) BodyReader() io.Reader { if o.Body == nil { return nil } return bytes.NewBuffer(o.Body) } func decodeRemoteOptions(optionsm map[string]interface{}) (fromRemoteOptions, error) { options := fromRemoteOptions{ Method: "GET", } err := mapstructure.WeakDecode(optionsm, &options) if err != nil { return options, err } options.Method = strings.ToUpper(options.Method) return options, nil } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_factories/create/remote_test.go��������������������������������������0000664�0000000�0000000�00000003331�14201470003�0024561�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package create import ( "testing" qt "github.com/frankban/quicktest" ) func TestDecodeRemoteOptions(t *testing.T) { c := qt.New(t) for _, test := range []struct { name string args map[string]interface{} want fromRemoteOptions wantErr bool }{ { "POST", map[string]interface{}{ "meThod": "PoST", "headers": map[string]interface{}{ "foo": "bar", }, }, fromRemoteOptions{ Method: "POST", Headers: map[string]interface{}{ "foo": "bar", }, }, false, }, { "Body", map[string]interface{}{ "meThod": "POST", "body": []byte("foo"), }, fromRemoteOptions{ Method: "POST", Body: []byte("foo"), }, false, }, { "Body, string", map[string]interface{}{ "meThod": "POST", "body": "foo", }, fromRemoteOptions{ Method: "POST", Body: []byte("foo"), }, false, }, } { c.Run(test.name, func(c *qt.C) { got, err := decodeRemoteOptions(test.args) isErr := qt.IsNil if test.wantErr { isErr = qt.IsNotNil } c.Assert(err, isErr) c.Assert(got, qt.DeepEquals, test.want) }) } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_metadata.go����������������������������������������������������������0000664�0000000�0000000�00000007761�14201470003�0020600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "fmt" "strconv" "strings" "github.com/gohugoio/hugo/hugofs/glob" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/resource" "github.com/pkg/errors" "github.com/spf13/cast" "github.com/gohugoio/hugo/common/maps" ) var ( _ metaAssigner = (*genericResource)(nil) _ metaAssigner = (*imageResource)(nil) _ metaAssignerProvider = (*resourceAdapter)(nil) ) type metaAssignerProvider interface { getMetaAssigner() metaAssigner } // metaAssigner allows updating metadata in resources that supports it. type metaAssigner interface { setTitle(title string) setName(name string) setMediaType(mediaType media.Type) updateParams(params map[string]interface{}) } const counterPlaceHolder = ":counter" // AssignMetadata assigns the given metadata to those resources that supports updates // and matching by wildcard given in `src` using `filepath.Match` with lower cased values. // This assignment is additive, but the most specific match needs to be first. // The `name` and `title` metadata field support shell-matched collection it got a match in. // See https://golang.org/pkg/path/#Match func AssignMetadata(metadata []map[string]interface{}, resources ...resource.Resource) error { counters := make(map[string]int) for _, r := range resources { var ma metaAssigner mp, ok := r.(metaAssignerProvider) if ok { ma = mp.getMetaAssigner() } else { ma, ok = r.(metaAssigner) if !ok { continue } } var ( nameSet, titleSet bool nameCounter, titleCounter = 0, 0 nameCounterFound, titleCounterFound bool resourceSrcKey = strings.ToLower(r.Name()) ) for _, meta := range metadata { src, found := meta["src"] if !found { return fmt.Errorf("missing 'src' in metadata for resource") } srcKey := strings.ToLower(cast.ToString(src)) glob, err := glob.GetGlob(srcKey) if err != nil { return errors.Wrap(err, "failed to match resource with metadata") } match := glob.Match(resourceSrcKey) if match { if !nameSet { name, found := meta["name"] if found { name := cast.ToString(name) if !nameCounterFound { nameCounterFound = strings.Contains(name, counterPlaceHolder) } if nameCounterFound && nameCounter == 0 { counterKey := "name_" + srcKey nameCounter = counters[counterKey] + 1 counters[counterKey] = nameCounter } ma.setName(replaceResourcePlaceholders(name, nameCounter)) nameSet = true } } if !titleSet { title, found := meta["title"] if found { title := cast.ToString(title) if !titleCounterFound { titleCounterFound = strings.Contains(title, counterPlaceHolder) } if titleCounterFound && titleCounter == 0 { counterKey := "title_" + srcKey titleCounter = counters[counterKey] + 1 counters[counterKey] = titleCounter } ma.setTitle((replaceResourcePlaceholders(title, titleCounter))) titleSet = true } } params, found := meta["params"] if found { m := maps.ToStringMap(params) // Needed for case insensitive fetching of params values maps.PrepareParams(m) ma.updateParams(m) } } } } return nil } func replaceResourcePlaceholders(in string, counter int) string { return strings.Replace(in, counterPlaceHolder, strconv.Itoa(counter), -1) } ���������������hugo-0.92.2/resources/resource_metadata_test.go�����������������������������������������������������0000664�0000000�0000000�00000014107�14201470003�0021627�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "testing" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/resource" qt "github.com/frankban/quicktest" ) func TestAssignMetadata(t *testing.T) { c := qt.New(t) spec := newTestResourceSpec(specDescriptor{c: c}) var foo1, foo2, foo3, logo1, logo2, logo3 resource.Resource var resources resource.Resources for _, this := range []struct { metaData []map[string]interface{} assertFunc func(err error) }{ {[]map[string]interface{}{ { "title": "My Resource", "name": "My Name", "src": "*", }, }, func(err error) { c.Assert(logo1.Title(), qt.Equals, "My Resource") c.Assert(logo1.Name(), qt.Equals, "My Name") c.Assert(foo2.Name(), qt.Equals, "My Name") }}, {[]map[string]interface{}{ { "title": "My Logo", "src": "*loGo*", }, { "title": "My Resource", "name": "My Name", "src": "*", }, }, func(err error) { c.Assert(logo1.Title(), qt.Equals, "My Logo") c.Assert(logo2.Title(), qt.Equals, "My Logo") c.Assert(logo1.Name(), qt.Equals, "My Name") c.Assert(foo2.Name(), qt.Equals, "My Name") c.Assert(foo3.Name(), qt.Equals, "My Name") c.Assert(foo3.Title(), qt.Equals, "My Resource") }}, {[]map[string]interface{}{ { "title": "My Logo", "src": "*loGo*", "params": map[string]interface{}{ "Param1": true, "icon": "logo", }, }, { "title": "My Resource", "src": "*", "params": map[string]interface{}{ "Param2": true, "icon": "resource", }, }, }, func(err error) { c.Assert(err, qt.IsNil) c.Assert(logo1.Title(), qt.Equals, "My Logo") c.Assert(foo3.Title(), qt.Equals, "My Resource") _, p1 := logo2.Params()["param1"] _, p2 := foo2.Params()["param2"] _, p1_2 := foo2.Params()["param1"] _, p2_2 := logo2.Params()["param2"] icon1 := logo2.Params()["icon"] icon2 := foo2.Params()["icon"] c.Assert(p1, qt.Equals, true) c.Assert(p2, qt.Equals, true) // Check merge c.Assert(p2_2, qt.Equals, true) c.Assert(p1_2, qt.Equals, false) c.Assert(icon1, qt.Equals, "logo") c.Assert(icon2, qt.Equals, "resource") }}, {[]map[string]interface{}{ { "name": "Logo Name #:counter", "src": "*logo*", }, { "title": "Resource #:counter", "name": "Name #:counter", "src": "*", }, }, func(err error) { c.Assert(err, qt.IsNil) c.Assert(logo2.Title(), qt.Equals, "Resource #2") c.Assert(logo2.Name(), qt.Equals, "Logo Name #1") c.Assert(logo1.Title(), qt.Equals, "Resource #4") c.Assert(logo1.Name(), qt.Equals, "Logo Name #2") c.Assert(foo2.Title(), qt.Equals, "Resource #1") c.Assert(foo1.Title(), qt.Equals, "Resource #3") c.Assert(foo1.Name(), qt.Equals, "Name #2") c.Assert(foo3.Title(), qt.Equals, "Resource #5") c.Assert(resources.GetMatch("logo name #1*"), qt.Equals, logo2) }}, {[]map[string]interface{}{ { "title": "Third Logo #:counter", "src": "logo3.png", }, { "title": "Other Logo #:counter", "name": "Name #:counter", "src": "logo*", }, }, func(err error) { c.Assert(err, qt.IsNil) c.Assert(logo3.Title(), qt.Equals, "Third Logo #1") c.Assert(logo3.Name(), qt.Equals, "Name #3") c.Assert(logo2.Title(), qt.Equals, "Other Logo #1") c.Assert(logo2.Name(), qt.Equals, "Name #1") c.Assert(logo1.Title(), qt.Equals, "Other Logo #2") c.Assert(logo1.Name(), qt.Equals, "Name #2") }}, {[]map[string]interface{}{ { "title": "Third Logo", "src": "logo3.png", }, { "title": "Other Logo #:counter", "name": "Name #:counter", "src": "logo*", }, }, func(err error) { c.Assert(err, qt.IsNil) c.Assert(logo3.Title(), qt.Equals, "Third Logo") c.Assert(logo3.Name(), qt.Equals, "Name #3") c.Assert(logo2.Title(), qt.Equals, "Other Logo #1") c.Assert(logo2.Name(), qt.Equals, "Name #1") c.Assert(logo1.Title(), qt.Equals, "Other Logo #2") c.Assert(logo1.Name(), qt.Equals, "Name #2") }}, {[]map[string]interface{}{ { "name": "third-logo", "src": "logo3.png", }, { "title": "Logo #:counter", "name": "Name #:counter", "src": "logo*", }, }, func(err error) { c.Assert(err, qt.IsNil) c.Assert(logo3.Title(), qt.Equals, "Logo #3") c.Assert(logo3.Name(), qt.Equals, "third-logo") c.Assert(logo2.Title(), qt.Equals, "Logo #1") c.Assert(logo2.Name(), qt.Equals, "Name #1") c.Assert(logo1.Title(), qt.Equals, "Logo #2") c.Assert(logo1.Name(), qt.Equals, "Name #2") }}, {[]map[string]interface{}{ { "title": "Third Logo #:counter", }, }, func(err error) { // Missing src c.Assert(err, qt.Not(qt.IsNil)) }}, {[]map[string]interface{}{ { "title": "Title", "src": "[]", }, }, func(err error) { // Invalid pattern c.Assert(err, qt.Not(qt.IsNil)) }}, } { foo2 = spec.newGenericResource(nil, nil, nil, "/b/foo2.css", "foo2.css", media.CSSType) logo2 = spec.newGenericResource(nil, nil, nil, "/b/Logo2.png", "Logo2.png", pngType) foo1 = spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType) logo1 = spec.newGenericResource(nil, nil, nil, "/a/logo1.png", "logo1.png", pngType) foo3 = spec.newGenericResource(nil, nil, nil, "/b/foo3.css", "foo3.css", media.CSSType) logo3 = spec.newGenericResource(nil, nil, nil, "/b/logo3.png", "logo3.png", pngType) resources = resource.Resources{ foo2, logo2, foo1, logo1, foo3, logo3, } this.assertFunc(AssignMetadata(this.metaData, resources...)) } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_spec.go��������������������������������������������������������������0000664�0000000�0000000�00000020665�14201470003�0017750�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "errors" "fmt" "mime" "os" "path" "path/filepath" "strings" "sync" "github.com/gohugoio/hugo/resources/jsconfig" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/identity" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/resources/postpub" "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/resources/images" "github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/tpl" "github.com/spf13/afero" ) func NewSpec( s *helpers.PathSpec, fileCaches filecache.Caches, incr identity.Incrementer, logger loggers.Logger, errorHandler herrors.ErrorSender, execHelper *hexec.Exec, outputFormats output.Formats, mimeTypes media.Types) (*Spec, error) { imgConfig, err := images.DecodeConfig(s.Cfg.GetStringMap("imaging")) if err != nil { return nil, err } imaging, err := images.NewImageProcessor(imgConfig) if err != nil { return nil, err } if incr == nil { incr = &identity.IncrementByOne{} } if logger == nil { logger = loggers.NewErrorLogger() } permalinks, err := page.NewPermalinkExpander(s) if err != nil { return nil, err } rs := &Spec{ PathSpec: s, Logger: logger, ErrorSender: errorHandler, imaging: imaging, ExecHelper: execHelper, incr: incr, MediaTypes: mimeTypes, OutputFormats: outputFormats, Permalinks: permalinks, BuildConfig: config.DecodeBuild(s.Cfg), FileCaches: fileCaches, PostBuildAssets: &PostBuildAssets{ PostProcessResources: make(map[string]postpub.PostPublishedResource), JSConfigBuilder: jsconfig.NewBuilder(), }, imageCache: newImageCache( fileCaches.ImageCache(), s, ), } rs.ResourceCache = newResourceCache(rs) return rs, nil } type Spec struct { *helpers.PathSpec MediaTypes media.Types OutputFormats output.Formats Logger loggers.Logger ErrorSender herrors.ErrorSender TextTemplates tpl.TemplateParseFinder Permalinks page.PermalinkExpander BuildConfig config.Build // Holds default filter settings etc. imaging *images.ImageProcessor ExecHelper *hexec.Exec incr identity.Incrementer imageCache *imageCache ResourceCache *ResourceCache FileCaches filecache.Caches // Assets used after the build is done. // This is shared between all sites. *PostBuildAssets } type PostBuildAssets struct { postProcessMu sync.RWMutex PostProcessResources map[string]postpub.PostPublishedResource JSConfigBuilder *jsconfig.Builder } func (r *Spec) New(fd ResourceSourceDescriptor) (resource.Resource, error) { return r.newResourceFor(fd) } func (r *Spec) CacheStats() string { r.imageCache.mu.RLock() defer r.imageCache.mu.RUnlock() s := fmt.Sprintf("Cache entries: %d", len(r.imageCache.store)) count := 0 for k := range r.imageCache.store { if count > 5 { break } s += "\n" + k count++ } return s } func (r *Spec) ClearCaches() { r.imageCache.clear() r.ResourceCache.clear() } func (r *Spec) DeleteBySubstring(s string) { r.imageCache.deleteIfContains(s) } func (s *Spec) String() string { return "spec" } // TODO(bep) clean up below func (r *Spec) newGenericResource(sourceFs afero.Fs, targetPathBuilder func() page.TargetPaths, osFileInfo os.FileInfo, sourceFilename, baseFilename string, mediaType media.Type) *genericResource { return r.newGenericResourceWithBase( sourceFs, nil, nil, targetPathBuilder, osFileInfo, sourceFilename, baseFilename, mediaType, ) } func (r *Spec) newGenericResourceWithBase( sourceFs afero.Fs, openReadSeekerCloser resource.OpenReadSeekCloser, targetPathBaseDirs []string, targetPathBuilder func() page.TargetPaths, osFileInfo os.FileInfo, sourceFilename, baseFilename string, mediaType media.Type) *genericResource { if osFileInfo != nil && osFileInfo.IsDir() { panic(fmt.Sprintf("dirs not supported resource types: %v", osFileInfo)) } // This value is used both to construct URLs and file paths, but start // with a Unix-styled path. baseFilename = helpers.ToSlashTrimLeading(baseFilename) fpath, fname := path.Split(baseFilename) resourceType := mediaType.MainType pathDescriptor := &resourcePathDescriptor{ baseTargetPathDirs: helpers.UniqueStringsReuse(targetPathBaseDirs), targetPathBuilder: targetPathBuilder, relTargetDirFile: dirFile{dir: fpath, file: fname}, } var fim hugofs.FileMetaInfo if osFileInfo != nil { fim = osFileInfo.(hugofs.FileMetaInfo) } gfi := &resourceFileInfo{ fi: fim, openReadSeekerCloser: openReadSeekerCloser, sourceFs: sourceFs, sourceFilename: sourceFilename, h: &resourceHash{}, } g := &genericResource{ resourceFileInfo: gfi, resourcePathDescriptor: pathDescriptor, mediaType: mediaType, resourceType: resourceType, spec: r, params: make(map[string]interface{}), name: baseFilename, title: baseFilename, resourceContent: &resourceContent{}, } return g } func (r *Spec) newResource(sourceFs afero.Fs, fd ResourceSourceDescriptor) (resource.Resource, error) { fi := fd.FileInfo var sourceFilename string if fd.OpenReadSeekCloser != nil { } else if fd.SourceFilename != "" { var err error fi, err = sourceFs.Stat(fd.SourceFilename) if err != nil { if os.IsNotExist(err) { return nil, nil } return nil, err } sourceFilename = fd.SourceFilename } else { sourceFilename = fd.SourceFile.Filename() } if fd.RelTargetFilename == "" { fd.RelTargetFilename = sourceFilename } mimeType := fd.MediaType if mimeType.IsZero() { ext := strings.ToLower(filepath.Ext(fd.RelTargetFilename)) var ( found bool suffixInfo media.SuffixInfo ) mimeType, suffixInfo, found = r.MediaTypes.GetFirstBySuffix(strings.TrimPrefix(ext, ".")) // TODO(bep) we need to handle these ambiguous types better, but in this context // we most likely want the application/xml type. if suffixInfo.Suffix == "xml" && mimeType.SubType == "rss" { mimeType, found = r.MediaTypes.GetByType("application/xml") } if !found { // A fallback. Note that mime.TypeByExtension is slow by Hugo standards, // so we should configure media types to avoid this lookup for most // situations. mimeStr := mime.TypeByExtension(ext) if mimeStr != "" { mimeType, _ = media.FromStringAndExt(mimeStr, ext) } } } gr := r.newGenericResourceWithBase( sourceFs, fd.OpenReadSeekCloser, fd.TargetBasePaths, fd.TargetPaths, fi, sourceFilename, fd.RelTargetFilename, mimeType) if mimeType.MainType == "image" { imgFormat, ok := images.ImageFormatFromMediaSubType(mimeType.SubType) if ok { ir := &imageResource{ Image: images.NewImage(imgFormat, r.imaging, nil, gr), baseResource: gr, } ir.root = ir return newResourceAdapter(gr.spec, fd.LazyPublish, ir), nil } } return newResourceAdapter(gr.spec, fd.LazyPublish, gr), nil } func (r *Spec) newResourceFor(fd ResourceSourceDescriptor) (resource.Resource, error) { if fd.OpenReadSeekCloser == nil { if fd.SourceFile != nil && fd.SourceFilename != "" { return nil, errors.New("both SourceFile and AbsSourceFilename provided") } else if fd.SourceFile == nil && fd.SourceFilename == "" { return nil, errors.New("either SourceFile or AbsSourceFilename must be provided") } } if fd.RelTargetFilename == "" { fd.RelTargetFilename = fd.Filename() } if len(fd.TargetBasePaths) == 0 { // If not set, we publish the same resource to all hosts. fd.TargetBasePaths = r.MultihostTargetBasePaths } return r.newResource(fd.Fs, fd) } ���������������������������������������������������������������������������hugo-0.92.2/resources/resource_test.go��������������������������������������������������������������0000664�0000000�0000000�00000023205�14201470003�0017766�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "fmt" "math/rand" "path/filepath" "strings" "testing" "github.com/spf13/afero" "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/media" qt "github.com/frankban/quicktest" ) func TestGenericResource(t *testing.T) { c := qt.New(t) spec := newTestResourceSpec(specDescriptor{c: c}) r := spec.newGenericResource(nil, nil, nil, "/a/foo.css", "foo.css", media.CSSType) c.Assert(r.Permalink(), qt.Equals, "https://example.com/foo.css") c.Assert(r.RelPermalink(), qt.Equals, "/foo.css") c.Assert(r.ResourceType(), qt.Equals, "text") } func TestGenericResourceWithLinkFactory(t *testing.T) { c := qt.New(t) spec := newTestResourceSpec(specDescriptor{c: c}) factory := newTargetPaths("/foo") r := spec.newGenericResource(nil, factory, nil, "/a/foo.css", "foo.css", media.CSSType) c.Assert(r.Permalink(), qt.Equals, "https://example.com/foo/foo.css") c.Assert(r.RelPermalink(), qt.Equals, "/foo/foo.css") c.Assert(r.Key(), qt.Equals, "/foo/foo.css") c.Assert(r.ResourceType(), qt.Equals, "text") } func TestNewResourceFromFilename(t *testing.T) { c := qt.New(t) spec := newTestResourceSpec(specDescriptor{c: c}) writeSource(t, spec.Fs, "content/a/b/logo.png", "image") writeSource(t, spec.Fs, "content/a/b/data.json", "json") bfs := afero.NewBasePathFs(spec.Fs.Source, "content") r, err := spec.New(ResourceSourceDescriptor{Fs: bfs, SourceFilename: "a/b/logo.png"}) c.Assert(err, qt.IsNil) c.Assert(r, qt.Not(qt.IsNil)) c.Assert(r.ResourceType(), qt.Equals, "image") c.Assert(r.RelPermalink(), qt.Equals, "/a/b/logo.png") c.Assert(r.Permalink(), qt.Equals, "https://example.com/a/b/logo.png") r, err = spec.New(ResourceSourceDescriptor{Fs: bfs, SourceFilename: "a/b/data.json"}) c.Assert(err, qt.IsNil) c.Assert(r, qt.Not(qt.IsNil)) c.Assert(r.ResourceType(), qt.Equals, "application") } func TestNewResourceFromFilenameSubPathInBaseURL(t *testing.T) { c := qt.New(t) spec := newTestResourceSpec(specDescriptor{c: c, baseURL: "https://example.com/docs"}) writeSource(t, spec.Fs, "content/a/b/logo.png", "image") bfs := afero.NewBasePathFs(spec.Fs.Source, "content") fmt.Println() r, err := spec.New(ResourceSourceDescriptor{Fs: bfs, SourceFilename: filepath.FromSlash("a/b/logo.png")}) c.Assert(err, qt.IsNil) c.Assert(r, qt.Not(qt.IsNil)) c.Assert(r.ResourceType(), qt.Equals, "image") c.Assert(r.RelPermalink(), qt.Equals, "/docs/a/b/logo.png") c.Assert(r.Permalink(), qt.Equals, "https://example.com/docs/a/b/logo.png") } var pngType, _ = media.FromStringAndExt("image/png", "png") func TestResourcesByType(t *testing.T) { c := qt.New(t) spec := newTestResourceSpec(specDescriptor{c: c}) resources := resource.Resources{ spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType), spec.newGenericResource(nil, nil, nil, "/a/logo.png", "logo.css", pngType), spec.newGenericResource(nil, nil, nil, "/a/foo2.css", "foo2.css", media.CSSType), spec.newGenericResource(nil, nil, nil, "/a/foo3.css", "foo3.css", media.CSSType), } c.Assert(len(resources.ByType("text")), qt.Equals, 3) c.Assert(len(resources.ByType("image")), qt.Equals, 1) } func TestResourcesGetByPrefix(t *testing.T) { c := qt.New(t) spec := newTestResourceSpec(specDescriptor{c: c}) resources := resource.Resources{ spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType), spec.newGenericResource(nil, nil, nil, "/a/logo1.png", "logo1.png", pngType), spec.newGenericResource(nil, nil, nil, "/b/Logo2.png", "Logo2.png", pngType), spec.newGenericResource(nil, nil, nil, "/b/foo2.css", "foo2.css", media.CSSType), spec.newGenericResource(nil, nil, nil, "/b/foo3.css", "foo3.css", media.CSSType), } c.Assert(resources.GetMatch("asdf*"), qt.IsNil) c.Assert(resources.GetMatch("logo*").RelPermalink(), qt.Equals, "/logo1.png") c.Assert(resources.GetMatch("loGo*").RelPermalink(), qt.Equals, "/logo1.png") c.Assert(resources.GetMatch("logo2*").RelPermalink(), qt.Equals, "/Logo2.png") c.Assert(resources.GetMatch("foo2*").RelPermalink(), qt.Equals, "/foo2.css") c.Assert(resources.GetMatch("foo1*").RelPermalink(), qt.Equals, "/foo1.css") c.Assert(resources.GetMatch("foo1*").RelPermalink(), qt.Equals, "/foo1.css") c.Assert(resources.GetMatch("asdfasdf*"), qt.IsNil) c.Assert(len(resources.Match("logo*")), qt.Equals, 2) c.Assert(len(resources.Match("logo2*")), qt.Equals, 1) logo := resources.GetMatch("logo*") c.Assert(logo.Params(), qt.Not(qt.IsNil)) c.Assert(logo.Name(), qt.Equals, "logo1.png") c.Assert(logo.Title(), qt.Equals, "logo1.png") } func TestResourcesGetMatch(t *testing.T) { c := qt.New(t) spec := newTestResourceSpec(specDescriptor{c: c}) resources := resource.Resources{ spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType), spec.newGenericResource(nil, nil, nil, "/a/logo1.png", "logo1.png", pngType), spec.newGenericResource(nil, nil, nil, "/b/Logo2.png", "Logo2.png", pngType), spec.newGenericResource(nil, nil, nil, "/b/foo2.css", "foo2.css", media.CSSType), spec.newGenericResource(nil, nil, nil, "/b/foo3.css", "foo3.css", media.CSSType), spec.newGenericResource(nil, nil, nil, "/b/c/foo4.css", "c/foo4.css", media.CSSType), spec.newGenericResource(nil, nil, nil, "/b/c/foo5.css", "c/foo5.css", media.CSSType), spec.newGenericResource(nil, nil, nil, "/b/c/d/foo6.css", "c/d/foo6.css", media.CSSType), } c.Assert(resources.GetMatch("logo*").RelPermalink(), qt.Equals, "/logo1.png") c.Assert(resources.GetMatch("loGo*").RelPermalink(), qt.Equals, "/logo1.png") c.Assert(resources.GetMatch("logo2*").RelPermalink(), qt.Equals, "/Logo2.png") c.Assert(resources.GetMatch("foo2*").RelPermalink(), qt.Equals, "/foo2.css") c.Assert(resources.GetMatch("foo1*").RelPermalink(), qt.Equals, "/foo1.css") c.Assert(resources.GetMatch("foo1*").RelPermalink(), qt.Equals, "/foo1.css") c.Assert(resources.GetMatch("*/foo*").RelPermalink(), qt.Equals, "/c/foo4.css") c.Assert(resources.GetMatch("asdfasdf"), qt.IsNil) c.Assert(len(resources.Match("Logo*")), qt.Equals, 2) c.Assert(len(resources.Match("logo2*")), qt.Equals, 1) c.Assert(len(resources.Match("c/*")), qt.Equals, 2) c.Assert(len(resources.Match("**.css")), qt.Equals, 6) c.Assert(len(resources.Match("**/*.css")), qt.Equals, 3) c.Assert(len(resources.Match("c/**/*.css")), qt.Equals, 1) // Matches only CSS files in c/ c.Assert(len(resources.Match("c/**.css")), qt.Equals, 3) // Matches all CSS files below c/ (including in c/d/) c.Assert(len(resources.Match("c/**.css")), qt.Equals, 3) // Patterns beginning with a slash will not match anything. // We could maybe consider trimming that slash, but let's be explicit about this. // (it is possible for users to do a rename) // This is analogous to standing in a directory and doing "ls *.*". c.Assert(len(resources.Match("/c/**.css")), qt.Equals, 0) } func BenchmarkResourcesMatch(b *testing.B) { resources := benchResources(b) prefixes := []string{"abc*", "jkl*", "nomatch*", "sub/*"} b.RunParallel(func(pb *testing.PB) { for pb.Next() { resources.Match(prefixes[rand.Intn(len(prefixes))]) } }) } // This adds a benchmark for the a100 test case as described by Russ Cox here: // https://research.swtch.com/glob (really interesting article) // I don't expect Hugo users to "stumble upon" this problem, so this is more to satisfy // my own curiosity. func BenchmarkResourcesMatchA100(b *testing.B) { c := qt.New(b) spec := newTestResourceSpec(specDescriptor{c: c}) a100 := strings.Repeat("a", 100) pattern := "a*a*a*a*a*a*a*a*b" resources := resource.Resources{spec.newGenericResource(nil, nil, nil, "/a/"+a100, a100, media.CSSType)} b.ResetTimer() for i := 0; i < b.N; i++ { resources.Match(pattern) } } func benchResources(b *testing.B) resource.Resources { c := qt.New(b) spec := newTestResourceSpec(specDescriptor{c: c}) var resources resource.Resources for i := 0; i < 30; i++ { name := fmt.Sprintf("abcde%d_%d.css", i%5, i) resources = append(resources, spec.newGenericResource(nil, nil, nil, "/a/"+name, name, media.CSSType)) } for i := 0; i < 30; i++ { name := fmt.Sprintf("efghi%d_%d.css", i%5, i) resources = append(resources, spec.newGenericResource(nil, nil, nil, "/a/"+name, name, media.CSSType)) } for i := 0; i < 30; i++ { name := fmt.Sprintf("jklmn%d_%d.css", i%5, i) resources = append(resources, spec.newGenericResource(nil, nil, nil, "/b/sub/"+name, "sub/"+name, media.CSSType)) } return resources } func BenchmarkAssignMetadata(b *testing.B) { c := qt.New(b) spec := newTestResourceSpec(specDescriptor{c: c}) for i := 0; i < b.N; i++ { b.StopTimer() var resources resource.Resources meta := []map[string]interface{}{ { "title": "Foo #:counter", "name": "Foo Name #:counter", "src": "foo1*", }, { "title": "Rest #:counter", "name": "Rest Name #:counter", "src": "*", }, } for i := 0; i < 20; i++ { name := fmt.Sprintf("foo%d_%d.css", i%5, i) resources = append(resources, spec.newGenericResource(nil, nil, nil, "/a/"+name, name, media.CSSType)) } b.StartTimer() if err := AssignMetadata(meta, resources...); err != nil { b.Fatal(err) } } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/��������������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0021203�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/babel/��������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0022250�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/babel/babel.go������������������������������������������0000664�0000000�0000000�00000015411�14201470003�0023646�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package babel import ( "bytes" "io" "io/ioutil" "os" "path" "path/filepath" "regexp" "strconv" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/resources/internal" "github.com/mitchellh/mapstructure" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/resource" "github.com/pkg/errors" ) // Options from https://babeljs.io/docs/en/options type Options struct { Config string // Custom path to config file Minified bool NoComments bool Compact *bool Verbose bool NoBabelrc bool SourceMap string } // DecodeOptions decodes options to and generates command flags func DecodeOptions(m map[string]interface{}) (opts Options, err error) { if m == nil { return } err = mapstructure.WeakDecode(m, &opts) return } func (opts Options) toArgs() []interface{} { var args []interface{} // external is not a known constant on the babel command line // .sourceMaps must be a boolean, "inline", "both", or undefined switch opts.SourceMap { case "external": args = append(args, "--source-maps") case "inline": args = append(args, "--source-maps=inline") } if opts.Minified { args = append(args, "--minified") } if opts.NoComments { args = append(args, "--no-comments") } if opts.Compact != nil { args = append(args, "--compact="+strconv.FormatBool(*opts.Compact)) } if opts.Verbose { args = append(args, "--verbose") } if opts.NoBabelrc { args = append(args, "--no-babelrc") } return args } // Client is the client used to do Babel transformations. type Client struct { rs *resources.Spec } // New creates a new Client with the given specification. func New(rs *resources.Spec) *Client { return &Client{rs: rs} } type babelTransformation struct { options Options rs *resources.Spec } func (t *babelTransformation) Key() internal.ResourceTransformationKey { return internal.NewResourceTransformationKey("babel", t.options) } // Transform shells out to babel-cli to do the heavy lifting. // For this to work, you need some additional tools. To install them globally: // npm install -g @babel/core @babel/cli // If you want to use presets or plugins such as @babel/preset-env // Then you should install those globally as well. e.g: // npm install -g @babel/preset-env // Instead of installing globally, you can also install everything as a dev-dependency (--save-dev instead of -g) func (t *babelTransformation) Transform(ctx *resources.ResourceTransformationCtx) error { const binaryName = "babel" ex := t.rs.ExecHelper if err := ex.Sec().CheckAllowedExec(binaryName); err != nil { return err } var configFile string logger := t.rs.Logger var errBuf bytes.Buffer infoW := loggers.LoggerToWriterWithPrefix(logger.Info(), "babel") if t.options.Config != "" { configFile = t.options.Config } else { configFile = "babel.config.js" } configFile = filepath.Clean(configFile) // We need an absolute filename to the config file. if !filepath.IsAbs(configFile) { configFile = t.rs.BaseFs.ResolveJSConfigFile(configFile) if configFile == "" && t.options.Config != "" { // Only fail if the user specified config file is not found. return errors.Errorf("babel config %q not found:", configFile) } } ctx.ReplaceOutPathExtension(".js") var cmdArgs []interface{} if configFile != "" { logger.Infoln("babel: use config file", configFile) cmdArgs = []interface{}{"--config-file", configFile} } if optArgs := t.options.toArgs(); len(optArgs) > 0 { cmdArgs = append(cmdArgs, optArgs...) } cmdArgs = append(cmdArgs, "--filename="+ctx.SourcePath) // Create compile into a real temp file: // 1. separate stdout/stderr messages from babel (https://github.com/gohugoio/hugo/issues/8136) // 2. allow generation and retrieval of external source map. compileOutput, err := ioutil.TempFile("", "compileOut-*.js") if err != nil { return err } cmdArgs = append(cmdArgs, "--out-file="+compileOutput.Name()) stderr := io.MultiWriter(infoW, &errBuf) cmdArgs = append(cmdArgs, hexec.WithStderr(stderr)) cmdArgs = append(cmdArgs, hexec.WithStdout(stderr)) cmdArgs = append(cmdArgs, hexec.WithEnviron(hugo.GetExecEnviron(t.rs.WorkingDir, t.rs.Cfg, t.rs.BaseFs.Assets.Fs))) defer os.Remove(compileOutput.Name()) // ARGA [--no-install babel --config-file /private/var/folders/_g/j3j21hts4fn7__h04w2x8gb40000gn/T/hugo-test-babel812882892/babel.config.js --source-maps --filename=js/main2.js --out-file=/var/folders/_g/j3j21hts4fn7__h04w2x8gb40000gn/T/compileOut-2237820197.js] // [--no-install babel --config-file /private/var/folders/_g/j3j21hts4fn7__h04w2x8gb40000gn/T/hugo-test-babel332846848/babel.config.js --filename=js/main.js --out-file=/var/folders/_g/j3j21hts4fn7__h04w2x8gb40000gn/T/compileOut-1451390834.js 0x10304ee60 0x10304ed60 0x10304f060] cmd, err := ex.Npx(binaryName, cmdArgs...) if err != nil { if hexec.IsNotFound(err) { // This may be on a CI server etc. Will fall back to pre-built assets. return herrors.ErrFeatureNotAvailable } return err } stdin, err := cmd.StdinPipe() if err != nil { return err } go func() { defer stdin.Close() io.Copy(stdin, ctx.From) }() err = cmd.Run() if err != nil { if hexec.IsNotFound(err) { return herrors.ErrFeatureNotAvailable } return errors.Wrap(err, errBuf.String()) } content, err := ioutil.ReadAll(compileOutput) if err != nil { return err } mapFile := compileOutput.Name() + ".map" if _, err := os.Stat(mapFile); err == nil { defer os.Remove(mapFile) sourceMap, err := ioutil.ReadFile(mapFile) if err != nil { return err } if err = ctx.PublishSourceMap(string(sourceMap)); err != nil { return err } targetPath := path.Base(ctx.OutPath) + ".map" re := regexp.MustCompile(`//# sourceMappingURL=.*\n?`) content = []byte(re.ReplaceAllString(string(content), "//# sourceMappingURL="+targetPath+"\n")) } ctx.To.Write(content) return nil } // Process transforms the given Resource with the Babel processor. func (c *Client) Process(res resources.ResourceTransformer, options Options) (resource.Resource, error) { return res.Transform( &babelTransformation{rs: c.rs, options: options}, ) } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/babel/integration_test.go�������������������������������0000664�0000000�0000000�00000004761�14201470003�0026171�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package babel_test import ( "testing" jww "github.com/spf13/jwalterweatherman" "github.com/gohugoio/hugo/htesting" "github.com/gohugoio/hugo/hugolib" ) func TestTransformBabel(t *testing.T) { if !htesting.IsCI() { t.Skip("Skip long running test when running locally") } files := ` -- assets/js/main.js -- /* A Car */ class Car { constructor(brand) { this.carname = brand; } } -- assets/js/main2.js -- /* A Car2 */ class Car2 { constructor(brand) { this.carname = brand; } } -- babel.config.js -- console.error("Hugo Environment:", process.env.HUGO_ENVIRONMENT ); module.exports = { presets: ["@babel/preset-env"], }; -- config.toml -- disablekinds = ['taxonomy', 'term', 'page'] [security] [security.exec] allow = ['^npx$', '^babel$'] -- layouts/index.html -- {{ $options := dict "noComments" true }} {{ $transpiled := resources.Get "js/main.js" | babel -}} Transpiled: {{ $transpiled.Content | safeJS }} {{ $transpiled := resources.Get "js/main2.js" | babel (dict "sourceMap" "inline") -}} Transpiled2: {{ $transpiled.Content | safeJS }} {{ $transpiled := resources.Get "js/main2.js" | babel (dict "sourceMap" "external") -}} Transpiled3: {{ $transpiled.Permalink }} -- package.json -- { "scripts": {}, "devDependencies": { "@babel/cli": "7.8.4", "@babel/core": "7.9.0", "@babel/preset-env": "7.9.5" } } ` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: t, TxtarString: files, NeedsOsFS: true, NeedsNpmInstall: true, LogLevel: jww.LevelInfo, }).Build() b.AssertLogContains("babel: Hugo Environment: production") b.AssertFileContent("public/index.html", `var Car2 =`) b.AssertFileContent("public/js/main2.js", `var Car2 =`) b.AssertFileContent("public/js/main2.js.map", `{"version":3,`) b.AssertFileContent("public/index.html", ` //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozL`) } ���������������hugo-0.92.2/resources/resource_transformers/htesting/�����������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0023030�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/htesting/testhelpers.go���������������������������������0000664�0000000�0000000�00000004426�14201470003�0025727�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package htesting import ( "path/filepath" "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/resources" "github.com/spf13/afero" ) func NewTestResourceSpec() (*resources.Spec, error) { cfg := config.New() cfg.Set("baseURL", "https://example.org") cfg.Set("publishDir", "public") imagingCfg := map[string]interface{}{ "resampleFilter": "linear", "quality": 68, "anchor": "left", } cfg.Set("imaging", imagingCfg) fs := hugofs.NewFrom(hugofs.NewBaseFileDecorator(afero.NewMemMapFs()), cfg) s, err := helpers.NewPathSpec(fs, cfg, nil) if err != nil { return nil, err } filecaches, err := filecache.NewCaches(s) if err != nil { return nil, err } spec, err := resources.NewSpec(s, filecaches, nil, nil, nil, nil, output.DefaultFormats, media.DefaultTypes) return spec, err } func NewResourceTransformer(filename, content string) (resources.ResourceTransformer, error) { spec, err := NewTestResourceSpec() if err != nil { return nil, err } return NewResourceTransformerForSpec(spec, filename, content) } func NewResourceTransformerForSpec(spec *resources.Spec, filename, content string) (resources.ResourceTransformer, error) { filename = filepath.FromSlash(filename) fs := spec.Fs.Source if err := afero.WriteFile(fs, filename, []byte(content), 0777); err != nil { return nil, err } r, err := spec.New(resources.ResourceSourceDescriptor{Fs: fs, SourceFilename: filename}) if err != nil { return nil, err } return r.(resources.ResourceTransformer), nil } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/integrity/����������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0023221�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/integrity/integrity.go����������������������������������0000664�0000000�0000000�00000006475�14201470003�0025602�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package integrity import ( "crypto/md5" "crypto/sha256" "crypto/sha512" "encoding/base64" "encoding/hex" "hash" "html/template" "io" "github.com/gohugoio/hugo/resources/internal" "github.com/pkg/errors" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/resource" ) const defaultHashAlgo = "sha256" // Client contains methods to fingerprint (cachebusting) and other integrity-related // methods. type Client struct { rs *resources.Spec } // New creates a new Client with the given specification. func New(rs *resources.Spec) *Client { return &Client{rs: rs} } type fingerprintTransformation struct { algo string } func (t *fingerprintTransformation) Key() internal.ResourceTransformationKey { return internal.NewResourceTransformationKey("fingerprint", t.algo) } // Transform creates a MD5 hash of the Resource content and inserts that hash before // the extension in the filename. func (t *fingerprintTransformation) Transform(ctx *resources.ResourceTransformationCtx) error { h, err := newHash(t.algo) if err != nil { return err } var w io.Writer if rc, ok := ctx.From.(io.ReadSeeker); ok { // This transformation does not change the content, so try to // avoid writing to To if we can. defer rc.Seek(0, 0) w = h } else { w = io.MultiWriter(h, ctx.To) } io.Copy(w, ctx.From) d, err := digest(h) if err != nil { return err } ctx.Data["Integrity"] = integrity(t.algo, d) ctx.AddOutPathIdentifier("." + hex.EncodeToString(d[:])) return nil } func newHash(algo string) (hash.Hash, error) { switch algo { case "md5": return md5.New(), nil case "sha256": return sha256.New(), nil case "sha384": return sha512.New384(), nil case "sha512": return sha512.New(), nil default: return nil, errors.Errorf("unsupported crypto algo: %q, use either md5, sha256, sha384 or sha512", algo) } } // Fingerprint applies fingerprinting of the given resource and hash algorithm. // It defaults to sha256 if none given, and the options are md5, sha256 or sha512. // The same algo is used for both the fingerprinting part (aka cache busting) and // the base64-encoded Subresource Integrity hash, so you will have to stay away from // md5 if you plan to use both. // See https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity func (c *Client) Fingerprint(res resources.ResourceTransformer, algo string) (resource.Resource, error) { if algo == "" { algo = defaultHashAlgo } return res.Transform(&fingerprintTransformation{algo: algo}) } func integrity(algo string, sum []byte) template.HTMLAttr { encoded := base64.StdEncoding.EncodeToString(sum) return template.HTMLAttr(algo + "-" + encoded) } func digest(h hash.Hash) ([]byte, error) { sum := h.Sum(nil) return sum, nil } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/integrity/integrity_test.go�����������������������������0000664�0000000�0000000�00000004063�14201470003�0026630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package integrity import ( "html/template" "testing" "github.com/gohugoio/hugo/resources/resource" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/resources/resource_transformers/htesting" ) func TestHashFromAlgo(t *testing.T) { for _, algo := range []struct { name string bits int }{ {"md5", 128}, {"sha256", 256}, {"sha384", 384}, {"sha512", 512}, {"shaman", -1}, } { t.Run(algo.name, func(t *testing.T) { c := qt.New(t) h, err := newHash(algo.name) if algo.bits > 0 { c.Assert(err, qt.IsNil) c.Assert(h.Size(), qt.Equals, algo.bits/8) } else { c.Assert(err, qt.Not(qt.IsNil)) c.Assert(err.Error(), qt.Contains, "use either md5, sha256, sha384 or sha512") } }) } } func TestTransform(t *testing.T) { c := qt.New(t) spec, err := htesting.NewTestResourceSpec() c.Assert(err, qt.IsNil) client := New(spec) r, err := htesting.NewResourceTransformerForSpec(spec, "hugo.txt", "Hugo Rocks!") c.Assert(err, qt.IsNil) transformed, err := client.Fingerprint(r, "") c.Assert(err, qt.IsNil) c.Assert(transformed.RelPermalink(), qt.Equals, "/hugo.a5ad1c6961214a55de53c1ce6e60d27b6b761f54851fa65e33066460dfa6a0db.txt") c.Assert(transformed.Data(), qt.DeepEquals, map[string]interface{}{"Integrity": template.HTMLAttr("sha256-pa0caWEhSlXeU8HObmDSe2t2H1SFH6ZeMwZkYN+moNs=")}) content, err := transformed.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(content, qt.Equals, "Hugo Rocks!") } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/js/�����������������������������������������������������0000775�0000000�0000000�00000000000�14201470003�0021617�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/js/build.go���������������������������������������������0000664�0000000�0000000�00000011576�14201470003�0023257�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package js import ( "fmt" "io/ioutil" "os" "path" "path/filepath" "regexp" "strings" "github.com/pkg/errors" "github.com/spf13/afero" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/hugolib/filesystems" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/internal" "github.com/evanw/esbuild/pkg/api" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/resource" ) // Client context for ESBuild. type Client struct { rs *resources.Spec sfs *filesystems.SourceFilesystem } // New creates a new client context. func New(fs *filesystems.SourceFilesystem, rs *resources.Spec) *Client { return &Client{ rs: rs, sfs: fs, } } type buildTransformation struct { optsm map[string]interface{} c *Client } func (t *buildTransformation) Key() internal.ResourceTransformationKey { return internal.NewResourceTransformationKey("jsbuild", t.optsm) } func (t *buildTransformation) Transform(ctx *resources.ResourceTransformationCtx) error { ctx.OutMediaType = media.JavascriptType opts, err := decodeOptions(t.optsm) if err != nil { return err } if opts.TargetPath != "" { ctx.OutPath = opts.TargetPath } else { ctx.ReplaceOutPathExtension(".js") } src, err := ioutil.ReadAll(ctx.From) if err != nil { return err } opts.sourceDir = filepath.FromSlash(path.Dir(ctx.SourcePath)) opts.resolveDir = t.c.rs.WorkingDir // where node_modules gets resolved opts.contents = string(src) opts.mediaType = ctx.InMediaType buildOptions, err := toBuildOptions(opts) if err != nil { return err } buildOptions.Plugins, err = createBuildPlugins(t.c, opts) if err != nil { return err } if buildOptions.Sourcemap == api.SourceMapExternal && buildOptions.Outdir == "" { buildOptions.Outdir, err = ioutil.TempDir(os.TempDir(), "compileOutput") if err != nil { return err } defer os.Remove(buildOptions.Outdir) } if opts.Inject != nil { // Resolve the absolute filenames. for i, ext := range opts.Inject { impPath := filepath.FromSlash(ext) if filepath.IsAbs(impPath) { return errors.Errorf("inject: absolute paths not supported, must be relative to /assets") } m := resolveComponentInAssets(t.c.rs.Assets.Fs, impPath) if m == nil { return errors.Errorf("inject: file %q not found", ext) } opts.Inject[i] = m.Filename } buildOptions.Inject = opts.Inject } result := api.Build(buildOptions) if len(result.Errors) > 0 { createErr := func(msg api.Message) error { loc := msg.Location if loc == nil { return errors.New(msg.Text) } path := loc.File var ( f afero.File err error ) if strings.HasPrefix(path, nsImportHugo) { path = strings.TrimPrefix(path, nsImportHugo+":") f, err = hugofs.Os.Open(path) } else { var fi os.FileInfo fi, err = t.c.sfs.Fs.Stat(path) if err == nil { m := fi.(hugofs.FileMetaInfo).Meta() path = m.Filename f, err = m.Open() } } if err == nil { fe := herrors.NewFileError("js", 0, loc.Line, loc.Column, errors.New(msg.Text)) err, _ := herrors.WithFileContext(fe, path, f, herrors.SimpleLineMatcher) f.Close() return err } return fmt.Errorf("%s", msg.Text) } var errors []error for _, msg := range result.Errors { errors = append(errors, createErr(msg)) } // Return 1, log the rest. for i, err := range errors { if i > 0 { t.c.rs.Logger.Errorf("js.Build failed: %s", err) } } return errors[0] } if buildOptions.Sourcemap == api.SourceMapExternal { content := string(result.OutputFiles[1].Contents) symPath := path.Base(ctx.OutPath) + ".map" re := regexp.MustCompile(`//# sourceMappingURL=.*\n?`) content = re.ReplaceAllString(content, "//# sourceMappingURL="+symPath+"\n") if err = ctx.PublishSourceMap(string(result.OutputFiles[0].Contents)); err != nil { return err } _, err := ctx.To.Write([]byte(content)) if err != nil { return err } } else { _, err := ctx.To.Write(result.OutputFiles[0].Contents) if err != nil { return err } } return nil } // Process process esbuild transform func (c *Client) Process(res resources.ResourceTransformer, opts map[string]interface{}) (resource.Resource, error) { return res.Transform( &buildTransformation{c: c, optsm: opts}, ) } ����������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/js/build_test.go����������������������������������������0000664�0000000�0000000�00000001154�14201470003�0024305�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package js ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������hugo-0.92.2/resources/resource_transformers/js/integration_test.go����������������������������������0000664�0000000�0000000�00000013540�14201470003�0025533�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package js_test import ( "path/filepath" "strings" "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/htesting" "github.com/gohugoio/hugo/hugolib" ) func TestBuildVariants(t *testing.T) { c := qt.New(t) mainWithImport := ` -- config.toml -- disableKinds=["page", "section", "taxonomy", "term", "sitemap", "robotsTXT"] -- assets/js/main.js -- import { hello1, hello2 } from './util1'; hello1(); hello2(); -- assets/js/util1.js -- import { hello3 } from './util2'; export function hello1() { return 'abcd'; } export function hello2() { return hello3(); } -- assets/js/util2.js -- export function hello3() { return 'efgh'; } -- layouts/index.html -- {{ $js := resources.Get "js/main.js" | js.Build }} JS Content:{{ $js.Content }}:End: ` c.Run("Basic", func(c *qt.C) { b := hugolib.NewIntegrationTestBuilder(hugolib.IntegrationTestConfig{T: c, NeedsOsFS: true, TxtarString: mainWithImport}).Build() b.AssertFileContent("public/index.html", `abcd`) }) c.Run("Edit Import", func(c *qt.C) { b := hugolib.NewIntegrationTestBuilder(hugolib.IntegrationTestConfig{T: c, Running: true, NeedsOsFS: true, TxtarString: mainWithImport}).Build() b.AssertFileContent("public/index.html", `abcd`) b.EditFileReplace("assets/js/util1.js", func(s string) string { return strings.ReplaceAll(s, "abcd", "1234") }).Build() b.AssertFileContent("public/index.html", `1234`) }) c.Run("Edit Import Nested", func(c *qt.C) { b := hugolib.NewIntegrationTestBuilder(hugolib.IntegrationTestConfig{T: c, Running: true, NeedsOsFS: true, TxtarString: mainWithImport}).Build() b.AssertFileContent("public/index.html", `efgh`) b.EditFileReplace("assets/js/util2.js", func(s string) string { return strings.ReplaceAll(s, "efgh", "1234") }).Build() b.AssertFileContent("public/index.html", `1234`) }) } func TestBuildWithModAndNpm(t *testing.T) { if !htesting.IsCI() { t.Skip("skip (relative) long running modules test when running locally") } c := qt.New(t) files := ` -- config.toml -- baseURL = "https://example.org" disableKinds=["page", "section", "taxonomy", "term", "sitemap", "robotsTXT"] [module] [[module.imports]] path="github.com/gohugoio/hugoTestProjectJSModImports" -- go.mod -- module github.com/gohugoio/tests/testHugoModules go 1.16 require github.com/gohugoio/hugoTestProjectJSModImports v0.9.0 // indirect -- package.json -- { "dependencies": { "date-fns": "^2.16.1" } } ` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: c, NeedsOsFS: true, NeedsNpmInstall: true, TxtarString: files, Verbose: true, }).Build() b.AssertFileContent("public/js/main.js", ` greeting: "greeting configured in mod2" Hello1 from mod1: $ return "Hello2 from mod1"; var Hugo = "Rocks!"; Hello3 from mod2. Date from date-fns: ${today} Hello from lib in the main project Hello5 from mod2. var myparam = "Hugo Rocks!"; shim cwd `) // React JSX, verify the shimming. b.AssertFileContent("public/js/like.js", filepath.FromSlash(`@v0.9.0/assets/js/shims/react.js module.exports = window.ReactDOM; `)) } func TestBuildWithNpm(t *testing.T) { if !htesting.IsCI() { t.Skip("skip (relative) long running modules test when running locally") } c := qt.New(t) files := ` -- assets/js/included.js -- console.log("included"); -- assets/js/main.js -- import "./included"; import { toCamelCase } from "to-camel-case"; console.log("main"); console.log("To camel:", toCamelCase("space case")); -- assets/js/myjsx.jsx -- import * as React from 'react' import * as ReactDOM from 'react-dom' ReactDOM.render(

    Hello, world!

    , document.getElementById('root') ); -- assets/js/myts.ts -- function greeter(person: string) { return "Hello, " + person; } let user = [0, 1, 2]; document.body.textContent = greeter(user); -- config.toml -- disablekinds = ['taxonomy', 'term', 'page'] -- content/p1.md -- Content. -- data/hugo.toml -- slogan = "Hugo Rocks!" -- i18n/en.yaml -- hello: other: "Hello" -- i18n/fr.yaml -- hello: other: "Bonjour" -- layouts/index.html -- {{ $options := dict "minify" false "externals" (slice "react" "react-dom") }} {{ $js := resources.Get "js/main.js" | js.Build $options }} JS: {{ template "print" $js }} {{ $jsx := resources.Get "js/myjsx.jsx" | js.Build $options }} JSX: {{ template "print" $jsx }} {{ $ts := resources.Get "js/myts.ts" | js.Build (dict "sourcemap" "inline")}} TS: {{ template "print" $ts }} {{ $ts2 := resources.Get "js/myts.ts" | js.Build (dict "sourcemap" "external" "TargetPath" "js/myts2.js")}} TS2: {{ template "print" $ts2 }} {{ define "print" }}RelPermalink: {{.RelPermalink}}|MIME: {{ .MediaType }}|Content: {{ .Content | safeJS }}{{ end }} -- package.json -- { "scripts": {}, "dependencies": { "to-camel-case": "1.0.0" } } ` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: c, NeedsOsFS: true, NeedsNpmInstall: true, TxtarString: files, }).Build() b.AssertFileContent("public/js/myts.js", `//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJz`) b.AssertFileContent("public/js/myts2.js.map", `"version": 3,`) b.AssertFileContent("public/index.html", ` console.log("included"); if (hasSpace.test(string)) var React = __toESM(__require("react")); function greeter(person) { `) } hugo-0.92.2/resources/resource_transformers/js/options.go000066400000000000000000000254031420147000300236450ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package js import ( "encoding/json" "fmt" "io/ioutil" "path/filepath" "strings" "github.com/gohugoio/hugo/common/maps" "github.com/pkg/errors" "github.com/spf13/afero" "github.com/evanw/esbuild/pkg/api" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/media" "github.com/mitchellh/mapstructure" ) const ( nsImportHugo = "ns-hugo" nsParams = "ns-params" stdinImporter = "" ) // Options esbuild configuration type Options struct { // If not set, the source path will be used as the base target path. // Note that the target path's extension may change if the target MIME type // is different, e.g. when the source is TypeScript. TargetPath string // Whether to minify to output. Minify bool // Whether to write mapfiles SourceMap string // The language target. // One of: es2015, es2016, es2017, es2018, es2019, es2020 or esnext. // Default is esnext. Target string // The output format. // One of: iife, cjs, esm // Default is to esm. Format string // External dependencies, e.g. "react". Externals []string // This option allows you to automatically replace a global variable with an import from another file. // The filenames must be relative to /assets. // See https://esbuild.github.io/api/#inject Inject []string // User defined symbols. Defines map[string]interface{} // Maps a component import to another. Shims map[string]string // User defined params. Will be marshaled to JSON and available as "@params", e.g. // import * as params from '@params'; Params interface{} // What to use instead of React.createElement. JSXFactory string // What to use instead of React.Fragment. JSXFragment string // There is/was a bug in WebKit with severe performance issue with the tracking // of TDZ checks in JavaScriptCore. // // Enabling this flag removes the TDZ and `const` assignment checks and // may improve performance of larger JS codebases until the WebKit fix // is in widespread use. // // See https://bugs.webkit.org/show_bug.cgi?id=199866 // Deprecated: This no longer have any effect and will be removed. // TODO(bep) remove. See https://github.com/evanw/esbuild/commit/869e8117b499ca1dbfc5b3021938a53ffe934dba AvoidTDZ bool mediaType media.Type outDir string contents string sourceDir string resolveDir string tsConfig string } func decodeOptions(m map[string]interface{}) (Options, error) { var opts Options if err := mapstructure.WeakDecode(m, &opts); err != nil { return opts, err } if opts.TargetPath != "" { opts.TargetPath = helpers.ToSlashTrimLeading(opts.TargetPath) } opts.Target = strings.ToLower(opts.Target) opts.Format = strings.ToLower(opts.Format) return opts, nil } var extensionToLoaderMap = map[string]api.Loader{ ".js": api.LoaderJS, ".mjs": api.LoaderJS, ".cjs": api.LoaderJS, ".jsx": api.LoaderJSX, ".ts": api.LoaderTS, ".tsx": api.LoaderTSX, ".css": api.LoaderCSS, ".json": api.LoaderJSON, ".txt": api.LoaderText, } func loaderFromFilename(filename string) api.Loader { l, found := extensionToLoaderMap[filepath.Ext(filename)] if found { return l } return api.LoaderJS } func resolveComponentInAssets(fs afero.Fs, impPath string) *hugofs.FileMeta { findFirst := func(base string) *hugofs.FileMeta { // This is the most common sub-set of ESBuild's default extensions. // We assume that imports of JSON, CSS etc. will be using their full // name with extension. for _, ext := range []string{".js", ".ts", ".tsx", ".jsx"} { if strings.HasSuffix(impPath, ext) { // Import of foo.js.js need the full name. return nil } if fi, err := fs.Stat(base + ext); err == nil { return fi.(hugofs.FileMetaInfo).Meta() } } // Not found. return nil } var m *hugofs.FileMeta // See issue #8949. // We need to check if this is a regular file imported without an extension. // There may be ambigous situations where both foo.js and foo/index.js exists. // This import order is in line with both how Node and ESBuild's native // import resolver works. // This was fixed in Hugo 0.88. // It may be a regular file imported without an extension, e.g. // foo or foo/index. m = findFirst(impPath) if m != nil { return m } // Finally check the path as is. fi, err := fs.Stat(impPath) if err == nil { if fi.IsDir() { m = findFirst(filepath.Join(impPath, "index")) } else { m = fi.(hugofs.FileMetaInfo).Meta() } } return m } func createBuildPlugins(c *Client, opts Options) ([]api.Plugin, error) { fs := c.rs.Assets resolveImport := func(args api.OnResolveArgs) (api.OnResolveResult, error) { impPath := args.Path if opts.Shims != nil { override, found := opts.Shims[impPath] if found { impPath = override } } isStdin := args.Importer == stdinImporter var relDir string if !isStdin { rel, found := fs.MakePathRelative(args.Importer) if !found { // Not in any of the /assets folders. // This is an import from a node_modules, let // ESBuild resolve this. return api.OnResolveResult{}, nil } relDir = filepath.Dir(rel) } else { relDir = opts.sourceDir } // Imports not starting with a "." is assumed to live relative to /assets. // Hugo makes no assumptions about the directory structure below /assets. if relDir != "" && strings.HasPrefix(impPath, ".") { impPath = filepath.Join(relDir, impPath) } m := resolveComponentInAssets(fs.Fs, impPath) if m != nil { // Store the source root so we can create a jsconfig.json // to help intellisense when the build is done. // This should be a small number of elements, and when // in server mode, we may get stale entries on renames etc., // but that shouldn't matter too much. c.rs.JSConfigBuilder.AddSourceRoot(m.SourceRoot) return api.OnResolveResult{Path: m.Filename, Namespace: nsImportHugo}, nil } // Fall back to ESBuild's resolve. return api.OnResolveResult{}, nil } importResolver := api.Plugin{ Name: "hugo-import-resolver", Setup: func(build api.PluginBuild) { build.OnResolve(api.OnResolveOptions{Filter: `.*`}, func(args api.OnResolveArgs) (api.OnResolveResult, error) { return resolveImport(args) }) build.OnLoad(api.OnLoadOptions{Filter: `.*`, Namespace: nsImportHugo}, func(args api.OnLoadArgs) (api.OnLoadResult, error) { b, err := ioutil.ReadFile(args.Path) if err != nil { return api.OnLoadResult{}, errors.Wrapf(err, "failed to read %q", args.Path) } c := string(b) return api.OnLoadResult{ // See https://github.com/evanw/esbuild/issues/502 // This allows all modules to resolve dependencies // in the main project's node_modules. ResolveDir: opts.resolveDir, Contents: &c, Loader: loaderFromFilename(args.Path), }, nil }) }, } params := opts.Params if params == nil { // This way @params will always resolve to something. params = make(map[string]interface{}) } b, err := json.Marshal(params) if err != nil { return nil, errors.Wrap(err, "failed to marshal params") } bs := string(b) paramsPlugin := api.Plugin{ Name: "hugo-params-plugin", Setup: func(build api.PluginBuild) { build.OnResolve(api.OnResolveOptions{Filter: `^@params$`}, func(args api.OnResolveArgs) (api.OnResolveResult, error) { return api.OnResolveResult{ Path: args.Path, Namespace: nsParams, }, nil }) build.OnLoad(api.OnLoadOptions{Filter: `.*`, Namespace: nsParams}, func(args api.OnLoadArgs) (api.OnLoadResult, error) { return api.OnLoadResult{ Contents: &bs, Loader: api.LoaderJSON, }, nil }) }, } return []api.Plugin{importResolver, paramsPlugin}, nil } func toBuildOptions(opts Options) (buildOptions api.BuildOptions, err error) { var target api.Target switch opts.Target { case "", "esnext": target = api.ESNext case "es5": target = api.ES5 case "es6", "es2015": target = api.ES2015 case "es2016": target = api.ES2016 case "es2017": target = api.ES2017 case "es2018": target = api.ES2018 case "es2019": target = api.ES2019 case "es2020": target = api.ES2020 default: err = fmt.Errorf("invalid target: %q", opts.Target) return } mediaType := opts.mediaType if mediaType.IsZero() { mediaType = media.JavascriptType } var loader api.Loader switch mediaType.SubType { // TODO(bep) ESBuild support a set of other loaders, but I currently fail // to see the relevance. That may change as we start using this. case media.JavascriptType.SubType: loader = api.LoaderJS case media.TypeScriptType.SubType: loader = api.LoaderTS case media.TSXType.SubType: loader = api.LoaderTSX case media.JSXType.SubType: loader = api.LoaderJSX default: err = fmt.Errorf("unsupported Media Type: %q", opts.mediaType) return } var format api.Format // One of: iife, cjs, esm switch opts.Format { case "", "iife": format = api.FormatIIFE case "esm": format = api.FormatESModule case "cjs": format = api.FormatCommonJS default: err = fmt.Errorf("unsupported script output format: %q", opts.Format) return } var defines map[string]string if opts.Defines != nil { defines = maps.ToStringMapString(opts.Defines) } // By default we only need to specify outDir and no outFile outDir := opts.outDir outFile := "" var sourceMap api.SourceMap switch opts.SourceMap { case "inline": sourceMap = api.SourceMapInline case "external": sourceMap = api.SourceMapExternal case "": sourceMap = api.SourceMapNone default: err = fmt.Errorf("unsupported sourcemap type: %q", opts.SourceMap) return } buildOptions = api.BuildOptions{ Outfile: outFile, Bundle: true, Target: target, Format: format, Sourcemap: sourceMap, MinifyWhitespace: opts.Minify, MinifyIdentifiers: opts.Minify, MinifySyntax: opts.Minify, Outdir: outDir, Define: defines, External: opts.Externals, JSXFactory: opts.JSXFactory, JSXFragment: opts.JSXFragment, Tsconfig: opts.tsConfig, // Note: We're not passing Sourcefile to ESBuild. // This makes ESBuild pass `stdin` as the Importer to the import // resolver, which is what we need/expect. Stdin: &api.StdinOptions{ Contents: opts.contents, ResolveDir: opts.resolveDir, Loader: loader, }, } return } hugo-0.92.2/resources/resource_transformers/js/options_test.go000066400000000000000000000117411420147000300247040ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package js import ( "path/filepath" "testing" "github.com/gohugoio/hugo/hugofs" "github.com/spf13/afero" "github.com/gohugoio/hugo/media" "github.com/evanw/esbuild/pkg/api" qt "github.com/frankban/quicktest" ) // This test is added to test/warn against breaking the "stability" of the // cache key. It's sometimes needed to break this, but should be avoided if possible. func TestOptionKey(t *testing.T) { c := qt.New(t) opts := map[string]interface{}{ "TargetPath": "foo", "Target": "es2018", } key := (&buildTransformation{optsm: opts}).Key() c.Assert(key.Value(), qt.Equals, "jsbuild_7891849149754191852") } func TestToBuildOptions(t *testing.T) { c := qt.New(t) opts, err := toBuildOptions(Options{mediaType: media.JavascriptType}) c.Assert(err, qt.IsNil) c.Assert(opts, qt.DeepEquals, api.BuildOptions{ Bundle: true, Target: api.ESNext, Format: api.FormatIIFE, Stdin: &api.StdinOptions{ Loader: api.LoaderJS, }, }) opts, err = toBuildOptions(Options{ Target: "es2018", Format: "cjs", Minify: true, mediaType: media.JavascriptType, AvoidTDZ: true, }) c.Assert(err, qt.IsNil) c.Assert(opts, qt.DeepEquals, api.BuildOptions{ Bundle: true, Target: api.ES2018, Format: api.FormatCommonJS, MinifyIdentifiers: true, MinifySyntax: true, MinifyWhitespace: true, Stdin: &api.StdinOptions{ Loader: api.LoaderJS, }, }) opts, err = toBuildOptions(Options{ Target: "es2018", Format: "cjs", Minify: true, mediaType: media.JavascriptType, SourceMap: "inline", }) c.Assert(err, qt.IsNil) c.Assert(opts, qt.DeepEquals, api.BuildOptions{ Bundle: true, Target: api.ES2018, Format: api.FormatCommonJS, MinifyIdentifiers: true, MinifySyntax: true, MinifyWhitespace: true, Sourcemap: api.SourceMapInline, Stdin: &api.StdinOptions{ Loader: api.LoaderJS, }, }) opts, err = toBuildOptions(Options{ Target: "es2018", Format: "cjs", Minify: true, mediaType: media.JavascriptType, SourceMap: "inline", }) c.Assert(err, qt.IsNil) c.Assert(opts, qt.DeepEquals, api.BuildOptions{ Bundle: true, Target: api.ES2018, Format: api.FormatCommonJS, MinifyIdentifiers: true, MinifySyntax: true, MinifyWhitespace: true, Sourcemap: api.SourceMapInline, Stdin: &api.StdinOptions{ Loader: api.LoaderJS, }, }) opts, err = toBuildOptions(Options{ Target: "es2018", Format: "cjs", Minify: true, mediaType: media.JavascriptType, SourceMap: "external", }) c.Assert(err, qt.IsNil) c.Assert(opts, qt.DeepEquals, api.BuildOptions{ Bundle: true, Target: api.ES2018, Format: api.FormatCommonJS, MinifyIdentifiers: true, MinifySyntax: true, MinifyWhitespace: true, Sourcemap: api.SourceMapExternal, Stdin: &api.StdinOptions{ Loader: api.LoaderJS, }, }) } func TestResolveComponentInAssets(t *testing.T) { c := qt.New(t) for _, test := range []struct { name string files []string impPath string expect string }{ {"Basic, extension", []string{"foo.js", "bar.js"}, "foo.js", "foo.js"}, {"Basic, no extension", []string{"foo.js", "bar.js"}, "foo", "foo.js"}, {"Basic, no extension, typescript", []string{"foo.ts", "bar.js"}, "foo", "foo.ts"}, {"Not found", []string{"foo.js", "bar.js"}, "moo.js", ""}, {"Not found, double js extension", []string{"foo.js.js", "bar.js"}, "foo.js", ""}, {"Index file, folder only", []string{"foo/index.js", "bar.js"}, "foo", "foo/index.js"}, {"Index file, folder and index", []string{"foo/index.js", "bar.js"}, "foo/index", "foo/index.js"}, {"Index file, folder and index and suffix", []string{"foo/index.js", "bar.js"}, "foo/index.js", "foo/index.js"}, // Issue #8949 {"Check file before directory", []string{"foo.js", "foo/index.js"}, "foo", "foo.js"}, } { c.Run(test.name, func(c *qt.C) { baseDir := "assets" mfs := afero.NewMemMapFs() for _, filename := range test.files { c.Assert(afero.WriteFile(mfs, filepath.Join(baseDir, filename), []byte("let foo='bar';"), 0777), qt.IsNil) } bfs := hugofs.DecorateBasePathFs(afero.NewBasePathFs(mfs, baseDir).(*afero.BasePathFs)) got := resolveComponentInAssets(bfs, test.impPath) gotPath := "" if got != nil { gotPath = filepath.ToSlash(got.Path) } c.Assert(gotPath, qt.Equals, test.expect) }) } } hugo-0.92.2/resources/resource_transformers/minifier/000077500000000000000000000000001420147000300230055ustar00rootroot00000000000000hugo-0.92.2/resources/resource_transformers/minifier/integration_test.go000066400000000000000000000023201420147000300267130ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package minifier_test import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/hugolib" ) // Issue 8954 func TestTransformMinify(t *testing.T) { c := qt.New(t) files := ` -- assets/js/test.js -- new Date(2002, 04, 11) -- config.toml -- -- layouts/index.html -- {{ $js := resources.Get "js/test.js" | minify }} ` b, err := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: c, TxtarString: files, }, ).BuildE() b.Assert(err, qt.IsNotNil) b.Assert(err, qt.ErrorMatches, "(?s).*legacy octal numbers.*line 1.*") } hugo-0.92.2/resources/resource_transformers/minifier/minify.go000066400000000000000000000035451420147000300246360ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package minifier import ( "github.com/gohugoio/hugo/minifiers" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/internal" "github.com/gohugoio/hugo/resources/resource" ) // Client for minification of Resource objects. Supported minifiers are: // css, html, js, json, svg and xml. type Client struct { rs *resources.Spec m minifiers.Client } // New creates a new Client given a specification. Note that it is the media types // configured for the site that is used to match files to the correct minifier. func New(rs *resources.Spec) (*Client, error) { m, err := minifiers.New(rs.MediaTypes, rs.OutputFormats, rs.Cfg) if err != nil { return nil, err } return &Client{rs: rs, m: m}, nil } type minifyTransformation struct { rs *resources.Spec m minifiers.Client } func (t *minifyTransformation) Key() internal.ResourceTransformationKey { return internal.NewResourceTransformationKey("minify") } func (t *minifyTransformation) Transform(ctx *resources.ResourceTransformationCtx) error { ctx.AddOutPathIdentifier(".min") return t.m.Minify(ctx.InMediaType, ctx.To, ctx.From) } func (c *Client) Minify(res resources.ResourceTransformer) (resource.Resource, error) { return res.Transform(&minifyTransformation{ rs: c.rs, m: c.m, }) } hugo-0.92.2/resources/resource_transformers/minifier/minify_test.go000066400000000000000000000025141420147000300256700ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package minifier import ( "testing" "github.com/gohugoio/hugo/resources/resource" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/resources/resource_transformers/htesting" ) func TestTransform(t *testing.T) { c := qt.New(t) spec, err := htesting.NewTestResourceSpec() c.Assert(err, qt.IsNil) client, _ := New(spec) r, err := htesting.NewResourceTransformerForSpec(spec, "hugo.html", "

    Hugo Rocks!

    ") c.Assert(err, qt.IsNil) transformed, err := client.Minify(r) c.Assert(err, qt.IsNil) c.Assert(transformed.RelPermalink(), qt.Equals, "/hugo.min.html") content, err := transformed.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(content, qt.Equals, "

    Hugo Rocks!

    ") } hugo-0.92.2/resources/resource_transformers/postcss/000077500000000000000000000000001420147000300227015ustar00rootroot00000000000000hugo-0.92.2/resources/resource_transformers/postcss/integration_test.go000066400000000000000000000070721420147000300266200ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package postcss_test import ( "fmt" "path/filepath" "strings" "testing" jww "github.com/spf13/jwalterweatherman" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/htesting" "github.com/gohugoio/hugo/hugolib" ) func TestTransformPostCSS(t *testing.T) { if !htesting.IsCI() { t.Skip("Skip long running test when running locally") } c := qt.New(t) files := ` -- assets/css/components/a.css -- class-in-a { color: blue; } -- assets/css/components/all.css -- @import "a.css"; @import "b.css"; -- assets/css/components/b.css -- @import "a.css"; class-in-b { color: blue; } -- assets/css/styles.css -- @tailwind base; @tailwind components; @tailwind utilities; @import "components/all.css"; h1 { @apply text-2xl font-bold; } -- config.toml -- disablekinds = ['taxonomy', 'term', 'page'] -- content/p1.md -- -- data/hugo.toml -- slogan = "Hugo Rocks!" -- i18n/en.yaml -- hello: other: "Hello" -- i18n/fr.yaml -- hello: other: "Bonjour" -- layouts/index.html -- {{ $options := dict "inlineImports" true }} {{ $styles := resources.Get "css/styles.css" | resources.PostCSS $options }} Styles RelPermalink: {{ $styles.RelPermalink }} {{ $cssContent := $styles.Content }} Styles Content: Len: {{ len $styles.Content }}| -- package.json -- { "scripts": {}, "devDependencies": { "postcss-cli": "7.1.0", "tailwindcss": "1.2.0" } } -- postcss.config.js -- console.error("Hugo Environment:", process.env.HUGO_ENVIRONMENT ); // https://github.com/gohugoio/hugo/issues/7656 console.error("package.json:", process.env.HUGO_FILE_PACKAGE_JSON ); console.error("PostCSS Config File:", process.env.HUGO_FILE_POSTCSS_CONFIG_JS ); module.exports = { plugins: [ require('tailwindcss') ] } ` c.Run("Success", func(c *qt.C) { b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: c, NeedsOsFS: true, NeedsNpmInstall: true, LogLevel: jww.LevelInfo, TxtarString: files, }).Build() b.AssertLogContains("Hugo Environment: production") b.AssertLogContains(filepath.FromSlash(fmt.Sprintf("PostCSS Config File: %s/postcss.config.js", b.Cfg.WorkingDir))) b.AssertLogContains(filepath.FromSlash(fmt.Sprintf("package.json: %s/package.json", b.Cfg.WorkingDir))) b.AssertFileContent("public/index.html", ` Styles RelPermalink: /css/styles.css Styles Content: Len: 770875| `) }) c.Run("Error", func(c *qt.C) { s, err := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: c, NeedsOsFS: true, NeedsNpmInstall: true, TxtarString: strings.ReplaceAll(files, "color: blue;", "@apply foo;"), // Syntax error }).BuildE() s.AssertIsFileError(err) }) } // bookmark2 func TestIntegrationTestTemplate(t *testing.T) { c := qt.New(t) files := `` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: c, NeedsOsFS: false, NeedsNpmInstall: false, TxtarString: files, }).Build() b.Assert(true, qt.IsTrue) } hugo-0.92.2/resources/resource_transformers/postcss/postcss.go000066400000000000000000000234351420147000300247350ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package postcss import ( "bytes" "crypto/sha256" "encoding/hex" "io" "io/ioutil" "path" "path/filepath" "regexp" "strconv" "strings" "github.com/gohugoio/hugo/common/collections" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/resources/internal" "github.com/spf13/afero" "github.com/spf13/cast" "github.com/gohugoio/hugo/hugofs" "github.com/pkg/errors" "github.com/mitchellh/mapstructure" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/resource" ) const importIdentifier = "@import" var cssSyntaxErrorRe = regexp.MustCompile(`> (\d+) \|`) var shouldImportRe = regexp.MustCompile(`^@import ["'].*["'];?\s*(/\*.*\*/)?$`) // New creates a new Client with the given specification. func New(rs *resources.Spec) *Client { return &Client{rs: rs} } func DecodeOptions(m map[string]interface{}) (opts Options, err error) { if m == nil { return } err = mapstructure.WeakDecode(m, &opts) if !opts.NoMap { // There was for a long time a discrepancy between documentation and // implementation for the noMap property, so we need to support both // camel and snake case. opts.NoMap = cast.ToBool(m["no-map"]) } return } // Client is the client used to do PostCSS transformations. type Client struct { rs *resources.Spec } // Process transforms the given Resource with the PostCSS processor. func (c *Client) Process(res resources.ResourceTransformer, options Options) (resource.Resource, error) { return res.Transform(&postcssTransformation{rs: c.rs, options: options}) } // Some of the options from https://github.com/postcss/postcss-cli type Options struct { // Set a custom path to look for a config file. Config string NoMap bool // Disable the default inline sourcemaps // Enable inlining of @import statements. // Does so recursively, but currently once only per file; // that is, it's not possible to import the same file in // different scopes (root, media query...) // Note that this import routine does not care about the CSS spec, // so you can have @import anywhere in the file. InlineImports bool // Options for when not using a config file Use string // List of postcss plugins to use Parser string // Custom postcss parser Stringifier string // Custom postcss stringifier Syntax string // Custom postcss syntax } func (opts Options) toArgs() []string { var args []string if opts.NoMap { args = append(args, "--no-map") } if opts.Use != "" { args = append(args, "--use") args = append(args, strings.Fields(opts.Use)...) } if opts.Parser != "" { args = append(args, "--parser", opts.Parser) } if opts.Stringifier != "" { args = append(args, "--stringifier", opts.Stringifier) } if opts.Syntax != "" { args = append(args, "--syntax", opts.Syntax) } return args } type postcssTransformation struct { options Options rs *resources.Spec } func (t *postcssTransformation) Key() internal.ResourceTransformationKey { return internal.NewResourceTransformationKey("postcss", t.options) } // Transform shells out to postcss-cli to do the heavy lifting. // For this to work, you need some additional tools. To install them globally: // npm install -g postcss-cli // npm install -g autoprefixer func (t *postcssTransformation) Transform(ctx *resources.ResourceTransformationCtx) error { const binaryName = "postcss" ex := t.rs.ExecHelper var configFile string logger := t.rs.Logger if t.options.Config != "" { configFile = t.options.Config } else { configFile = "postcss.config.js" } configFile = filepath.Clean(configFile) // We need an absolute filename to the config file. if !filepath.IsAbs(configFile) { configFile = t.rs.BaseFs.ResolveJSConfigFile(configFile) if configFile == "" && t.options.Config != "" { // Only fail if the user specified config file is not found. return errors.Errorf("postcss config %q not found:", configFile) } } var cmdArgs []interface{} if configFile != "" { logger.Infoln("postcss: use config file", configFile) cmdArgs = []interface{}{"--config", configFile} } if optArgs := t.options.toArgs(); len(optArgs) > 0 { cmdArgs = append(cmdArgs, collections.StringSliceToInterfaceSlice(optArgs)...) } var errBuf bytes.Buffer infoW := loggers.LoggerToWriterWithPrefix(logger.Info(), "postcss") stderr := io.MultiWriter(infoW, &errBuf) cmdArgs = append(cmdArgs, hexec.WithStderr(stderr)) cmdArgs = append(cmdArgs, hexec.WithStdout(ctx.To)) cmdArgs = append(cmdArgs, hexec.WithEnviron(hugo.GetExecEnviron(t.rs.WorkingDir, t.rs.Cfg, t.rs.BaseFs.Assets.Fs))) cmd, err := ex.Npx(binaryName, cmdArgs...) if err != nil { if hexec.IsNotFound(err) { // This may be on a CI server etc. Will fall back to pre-built assets. return herrors.ErrFeatureNotAvailable } return err } stdin, err := cmd.StdinPipe() if err != nil { return err } src := ctx.From imp := newImportResolver( ctx.From, ctx.InPath, t.rs.Assets.Fs, t.rs.Logger, ) if t.options.InlineImports { var err error src, err = imp.resolve() if err != nil { return err } } go func() { defer stdin.Close() io.Copy(stdin, src) }() err = cmd.Run() if err != nil { if hexec.IsNotFound(err) { return herrors.ErrFeatureNotAvailable } return imp.toFileError(errBuf.String()) } return nil } type fileOffset struct { Filename string Offset int } type importResolver struct { r io.Reader inPath string contentSeen map[string]bool linemap map[int]fileOffset fs afero.Fs logger loggers.Logger } func newImportResolver(r io.Reader, inPath string, fs afero.Fs, logger loggers.Logger) *importResolver { return &importResolver{ r: r, inPath: inPath, fs: fs, logger: logger, linemap: make(map[int]fileOffset), contentSeen: make(map[string]bool), } } func (imp *importResolver) contentHash(filename string) ([]byte, string) { b, err := afero.ReadFile(imp.fs, filename) if err != nil { return nil, "" } h := sha256.New() h.Write(b) return b, hex.EncodeToString(h.Sum(nil)) } func (imp *importResolver) importRecursive( lineNum int, content string, inPath string) (int, string, error) { basePath := path.Dir(inPath) var replacements []string lines := strings.Split(content, "\n") trackLine := func(i, offset int, line string) { // TODO(bep) this is not very efficient. imp.linemap[i+lineNum] = fileOffset{Filename: inPath, Offset: offset} } i := 0 for offset, line := range lines { i++ line = strings.TrimSpace(line) if !imp.shouldImport(line) { trackLine(i, offset, line) } else { i-- path := strings.Trim(strings.TrimPrefix(line, importIdentifier), " \"';") filename := filepath.Join(basePath, path) importContent, hash := imp.contentHash(filename) if importContent == nil { trackLine(i, offset, "ERROR") imp.logger.Warnf("postcss: Failed to resolve CSS @import in %q for path %q", inPath, filename) continue } if imp.contentSeen[hash] { i++ // Just replace the line with an empty string. replacements = append(replacements, []string{line, ""}...) trackLine(i, offset, "IMPORT") continue } imp.contentSeen[hash] = true // Handle recursive imports. l, nested, err := imp.importRecursive(i+lineNum, string(importContent), filepath.ToSlash(filename)) if err != nil { return 0, "", err } trackLine(i, offset, line) i += l importContent = []byte(nested) replacements = append(replacements, []string{line, string(importContent)}...) } } if len(replacements) > 0 { repl := strings.NewReplacer(replacements...) content = repl.Replace(content) } return i, content, nil } func (imp *importResolver) resolve() (io.Reader, error) { const importIdentifier = "@import" content, err := ioutil.ReadAll(imp.r) if err != nil { return nil, err } contents := string(content) _, newContent, err := imp.importRecursive(0, contents, imp.inPath) if err != nil { return nil, err } return strings.NewReader(newContent), nil } // See https://www.w3schools.com/cssref/pr_import_rule.asp // We currently only support simple file imports, no urls, no media queries. // So this is OK: // @import "navigation.css"; // This is not: // @import url("navigation.css"); // @import "mobstyle.css" screen and (max-width: 768px); func (imp *importResolver) shouldImport(s string) bool { if !strings.HasPrefix(s, importIdentifier) { return false } if strings.Contains(s, "url(") { return false } return shouldImportRe.MatchString(s) } func (imp *importResolver) toFileError(output string) error { inErr := errors.New(strings.TrimSpace(output)) match := cssSyntaxErrorRe.FindStringSubmatch(output) if match == nil { return inErr } lineNum, err := strconv.Atoi(match[1]) if err != nil { return inErr } file, ok := imp.linemap[lineNum] if !ok { return inErr } fi, err := imp.fs.Stat(file.Filename) if err != nil { return inErr } realFilename := fi.(hugofs.FileMetaInfo).Meta().Filename ferr := herrors.NewFileError("css", -1, file.Offset+1, 1, inErr) werr, ok := herrors.WithFileContextForFile(ferr, realFilename, file.Filename, imp.fs, herrors.SimpleLineMatcher) if !ok { return ferr } return werr } hugo-0.92.2/resources/resource_transformers/postcss/postcss_test.go000066400000000000000000000073471420147000300260000ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package postcss import ( "regexp" "strings" "testing" "github.com/gohugoio/hugo/htesting/hqt" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/helpers" "github.com/spf13/afero" qt "github.com/frankban/quicktest" ) // Issue 6166 func TestDecodeOptions(t *testing.T) { c := qt.New(t) opts1, err := DecodeOptions(map[string]interface{}{ "no-map": true, }) c.Assert(err, qt.IsNil) c.Assert(opts1.NoMap, qt.Equals, true) opts2, err := DecodeOptions(map[string]interface{}{ "noMap": true, }) c.Assert(err, qt.IsNil) c.Assert(opts2.NoMap, qt.Equals, true) } func TestShouldImport(t *testing.T) { c := qt.New(t) var imp *importResolver for _, test := range []struct { input string expect bool }{ {input: `@import "navigation.css";`, expect: true}, {input: `@import "navigation.css"; /* Using a string */`, expect: true}, {input: `@import "navigation.css"`, expect: true}, {input: `@import 'navigation.css';`, expect: true}, {input: `@import url("navigation.css");`, expect: false}, {input: `@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,400i,800,800i&display=swap');`, expect: false}, } { c.Assert(imp.shouldImport(test.input), qt.Equals, test.expect) } } func TestImportResolver(t *testing.T) { c := qt.New(t) fs := afero.NewMemMapFs() writeFile := func(name, content string) { c.Assert(afero.WriteFile(fs, name, []byte(content), 0777), qt.IsNil) } writeFile("a.css", `@import "b.css"; @import "c.css"; A_STYLE1 A_STYLE2 `) writeFile("b.css", `B_STYLE`) writeFile("c.css", "@import \"d.css\"\nC_STYLE") writeFile("d.css", "@import \"a.css\"\n\nD_STYLE") writeFile("e.css", "E_STYLE") mainStyles := strings.NewReader(`@import "a.css"; @import "b.css"; LOCAL_STYLE @import "c.css"; @import "e.css"; @import "missing.css";`) imp := newImportResolver( mainStyles, "styles.css", fs, loggers.NewErrorLogger(), ) r, err := imp.resolve() c.Assert(err, qt.IsNil) rs := helpers.ReaderToString(r) result := regexp.MustCompile(`\n+`).ReplaceAllString(rs, "\n") c.Assert(result, hqt.IsSameString, `B_STYLE D_STYLE C_STYLE A_STYLE1 A_STYLE2 LOCAL_STYLE E_STYLE @import "missing.css";`) dline := imp.linemap[3] c.Assert(dline, qt.DeepEquals, fileOffset{ Offset: 1, Filename: "d.css", }) } func BenchmarkImportResolver(b *testing.B) { c := qt.New(b) fs := afero.NewMemMapFs() writeFile := func(name, content string) { c.Assert(afero.WriteFile(fs, name, []byte(content), 0777), qt.IsNil) } writeFile("a.css", `@import "b.css"; @import "c.css"; A_STYLE1 A_STYLE2 `) writeFile("b.css", `B_STYLE`) writeFile("c.css", "@import \"d.css\"\nC_STYLE"+strings.Repeat("\nSTYLE", 12)) writeFile("d.css", "@import \"a.css\"\n\nD_STYLE"+strings.Repeat("\nSTYLE", 55)) writeFile("e.css", "E_STYLE") mainStyles := `@import "a.css"; @import "b.css"; LOCAL_STYLE @import "c.css"; @import "e.css"; @import "missing.css";` logger := loggers.NewErrorLogger() for i := 0; i < b.N; i++ { b.StopTimer() imp := newImportResolver( strings.NewReader(mainStyles), "styles.css", fs, logger, ) b.StartTimer() _, err := imp.resolve() if err != nil { b.Fatal(err) } } } hugo-0.92.2/resources/resource_transformers/templates/000077500000000000000000000000001420147000300232015ustar00rootroot00000000000000hugo-0.92.2/resources/resource_transformers/templates/execute_as_template.go000066400000000000000000000045131420147000300275530ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package templates contains functions for template processing of Resource objects. package templates import ( "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/internal" "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/tpl" "github.com/pkg/errors" ) // Client contains methods to perform template processing of Resource objects. type Client struct { rs *resources.Spec t tpl.TemplatesProvider } // New creates a new Client with the given specification. func New(rs *resources.Spec, t tpl.TemplatesProvider) *Client { if rs == nil { panic("must provice a resource Spec") } if t == nil { panic("must provide a template provider") } return &Client{rs: rs, t: t} } type executeAsTemplateTransform struct { rs *resources.Spec t tpl.TemplatesProvider targetPath string data interface{} } func (t *executeAsTemplateTransform) Key() internal.ResourceTransformationKey { return internal.NewResourceTransformationKey("execute-as-template", t.targetPath) } func (t *executeAsTemplateTransform) Transform(ctx *resources.ResourceTransformationCtx) error { tplStr := helpers.ReaderToString(ctx.From) templ, err := t.t.TextTmpl().Parse(ctx.InPath, tplStr) if err != nil { return errors.Wrapf(err, "failed to parse Resource %q as Template:", ctx.InPath) } ctx.OutPath = t.targetPath return t.t.Tmpl().Execute(templ, ctx.To, t.data) } func (c *Client) ExecuteAsTemplate(res resources.ResourceTransformer, targetPath string, data interface{}) (resource.Resource, error) { return res.Transform(&executeAsTemplateTransform{ rs: c.rs, targetPath: helpers.ToSlashTrimLeading(targetPath), t: c.t, data: data, }) } hugo-0.92.2/resources/resource_transformers/templates/integration_test.go000066400000000000000000000040251420147000300271130ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package templates_test import ( "testing" "github.com/gohugoio/hugo/hugolib" ) func TestExecuteAsTemplateMultipleLanguages(t *testing.T) { t.Parallel() files := ` -- config.toml -- baseURL = "http://example.com/blog" defaultContentLanguage = "fr" defaultContentLanguageInSubdir = true [Languages] [Languages.en] weight = 10 title = "In English" languageName = "English" [Languages.fr] weight = 20 title = "Le Français" languageName = "Français" -- i18n/en.toml -- [hello] other = "Hello" -- i18n/fr.toml -- [hello] other = "Bonjour" -- layouts/index.fr.html -- Lang: {{ site.Language.Lang }} {{ $templ := "{{T \"hello\"}}" | resources.FromString "f1.html" }} {{ $helloResource := $templ | resources.ExecuteAsTemplate (print "f%s.html" .Lang) . }} Hello1: {{T "hello"}} Hello2: {{ $helloResource.Content }} LangURL: {{ relLangURL "foo" }} -- layouts/index.html -- Lang: {{ site.Language.Lang }} {{ $templ := "{{T \"hello\"}}" | resources.FromString "f1.html" }} {{ $helloResource := $templ | resources.ExecuteAsTemplate (print "f%s.html" .Lang) . }} Hello1: {{T "hello"}} Hello2: {{ $helloResource.Content }} LangURL: {{ relLangURL "foo" }} ` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: t, TxtarString: files, }).Build() b.AssertFileContent("public/en/index.html", ` Hello1: Hello Hello2: Hello `) b.AssertFileContent("public/fr/index.html", ` Hello1: Bonjour Hello2: Bonjour `) } hugo-0.92.2/resources/resource_transformers/tocss/000077500000000000000000000000001420147000300223365ustar00rootroot00000000000000hugo-0.92.2/resources/resource_transformers/tocss/dartsass/000077500000000000000000000000001420147000300241625ustar00rootroot00000000000000hugo-0.92.2/resources/resource_transformers/tocss/dartsass/client.go000066400000000000000000000066501420147000300257760ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package godartsass integrates with the Dass Sass Embedded protocol to transpile // SCSS/SASS. package dartsass import ( "io" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugolib/filesystems" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/resource" "github.com/spf13/afero" "github.com/bep/godartsass" "github.com/mitchellh/mapstructure" ) // used as part of the cache key. const transformationName = "tocss-dart" func New(fs *filesystems.SourceFilesystem, rs *resources.Spec) (*Client, error) { if !Supports() { return &Client{dartSassNotAvailable: true}, nil } if err := rs.ExecHelper.Sec().CheckAllowedExec(dartSassEmbeddedBinaryName); err != nil { return nil, err } transpiler, err := godartsass.Start(godartsass.Options{}) if err != nil { return nil, err } return &Client{sfs: fs, workFs: rs.BaseFs.Work, rs: rs, transpiler: transpiler}, nil } type Client struct { dartSassNotAvailable bool rs *resources.Spec sfs *filesystems.SourceFilesystem workFs afero.Fs transpiler *godartsass.Transpiler } func (c *Client) ToCSS(res resources.ResourceTransformer, args map[string]interface{}) (resource.Resource, error) { if c.dartSassNotAvailable { return res.Transform(resources.NewFeatureNotAvailableTransformer(transformationName, args)) } return res.Transform(&transform{c: c, optsm: args}) } func (c *Client) Close() error { if c.transpiler == nil { return nil } return c.transpiler.Close() } func (c *Client) toCSS(args godartsass.Args, src io.Reader) (godartsass.Result, error) { var res godartsass.Result in := helpers.ReaderToString(src) args.Source = in res, err := c.transpiler.Execute(args) if err != nil { return res, err } return res, err } type Options struct { // Hugo, will by default, just replace the extension of the source // to .css, e.g. "scss/main.scss" becomes "scss/main.css". You can // control this by setting this, e.g. "styles/main.css" will create // a Resource with that as a base for RelPermalink etc. TargetPath string // Hugo automatically adds the entry directories (where the main.scss lives) // for project and themes to the list of include paths sent to LibSASS. // Any paths set in this setting will be appended. Note that these will be // treated as relative to the working dir, i.e. no include paths outside the // project/themes. IncludePaths []string // Default is nested. // One of nested, expanded, compact, compressed. OutputStyle string // When enabled, Hugo will generate a source map. EnableSourceMap bool } func decodeOptions(m map[string]interface{}) (opts Options, err error) { if m == nil { return } err = mapstructure.WeakDecode(m, &opts) if opts.TargetPath != "" { opts.TargetPath = helpers.ToSlashTrimLeading(opts.TargetPath) } return } hugo-0.92.2/resources/resource_transformers/tocss/dartsass/integration_test.go000066400000000000000000000070231420147000300300750ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package dartsass_test import ( "testing" "github.com/gohugoio/hugo/hugolib" "github.com/gohugoio/hugo/resources/resource_transformers/tocss/dartsass" ) func TestTransformIncludePaths(t *testing.T) { if !dartsass.Supports() { t.Skip() } files := ` -- assets/scss/main.scss -- @import "moo"; -- node_modules/foo/_moo.scss -- $moolor: #fff; moo { color: $moolor; } -- config.toml -- -- layouts/index.html -- {{ $cssOpts := (dict "includePaths" (slice "node_modules/foo") "transpiler" "dartsass" ) }} {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }} T1: {{ $r.Content }} ` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: t, TxtarString: files, NeedsOsFS: true, }).Build() b.AssertFileContent("public/index.html", `T1: moo{color:#fff}`) } func TestTransformImportRegularCSS(t *testing.T) { if !dartsass.Supports() { t.Skip() } files := ` -- assets/scss/_moo.scss -- $moolor: #fff; moo { color: $moolor; } -- assets/scss/another.css -- -- assets/scss/main.scss -- @import "moo"; @import "regular.css"; @import "moo"; @import "another.css"; /* foo */ -- assets/scss/regular.css -- -- config.toml -- -- layouts/index.html -- {{ $r := resources.Get "scss/main.scss" | toCSS (dict "transpiler" "dartsass") }} T1: {{ $r.Content | safeHTML }} ` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: t, TxtarString: files, NeedsOsFS: true, }, ).Build() // Dart Sass does not follow regular CSS import, but they // get pulled to the top. b.AssertFileContent("public/index.html", `T1: @import "regular.css"; @import "another.css"; moo { color: #fff; } moo { color: #fff; } /* foo */`) } func TestTransformThemeOverrides(t *testing.T) { if !dartsass.Supports() { t.Skip() } files := ` -- assets/scss/components/_boo.scss -- $boolor: green; boo { color: $boolor; } -- assets/scss/components/_moo.scss -- $moolor: #ccc; moo { color: $moolor; } -- config.toml -- theme = 'mytheme' -- layouts/index.html -- {{ $cssOpts := (dict "includePaths" (slice "node_modules/foo" ) "transpiler" "dartsass" ) }} {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }} T1: {{ $r.Content }} -- themes/mytheme/assets/scss/components/_boo.scss -- $boolor: orange; boo { color: $boolor; } -- themes/mytheme/assets/scss/components/_imports.scss -- @import "moo"; @import "_boo"; @import "_zoo"; -- themes/mytheme/assets/scss/components/_moo.scss -- $moolor: #fff; moo { color: $moolor; } -- themes/mytheme/assets/scss/components/_zoo.scss -- $zoolor: pink; zoo { color: $zoolor; } -- themes/mytheme/assets/scss/main.scss -- @import "components/imports"; ` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: t, TxtarString: files, NeedsOsFS: true, }, ).Build() b.AssertFileContent("public/index.html", `T1: moo{color:#ccc}boo{color:green}zoo{color:pink}`) } hugo-0.92.2/resources/resource_transformers/tocss/dartsass/transform.go000066400000000000000000000125501420147000300265270ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package dartsass import ( "fmt" "io" "net/url" "path" "path/filepath" "strings" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/htesting" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/internal" "github.com/spf13/afero" "github.com/gohugoio/hugo/hugofs" "github.com/bep/godartsass" ) const ( // See https://github.com/sass/dart-sass-embedded/issues/24 stdinPlaceholder = "HUGOSTDIN" dartSassEmbeddedBinaryName = "dart-sass-embedded" ) // Supports returns whether dart-sass-embedded is found in $PATH. func Supports() bool { if htesting.SupportsAll() { return true } return hexec.InPath(dartSassEmbeddedBinaryName) } type transform struct { optsm map[string]interface{} c *Client } func (t *transform) Key() internal.ResourceTransformationKey { return internal.NewResourceTransformationKey(transformationName, t.optsm) } func (t *transform) Transform(ctx *resources.ResourceTransformationCtx) error { ctx.OutMediaType = media.CSSType opts, err := decodeOptions(t.optsm) if err != nil { return err } if opts.TargetPath != "" { ctx.OutPath = opts.TargetPath } else { ctx.ReplaceOutPathExtension(".css") } baseDir := path.Dir(ctx.SourcePath) args := godartsass.Args{ URL: stdinPlaceholder, IncludePaths: t.c.sfs.RealDirs(baseDir), ImportResolver: importResolver{ baseDir: baseDir, c: t.c, }, OutputStyle: godartsass.ParseOutputStyle(opts.OutputStyle), EnableSourceMap: opts.EnableSourceMap, } // Append any workDir relative include paths for _, ip := range opts.IncludePaths { info, err := t.c.workFs.Stat(filepath.Clean(ip)) if err == nil { filename := info.(hugofs.FileMetaInfo).Meta().Filename args.IncludePaths = append(args.IncludePaths, filename) } } if ctx.InMediaType.SubType == media.SASSType.SubType { args.SourceSyntax = godartsass.SourceSyntaxSASS } res, err := t.c.toCSS(args, ctx.From) if err != nil { if sassErr, ok := err.(godartsass.SassError); ok { start := sassErr.Span.Start context := strings.TrimSpace(sassErr.Span.Context) filename, _ := urlToFilename(sassErr.Span.Url) if filename == stdinPlaceholder { if ctx.SourcePath == "" { return sassErr } filename = t.c.sfs.RealFilename(ctx.SourcePath) } offsetMatcher := func(m herrors.LineMatcher) bool { return m.Offset+len(m.Line) >= start.Offset && strings.Contains(m.Line, context) } ferr, ok := herrors.WithFileContextForFile( herrors.NewFileError("scss", -1, -1, start.Column, sassErr), filename, filename, hugofs.Os, offsetMatcher) if !ok { return sassErr } return ferr } return err } out := res.CSS _, err = io.WriteString(ctx.To, out) if err != nil { return err } if opts.EnableSourceMap && res.SourceMap != "" { if err := ctx.PublishSourceMap(res.SourceMap); err != nil { return err } _, err = fmt.Fprintf(ctx.To, "\n\n/*# sourceMappingURL=%s */", path.Base(ctx.OutPath)+".map") } return err } type importResolver struct { baseDir string c *Client } func (t importResolver) CanonicalizeURL(url string) (string, error) { filePath, isURL := urlToFilename(url) var prevDir string var pathDir string if isURL { var found bool prevDir, found = t.c.sfs.MakePathRelative(filepath.Dir(filePath)) if !found { // Not a member of this filesystem, let Dart Sass handle it. return "", nil } } else { prevDir = t.baseDir pathDir = path.Dir(url) } basePath := filepath.Join(prevDir, pathDir) name := filepath.Base(filePath) // Pick the first match. var namePatterns []string if strings.Contains(name, ".") { namePatterns = []string{"_%s", "%s"} } else if strings.HasPrefix(name, "_") { namePatterns = []string{"_%s.scss", "_%s.sass"} } else { namePatterns = []string{"_%s.scss", "%s.scss", "_%s.sass", "%s.sass"} } name = strings.TrimPrefix(name, "_") for _, namePattern := range namePatterns { filenameToCheck := filepath.Join(basePath, fmt.Sprintf(namePattern, name)) fi, err := t.c.sfs.Fs.Stat(filenameToCheck) if err == nil { if fim, ok := fi.(hugofs.FileMetaInfo); ok { return "file://" + filepath.ToSlash(fim.Meta().Filename), nil } } } // Not found, let Dart Dass handle it return "", nil } func (t importResolver) Load(url string) (string, error) { filename, _ := urlToFilename(url) b, err := afero.ReadFile(hugofs.Os, filename) return string(b), err } // TODO(bep) add tests func urlToFilename(urls string) (string, bool) { u, err := url.ParseRequestURI(urls) if err != nil { return filepath.FromSlash(urls), false } p := filepath.FromSlash(u.Path) if u.Host != "" { // C:\data\file.txt p = strings.ToUpper(u.Host) + ":" + p } return p, true } hugo-0.92.2/resources/resource_transformers/tocss/scss/000077500000000000000000000000001420147000300233115ustar00rootroot00000000000000hugo-0.92.2/resources/resource_transformers/tocss/scss/client.go000066400000000000000000000052601420147000300251210ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package scss import ( "regexp" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugolib/filesystems" "github.com/gohugoio/hugo/resources" "github.com/spf13/afero" "github.com/mitchellh/mapstructure" ) const transformationName = "tocss" type Client struct { rs *resources.Spec sfs *filesystems.SourceFilesystem workFs afero.Fs } func New(fs *filesystems.SourceFilesystem, rs *resources.Spec) (*Client, error) { return &Client{sfs: fs, workFs: rs.BaseFs.Work, rs: rs}, nil } type Options struct { // Hugo, will by default, just replace the extension of the source // to .css, e.g. "scss/main.scss" becomes "scss/main.css". You can // control this by setting this, e.g. "styles/main.css" will create // a Resource with that as a base for RelPermalink etc. TargetPath string // Hugo automatically adds the entry directories (where the main.scss lives) // for project and themes to the list of include paths sent to LibSASS. // Any paths set in this setting will be appended. Note that these will be // treated as relative to the working dir, i.e. no include paths outside the // project/themes. IncludePaths []string // Default is nested. // One of nested, expanded, compact, compressed. OutputStyle string // Precision of floating point math. Precision int // When enabled, Hugo will generate a source map. EnableSourceMap bool } func DecodeOptions(m map[string]interface{}) (opts Options, err error) { if m == nil { return } err = mapstructure.WeakDecode(m, &opts) if opts.TargetPath != "" { opts.TargetPath = helpers.ToSlashTrimLeading(opts.TargetPath) } return } var ( regularCSSImportTo = regexp.MustCompile(`.*(@import "(.*\.css)";).*`) regularCSSImportFrom = regexp.MustCompile(`.*(\/\* HUGO_IMPORT_START (.*) HUGO_IMPORT_END \*\/).*`) ) func replaceRegularImportsIn(s string) (string, bool) { replaced := regularCSSImportTo.ReplaceAllString(s, "/* HUGO_IMPORT_START $2 HUGO_IMPORT_END */") return replaced, s != replaced } func replaceRegularImportsOut(s string) string { return regularCSSImportFrom.ReplaceAllString(s, "@import \"$2\";") } hugo-0.92.2/resources/resource_transformers/tocss/scss/client_extended.go000066400000000000000000000034451420147000300270040ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build extended package scss import ( "github.com/bep/golibsass/libsass" "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/internal" "github.com/gohugoio/hugo/resources/resource" ) type options struct { // The options we receive from the end user. from Options // The options we send to the SCSS library. to libsass.Options } func (c *Client) ToCSS(res resources.ResourceTransformer, opts Options) (resource.Resource, error) { internalOptions := options{ from: opts, } // Transfer values from client. internalOptions.to.Precision = opts.Precision internalOptions.to.OutputStyle = libsass.ParseOutputStyle(opts.OutputStyle) if internalOptions.to.Precision == 0 { // bootstrap-sass requires 8 digits precision. The libsass default is 5. // https://github.com/twbs/bootstrap-sass/blob/master/README.md#sass-number-precision internalOptions.to.Precision = 8 } return res.Transform(&toCSSTransformation{c: c, options: internalOptions}) } type toCSSTransformation struct { c *Client options options } func (t *toCSSTransformation) Key() internal.ResourceTransformationKey { return internal.NewResourceTransformationKey(transformationName, t.options.from) } hugo-0.92.2/resources/resource_transformers/tocss/scss/client_notavailable.go000066400000000000000000000017431420147000300276440ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build !extended package scss import ( "github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources/resource" ) func (c *Client) ToCSS(res resources.ResourceTransformer, opts Options) (resource.Resource, error) { return res.Transform(resources.NewFeatureNotAvailableTransformer(transformationName, opts)) } // Used in tests. func Supports() bool { return false } hugo-0.92.2/resources/resource_transformers/tocss/scss/client_test.go000066400000000000000000000027121420147000300261570ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package scss import ( "testing" qt "github.com/frankban/quicktest" ) func TestReplaceRegularCSSImports(t *testing.T) { c := qt.New(t) scssWithImport := ` @import "moo"; @import "regular.css"; @import "moo"; @import "another.css"; @import "foo.scss"; /* foo */` scssWithoutImport := ` @import "moo"; /* foo */` res, replaced := replaceRegularImportsIn(scssWithImport) c.Assert(replaced, qt.Equals, true) c.Assert(res, qt.Equals, "\n\t\n@import \"moo\";\n/* HUGO_IMPORT_START regular.css HUGO_IMPORT_END */\n@import \"moo\";\n/* HUGO_IMPORT_START another.css HUGO_IMPORT_END */\n@import \"foo.scss\";\n\n/* foo */") res2, replaced2 := replaceRegularImportsIn(scssWithoutImport) c.Assert(replaced2, qt.Equals, false) c.Assert(res2, qt.Equals, scssWithoutImport) reverted := replaceRegularImportsOut(res) c.Assert(reverted, qt.Equals, scssWithImport) } hugo-0.92.2/resources/resource_transformers/tocss/scss/integration_test.go000066400000000000000000000071521420147000300272270ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package scss_test import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/hugolib" "github.com/gohugoio/hugo/resources/resource_transformers/tocss/scss" ) func TestTransformIncludePaths(t *testing.T) { if !scss.Supports() { t.Skip() } c := qt.New(t) files := ` -- assets/scss/main.scss -- @import "moo"; -- node_modules/foo/_moo.scss -- $moolor: #fff; moo { color: $moolor; } -- config.toml -- -- layouts/index.html -- {{ $cssOpts := (dict "includePaths" (slice "node_modules/foo") ) }} {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }} T1: {{ $r.Content }} ` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: c, TxtarString: files, NeedsOsFS: true, }).Build() b.AssertFileContent("public/index.html", `T1: moo{color:#fff}`) } func TestTransformImportRegularCSS(t *testing.T) { if !scss.Supports() { t.Skip() } c := qt.New(t) files := ` -- assets/scss/_moo.scss -- $moolor: #fff; moo { color: $moolor; } -- assets/scss/another.css -- -- assets/scss/main.scss -- @import "moo"; @import "regular.css"; @import "moo"; @import "another.css"; /* foo */ -- assets/scss/regular.css -- -- config.toml -- -- layouts/index.html -- {{ $r := resources.Get "scss/main.scss" | toCSS }} T1: {{ $r.Content | safeHTML }} ` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: c, TxtarString: files, NeedsOsFS: true, }).Build() // LibSass does not support regular CSS imports. There // is an open bug about it that probably will never be resolved. // Hugo works around this by preserving them in place: b.AssertFileContent("public/index.html", ` T1: moo { color: #fff; } @import "regular.css"; moo { color: #fff; } @import "another.css"; /* foo */ `) } func TestTransformThemeOverrides(t *testing.T) { if !scss.Supports() { t.Skip() } c := qt.New(t) files := ` -- assets/scss/components/_boo.scss -- $boolor: green; boo { color: $boolor; } -- assets/scss/components/_moo.scss -- $moolor: #ccc; moo { color: $moolor; } -- config.toml -- theme = 'mytheme' -- layouts/index.html -- {{ $cssOpts := (dict "includePaths" (slice "node_modules/foo" ) "transpiler" "dartsass" ) }} {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }} T1: {{ $r.Content }} -- themes/mytheme/assets/scss/components/_boo.scss -- $boolor: orange; boo { color: $boolor; } -- themes/mytheme/assets/scss/components/_imports.scss -- @import "moo"; @import "_boo"; @import "_zoo"; -- themes/mytheme/assets/scss/components/_moo.scss -- $moolor: #fff; moo { color: $moolor; } -- themes/mytheme/assets/scss/components/_zoo.scss -- $zoolor: pink; zoo { color: $zoolor; } -- themes/mytheme/assets/scss/main.scss -- @import "components/imports"; ` b := hugolib.NewIntegrationTestBuilder( hugolib.IntegrationTestConfig{ T: c, TxtarString: files, NeedsOsFS: true, }).Build() b.AssertFileContent("public/index.html", `T1: moo{color:#ccc}boo{color:green}zoo{color:pink}`) } hugo-0.92.2/resources/resource_transformers/tocss/scss/tocss.go000066400000000000000000000135131420147000300247760ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build extended package scss import ( "fmt" "io" "path" "path/filepath" "strings" "github.com/bep/golibsass/libsass" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources" "github.com/pkg/errors" ) // Used in tests. This feature requires Hugo to be built with the extended tag. func Supports() bool { return true } func (t *toCSSTransformation) Transform(ctx *resources.ResourceTransformationCtx) error { ctx.OutMediaType = media.CSSType var outName string if t.options.from.TargetPath != "" { ctx.OutPath = t.options.from.TargetPath } else { ctx.ReplaceOutPathExtension(".css") } outName = path.Base(ctx.OutPath) options := t.options baseDir := path.Dir(ctx.SourcePath) options.to.IncludePaths = t.c.sfs.RealDirs(baseDir) // Append any workDir relative include paths for _, ip := range options.from.IncludePaths { info, err := t.c.workFs.Stat(filepath.Clean(ip)) if err == nil { filename := info.(hugofs.FileMetaInfo).Meta().Filename options.to.IncludePaths = append(options.to.IncludePaths, filename) } } // To allow for overrides of SCSS files anywhere in the project/theme hierarchy, we need // to help libsass revolve the filename by looking in the composite filesystem first. // We add the entry directories for both project and themes to the include paths list, but // that only work for overrides on the top level. options.to.ImportResolver = func(url string, prev string) (newUrl string, body string, resolved bool) { // We get URL paths from LibSASS, but we need file paths. url = filepath.FromSlash(url) prev = filepath.FromSlash(prev) var basePath string urlDir := filepath.Dir(url) var prevDir string if prev == "stdin" { prevDir = baseDir } else { prevDir, _ = t.c.sfs.MakePathRelative(filepath.Dir(prev)) if prevDir == "" { // Not a member of this filesystem. Let LibSASS handle it. return "", "", false } } basePath = filepath.Join(prevDir, urlDir) name := filepath.Base(url) // Libsass throws an error in cases where you have several possible candidates. // We make this simpler and pick the first match. var namePatterns []string if strings.Contains(name, ".") { namePatterns = []string{"_%s", "%s"} } else if strings.HasPrefix(name, "_") { namePatterns = []string{"_%s.scss", "_%s.sass"} } else { namePatterns = []string{"_%s.scss", "%s.scss", "_%s.sass", "%s.sass"} } name = strings.TrimPrefix(name, "_") for _, namePattern := range namePatterns { filenameToCheck := filepath.Join(basePath, fmt.Sprintf(namePattern, name)) fi, err := t.c.sfs.Fs.Stat(filenameToCheck) if err == nil { if fim, ok := fi.(hugofs.FileMetaInfo); ok { return fim.Meta().Filename, "", true } } } // Not found, let LibSASS handle it return "", "", false } if ctx.InMediaType.SubType == media.SASSType.SubType { options.to.SassSyntax = true } if options.from.EnableSourceMap { options.to.SourceMapOptions.Filename = outName + ".map" options.to.SourceMapOptions.Root = t.c.rs.WorkingDir // Setting this to the relative input filename will get the source map // more correct for the main entry path (main.scss typically), but // it will mess up the import mappings. As a workaround, we do a replacement // in the source map itself (see below). // options.InputPath = inputPath options.to.SourceMapOptions.OutputPath = outName options.to.SourceMapOptions.Contents = true options.to.SourceMapOptions.OmitURL = false options.to.SourceMapOptions.EnableEmbedded = false } res, err := t.c.toCSS(options.to, ctx.To, ctx.From) if err != nil { return err } if options.from.EnableSourceMap && res.SourceMapContent != "" { sourcePath := t.c.sfs.RealFilename(ctx.SourcePath) if strings.HasPrefix(sourcePath, t.c.rs.WorkingDir) { sourcePath = strings.TrimPrefix(sourcePath, t.c.rs.WorkingDir+helpers.FilePathSeparator) } // This needs to be Unix-style slashes, even on Windows. // See https://github.com/gohugoio/hugo/issues/4968 sourcePath = filepath.ToSlash(sourcePath) // This is a workaround for what looks like a bug in Libsass. But // getting this resolution correct in tools like Chrome Workspaces // is important enough to go this extra mile. mapContent := strings.Replace(res.SourceMapContent, `stdin",`, fmt.Sprintf("%s\",", sourcePath), 1) return ctx.PublishSourceMap(mapContent) } return nil } func (c *Client) toCSS(options libsass.Options, dst io.Writer, src io.Reader) (libsass.Result, error) { var res libsass.Result transpiler, err := libsass.New(options) if err != nil { return res, err } in := helpers.ReaderToString(src) // See https://github.com/gohugoio/hugo/issues/7059 // We need to preserver the regular CSS imports. This is by far // a perfect solution, and only works for the main entry file, but // that should cover many use cases, e.g. using SCSS as a preprocessor // for Tailwind. var importsReplaced bool in, importsReplaced = replaceRegularImportsIn(in) res, err = transpiler.Execute(in) if err != nil { return res, errors.Wrap(err, "SCSS processing failed") } out := res.CSS if importsReplaced { out = replaceRegularImportsOut(out) } _, err = io.WriteString(dst, out) return res, err } hugo-0.92.2/resources/testdata/000077500000000000000000000000001420147000300163605ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/1234567890qwertyuiopasdfghjklzxcvbnm5to6eeeeee7via8eleph.jpg000066400000000000000000002607331420147000300314010ustar00rootroot00000000000000ExifII* (1+2;i%(RICOH IMAGING COMPANY, LTD.PENTAX K-3 IIAdobe Photoshop Lightroom 6.12 (Macintosh)2017:11:23 09:56:54bjorn.erik.pedersen@gmail.comt|"'d0230       24+8 2017:10:27 08:38:522017:10:27 08:38:52Тt@BfK@B 4d    smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDMNW*BJ08 A 3 K bTjTrz $Ax''Dd& d8ddWGS-842017:10:27(HH          Adobed!a1AQ"2qRS#BCb%34QA1!#a2Bbr ?h- FĨ‚ !* h  P>+~DADAM 4"hM4 O 4($L?1QAFƪFĨFā  (B((B: h77ADPI}AA4PIQ_9@b[![lJlH FĨFā ",B(,B:     Dh8  }It}QFA.dlhdh* Vā[ l* l(-A  ,@(@: 3~DiADitA:@N@NDW+9dhvDfDlZ"Fª âl(l*  h  O 6)A^DFxmZò"M6u. ( 'ShN; k#] ȕȐt2-3"@ͅPͅ+a@6 #`6!6PD}[iAbD)tK)A ]IA>, QBmTl]\ĈdH* vDlHQJTB6P#a,+aK4K 4K }6DDbDM,P,W,khmK}րmE,DqnF8ă%dH%dIaXVDaa[XF斴fYEl ZQ[NfӥVӄ)#i(K)BD)d% ZFvK)vRdq,>D;R4lZ)ie:c,C#K)ie%:K(̈%vDZ[eQQYEk3#R3"K(͉,Q[eV¥,BR)e7Mg6)<btSeؠ ا;6)btQNMtlS8b1ŢdIlSFd:&Fl)[F›&l*lQ lhl ndI[ԭ75X75P7]UMYMXaMTTn7]BT$)𩹫4*c74uGJT4tL{'bꎔS!b莐NGC)e;CD43itSt3)tRy0(NXW}ЭfyZ3.Kqhj)u'jiF§iFQIܽJ'q ;pzbSzRcSzF:@'ztSF{Y7ɜCGtQgtvEStuG{)غ:cv.ڧbƩujvjv.kb b[}6&u 9ͳ,?.kx1f!`^yu3Xg bjNӬhSzօ^;mgzu,YNSz[S^Y%k%[ ϲ0Oez빤r3<I\L|,8*kKC*ƎۤC*wRmil}Ӫ:ܵNVGKC+"ɩYu-u0&e\}cS63gfmXcKdhj-ezmj t5 $rիy_?ʼnneK;9mS;քLUuz*Yfy+jbsj8*bskbԞF*by% w\畸gb[5ݗU6툯yĠ9xO|Č<&a&soM;Ecn]ӭr7T=ڷ">cڅߥ},~^Nwi(.Y G?qoN! ?\ǓFa㗉;cόYp|l:G.?^'z%E3Ŝ5sL#Yڭ[ofVW`s ;r/ [rMu8sc(jD{+D/kc6L<쵬&nmI#%ҋk1f)HFMf!3݄aM`I&֮tx`iCAk U]i/6`>_b"rC&p smc#n^2{Z%!n79-l`hT돋?[鴰ٱ@_BS]Ʊd8@p:^ܾo|0t=ݗq47F+ߗ֎m ΤFmE^~} ;)p49BH~ <8#/l0Zh8AxR{-{t3u`ųA,n?Sůk/g:6Z^wS}ok57#v]@o5OOi=D[%pu?뺛RG'^?^~O0K;{D9"i`1o|ywFYZxtxaS8Qm6xlcqxsg]3}`ǏLd fi=n8aye) $?~*3͟D[va crG[OWg`%l ̪8Jny+E A)r< HrAB\${悸`;d~ 1r3AxIX ŘV=wf:_ۜxTaY9̛p(LlM{׸ qayu-ԋQq)lx 4mBi!cYI&")d&hFہ_(-_ 0J9(I\h\5 WAdd)Eg g%Q7 q'!ſct0tGa{}Q˓O1"~(a{\ai xg6䀝b0]`A|QkI20171027?083852Pbjorn.erik.pedersen@gmail.comZ Benalmádena_ AndalucíadESeSpain8BIM           Adobed!a1AQ"2qRS#BCb%34QA1!#a2Bbr ?h- FĨ‚ !* h  P>+~DADAM 4"hM4 O 4($L?1QAFƪFĨFā  (B((B: h77ADPI}AA4PIQ_9@b[![lJlH FĨFā ",B(,B:     Dh8  }It}QFA.dlhdh* Vā[ l* l(-A  ,@(@: 3~DiADitA:@N@NDW+9dhvDfDlZ"Fª âl(l*  h  O 6)A^DFxmZò"M6u. ( 'ShN; k#] ȕȐt2-3"@ͅPͅ+a@6 #`6!6PD}[iAbD)tK)A ]IA>, QBmTl]\ĈdH* vDlHQJTB6P#a,+aK4K 4K }6DDbDM,P,W,khmK}րmE,DqnF8ă%dH%dIaXVDaa[XF斴fYEl ZQ[NfӥVӄ)#i(K)BD)d% ZFvK)vRdq,>D;R4lZ)ie:c,C#K)ie%:K(̈%vDZ[eQQYEk3#R3"K(͉,Q[eV¥,BR)e7Mg6)<btSeؠ ا;6)btQNMtlS8b1ŢdIlSFd:&Fl)[F›&l*lQ lhl ndI[ԭ75X75P7]UMYMXaMTTn7]BT$)𩹫4*c74uGJT4tL{'bꎔS!b莐NGC)e;CD43itSt3)tRy0(NXW}ЭfyZ3.Kqhj)u'jiF§iFQIܽJ'q ;pzbSzRcSzF:@'ztSF{Y7ɜCGtQgtvEStuG{)غ:cv.ڧbƩujvjv.kb b[}6&u 9ͳ,?.kx1f!`^yu3Xg bjNӬhSzօ^;mgzu,YNSz[S^Y%k%[ ϲ0Oez빤r3<I\L|,8*kKC*ƎۤC*wRmil}Ӫ:ܵNVGKC+"ɩYu-u0&e\}cS63gfmXcKdhj-ezmj t5 $rիy_?ʼnneK;9mS;քLUuz*Yfy+jbsj8*bskbԞF*by% w\畸gb[5ݗU6툯yĠ9xO|Č<&a&soM;Ecn]ӭr7T=ڷ">cڅߥ},~^Nwi(.Y G?qoN! ?\ǓFa㗉;cόYp|l:G.?^'z%E3Ŝ5sL#Yڭ[ofVW`s ;r/ [rMu8sc(jD{+D/kc6L<쵬&nmI#%ҋk1f)HFMf!3݄aM`I&֮tx`iCAk U]i/6`>_b"rC&p smc#n^2{Z%!n79-l`hT돋?[鴰ٱ@_BS]Ʊd8@p:^ܾo|0t=ݗq47F+ߗ֎m ΤFmE^~} ;)p49BH~ <8#/l0Zh8AxR{-{t3u`ųA,n?Sůk/g:6Z^wS}ok57#v]@o5OOi=D[%pu?뺛RG'^?^~O0K;{D9"i`1o|ywFYZxtxaS8Qm6xlcqxsg]3}`ǏLd fi=n8aye) $?~*3͟D[va crG[OWg`%l ̪8Jny+E A)r< HrAB\${悸`;d~ 1r3AxIX ŘV=wf:_ۜxTaY9̛p(LlM{׸ qayu-ԋQq)lx 4mBi!cYI&")d&hFہ_(-_ 0J9(I\h\5 WAdd)Eg g%Q7 q'!ſct0tGa{}Q˓O1"~(a{\ai xg6䀝b0]`A|QkIELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km[ehttp://ns.adobe.com/xap/1.0/ bjorn.erik.pedersen@gmail.com Malaga Torremolinos 160/10 500/10 28/10 28/10 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 centerX = 0.317495, centerY = 0.539287, radius = 0.037149, sourceState = sourceAutoComputed, sourceX = 0.437723, sourceY = 0.539840, spotType = heal, opacity = 0.1753 centerX = 0.319353, centerY = 0.539993, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.262521, sourceY = 0.539993, spotType = heal, opacity = 0.1753 centerX = 0.315717, centerY = 0.542001, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.258712, sourceY = 0.542001, spotType = heal, opacity = 0.3316 centerX = 0.311387, centerY = 0.538226, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.248336, sourceY = 0.555915, spotType = heal, opacity = 0.3316 centerX = 0.312516, centerY = 0.541311, radius = 0.045786, sourceState = sourceAutoComputed, sourceX = 0.460210, sourceY = 0.541864, spotType = heal, opacity = 0.3316 centerX = 0.978481, centerY = 0.252986, radius = 0.027387, sourceState = sourceAutoComputed, sourceX = 0.894010, sourceY = 0.252433, spotType = heal, opacity = 0.3316 centerX = 0.974345, centerY = 0.252157, radius = 0.027387, sourceState = sourceAutoComputed, sourceX = 0.889874, sourceY = 0.251604, spotType = heal, opacity = 0.3316 centerX = 0.975887, centerY = 0.251968, radius = 0.036587, sourceState = sourceAutoComputed, sourceX = 0.900226, sourceY = 0.251968, spotType = heal, opacity = 0.3316 centerX = 0.596090, centerY = 0.159539, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.657413, sourceY = 0.192430, spotType = heal, opacity = 0.3316 centerX = 0.857023, centerY = 0.075264, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.785508, sourceY = 0.074711, spotType = heal, opacity = 0.3316 centerX = 0.936523, centerY = 0.223695, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.874509, sourceY = 0.204900, spotType = heal, opacity = 0.3316 centerX = 0.050101, centerY = 0.345555, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.114879, sourceY = 0.315151, spotType = heal, opacity = 0.3316 centerX = 0.055633, centerY = 0.343137, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.129739, sourceY = 0.278460, spotType = heal, opacity = 0.3316        qAdobed2!1AQa"2q#BRb3SrC$4cs!1QAaBR"bq2C# ?7iq[@m(@m  h(P`,`P.0YE cqqB(XBc , P.0; .; @ \ P \ v;.; ap.;@@ w8p;  Á8 w@xp; aa L! 00@@ L L v&0;=iq[@@mZ iE hEQB` XE qPYE (X   \`\`P.2Apq\`P;  ppB@ \ vp@@ , L \ \ v;a @ v;r&; 8ap] @ Á0 @@@@H&&!H A0S aa_Aiq[@@@m(@[Bh (A`PXE q (X (X,P(X, #P*pBupp\ v...8$ appB pHUB&; Qp\ N*apB;p'pCN;aap 9 @@ 8aaac@ Giq[@@@VЪ"  T XU @@A`  ccBX,!c a, pqe$  @@@ \ \ P.;$a@ v \ \ v&&.av B&&; ÅB IQ8J@8@ B!H p @@- `uKiq[@[B(-[@V@mQm *.0 +@@J(X,B–02"BX` .2(A`P; ,  qqpppp@@`v;.;a0;@@ L v&&&RaaqHT)!@haxV)0 @`L L L!Da?Oip %(-P P% PX@@@@Ae, P qA` (YE h,  qB@`\`\`,`\wBv=P.@@@`P^(XpqpXP;h aax@@ L L!*aaaRĂ2@J@@% L v0 Y1J@%`v0&+110?UipP [@Vm % h,"(@@A`+@@J= >!,` 0X,QBXA`\`\` (X, `\`PXE `\!Uq\ \a B@.0  #qpp v;@ vaQH&&;(B 0Z) @8@d* @ L``B [ipP P +@J((),PAa,YB A{@A` YE .0X,  A`\`\a ,  (AdUTpYQpB@X;EAJ(YcP@X`\$ Ô7B@@ v;@`L v DüA @J; )aa BI) @%`B I( B0&0 _ip+@@@ !(  XB PA` X, c(X`,a,)BAa,  aBAqq,dP.2  cpP&8$  @@}v.;ahv;;u @ L9H&!(8H! R)J@%!D @%:@8@@$V)0&?hb8-P%BXC (A` X,PA` X, AaH,  A` (X`P Bd B B|@ ಄@A{@`P.0(X,a " L!T@!] "aa @!HA) H&!HShR@0 @%`L`!Xq1h8[J- !Z (a`PYB   A`0 0 0XB X`,L"2qd,c .> PQq   %$ (A \` ..;hp@ \ v0;"{B8! a0 0@ H @ % hR)!D"`L Vl8m(A` YB a` YB A` PaH,A`<`\` .0X,(,B2(X )  YQ.008,Eü $ B a..a L v@E @.&.:8a ?'($Pd @% !Hp O H @8BI)t8iB@(`0(X,T X , 0X,! Aa,  , PH(YB  ,`\`,`\`P(XBAB(d/x,ApJ.2"W$H@ v p;p\ waa~ N N p'4@&i&{‰pi4N) % JBORNEB?z8!P 0 P 0X,Paa,)0X,@XA` X, Aa- X , B@`,` (X$ QB0.8$aaPX/$, \ PB.7B8' \<@ v;t\ wᎰ''?'4N p d@%,aDӀ H IA) 8@%<@% B $Tz P@ZP@@aa,) ,  X .[@ae, aA`\`,` OX, BA`,~(H, (QpqBA (H pBB@E A7Pp pwAE9Ba ..a 8D8Wp'pGCN4OirP8Z4B)@ qJ@&R(L<@JX,h X ,˜XB Ae/H, P  A~X,  qP0> P.]@X`\w@X@`, P.0X, B" QBwp\> waxS8Ea1Bu\6xppBR@ i @<8XiITM9f)J@% ily@zsP0X,X ,Paa -BX (A` 09B A/X, ` (X - X.2 P@@Z X(X (X'@BPN@ʤ c" !/pxmk@ \!+p(YQBv #u%)\ L>&6p^80R)4COÁ ;Ȭ-* "H4fi ?'+{<8ӐLi̧p{@x & 8 @8`zsPa`0T0X ,(,` X}P@X, 0IE X@A PǼ  q !BN.  wwx@;@a?aB E(HS!N* \?@9GaH(@8} ^+~>;8pN<1ri!f4KĀpiii̤i pp<@ae, a` ʤ^ܠ0 (,hX , @a ,` X$  AzЅ@ PH  , PIQB$J(IJOB  (A < nPH $  vx{yE8'X v/4@m\a4@;Ӂ @& Á ?i0ix ,d, X, @,06cA )AdR" $ YB  " Ǭ aaL$!aEXxU "ԂB.)xqpHa @x0 @8@$a % BX( @̧R)2SR)<<@urh4P@ hh D `h@ 0?E@a`h@@oJ_HXR, H ,xˆ ,XAdS -,<-0a (]䰂XbzAaH/.`0XA` ?,0(X, y  aL ȍO@A PO4 A  aB`P.0.;; B+c1p0 @% H(%$2`Fe" ,c6HX ŀV,trj F$_@ QEXhCUūE4 _Xjm ^Y 0kF,0ņ䲌/h .jAa -Ԃa|@Ad(X C % @`@@Z ay@@@`@ao`0_az@A X,PzoH a(XB YŋX"cXŎ,\`v0K ;,qXq ʼn H`YHSX̬,Xb+3+%V,fV,` biͰzBF j5 4U(abƁzWXƁ{E-ZIhDX mL, /,0;@ab0 0XbG8 ,X ,, $ņX`mXV ,X`HXX,0ab -"  X0YFm ", "0"K(ŔaLYD, a1a(Ŕab0eX,-H,YEqRRQ)qhq)Be;c;YN,cIe;lK)EEZЕ) Ie XXbJI`( ER,)%̤Y@R,+S2X `ߔYODl `hō0"ƪ<@/`5HQ@ōō a*ũa 4 XXao%ņX/, ~QeX((Y-h(ŔX)p)q(Eai, , (_YD, K(w(ņ%OiF-h︋$QYD, a"҈,YFKR QAbֈ,YF,,,,, e2YD, Ab\b\b\b\b\bv1e.1e.1e;YKZcS\d,cRc&1e!X,+%%be Y,+P( Ŕ̬Y@%bf$YLŔ8)1hV-ZōUbUZ4UVƪc@o%,5cU_,hS@" -Z(CUVze4 DX , il %4 AbՠXY,/X %av(Eam%[ŔA/Q-ha (E" iDYKYF%A>FXeHĖQ(E$ab YDkFZQ(EX,Ab֌,YDEAb0eX,YDK(eY, Q)BŔAb֗/,,,cR)q)q֝ZSZ\bv1e;Z҅֓,bBYBV,-hJIe XY@WYBVK( Ŕbe3+%̬Y@V,edYCYOUm[*Ŕ,ZU[ōh,"Ɗe4 S@hSE_SEXZEH(,(~e_kF,-Qy,U)_YFYFWYFK((>kDK(EA" 0Zфx$YF, Q)ťX,YDQ, Q)B,{EI, SENZф֌$(}KF)BƊ0#EHD4Q(Ɗ h (F0/D4QAcEI4abҔ,ZA%,R)q()BŔŔŔb\bv1kN,,4$+%e;,-ibLbYBV,+P(JeXY@VK( Ŕ̯S2eX(JE Uktʟx)X*E4 %R,e4 SEASUA֍Sǘ~kFSUH$YM}䵢 .kF,dPhQEH 5Ne4 J,%A" eI-hEa$ %a$F, xSf[)pJ," [(҈,YFZф(PYE-h}IkMgKMBI ~$I 4dFI4eBF0$4Q$4Rhѓ 2Adѓ 2AcKD4dƌXd.H( $4eBƌ1+hʅ\cFWѕh2eNMcK4eƊv2ircE;1dє4Rc\1"VMBhȕ&D\X@V4S2h+J( ƊJ DhTwʑkM YM )ӷ,iťSQv)Oj'Qe4Z~7h)h)ƖS۔hM>!YMkN,hIS-4E/Ɗ0S&$h(F)(94Qq &$Z1NM-dhJ)Ɠ+)xV228N-M% QKEEY4Η-IɄY<$ɢ/I4Q,#FH$2A#FH$h.H$h&H$ira$ђ 2K$M $4dƌXђ4d\cK 2ƌѕ4eq\cF]h˱\eїc&ƌɥ˱Bhc2cFD2cK"4dH$ѐ"6#K"4h2#F@eѐa.ag,ȗEU>eSmrhkMuE4TiU&(堧&h)ߤih8M4SAHcE5ZDAO)MkOcFZ }ExFѢ _-&h)bM94Q^6-(-F1JMB4QqiƊ1NMB4BZ54b\&)E8ђˤʄIa..i)xqSa#EI4dIɊw$13kO).MRM5 3a&$M A$EhɄ4dPirAcFH( $4dɣ*4 $4d hPc2ƌ1*6eqfWBƌYveqv1.6e.6eɳ.6v2mpckc&V6a mpIhف"6`H#i"6`i"6a Dl2#iaLa5,]3f]3"]%?!D>.J"I-8MV4iѢZlXіi4SEHMKM(іLiɢ[kF b bM-4ZqShK)4bhANMh?4QqZ}hLIRHwF1J4d?2BhƊ1N4QKEÍP&S@ihI Z\#IZ]L-J\eeBv2Jxѓ 2A$ђ &$i4 :\iraftL,\Y4\D(-Y4R(ƌY4Q-(XEh &,h &Xђ4Ph irAcFT,hc\2hc&*h2Vv2ir̨XmLkZ6e֍ukZ6e֓kZM]i6ѳk i6aKI0%d #0I#f`fci"6al0ͥ8dffy'T?=צ֛*)q&ɢ4SUKIFl&-FjMPF-U>Ѣ*IƗ-oh $MFh#KEh?Ɗ5AZhMa#EM4Q-4Uh h oZ,dD4QadKDMAd&ܣE-E(4RFˤ4dƌY4dɥɅKM.H,ΚɅ6MeBɣ&M.Vh˱.HdFY4d.HђMFirAcFH,\Y4d.H 4d.T 4d\ѕ4 $ٕM.Vѳ*\lɵ̬\]Y6e6e֍tmr6t\mMiZMmpk"O1p$I06` a"<2#0<4l30ǘeac3fn9<7'.+Q~br/-is)UIkMUzFjI"jM@ZhYMTFhiiYMmZh&06)cFMG4S@ZhhZjM`Ecq)Eo&&"1(hYEi4RZ $DihEZҁ%e-X)YUc 4SO=f=: O_Pר2% (؅Ӯsy/<~Z.L&&2@IɁ&3&$Z $KhNh4dh$ђirhZ4dKM $䀍@Iʁ&$$ђMTI̔\FHF+&+&̬mrMY6]2mrٕtlˣfV6tyL5535I5LQ:gj8:O1pB$m''`0<3b` yym0 ˴622c5ٞ 6'6"tns3q͉m?+] lZЛu%6SZUjD)Ɨ-I,irsMF("M1).LFE4XіM-FɥAxѓ$#FZ(ţE,hYJ2YD YF$e֖i,ZӷJ[ŭ8 e?/>ޗ}kV:_QtPi}] i>ӎ|xViJ.QNTXoGOWǩ~I~{ XQkji§Rv0{?9O>|=h$Ě\h 4L 4[IMB4@IR@I$$ɣ$$ѕirQ+\䄚\kirM.TII*$lʃ\dٗ^M mmrk^Mxم\,y^Mu\,cXtϘ[a.&|Ʋ섞ae3-&Rl6S%ei6mPk@ZM3&6d 1pɌba1&i|6i12c,sfx3c7&3sbx1flO-(FoB3mD=66Sa3kMkMP䵦d{e6F%5SKZhx)֚)e5[Ie4XPd~E4FQ-)1kD QSAƖI'h4\RiK}ŔQkF$%B-hKZX%e:kMa%]O=IW&;ky(i?I5ҙ|T2`+7 .Ȍ.\q}[xSӅB}V%TfU>Po">^IE2hɥZ3M--(2YKxђF"MFH4 DirFTI$$AKirBgK:k%&$-3^M.]q2@4Pdѕ\n$ddD\ˤd;k+&.l˯&.)IMvRe&LvRM6.2mD ڳ&6kLFڦemS3RM3/jɵll_10͚n:Mea%_YFKZ0,VZ@m0K(ÁQ^'.V(-;/AZ@K(Abeq줲;E;9,epΪ2i,WOmT3Rtڛ=0i88'yWXSQQp;lw5uPh+9><23g&> QU`~Bߡ+Ei-hIkDIkFf֔<-W卻u_b9,,KZ K(ihI)4A)CFiiAFH0Md 5I:)AM[ɥM-ї&%y4[鬭o3by5ΚM-:ftS&LƊvBME.S:JL)2hd&vRLy6((mGZ6 la&fDi G2i62cj1 mL]Li4͜FMS2j9dF'"t6J|Jj iJ d;&&j*"Z ?9)m䡨JiW% ּU;V[+E kơE@ j+E1\m cQhS1\w!@Mu?;9^Vh%J!\EbkF+kMaQo2Zq,xZDS~-L^4]w6 ZO"gctqj{?<9rro`=si~Q|Oak躍kzR؟{QE( fy>!?\gZ-OEQ%4DQ Z $|kJ*֋$^(ֈVZq Z fmiEi-r\i, ZaK\&mrBLY1VKZ.,^',qd弔u1CEjIKf5]j2REAWh5^d!%5^bƯ̔JR;5~d!bz05#-kdZh5^dZ5ijyjK2-/⤵Ϣ Vm+>Yx^;q|?wEu 7>*^78ޠWu+=*wO_.:{=.YD߬5_`~ P)FEEE2CR;ȴcP;ȴ_i ^d~&fڎ%3-~'ns3-GDxw&mp<͘N<͘w͘wKL;%!^few$*2Bh&mWͱ0LķM̹KusNS- 2a6l[90mLIX:Mi%樢kN/-KKn"[v X[uy%8XM7Xo3M-^n,Zj8mG͵f,P;5'R:D1yS\JĈ}<'N>|rʇ޹F5ST5t=:֝qzD<O>+M?^HRp?u"N^ > +z{+NS#'<=?&r~>OOSāF~O _V_M'9{Ci/h15(6Co<SS]G5rH{#~mCQN~|\#O#Xl<9x>&jußK;wN|/S9r%CBTJTGTw=.@rH2ս[mZT"M.\98_JA8*=6CyӚOǜ\>Վp˭O8ʣ*U͕]’O`H3 <>Bom'puFJSm!(!<~PGRWQ^k?IMG=#Rv|&/ZJjʐJkRJS甔5d1%) )HkJC_i)TkA~8\O3JW:fGkT"@# =6koY~ю}iqo^zQ7NJ@Dy^ 3~P}ƪO"ᦉӨfxx.jzܧZ5&;)E7fe0"ae0CQeDEaky'texJ9̸L=t̸r')p)qlg794ͧ/6Lq樖Xb][i/ V<5זVxԯ,Cqyjj<Α87[ Un8w#Q[W_n3P2< v+* øPAdR@ J ǸׯTV3fcG,(`wm^UƧGTҬ9؃q-wxq]O%mB %WQ##=g((Z:pF9rt׌:GWzL]UZmQن >6 &lP2$1L-/Yj/3~~NY{({Qqjݪ/ҟtԏOO]R 5^ӵ n:6pnO ;|R~u>ۏUB[pNm1?-Ǎ4>znz֕cor"|pKѥt*Ҭkgz\%Q>f2ҍo.̘S38[1Y2cW~e1&K=۟KCCG:G\09O{Z3˩=ӫze!ĩJ}K*OQE| ?QϗGwywgZ- jPpC'fi筴ZXliMU|?(֦ͦafeYQ/g>Xo9sFU9."~9}u/eQ&Vky2_&K!=RamFߜ[!L[!=מa/8U=Q&=@ D8n$ǩmbx5_G1]̘h|WG̘U0=G̘U&!'UL)P&z5D=@w QPpC^;市39j ƿ338t13<"kykOH38t13<[0CWLY gCULy313'ey.sW3<\JpPS,YrУiHx~O/){i *yKKO|N˝=?8&|ܼזx;qoY>G_>Ks)cyM}W tuHtr'qg^k]EQ 2Rөc c:^pԞ}Yy}>TPI$s幟Gs}.qȹ#G9^?/VB&UR c옧B7WMU:*/agD ofz1GՏ&bg_i'jyd{D4RH.z'!O&Wpڃ'Q)<U_]ei<=Yg]V_j9VO昞'L-8/di赸!gɖ OO&WpCՓO%VCgkpi8z?yyRVz!c3ZKLqeW'-nz?y&[pcfz2rOfz2Ǭ'&]#4_Xbz2)8F]#4_X}e9CUz?>їX 8OF]c6_V}e9CUJ}'.R}Fy-'-W]HzS5 .sҟg9 pӟgר>]9} '}rsϳ4vfx|OivbxKχ'ԡZ>ϧ/>2ZvHOz]J8ЊLq~+=W.YR4ݙ`}BO|3u9"|Ʀ3zyxz=zzvtr Ckg3üwSsӚ>ꏧ'I17@_qOt:X#juq{}.PpZ y|MVH/α^.^ω 6&ㄽ:\Qtҗ˯47~=)z#/W4)vVDz}o[ӯzx~R˫ËWN/OO s=\|ƾT\Lә* /^V66po&͟gQ%CFPTّK9 Y>>VttƵ%6/ vytOJ} [F3Λ ~Sk|~Ѩב>czZ5UkJ-Pl~>B0'PN=0WBmcүV>=7VޝZhV:pD9xC[I+ѿP`xo>rzƛ_@: :}= SxR='Pjڇdҁ]@$LJ|}j=7KP(!C#ǧ]9R9mmVu^Ԫ 5j``Ia:q1\kׄ͢L\α.2WIvnv[^s8<}Zȫu$oM~{EԭUVq7-D/ϲO^yYx#W+ZypǓϷ#ҵءXz<>n}j\h54Zf:5ߕoL];}?W;9^$]xW>CvPRȆ3}C뉶TlN>UP V%CHrT=AH Fy>S#_@Ԥ֓8#?3> ;G+Y`MJ`r8{SNH$\n{|%_J)x>uO@pv>S '%[ob_{w:s>~}w4>ԧ긚ʊ]hPL^WbX~lŹz /7kHVZE]r x>^HHS.y}Sdk:EE6b>`.ݯzN_7"c}ڏ}:TB%6|Ou}4[nD!#n-gtGTOM1S>V̓x}ڏuV:m73>ۏuߔS>]ZLO.k)}'TvIc>G+[U b5H3/isQz۲ngmǼG/};2ײvt}t_ݺiu3J+-L_~\LO:>gXO+оF8F}tG׏?ݰ_V F?x~ԁ#ISc"m<>qt9/=&T <|t G/zTH7ښ'b񷗭Δn?iiFdS{}'t:c+Ǐ\ӏOOw߿qhUM\|#=^]^q9|Oח).ސ~\8\~u^zܮ<g<}xZh_k*S-F=QOmז':^?g|}_z5=B5@,WFgqkkuՂz?9~_ǤWPg=M;1jhݽ;_K#_ǧ?<R:*v' |ʭ/܏{:6T|OH'r=~<ܾ;r(6ө# U5Q$k?)ߏ~<3~I?W4mf NC"'+G_Q );GZnYҁS>̀'݇)_ߗkq'HqrS짦KTUn@7.#`j =7?1>#Kl6^bۇ$vR@YM.RQlƐck66S%RDEE[]&ǟ>vh/kn<mEXb]+[ m~R m"›J X-MQr`(zH ੷E F2lznPKast ,vSQ7_R(_Y%U(7İ[IpdW=q%(隟[kX\4/Le2 ^~rQc(*ïwT"$nrTzAT,SkHí7jPzCLw$}L|tLQmI-*R6NH?蚑 u *w@k8|N%zg;Ө>,9>~(j5)P*p#a3I?~Zm}\Wpy݇a5"S/tꞞ]]:=7"y[SZz\.dwn(;U\,0ldyF$t?ziϰ 뵹=E,Vװ1j P9 ڙơ' ExXZ~:-­/a[ff;rּj@i(O"X.VP)2'eQNVȲw~ E[= i}1F2b-V5ic`//5hizF{q3ݽj[IzZm[7bBߙɁ;s {FTPo*,a/OPj,rbK\;#*hFjzAHN50;7=^fxDZSZikraB}Ѧz5IVMIǘGڲ૾TbrR|MzUڕGRPCkx>2s5.~&7~[%4?U{L+42.N=Ox p~s.rn:o*VU9BG"T>Ǵ?^jתʌ]|JaEôx^!:cWY:*uEF[Hg>=.\#ֿO&C؄jGB8,(n5>}'6hQY~=ӗ.Ru<^Whe}[\:V*BE [{_@zy¨Pε(ud_S3_1}?hi 2dפP =x)}nofU,I `H>gSOtlLwWdu4NO2 $o|D<zGm:=M>w4us䚡ϬSnj[Q{5N᢬IާO7x؇Ʃ]2uj*YvjfVSDv|N3?UƦhMu7;G<|?wޟKE*zcz0.t`@mwDQp[tț ޺u!* E"P|Ko=ͫ ޓd [T$sT8}V!ڄ*hF(Wo*@GJ>]4:QAa+Xމvw2OK6ɕbڰ_7Z*QZiSH}bTZJVɳćEUJܨc`Ou"jq~P5J+En6TpdC}=V &V5 y"u*X+0`r߮3oy`%CԪj|cFZ04k H/ :r0KJ] ?P )i.AC^>A"uLBO=Tba'/R J;FI%nM[ X97rk;%F֊j&y)b^mYkaߑ:yޗzALv,@/+_tԙ{u X=\lGn9qzL%^yyz}j}g [y'GuYeer6?ˣ暿5JGӟRs1o1bx|g N 7^q~󝣋=O5T?WNB5 䝘\75\5DAOrvZXf[\RdC:7V',R+snnI?KgV=@/9Y{4~jtm=FRñxr GV1VB,ZFې<}X];+iF |deFu5Y8Y81ו[Zw .'0W?c3EZqV!ו+oQ> D;m#ÜZsmOA`eYI.N<(j/H;ub NbjGL^ɨ}52@{-&SMed ˙pz2ԥWRjihܙ+ά؞P: 恟d!:oU7-s{PvĠTi9޻|P|O{= WT3!եV*m)7Ӯ/l-\o}ȭRss i|P0<_*('*6EEFԝ5BBi:8VsM㐔x)j]6="Gn7(7cM 6$^+2l8}IiSD)r?v & 4t54 @[<% #5lJk[{wx*{ST{2 cwX2J4Gms#ad~6R@5Ht}P;<{mQS`O.R-0` YO/*lo4s@RNGe_Ơis{@ JPP:Xs6$-j@Y6jRےdPU"Jkkc̙,IQtZ:tvΛWNqsy5keâoqr1N(N O3Ӈ&R 9az5d14ﱹڎM6۱2rìjjYc˘Gg˽R11^y򺳮h.I 9 Ei L*i$j!s~v4h91߬$w@{>!S|(;Kei)-lO8UaqXhFE-iKS\cw|YH=8ݻJiAFɷN#,A2֚%{ Ԙ:ǼazthHJ1;8j}=+r} %)PJ~WvP݇+ZJ |"NhuȸS~KzFD*jG?S%JaL髵jWYѭJm(?/oHj&?uj9?mR,z =.$RWT7sk|(iiEjF;Y곭JqӥK"s6MtZjf*Pij-AM~@$SіWAMf6 OɌ]uZ=+QSGK Q&b:Q /K=KSzզ4fYo~@3Q́EFu9@Β8U`{Ǹ,ʠ*Q 2LW±UJ;ELyohMYx0>m h5He13@r\@y5T,+Mk۸Vv8$GYF0(z|ףFXVpP~re %6U9v6L)w{ALn-ONRot2+SEJأx}7ӛ%F@W8h2oUs(Z {VLkE룪ALT#6 ؃S0;?5K"ݤf~_)@զtG26>G( Gmn%-SRj>DmjV(Lv5,`9 P̼ug_ۘAo}UoETnIkߜ[Uf{`nB gMK ôt*TEI2D9;(=Ѷ]y:4+\rKiO==JAG6?ia㙦Hw: D(<ܟ"Qu ccrdz\wvt5⧸ʬ ok%Pq#V# [9' w}WˬJ`_GPBUkM2т̀@:j IM*ÖC}( ȫ^ܘjCvf=4 n{j_ O}V9ToO9| ήA?IRΝv@zbZSjYЙoN׽"ir2$cf@\#dG'9H+H/eO(ɖK5 頢7rp9TcU. 6Lp-&3{NL>JoPV¡^)rFv; HZfdQ1',˱ y.@@QQs"gyxP R&]]"rizccM#ɨt#ѥњx5BQi&kiڍR eM/KiONR9-iRE۽S"V\˴Q.Wsͪ,H^*(P)+sGeh騫K::vxkӦ+)JovPn?YQtɤ4J^ٙ,~L޵pk)R+\?2A^Fz 9^تEK2w5 [AGCPE}YSTAQoVӲ2 u[nDQDDYzDA)$XUkvUC__uյʭf-mEE2󕸵-:fvdČxVS"A)Pҝ ^R+Q>;H6ckU9GӧMh Jd\2u4)h+dz L)d~7ZiP..Vw*5>p70<:ƒL{oQy9%TG7 ҽ,~VcT|nBTAM mRI*+lwKlo(ū~k2lj q_UV \_-XCajy*Ң5hŋHTrI[[x긬(ZÖ=zju4੢B)kuPֶT D%jTeP`;^%IoPmJVXiF#I!*A;b9(X.bA|o֘SUi vn630+zZsr-v#)m 6Kٱm,KoIYgY*5cPEXs1*vbVWT-33-b~v^ Iױ5#3yfBjU fЖ(} 7!^zt[TDwWD`KP.5&mc6'8)J %9/9{o+Jnԏ&Vl̎FiL~x8N" ɌuYOQ9،B(gYq]-њ.ʟUP7V?U1u*ZFZ y"s[ގu5 bC@'\I3KMihm;X4 MP:LFCdZj6,*n-T{"j gX31Q1t2w/\܏-kE>%KªX߸;Lw^ua+o ȄN6U!]B_e;Q ZlrT ٢x nծ7j6]ŀK6~jkVAr"$kz -$n " (SlLnx^*T[0(WPI'V?A3nsOFsr^A,Q[A8@MP6ב^J["U]UB^Q@#s+:a رi6B&Fطuj{ʷ^PMV gZL{-ɵJԂUT ڍUʱս7=R}=b%M ]V6Eĵm,fb0er=߻cZzA[N+M iҵTMIRjMQ*?XPBԀժFA+u*3R_K&nKq{I_u>EFUoCn*e4t15NnێpeOTutҦ:\!lWzOOM4 i@7aoםX,ܑ~{JҚ-suyuf$S-`PzcH~vQS`jW`-f[ ®9T6TKW z\ۜOMAkE@Qhs]hW=5ahUIT7O#Z_H-FۜM}E@@x" @@,HzčE`ڬv3+SV^B62ZW̦j: 4>tgfnBѢHe iCQv=!H-C{32V&ROrl?)-irC1,drDq{=GӞ Z3-qoJf!|Xe򗆄1S"L5j]U{A%-`T_kY`X Gj\S{ [ q9֮^aBx#Q*eϼE ߠJjlOx"1Q\8?r䚘gJGMV7%}[u (e3Kmkjd[ Fn|n iѾ}dWT "\xHí` [!ΫT!eeS@R*GSR[l2:\@?C2MЫ>^aItM^-̙u5l(~(R6&\dw5j7X$KGR2/S{s2[ΩӪ9:VG"7=yf91$daR@'x k+ehZlv0MNûlyWe ^QA}--%U̢׮qͰ7W)N*㜀kcqVO䲛#{WQp.vTiJuZ4H.w0^a=[[0DT73(q$5 p $CӚ"k0b}|3bzHvO½= śXF Q,*u$;\U XH &X.*IaNmxZT~gdMxa`@8UɑD!Lf*sc Gd/ -itV@w٦hg6s&!rqE5aO+ ؞QXUٓ6&Tvb}5?/8& M609#Xu&}![k?nCnV yhխ{o$>N!P6eݷLbnzJz@Y ,Ս%0E-ui$[xq);Ef{G6AsR {VJqn`9ܑ`>҂Wk1fbd0 B *ZLVQ(5p7!Wro (Z5KqP6b[H9f6qLXXrfyP]q!-Ak:NJt!\B("MDR[.+'\~RX:ٹ x\]m:@6!Oޕ `tEStSTRzF1%\5kyW5g[`Ve 0 oњ3[CjNj;(۰]t"[Jj( MD`Ijʥ kPS#ıJx*ך\MSTT6a-X4:}a\#Rf:F{c~<:@4^v7H u0#TdMޕ%fMPç)KXT A8x(@-^A =47nMo UTs')K۔XT$EȧU.ͤa"c{Y:/&ԨbhUn9㜀TR <|vzk-O){QV߹߼(2H (T[bf(7`9ʎ|Ù*<*]Z+amZ s&Bބvds24+Qā M /l&0\[``hW,J+oRRTR0/-4JiNulFĂ9J o&ñr8K Zk Ԫ5Yk KI^vIkOuLP},m6=/Ӻ0Z׾ZiXT9_CR-bOV*d&jֆ"=d.qrX%&jvb,qm:R +S{)iկQv/~RtpS)BΛ|-x03\`m#mow"bKERەy5^/y\ G(KM$ANrs[P꾑P OZSCQMd*SUم!\sM{/n%ZQlK5/?Żӛ(;:@Ω[yfH 6<ŷfNaB發MC ;NC-$ `TTjVR4* 옐2 FJf6\QTcƩH A|8-^"jRZt2#wZeBe[ҫQNKEwۙ%\#dK?DDBܱ]~ jw7[}H0W+6lIskIWYp5l.YrO[^VXҪ_D\n`]Vj dP [x5:UUo q綗RXSXkW5΅OkH\SR[Sح۔(H:B@t0:+ FغGv6@Zj ,mdP\XQ';@Y;]nЛs0mB9@ƵEg\(Sfa!V_j~NMꕳύ ZK>UV<,LmHoAZAu ケZjdQP(̫5rHnpWTY{n XPƟ izLPU+֑m8:-1lߔӢLYI ^7Qia$v8j5 Ew =K_tkI-DU<%3QΩ,.K,lFU?EG~%Sf# ݿ)P8)$Tf&۬#Q5̂{?_}q+W4Jfj+](6^PQ~!p*mm1xLwX[H+}Rfz_MTcq@3]?QIjB[2gZ 6%AlIKQ ܮO:^5S }& fJE.(kh XpWߜ0+tNm]ME핟}9}MyliZ}bwoa&5RRQsa(w P9[M9f + sG֥ J=?wxF&N%#đIߕGm9@b1=z!tt:@?hh@t: em BL tvqrw Ɂ/#/bts+ndw ?a*0BT6˼rXx`lihss"ժF9XkK`IaVF`uk uBhX} {s<¾MR#jhwݻLM ]~kLk; K ΂v&T㔶 !bZ**e]: X{ve {%C 0CzP݀)*[&AOL^-N"cS&W^!;»xE5+U!G!PQrۤ&[<{PQb[*r BԽ9rmB1>I@@*8m ,%D'{¸akHs̢EG]M@G+}IѤPj-R)[4|,3@_( z[F΋P}=jWл/U)dv$+Q[:;UL4Qb)wjckRMǛf KS[TTɪVw!.?A,ԉ*Uj \{ߜQiR;Sz|BMbG@T)z(wzCj*rַɨ̽FGN/o5~2oFWzvKs%[䝞M7- p{W?,vyu^OAh6R߇|וToۤ2M>OSPn@+ێ*)#w_u.|ܕxMӪ.m!5'\-!<,̄EפDTdP J1%&crj.oHJԢrXU :IEבFJl,CTLm 5eEJ `D -*Zo8\͂{ߵ" cD`pq \FOHv:`w=uvt+w8c`wO08xr??"Bc+'PE07a(U=6< KCtVa{{B[YA MVnuN*{~ =a+򋐽Z \ txhHrHn"gSPŹj6Icb7Cr/ ӈiչ]9@9 Gp9y@,I6%`9S6MO@=E[`fyKOP!"6=KsQ3Q pm݂Ju~$2~JӦoʫU);zO@Ԋ.&jMl^`X`9bdSBApF*vvHpT3aD$}6Kmk*1Q*{PEwVGb}gS5t\骾qMW鵺TiT}A7iu2PivΊ~r%IkLYGj W :>"}|UTpU[RqM"iVTL؊"6J81͗v$<֬ZAvAUED;YE*~c#%%*ڮ4MflimM=\=FPMFh&aD=@ Ev4rn$WV*i!`6 /Y֭*|T<Ko0Sy}ЦYHQX_:bosN?!4ĺ*<(5ZVn.5 FwZi~́GmFE6O,RuXSϼ|(z)lf<jѷH\^ۈVliG@p&#ۗ":ؑߥ?$6m)!b- Qrld(J &/n " JwʍNÖwňӯ8ңglX HIu ״&ِ~$]I.V s عۺ" JlXZoq!۩$NȮ'ŠHЄy@|Hij%XVdZʤ@ F͍&FJ#Op YO+y pf>U|'HUߙhAP67=`lo(vLVvm)}ii- MJ}+m iЎqWdhYNYB,ݶ*/ G3x 9 %3$ Pkʕ!ISQmVb݋Obf5UXNN 7DQoE-FPTV;=Z`2LAgհ=@ o"PYZP؟=>)]ѫgpwyZd,@njL:Cۈ7Z]*?徹rRԨ[NY'b}vSAް-)P֊UNSIp:rh骓Ι-,T) }+OD}Z+5liGQ@Kc(CFj4VlyK|TMR [{hRVO(a) Rl\Y nW\H. @D>茧 ~=JޔBE/ol QʮUO6 0vXGQUժp7=}Pʅ-=P2jk5Ŀ3]j=*IAkf~{" yF5MMscX3TG80 pZelvFImѦa]u4od]SS;ö5ii\*Tp>r;!n2кMf-E.u 󰖒ؽ E Keb6vr 1b67+Qi(VԐj GjRFQU\_Kcwyx:(x%+ Jd>'F !O6 (]yQ4:ZAH ȦUE%[Q*p tn#BKZmO UtQȫL);uß73*)q֥M@[򥳭@Kn Wbו›} ԃjj ?bbۥ-+VO?QR 2$&ElޟQE,%,~PS#zbŰ /J8[)rjdh !r2no-֏ UVDz2{QEt-Bjʰ98݋۟EMYDL?i^ 3*6(8=ժfbGܐ%*n2O5 bLʊ7l:moh? Tr/,x'6x(D"%CQ KǼ@B{*R۪P('nf(boȋ[BAo*$ܯ\`uȁU9iTv;BFW<f܉ H%ź.%VnyB:9ۮѩkZ׵2W)!Q.pD9"㔡ܟlڎ*Io{򁌃Q ֓*[@hD,~c6>|-kbn2`KS[UDU*eQl[UE䇑48iRmM\yNpՏ}$ 﩯jcek*!'u`.eԥ75!STʼn2+_&ѩJ}FXR/]>+1o0kaÝx#˩J5=7ҩҵ,"&}b@J: )[fz"W@ɞ+QJ/lCT* 3[*T6*j#-kL~PҟWQ:g$q:iƜ@*xekG8fx} Vg4RzP˳'[KXi6r-q ~r̤hk5 i֓N@Gk%4EL@܉GjUi SZ߽>l(>I?k@!r{%TܕQaTfWuz5TqQVQiӚ*S"ĭ*Hn)ʘj]UEeZYAE0 TiiښZ:H8P_ʅ ~?hh UlO[dh+4RP.ȨܥCj4 2ZfSďJoN芔V "yk+Рk& oٌ.K(Qe5BZ4\(?4}R55;*6_BvrdmmWnZ #QGMBT[S:Ҭ|:/xѣM:G>@oJzom MdӑEH, T/9>Υ&KF"¢vѐQT,>Nݎ!*Ҧ馨lG r>7YPPyQb7=̮8Y-SJG#BUe*Rw/66[ZECj5Z&pt/d*e7ЭO[az /gjw4'牼wriaH8U4R!$+iiu ZQ[?(F .XLQo-*Tiبiԏ,|GU5SMi"<32 Q*A`-ne.tVOGOׅEact:*QiUh}"ѣo{GQ[niQZ 5Gu#z&]JPÕ9-^m:jj%JZjPqCuLQ5 uf6kʼnFH;ީnX c|M~S$TH}'ZT=ESni-ۚdq6j&ÇPOq E)wZcsHYTĬ)K^H4}[w)d.\$(bt̀:,yj_t!خ$礃" `~+t%ZmTdr@|-kX~qJKq9_R3" ] \3xU ^1Kl7cRġ;.iA` ݱ Gnp!lEfI?(WH:TH@WN}+iN9}XPyX}oS8u*ߚeosxe?̇l:xnrSw;!▔ck}w},jQεZQw\EƁ**Z=;W;[^E89OM]$~R՞WTHedh5:iM߹`~qP/y[VjSCٜ KEE[7>Nur?95_BkzQZiP+Rԋ/eo/%Oħ=Aj=6,Zj٤8t/HjWr)bm/kQq!J[Ij ?8]Ea|jOA~쫗*i)TLP@"jlPӨ)geHSJtuȰ7r2i(ĭ*f;ۑ05SSZTWuLvo#gze5ڋos %zuLB髕ÕPG 4Y¿ڏX'躦NEp?sER3 PF2jE_P9ڮ$[ToWOSĭGKtH P|ȸy.-)j)FS@iZ*>E|E@9UbTEM70"ƪ = i-iX,DYOU%J0&\Eǔi4?Θ7QP@5[V3TAj;Ŷi,+h%m!57%-M--Vm= Y]U3wɵUON`Wlk;zmPYX2 ]JzkH_QpA)8r)M ^ZOk!e.j:]=[ƺۗޡ+5tE͛Pž셥SRfh SԻ!,-F*RW< ,lQQr$oEIE[PSTFB,4UuNW{EjRLЩPOE-:?D4^ʕX#=6)-_O_Pi;7FSQno`bxByKoWG--5TLEfQRin-Ԗ GJҠ*諵@DmvSF_JhӬGQ*W J 2o!~.ӐV;a| dOH\*T=Oaɀ̊::lj1ff'~w+*L΂iTkܢV@.h^ۆHA\#hT,i;Sv悡u~| MHV:-fs<ԇ*x!LӦޢUlQȇR/-i@Ѭ\G$Zq,  pj7kiSț//U)ONVWFZ\)v*H6h-TZ)Rz5 Tc@-Jdd(-M@f g@Zß3}{ E+"-"t:@zEZ",BE N [= jʌ;l:5*2cɼi$NUO~RzȬv[_,9Ef\ra#m8`NP:$ FNSZgpfZ%V2%EO̘*I1ƗqS,q^i:hRU]mᝬzc2КgQtP\SZT-JLr+ša|9mNuөH)!i[SԊt:Ujtϸj*GsͤP+j}V9rD./!S7AN(Q(`q6` ۣji_jkjuh U_UZiOZlpQkӪ;lK5"At)j!:6M2UjW9y)+fhZ`Yj-{EKD~"u@XϤ#SҿZ.Ts%-4BhzW7,2m(bKTmk//tzcS%>#RE|zA&Ae2IEzOZRj " *QJob~ =jl)wSQXdrM= j=FG7+Y#sȓqcU j4RЁ܃ T91UoӬF/Mwm~״ M*R"wT4Sž%+``WTc6`\sSoNDBOܩ6̌G%ĔEm=UKlʕ6"*Hۃx *j6\AH%Ў c`UB s>7ŸK QMPd8\X5RE@*w#/)xeyJKȮ۴sxB$Ю&ڤvɖ7pLJ/NGu6~vWknN?1pTКdq5:]bM}-""5s\7\ j~N'PE־R4i, ᚗ* ~6ZfU2~mY2(?3%<ѸJ,E~_]Jd MGKٟ^Xƀ??%^8@>ZG2x楪>'JI+_LhuWO? aQLXiFPuEB؂|^T3& xʎJL«e' gN|IS0 bTj]*&OznMl͌T)ׯQoUPjn$k,q zAjWI$ ן¬HEցU\Vze֦WJu,*y1@SM_K]Ɓ$YTOQT{V}AңU-e?3+%[~QHKrU(MC) \bs&XSk nY_M@CkzrQi}kFŪ%j5&,g7i.S9~Qe>P2xe:PQ CѣYXTBìjV%{Iyly)RN ckA_FtZmh9ު*(*wnCQ(5K6m,);#Wʢ JRVONC֚:JIm-ͪGKTk^R8gWk ]P[j4NJi`~VeZR!m1 XHmznOz|JezqT ]KR*5Q֣oQһPҝC8  AQQT AF(qk;}JUP~$:2-a&[w4ZsTzsE9z3OLM*&TkE+-WG RVX.*WU*=T ~5-gԥSMxU)Z@Y[Mֆ+h^UKD|]Hl Uߕ[CO[-%$,j ;n,Q=%]Z(zX V?(755:ZR4 R}ă5-Ik-&eUJon۹0F᬴8ԫM8;.h2*&H] *,xk~E}AG]KQF*=@@~:R(tҔո{7g[XN +j*Se{AQlZs_I-ApzA2 M3k=L)#q=>3=OA) K.-*ۭ}W)jj5.AEݻUw" SҧlB'Pv;FSJLڍUPB*Y66&د^;S&BI5idWxj)9UJk]Ÿ*ڕP@Fﱴg-:^4Hǰ FJ*DA2 PPtx6PO`-5 ) M`ErEӿ+*Jt.WcFցM5tA$ eKz-%1 'ԥV .mpJ+l•S}B\NGljŏH%57,~}dVQE\s' YseM#R@<(C/;"kZc~f®!ׁ$t:fR;SEF@򜯻L*VnC6Z;LLP@bHm5\bаDw V;_a-َLO.@¶NB?:_㦭Pfy,>LN> zY['cϙ&vqeWs/7)u==B!/P{h}KwmUBSZa[ lTAMI`ykU=4RG*U]_ oeΨKWMi(E;]^j16HmYe*H)QvjIzD@΀ =U&$էMUJr֭Y\`HiV/VeYb =/b^/i0#HکEed=I *TvN8[_֥Hh0E ) HZBƫ$Fgzf{ܓ2ZIa%=TT$A^1IМd럎``Rҧ.~7{^HAfVŇa4BEu R#x 0jeS@ H X@)HXuOV/={ilC:gN{@ GZTq=Y H aNU%*bb 8 !d[wgufDT;k!V8G&TzЀ½=+ 8 1[0$'ʄŠ, &,ϗ xI*d8 ]N*WH5pǦrCjQK(@lZ Q,IA( Zerb6PaLQc~r#jz,'b0B؁Pe`RCf]0! 82!wz̨4mYs0%%IIKaSt]s~֟Ed")@GլJAAӆY$OULTE"R'VPzVIJkt EgZ hx23J@Ŋs+>]'d,Tu,Q^-Z ؒȗALHNjeZrfAR{H9@^O^@ZO ӧ0{W᤟W1*iytXC@CDNN\p-j 3O  T+0A68THڐ``T#v!Whu$vbEܢV YB a28c*eLW Wkl2Il+=W؞u~ß@jU"֫See|8SV ڂ25Ҩ%FA! 0HD ( T ' ?Y~ )К bM*vGT IP ZNEr vؚ N2Қ,XF(C !`r uO }ƪjM$VW4Mۆm뀹jcCupfD*cBAšŴ#52gHT"QiUFF1HjjQX&2ױP&?&FQBg7R `"ـOG-Jh,MA}4WF@=5!)PCFDT˨d&+Mo8wΡeK-OA|_5w3M BIB*FBjAf  Nf%DS@Q-8BpLBK~FvHR*׉ߗ7$Y"A+FҫN-R1\ ;-3.Yh xĬm@,L9PkO^'f%acJ1K)(#rUn76>-$˗W0Kd`subZ+^UkYXiVk@AXIf!숨㜺(r~5{xӛ t#?@㺖jTWT7r829 B5d H={31k.0Vj-[ hB& x00p0 !Ѣ R @X)Ośz \;Bg\*LlԒPpZ95Y)]9 d&TY65 |Rd(, "MpT"w9@lZMqb jXbI-CV)7JF[Tj`O7J4'y,A@!ߝvu(kt1A{B@H?C nQ2}d=0E>J5!I/O;,4>`4_b92ZP Tt'O=7DxR(^[ PnQ R8&]VHýMݿeکmz )JNAtJݽ]IZQ"-- Z1{AۼDV f.њ%H==eXR6fYҩI-yMcׂ63R5IjUԭs91}/xA<#RN2W3K,d'@[IE@[p. ul|KA*ɯJH"-PyW0z|*];lQ nAoy];E-܏T̬ +hZF)7 cYւVD Y8siEG^F mUjCerK~/"C&W9& J (,c@:Sj1p.=ШU#`n܅x\3p l8/@P U ׫]Pə@q tjnl m='i'L,K<. E`1e.]R/wf (+5+#b.a*q% NiZCtoRCzN[ [=;X*2J+0G X2ȉN&QEPju Q MQ0xm m@>gDvU łۿZ[q%asd*F1B(ybQr_8Z@H"բ\(+Vk"UnY wD)0dii5D]Rs Lmor!^y@p!>= PHU,nzL6j Z-DDdF 4GR^D qY EXrk02ݲ=֡(ū t*=u-,jkY a "T<\DÏ]`rr^o7Jo p #7w6Kgso*PR\*SGp̀ OFRU?(HT{̋6O tvXCuUP(8&P7~ .OM! ~m296zmX{uUuQĠ!a[/< 4 )r!sf5syGjċ ;EN%XH6yST}\ݖ?=ˎo@,ap]zebB=R %{Xz{^d<Ӭ>"Ս^1l)A ! =@_"-3hdsĔBRpc!Y iq2@?5УDz |)]*cV. ۘG])U`qkm{&OU)=O}bYQoUVDȚ ,@@, ,ԆV!7}Uu?tfA>{ c0':甪!*ExFNAd^xJk*0x@DLɰDJpsdV(0SQE?`<&J8ăJ2YWdA -?Љ,TaN!T] L*Mx/CoG1sL}@!K)S RnX>~)p DZp @X+Z 1 N%CЁ&%4hOiϮu\#nk\ٗ| װkTބ_C2f2*(dv_eHPoj2K.ĪYM!F7q`H_VU~P-gKa 'UKXZ Wl֤Fk.de{-zF.ϖ<)&͗2fҷVy zzjۑ1!A$Ħ\S(BgHqbH,\B8CY P`REP*tnԐA}=Y.?@\2mϪL&%dYkgԬĽ}:Kt`mLB,Y̧E``ι&dF8H&fhZH_{l7-yVVr]bk>2w7$,*P2#SQ&f)~535ȊbR7K ڷJW[[$"EvQ.7bߋ2YH f{/+(? d@ag z,iJB ?:j{>I$TWmjS#Ђ%/a)@| ZK9J8T{XC.T%CLcuIfk۶1: W&1OC!VDXLi Io]YJ|z8x.,t&`fbrYf|`he 뀱Q89IJ; J~zMsU7\Cy@.YjA:3Wm4ַʬ6( `Xn5$#pT9Ar$ a7}·cyz\!K=dII˜Lm[ SM] #PArg, ^?U-W޸[ ;Mۆ)\TUN|Ab[ 0JgB8CUEu4*7jrl8|?[3Z\w\jM֩4ɃcxS\+mLktj0F`=8f:Ȍ8lY,L&&spմ<.S|W;pkzbU2R ur! h " k X9V*b4nRl2hp0>T~mUeYmK".ڣ5= Ѷ$ydRTD3[Fa@{FO`++_&#Qb梌AVe'*SK8RZnv鋘ONBݯ$ g VdmV'afT:mzVBkٷ{VWyTܺ[!*]t+|j\6 lYDHJ` /TxEo`"O2!RH!5c=^=qM V{u&*lqCfCs΀shb}@h{zٽIkAoǕZE_HQ/r:֔ c,2,x*ZEb[Smϗ$ru%V_@mDϞ3z]ꛊ"Sl9**Mt^apمgtbY-pωA&ׄ mCH]ƅ-zƫU^V8uweyZ l=Ϫ ")Wο%K)?ݭ;D~\ x*̽V&WiUʸҊqr]wCE)U1VHf"Tń^<x/< E@J0c1w1WINllOM=;ssǍ7|or~XĊGEHlbC;ٽB@DA"GBП~?DMUZZf-HTPIa.$H܅klbX(u}Yy-ZdðaK?-,݊H`,ubjeO ,̪ GՏ)#kjv^`bCZڀ=eIJVsi`_s-i{5!0txv20-mF3wXR KGBPZdxZ$jwӬDlXGB&Rfk()ݽ}/@/Y۞#M$vݺW{pٸ7vE\d<2,Pf[z>:KoBŋT J w!)#&dߐs ]X )w.څT~Eov,r>4`{_uWf^1yη;a\.IRBiYVDk+եl'JLR#Cu^f%">U8!]AD@KpNPG@QUnVZ+5P UoulR0ӹmsk p܉3(e^Y_%/ͱ^ӗU6ѓ,!I 7n`wѕx0{j^G[.Iy6Sɶw&WRkB(AP>hW9H_ d<#.!0&ȆZn^Ct M (Vagg^m(&1<-&TE2 YLdN:wixH<{ p$r0`6 1$)X|cG1#,n{76ǧBG/z,Quj<Ȼ 02.ڵS,%&L$ vJ?@3FmNQS_]ɦ,Ic`s9<`ݝǧaܷkz@W//.+HX)PH|R gS@Z3ZqA.4KBRA#2 < ,|k]aøNPoΏ?(gIEDVF`1*$,?@^oT214Ư+-Q㸵qU޳Nj DƱ6b$e^0=ۉlO4: qq_BC d-䧡UhPK7i᳹Rq]Sn'hYwʕg1%;s:nͲ5lZ¤ߖQ+QN*XB-O_; ~VE1>/c ,%fgRuۋI/[ClDf N)ˠ! {8 |Y\O.e%Iaظw`aaaߟ:`/A `5 n zsA&0F!oyXg,?KE d0KRNSHeܧI}u{|t;}sT6zW MgwsYƍFZ]K|P-bN$G@$*8^ n98frd8.G7el)ƴhn \l X5ay)Ŋ@y"RQ ݲGՌG/ֱ<u{M5G+o+ o)PBTZwEgПډٶt<^ʦWUA$Gqꥐi^ suZ/R%acxhcc5E;.*{⋨s-&ݭ AFId]Y$,~XE5kX,D\b\'ΆrSNE.k")(\h&d#;9 Xv+8`\ "lR%OeEC l>`O6|8CծKwc ӮVGE<C YScfXe|a0\;mȖM GV:59(aXٺhVx~yCg0"znD̛MHCuW&E,=3};/_ti+8@؀ń A'gAoyW$@AE tJ2:=.3\^2Qp]=O}\E]I}d+ƫQJmoܢA,3PDv] "Ҡ|Ƀ=ȃޘ *( n=Q.oJri[S}6$cH*Bij<:dOQtdP8d.,H[4Ry[yPM[*5\(Y\5t}6O,;6^g\ ?kQDȹ^ t֫C0Tq&Fz\re/+&P="5>5/pcLP!8(qXedA>FFuNUQ@_@`N"Ky_\g 342Ш!%F3 `r1*Wܼ=x_rٰMo( (Ee|uY{P̱`Vŝg4W5E][B2 JwͪIA@(L^?A4Tn–>&:7}X@ͺ'p:>5~S<ЫB2H?7&b^:d]q[%Ѯ?aS-@Zz,#^/ 7P,38x.N-xx_ sr[ ɽXimE41T!b..3/ q@^/#BYdf"(Hb6jegxLQI sȐ#bI +9TMկjJD˃ɘy]CfIZB~.q,N/cv]P*Kj{o Sz$ؼJ+fs2㦼#s}HE34^(U c)!HgB۵!R:IUEHJ>MEƌ eat%hq4#bV*:** }%D@ޕrR!{aa GȩiV'iY,`٣z?Wf%J) /xɏUoM+DS+DObfR1%QIq>t"=Q.))B JmN #/1?~d7+ׯ8KNP;"ۆW1t A+li&-Z2ЬEq'<7sp-w\w7.{φ*!ClBJ}y锁nX(r@ܲ6ţV~PoٻFɵziPW}bNbY QdEل')Mh 4ec*< ex#m?؏{;p#]{BL"j{Rq.W-턱3 \GΩ%5a`x*>ϩT|ܐOhdļXR1 VB׊|z0!A^ Jih sSq#BoL8C!$V;8d٫tSz:PSDzΑZ< AA!j K=j"qj--oL.:wgO]w!`9.RdhUwȘ, ނ5uDͤv[\y~e{3p$w1cH%VSɥb0UNL!51{(@TWfmfa@T\ zYsL9N[O!v9&I/ʣ.F~c0vh\pLUnYH\έv50cɐ6bʑK9ܶONN1~WHEN&S Y/ʲ-;\{-d ]quV^!?q7Dqъ޸>]=WnVT%Q-g 6@9 Zd Va"̫ eȹ1x&d߫uHG|\qv&qNw=jcssvϦno6KάFR-lSTwu_cwp[CZ='_꫾*-܆\省kuUpJZ uw+eݒ պ2 zVg.[,Q5UisKU,s 4]slж̜g)I~+5?ԇjC]FZ3Ʃ 1$E)_Zt]d*Do ͮWi).{sZ#Hf\r!7}ҒUBUZ+WAr9# e0zv+# ׫ F˸ELo`@vTb-n JlxJzJɅq';n+N>H[ǽfas&O2֘c)sh ֪=9AXXNR٭;͕IkVJPf Zɶqzs\u1cǪCR&ܯ8C 鶴0/bXSU2n\c'UBT8tB.h)0HAQ^n{lZU [X`h&h V"Kez V@r00U!%U=/2-qg'u\Y FUSn{@BZ``  xd Z\B_qEɀl3/ x*>|aMѻ[5]RPWn-6VzoAdks*&7gw@uG1¹7߽;\gI:Y_CSPK!dVzS^ Kb"rZiVkz;(Y(=WdE)Oc Û BAo`_mU^ZZ؂ĺɃI4*㪩Bgs,]krՀpȸq Lw/ ʱQ#&-|L#B:$5rN ԋUbzh[Z0 {`g#0u}(*dkdUp73`q Rܸ4'b[8. l&(|B@$b1m&Zm3W4ї-0@(,aA7:N9GuM{!/v&ҷ1'ɄY;?B6rϡs !,YA'Ԃֽ@uqm&s|W:`ɘ-ʳv ђ{::=JFyx РH̍Ns1j9JT1B[Z6S^ھ??w=qgdĕȡ=.KZAX[GJ,0 g^cVԴUj=iv1R*՚`Kzۗ#^,>+F\wJN+.1!bR#h('DuR>mzɷtn:nZ]ccxӅT+ri+6!TNF@)ZnE9a !)Rk!E/2Hh3aض'uzޙ0;OY rݟ}JPZ9d9YM6%q8 w.0+߭~ fq`0{^܍ݬYvÆA6LhڒdwUfs"q2+G䈤T@TwuU5|F%d[&T Xeȏ) ZmDK%3Ir>Sq=C ] )nnDoR+F`Li8W`I͋h٪*`}/|6,0QcB.?>Tϱ/^XvQqX.t4XS2☘_A/N!}ybxYC{gob )cdkMfK@D=*"l}U$XNbxm]~v;5H\?ꋢµz5xKDvms$k̓w|f'[A0t~E78؂q Rԣ<dzU^瞅{Vc4_t/y;]cdAFʑcC/jOoɰ޴ )`{FK&7pC}ZguXЛț-YHu. mx2:s %lsNc(3I$O|HR~h?{ܬݿ:tVi45+p?*V5"ZXU*؂r=WCU i6D-se2ܻ= {J2R[Ғ+3y)tZ0믲}= nU}{@\]JES">d"&Ә<06]7W,g&iM"-x3s)ш6]_' g&v/RLEUhp>:m915A!q+Y QC (>TR|#X@a(pZ=K!5+(D]jk]="w`1'|V\{D|-ZgP *36zMVA1b0 I6ļL1 m0 iZ~6rh/0Ze$&fs%*G*eQ]SUW x$ 0n4yhk"|"ZqQ}N.ʙ#rnQ;.N=ZVu-* j(e}ӗwC UjjҠ[+39X 9Poh@槿h!J ͲӪ^r,HL#jgOdgX7Q9$ZѼRu (UTNpePxZxP"mf^ԲxPxea9yU\6h`n[=E=tyQ?uyh}u"DG^§8KH٥yMǺ7obr=c0Xy 6_˸%'x=?@`n97Iִbmii.Tt=QBhp 'q`X=A\b S5ހi/k;c8 \͵7 76K\&h8B#^Xx O;X\:z~=cU +a¥o/l@_Zftk5k#cH1F]vC3g?E^~w9&$$aB]1ZE7ɨ 1]r-P Vq+p9')@ Nؽm׼J%8wRd*7=r.[v Gu^X3B4ଦ.S Pg;r(HT|4GJ @BԬi l6c3W!7ٽwqݬdkY pg)DJUv5,PJ,+UKL= o ,;@y42'LEYj 0FUXLUPIx{U]ȭ pRsऐYYk؊MrOm8DG<T]vIɓuHr*ԝ7 =u̴C.VT aLOB(D$NpG/ro<+3Xxx<.._die6~< r 8{ #]$\{BH5u;JŚ&n W2%ہo $q 1692ۧim!~{ŋ/W+YCHr [\d_9A mEF#啟3, #UI+⮞a9i1r۷x5zn**e_lr$c ah#Vyh6H9sȏoz_%>:@zڮ6ga1tM $./y;P Z) WCS %8JDZk(!-,sJh(bh/3\'>R,NY)#6$Ꞟ-A*= $}]m#__H;YH&SK_d 6C[drL[i,^#!]G~87n Py <;~pNx2~RB,)( XV%,OdXQAKHcڂWJ'R$bDZإtgM*EuQ-Jk>4oa8r6^ȸ2 lE0Q[ɘ 0b6AXK_‹x_oj=@\ϟC8=}BJ; o~Nd,@&+]0W$Cꈵxr )(SրJդZh4d[P2>d2^T.c1GijUV M }nGkmE>xi:B̙hT9 19 pemd(OV_ ?g!^uQZ 5$ō4,B.!8*̏2#)e:^ZF7£) Te$T‹Ƚ,` *O_سm*GK$FƧXzǨ y Va=Q KfGAx]dSUzMUsK.2aJZ%= r]MR,])s%b.ɔ 0R SĜY\]$ _ 0&d2Rbb!6 ]@Q.7X |r&k!s`6a&qͤߪTrKJ'2ya< R}M}0Jv!AzB!GeL|<@{,k$ЦuV1_zkHAҷ6AV Gd2ֶB]E 4^HYJQ _)E ÊWɕ6:h,]hv_}~d.< c*2xŬ TԍØsH)U" >Id6;0&Gjn 01W=3/ 嫦y@ R FdguNQcmfkK:MN[M B*_7Xȕ0n>̗-~*=z#@n2  3F~ͼ|oIo zHVl=BojD9),e5r p: e@ͳ4zqQ)$%dLb+̰l^HT?O𵵥Aq`GX^> pO2e8ɡb5(g,bvQ1$#F̡uXRB%ڄ-q^R)$h$G:;-°ݗDgp~ ! P= 4Vv/ ( _?t( 3tф H*#aQv %l @[$SE?A+H,&HiMV#%⏨65" m[uoEqѠ:oit&Ͷ"פOi&&vO#@ޱhX2?*c=A8NPvB( 5i>e}#>юAm=>F;hGÎ9#@v;;hGÎ9#@v;+YoqIENDB`hugo-0.92.2/resources/testdata/gohugoio.png000066400000000000000000002202361420147000300207130ustar00rootroot00000000000000PNG  IHDRQKiTXtXML:com.adobe.xmp -CDgAMA asRGBPLTE F~( Gҙ ֞ Ж ԛ ͒٣ ܦ ީ @ {1u+ yˏɌ7LRؠ ptDF~i izLwnaGYx^ .$'@>DӢ :SZd#6ɸ%9E ˳1Ҧ%Σ¹-LTp0CO{L͜%7@ϯPѫ,8:/:(1"l& ˩zNp\cD9%KI, ÚѸǣZbTi5ê-BƉ" )'wtrg@]ٹApPZ{k?fX=~fr>vnHt5{٫ m{IrƠl`߾yDֲݳcjbZ .byYÄ $@W&*m>d, Ȑ vơHDßا2X߿x)sQNWȷu/kϱzvDۮs̚qc5TTSZ;87MƢ=Ի IDATx{lն]NHn U,PD "ˎ4+D.fD@ Ml$@Jz&ww1oc9|յFYOKEקqcGLv c ,6ʱM'M6:is=m6C26<1FكFm¸ fk5{f{d#m i%[{XjC+ֶV.P8PD @X<1a0-4>K(D`8iCI>’B#- $rI-$AXAXAX@KSr)R 񦬭@PCض?q'B8*E4BhDRN*q-3atzB8IKO4 !- C G:_ !a"h B( `,Bx12H0%PD2j-cPs8z"oc) G>HqG30hpfB[ 3:qFcJhP躣Cڔk1l鎲J\` B`p(jD%%Ap4'P!$N%B: *GRBHu0pF]>rVRM̌R !t2uQ;(P +Y14" 2!FV C_&f'!!&:h2ތi '( Y$$A+>a Jh2/0B5ΨEz!!:Jb^ƀX6\)N ܨE qGiZf˸J($G 5Ajt$ ҴBB2LnI*%t)>"TbZ? aD5B'/c1t2m@8GH!B3*p4#JuFqI:Ky!hj_Q(+c/:`kvY0!!IDD MJg8J()۴LPp~™$5:S#7y4%OEmf?nV ?DHj"B< ]!MAZp0ʐ^1a0Ly$tFC!)O8?e!N<\I[B(J膄7JΨNce%C8g-:I[FQgƄ;tyJHt)PS92epdFAF!xcP \˚O<)!I ֆH [#\gGDsk&:he6Sn})ӻ kOYZCp6"8;ҮQa|q^ZkhcZ!!\FBBWnsuz[azGS!UZ!=(!si5(d@8PwZܐЋdž%R'Z! KNp ӹ'| (m(ӯ#~j4ڸde&iT̸07 8+ )O "&ꌺuzFH[y27J["!BnWƺgЮQÃh@a{Lry gy7{̨XwĐF5 =LQݎ5{|%ԕzJ贍("8`s{-O( -L6f!,CRnZ)W;K싶BxS TQόpw1d~;Ղ CF%"F™S Ɇz,J-~^4BCjtAFW'e&ᓶFH t|܉r*a "9.c#+#/W FA;YFۑa!CVo6c'd(6"Jy{vH3؆za2hF-:}z[mu0tB~lXpe[O-3l/:Fss1m3ɍ# 0?1+gy-ӛvY)Ot~HrSB˔42Ag'ġu{ĉg8ms{yCv;oRz&1:+km>Ꮦyʛtde6waaVo!\.3jA,"em';bӝnFcY2aVY!0 NXBL`2Cp1-Fu=L6B222٣eR"_:|XdqGfgS4+"8M7ԷBxnZL$ROՉp(s[LjCl(7lʰmx!|4pH ^j.fG/=gtTJ-$ORMx{GӍnfA}n7aacg2y{zN=L3"S-2rS2+oVOw+7CD;bWV9lftꜩd;"捒‡C^ D)R82 ̄qۍe 01YP '9vH[ݰ&u+ӟ;"L㎵HYD̎ؠC~ ۱(2J3OЦȬQW!|*2M9)/NVwO{FrS|'KNxGLwJy62e MDȔ鹈pp?bVr3/%ʼn%BiEp =ʄi3ϟ;yh cr 5fg :j3Sۘ{wXڹ݆t˔j/o+7UH-= -׌5Sef[&9cH;kFG f#S^ ;֢R|zo3شNe a:&--㍖QDɼdfYX0Qgš^qHZP!41!QTP[B49兺5AO>I'<X[lcGˌiX $61MʑɆz~7/'Y'Ey˟fK6@‚il&Fݮ!ENu"°D8'>b-4-PNfeƥk$7NBH;k61Q4֫Oxe[d}+7iZ'F-wLݞ?PG2Z֜f?7+hNّ5^ Ӈe\&y E[mK1 Rw0b"<0qJh{5BIe#BIU' O NX{ԏ 3-Dq›NS8=;p:MΟnJF #9z Nс3x'[f?v;&Vow83݉?|w_4ROCYFmIE3`ݼcn¤,?k"(nkԛ-be3'T6QmH'#<ʍa'gPV^ YsFQ/"ȌX ;9JȔ- :<:iLg'fBB 댲(7QwSTtN孉?39 ύnsuz~SлMЮQ~ZC`"(9;Жg&yݶ5o@(Ke 2muZ edZ!e*3ey$"}htlv[ER}3g23A}n06 -Xh{F#zJ헉+n85hHȍ\Og09'Ixn n'ZV%Fș$)3¡~rB8'j?&6Zfx>)P :$pv k|TV&huJc-ᓶBxde^Ft;#s-k^f)2wsL[.$,/y;›Po`F顠F©f9̸_O0In UBv;ւ9;RsF>Bg"QvSFpa [!y2^M̸mkΛ8/wHH[LybR,"6!88M v3ǂAŋc+7WVG=U¬Ԩ6ʌX  z[ӱ:}Fm$IcBNS 1([%0)/Z 9$+45Pu.9<3G Gotf P :hv$JT+90V%`z3mtT0Z&<u2s ጵ NHH Ԍp̴i߰Ɍ-,ƍn)›Y&)WBNvSݼNzWGJFgOq> wO$|4_gXE!-\"l-D!\3-Fu4 G2ccL_4}Q,?1AD>(!U|r9lyk 5B}м͖B8G]wqFgDBv!0Ýt Fi~{D=#lרqG9l?Z6X  mNushpNp*h]GP_쟘na$aQO}p_pPԌ>_2X=V!;Xf@ae0c2HvF~ 2> 曱杆pmv}[=YBFSim{-`2R ?-cud^h!eQ%$g6 fC}-򧂆 nb7S9a(FKx^f7pS%dvR)!1M6oOaw17[ V!2P` aFGf$δ>$eH>5c>1;kQoE0AcopTO\I-аD8=A0p:{LXN l)6[S`f{?H8HXmp:GӱO|w/? {IH!3݉閑NLtˬ3 0'e e:}$& z]Ny8\(B!.GƍHv)H|ܗQ^S\!dBB}ILrӝyGԻP'?-#P{eq'hyk@|CL oG6Q# ;~A.7*#…d \pyJ mKwZk1[%'^ CӟgˬQaC⋄4"Zn G,ALFh(\8pAD(pX/浍% m[vW1M:􏟠QCgղVIH趍fu>wLx aX-sCS`2 $aRbHR| Xvm4EZlٿݙ|;uw`[Kksm5u{F0;900=a2߂NEe7%AaS>`MV;AOy`XhλLqb͚bB7 QXPo63mttdCpD<-v2SB0g.4BPCP cDwOv?Db&ϋ9!η0%< ;Slb e؆X̜茌:}dG} !Ɍ:Op[ BpvHd}B2(DχPP8uG>yK ajY^ܮi)?H _gy˗ O 'n>8;r2x8~"&6J?13:Rp Q A (\^ O(Gk-?v,s2-cAƈZ/\IEl1 sDKd?Ar^ :)?-3q(O:Gy2lh ;d- 9dFKQϕ'숵GeBX UjT`XQL%k%ԷmӆX@Tpgm ,!2^b)P e"!0sO0ިƛF9wtR%ftp2C- Aa pSfa5w[j A [d$te fY2Ǡ 站Л6Jtpb*"9dƚCI70YI82ߘCr6/Os2 @tE:8_ D u!-mys/wsa,g`bׂ^^z6${#ihѩ;dp2#րq鑿>BeB!T(d̨*Da{XP*3#%%jng ayIe- C0%WHpY構} M'녞İר 5:TI(;ddTopfՉ'5e&$temnrE1&D1R J8o o*a۶ d,aiü*ȓs-Q%/a $^ s>S  ڼMn?1cͫs0e92A02n'71i \$ApGRxd:mNÝJ a=arS:5 [ Nq{k4 ¡9LԨUYxf4H8:<7)ӱǹYqm:7X%֖WΨporGU~TĄ2cmDt 1Òia f4 BwܐŔ©LvH},$ dޠm-O̲B8 q[֘dBc $zJH (a;/S, _ς|İT$. S\!V^y2r5 (/lneZQq7DN]!Jh2n\:W_Ypҍ* JJ`L o錖XG_`X)#$D,s\zbՆ&ʩۜ?:?t{D=;Zftt;/Pw4U`zFd2 Ǔ-Pp"Bٵ2X庣 /6tH!fŐ[1-E6m=r”댮2 7+)m @J!NL K!uI_ϨE "D!ttPkਰg?~nu[ze\ #FOL&xO$0Xl$!@K*b],czR O:vLx+GKG0'ZNxNCbaxOˠC$f_}GŠQ{nr(3m':9tSpuHHFÈp;ӂGO}"1bMwfƆ%U`UbFY~ڌJHPң2sQ kSa" $'P_ 8,(no@ylH';F*$T2fp4 gmӽ=+508 -cqG"U1+mVF=۠PxedTai ` 2|%v|3vAvI A/"LMXn'Ѓy^ީdh@B8= DŽϽw0Z1-CeVYWeQyaߚ*P m#X^R3u0_x0jcSӕ+pPha r: b>v!*L?1~<,wQBu69| cSȱ#"@]#2k+W!ڬ1$DXx o:X ; t2?u_cZXpb^)] >pvubTظ gONy:=|b3bt˰M!BDAL4"dГf'N FFC%n; %B7*G 33hsMd`65崚+#=lK*/)TRK%p()Jn&Z|g8Ruf_?e#O̞͆'z+ Q [\5U 1!(nG(MaZò aJ4dMbkaD9;vmqϲn E%܎ n'NT:-kx'61:vNX!ĎXg>g;[b ҁ@!"•ZS!%D ATxPƄ:RZV !9Uf[86a!;2oBO"-\HO"Z  aF3\j=&ٯ0xtBH8Mp}VZ%L{ZQ ;I%<_X,[Bئ8 K!X,ln0i&)5wYOAV [!qQB@P[PŸ4矝t\u&'3UWq=32 '{NC; jw3ffeC`50 }T@(0!pIH!( ݆ۇܪM8,â'̯zv Ga0(|szq?<+a` {u-~:|X%N]oe0K(LypM:WUݜ >=ix)bzC f9w$xTG9! .a2Wℰyiw aaP R <Ӡ4Q@h:XV4EWI&}ѻ[޽' V-)D!tx *. u-§!1ZZ oNz:2xH'82H^BPꠠPhg>H%\2~I8u)F•4 wBTpPlThֈ1|&ŰEQ^:2eYsZ(f !Nt>`~}z~_M …ovZ _tSaI[ 2(B[,dJ)D%|@*3h2(|hT3"FɑGG#XE;:klA%˴/j=djDͻzۯ(l{@ oSRx-hL aD{kCYvUSk$MN؏WS2(,YK@G05RoŒ{Cj27EeVFŰ $| *a= Ծ{"(n@!OLB 9d}1`JG lKfk bDR=sC•+ 7R/)VAPx@86 j؂f`eYWB5!t*Zi+5{+J 0" D&\sC8p\UJ8g㰌/> hBF5{Apbr*!!fJG'E'H?KtD8efg#tBUDr)U5W5$S3;%oK PPjgg: :>S /f ^@r|@~uEH)ѩAV+|(gh!KEA{BQ _ΨA j @HH<:t(Aϔ5^DŽY=)~oJWZw4O RA!F!h!fHY-=4AwR5d2j),b{ؙL%I! 2du }}FTj!'1D%H A y&kPŚ@A֌BAJ RtPR&FB@<  bmB ?=deZC#B A%ٵ²⅐dFKVm)8l ,)|0   <̚+|,.F/ƜC{|3 BBh( ]QDPxH H"UB6R` \lL%0R莮Ze R8  - R!Pp)t V@MF}Ҷ%Wl!4/8WtU`X c,3(_& |zBM!"5ApxD0$P "NaC|de ZA1%|oP#ht|pCJJJިQB`qْe]6SGf !|3ZfTAIR`CSõ)S*}A)1aMy !`dFPسcsRsBY 㧏)D NHE%ԞF3:*4:h CuP .d?e pSRhB%B%339;zG.*wK+TK-1;UP˝{p))+:ha 90>N( LAxX |0Dž0\=oQÇ?YxBQ-"h1D%QZ_u|QAcC  DU"(Q+@"Jh8\K*!R&Pɞ&fpСG-[7Ωo^͹+bT r3Ph0d76DOayi!4B:}J" U%.pH#hw3 fBHHNCh@$0 xX>@ ՋPH|N @! ZvD"C@!x@܄ %Ψ2}08~B>*90 %⪮vCصy}w1a7zZ9 0LKayi B1R$e2ހp [B:[3B2Pcx.!Rhgu}pXBG=oT"!D^ŇB2(|=qy:hHlo!(*ėj A 7:*GިZ7ڷo_BPQ d,䰙aJqh ;z5v Wu<9 aYJ 2Z(JW=fpY@uP *;yw^u*s@"& x—^B_p2Ay3tEéR pB*` %LvPQHk/͠aCuo4G $at-sʾw"` hDx?!rxJx0<,/kH ~g)7mI2I=ZQEugCT J= =wx!D/D)o pAyœG&fVV9E-$[N7'D5,e * q衻vlrAaAdv;Q4kw7=_t2!$2!mTZ z/%:UPƄ!(TpO"^ Jb2ʈ`:Bwrb\ ؙ¤77Je|E=)WmLLAxc)p|D}7s;䢾Z!kZ Z@zŹ:r?_đA w"0Y 1J B`/r2`:7QPϹy@%.PQ؉P772 +R(7knЉPR`u|I[H+S^eẄ+B uGz ڢa@bmX,`='4, .EZ ^O첮. ;@@%GX %oUP( ht)@ ?v?x?I1Ga"&ljaW(ZW|9/2CŰw CnLJ{.}K@=b:0x*~D I.qpGO& %a%BH(*A~w9 :M /GX ATX0R33[ſgTBH*S 6XO:L,Fg` wBHPS!aDPYvJQ`zxRx/o,`տQI@(Hƺ |LipHW Wk_KAǂ?aC wXTDk2#.4D!;! ٸ~eMzjNoQٲVECBIAJX!pa\{\gpcbP'*,+\oIDT;(APrաp0BC& W^ Ea0.]x$%!D ~5b(Psjk@aBǛ "(.i`0\). 2K`A߁BeTJ`/ă %:p%b2K i!?A  ugÀBF c6er.宁 E"T 9M21-W%7i}OXZ Km ʚo*&\ Ow }*! "8^zT-]CBˤPF6 C }`R!&5@?گFR:Nq+g <:_3҈3T6f@p5r$pMaR w wX D۶va1 F#T qׂ?ieG^BʛIP \~4N3L̀?TF(tpXs?sw ɤ4hP1@+aW#ReHX a{D\~kRS*ka!;OTmۊsP Z6~ @A Q +R% pZBP0(N-JXѷBSحd)lvPX&Wv+=zxa!!Dt{5gG.K@H0HSh-@,k:vHA%KRrFk^z+J_%BE!TbLJL%RE!(\A;FL),J c ޗ5v:X˜ÌY} >G [)|^VB_]J(_jo>ş@cy/G_׋ዃiJ5̀R)̎V20>x ¢0a*94ȷL)~u\4 Gd@肨?=(0b ͩmeEC`Y/6xW^.) "bz2ԸI%P1P]DžägK&G堐BMa_SkA-y -  `[JwDpoBwETΨTBiZ2. IDATAD9ju"ˤ?J"2"[J&k:$a(}CP%h '('(tp+F p2R4䰘9MPe QL+V<"JBwBM@{rm m{xZ(;q*+Fg/i) w\hp)Pj%B̘pBG Iw :aa !\#[eAJ\ ]PT̋/P댎$=%Zb IܺE~{oRjw+ /D @DZQfvGB8QBA!NɡQ!J𧢞5BN KQoT]&˄CL En B-BP xF\=ZĐpdBH!DQB/)% zEii %LLTffHLBG M\ؽV:Q Y4-P!BJ!OacN-T *,U1X厢 =sfߙJUe-o7?3H+/",[Z(jĮ5.Չ\JhK b5KaD s9a,>Rd "wjf@xF3 !"$5*!÷PQዯJ8p P+a\V W*wtJ쨡hkE?3U?œJ9]B ]I 5!T+@P a+ n?.tFsAM.kj)+ ~6ʠXElW@+J ӈ/CB YVZط異wqH*U^@x~}7!,$A` AhCAX4FfA`(@O\R*醤`"*YHb8oyj!B`XCoO cgDسgFT~m 'vֵ,&trF[L a Q'|Euu9pHD`)Ѳ~# |B\oMBH! Ζi>apd0Vk0F a!͐$] Q&+#!쑀~Baa1Hiʫuoz.-(uC!̂P]J@z&E_/˄b( D@~_}M?*84zQ+@i29*Q\JHBb7ZYҹg0lX!5R폖U$;"a axK&5]xd~4"-+úEJe@xwD nK[,B\رc_u!/|ÓBWm4QL8WuLФdw@uzŵaC,$^S7ڣ`)+VSˮ !l1%\Ψ") )Y(R%PTHx J(·B%-~Cqz _|ťOQv)#Ye~ЬWq @;I&RRQg|A!aE |_:J +ai䃰/P\kk tpO. Q JOTB&s}[VP(F]2;aVD\J+ ; ZXꖹa<1 Ena'-NT鏖ů,5}-aŽ@r+'wh1-u@""eCÙ3?J@X+^m-R(.\~I!AP"c69Me} hZ@ A 0|? z EXkׯO@I_ +S%|AAfD= A ~ j:6*eTbf-!Tj>%3Iam6nRyE˟#u9BT-AoTr(5̡sń:"^|WdHHTPx7J vJ-5"#9zÇRvɉ6Bn a #F$ $,i[F e$?$PY^wT!~}<}Ys]!h9{\T_&\׋?*BPB-hnFyRoVK % uM_'N$\ן+)CKPBw`PC%ZB鏮Щ"ImDBP2>Q( G@w%^UY B~Pv;}vFup* ` EovQɄgtO~t!Lukm.wS9h%*!xtp/`J(=gT(" ~u!AA#^oїP T ?UB4:/KL)(,^ 5/ Tȏ:Q2, w(uiJ PM.;J &!bXV!~8 GO{鈂}+ܨ$APBB%25 K<0xDLuGB?<BY,HNj`Fe-!ȡL6G PB! #)J3 &!2* UjpDPsk)yD sA7O OT&!L1a)ٓœ˙!?KV\MAx#BC ?;j$Z D!LA(🀠g0ƻCzDF&#15$ P?2 {J!G^ ÞA(]&ma{P4K5g֘J)[`j/)(aeZ_Tد %D!%25*(,@!#(Ur@Aٳ, \-̂0250蕉W _==W_Ѓ#B{Y!<$ rz !E)%t8((hWe |CiF•Zʠp ha^%d08gEomna>/ڳcϘ*/1 LAhC0#̈́lBe WI%tbBEIBV Uv4?]?j4̎0iSz" !NPX5钂I͂.n ]'g)]˯\3J0DV]@‚њdLJ)D4C[厲JؐPB*h5vs*}({ a*`P'| vp lY&;4C ?I+A sCؐVK$pQ,0;wn1TJ+͒:ѥvSBTL"RXa7\_Zz"0(!\1!w$g«9GPr)˄g/)~YJ* %x񎙚KonJQrBpR ᎞(L ۖB  { ̆}j/?(%TN)1!Cab`/ANպYJfedHi4I`7j`QvnjgRJZ&ѕr)\+jwl@'awϵӣ²(VL oB, _J,aajOKL Y1!\@[ DU7 G MCx+^VBr4a/p*p#zWjZHt0; ϠoH%ӣi{济1%Qdb|&O-; 1!l_0z?8H1Y kkRG)tmOr?WNZ櫆$T~(aLkoI!|WK*X"*X'yBY)y ӛNWݛ aQ'(%&ӣ?xuM 4fM]vὐPQs)6wGSZ`zgWNLyhrG ̗KIݨP(!,j)45_ Cw4U9Ya?;AњB'|6 vu*#+zP%7h憰P%<M$f[ؘʈGzKj.%!)Wݸtҍ+KUP •05Hr-4˂Mv2pY[[^uCXnٸ'WޯB* Agj9̬22)kre3J渣C%l ^0@!jvfQ-UgQ#01獞H<<)Z ;t0.]&l[*i%d)L*W?zՄ͆ϞPBNJXVkrB|h &V?Tr-P*b_̨~V^7 B8ʼnĠs29vԫ+LB ,IjkYX2=z6wLS ~ɑJH5Hkr)P[%DwTQ8sԈj9᎞`0AVI=P燄A;^IܤS(İ@SMV52a{B!Rg}ý3(bx2Uo0i UvmZCK,O$g^$ %~镊BN6BXxDbdۘx?ޓrŽQ!Jj3($>#LEr/{ j0gcBA''В2Iܔ(EeIQF᧑ T)!&J8 X_Pߚ&A ɠLmL\rvbؘS Sq '?rY"b:H/r=s@$_/ۅ_kr@ Awj:?B*j6AtH/s䙄t'aEp@AQ*LBx{NueF9F&0k|e.TQd٤7OndR3vQ9Z!-K-ZVU2헲X%.Ѯ/)diޢJ8ܘjOA%@w̤ң|4 UT['1 ;!ǦƦx5̳&b>qٗx0']*BԙԨ@c{4B1#w123FtK?tQ  ^Y'>y >KCB;:v̋_P0 0JrY M~X(>Vy@Q`gv=[R+ J wy Q KX6&ِReL[浅¨ Df zAa׫0Hů~*/ |ֽ_.BPx{R PfG?*q⍾e0]'Q<"oLa03鍲(me"BtPb)T1#~.*!Rh3{= %SYwy}%}CPalgR`fYhCf', ݖ 9jBBZ'%,j%vURX?ҰQ g[ _/-{cpJO%JhxB障"HY1!E?&/̝Y޽# %̚!Vw/^ /skdBYY6R\JFoבކ+=)0,?ZbB@ vQ!(- yI4_ W':Z!!ϋ3FvJX͇ЋmEC)L[7PKq/XHa&{T NV2!R=]*5LԿel p0!SVfAX]3BXgOoN%ww(T mL(!\qtj!aX^7׺=GWW`nbxQ?K)]&)+7ot `+‹2'ZaRx Ʉq;y}!$zh:͡QvP <t+%JfCXF ϗV B O/1(2*-jf+aqQ ; V<d \Z.n5 9sOH!\!!]fAXh]TBJT 2B\Y*U UcxB E` <eEܮ VDB{SB3|X@UbFeGA+]t7\;"+]WSzk%dP a(pPJ~뵷j_T`1*_ fA0_HS;p-J8hPS)Oac& l#8+vTBAxC^EG+f _Kpkgeec-:! !"XQ-(w49)+3jޝzxdGef(vhv=w0!WW[:uukfIaeд2GƄ'O/Gm>%-*9s1mN1(*;f> ax2Z MQ+K! <_-;QlWICB JX>̙"wRµĄ {NP?/Tv x XLQ鍂nIת'{֤惰BKPxi@I˸=dSu,?ڴBӷ높@L[3[6A*#1"7.v͂9`̌\)8J%e>BYecáHߧp A>Z tb=2$./Q_}K 5\_[~ABce_iN41#AU$dG[C ԉO p2vs0L%͙'nr IDAT5PGŽ9R :w"Z7j!AB{Diզe0Zה"h&K !eA} L0"McG!*G34]Ū4U v ^@ςP#xL^ !p!z(a~oEE ԐAa2* . AO>yrcM߇ӎv@&(XV» /WFKj&)Z?FAXgx^/(>ucp$ۅ744~A]OGA 8/D%D>·k .Vy>J U\ngEE>  q. .]2-B^e(5 C?Sj~bc %P0\!>?x$:'(C5DpcVH5\"0*?Va!j^ ~_IBbki֚x9h_;W#LnT~!o_ /ճ߁~|֗>d̻ ~JҵjAW !233X dptFú!vI)=ey@!$P!O1\ WXpnчfX([5J->AqxVb(e3JPx%Dg~:(C Iu\_)DK@kU KF `5\j%{"@*BVML }1 F%Z'F =84~f)9?:Ec!`Ӱ32<#z@\CcH!<$>aP ?֞Z) ʇ$QA-`{$9U(+/XT1CxZ ~.G7JA@SN@R؞@hR7= <C0. 8X/Ez ?<\C!ucAMQ ?RR kaAXXV' uG^P1'QR $ > _KC&7p. pw @6*0 ąZ*b+03825[F 7j33aT蹤(Ah`w#8vE}} q\>=EBɢ­Z Q !pZ1d`p=h I̘93NzL&&K!|[+p)P (7zC<AܲQ#qVBpBQq趖@-;þR p7p}gaEEC'ۣ?NZgfB!`Đ PxvP,/l 0dCWF97;*jzw0 F-\ zOqEK(ᦺMA̾}JG"ZF 5_B oN(LxauF!|AAP~]K :| 6mJ7QV'4BMz;~amݭ"J.DU:sF03RIxE 7Ejk)_pҴo#8"Kh&?cXL:ի[= d:Ix .}(ݒD)6 CF1G=Uzok~l5+|#* D@~~)9ܠHD[Zai 4 R٣'Y;wݹ(qJ`70!_mT8QN30Q k.٥І) wAFݷra. iZ?9 qi[ X@pJWk!|vo+^&XB 7i- )7 5gB}xHx(5yzTc}A/AćP aK[oH|W pQ$f?W ǏO>.)AbQ'cD)  wKз[ :[p?(9; w ڼ aQ. ҎJϏ;"9DCBƛAZcaodCsDs?=u:zՈ!z[%ֳr} g?VB(/o vÒ)X (;c0&) R %D _Jw .pF_KCdS J 6X%|CJ-ȟBp)D@`;w&A N(?NèYnb:79a!',:+X](wL(ߴ؀+X]^EcAN *3/i!ACmk[ 9 BXgv w+k%F;x\ABG/rJ /I_:"nR8ܠ J E.`P.GW5O`h= _T7.ذe9T(u- f ad CoRե~:g d,^g~AAӌ`߉`:?Oj?uj\\@>Iܕv(-D!ś6*jR"JG)ߋ;;Ψ/!/\$ UP3(.@ ƃ+?MyKKP@pC;%b8l+5"AaRB؆\>ܤ }QKPHA-[iLwn?G ;&$W~JPxC@$[_{5AkCQPc) " ;vPMnO>w$DdF ;,j D#p}.uR3UZ(0q1\2TR݉i7D8h8=D\JҙDЁ` JTYH5Io"AS`fÞGB(\E 5@A}B ;!qiu S6L^҆@'TD;u$Ϡ'EeR%d횲?v,qǢ=74`wZ(PxZ`5ȡP-]Tq) .%ܼ?c9)s@Y'?Fany߭2jZ N_6]aR .t5|͖A&%v|ǯ{KFT nȥ8}  $צŚ,@ зC3\ >zLRY$UƨO%Ked*oEW_tB_ 5@Pm,h,Sװvv'ue5N~;I1\ #/Š/u 0 uۯ>MsDb?'kCֱ_+!Kjb>@ ?P2bsb SPM>Z<#6 hݻgYei1aK*V#0iOYX.²]Q( wPi*\l@!PS=G(* xPB|{/kߞy`g?oބpf&=eQ@!@D3AXUEoU@ R Ιf7oxgzCA߇^;aO%W^"Ж—!-( | һRAz~|F@& 3 Q()D;RBb[r3QcyˠY3fxj|5< Ap0 xơSg\|;WKIHF`N[N~WuJ o!!hv Bx^܎f/k3E 庈!M'? ƹT -j07uI𥳐% S"p'{ 'jG"((ÈfzGj8N/Z !0,X *+*P5A(-zxiZ A & #C + f6R4tGf,t2LTA2 &D2 $(BS:8`[-EA`Ks ~ip6x;nC:(1V!8?L#;x_ ^,8uܭ[f*zn4L@yf0an8WO@zJטz+  ^ArU?ZMaJ(pK/IC'EvF; yRf(!a*09L><8g#ӑD̬@-]m& [V@(:+t )18 (D%!!8UPQTA1JpDM!*GHqu62h0BJ wl2!EՇP`8~G  18L0BR kA ׊r|2Əʌz5YĠUPn@Z8U DPg08 Fv%Z47dT#U#܋A aRA/~66)`H~d0 ^=@  2:XHQF3 B H pyN7BV*Z㾍{K!anq~8:Κ%1HTg5ef1) ϯfNPeeAs'4JH"Y#&PQ)n n?_udʎG0ew0{7&}'G^;WaH_b P>v)tbA NiحAPgF $FUaUO +%F7(0H*AeF5D KEK6ITlvAy:0 ~e?) &$en ˎ0x!Ő_$PR XBQPBq IDATpDP9>l$ %pQBz"(Bp1H AG*1#(k!-sA*`YoECJ?˖A`PgfN$LgD#5R.. ^"1{Y * t'0OAE/xaPn($y;=Z?!۩DܮS'K4Bwp%_ n#QңaGR#8RZ7AP B"BȋI G *(E':?tnD]Fe9`/7M!2(,< t l;}a /,8;_-&J ir =o %*'(Gij#$ *%ޭeЉ!ԏeHA gDtpdڵJ 7 xl%! Ʋ̌iW9tp~̂XI!̯f^T)H9RQy{$%xTWVeѮ]= y Cn2Fi^^Uz/cQwSJV |$WX"|\ wCge"~Va|Y ZVԊ{uV1 2!9:QڵQ wo 1 |^Q;1(!ffP  7D'kIO&Z2"# GV(v6XI^.n0mLwyiԞۖƆn-  ۈA _:(32(vdpp%\LQJTB !(! ƃRn;)sANr4n8H%*`pVBkk1;#B" ]CB2hG/BN^fjcMv1PQYS3hIOVbgcG{6󇆋^n&P jQ2eƁۧLa ,R4cPJuƕD^}0O2u} yiNeGtC$?h3 !! FpOmUJv߭R2R]`{__Ja('poY#!ңV~` #E*! $Yd$menqmE7#{^ssKKKSSSIxC?onn Oi!R0بG9E26qg1\˄Zwh_ k3j]׽ L_%DQɎx?W:3 brdfBHJHBN^л4XY `:iv1%BB5:QX(dGI EIniqd+(#R8υ05~3%#U@4x7%ൡUD>!"!7Dݎ {w; A RK?"g ʌ5 dP()4 kɌ ^F[P9Yvi^6ܩWq*5Do? dnTSr vsy 1(Pt  PlʄbP7룎j/.6pĐtϔ !eF .umppH qx?MX_^B(e g)4J(BFupO׏HP|AbuӘVjXpuZC-̔5!]mot$Q)]Gb4U]$]?2!o _P?L<arl,"Sғ(nL'X14j EB]72HFT ƌpP}{%j!6)G~ˤ (_#DuZƄA (Hb(lTA+2ޮқ H!!cEiSw$YŅP'T K24sT ƥ0REE)@`;4Gx`@p5]E% AIa}_qf6 P Kt~B4t~9 Bp?'/ "ŪF(‘uP Bohp7!1O947"J!+"s1kW .3*M (|ݒzta),JM ,PDG /Ka2ruxgB ^eʨ*'c7X *Mdfڽ@-*'ݨBBH)$?Y&ݨcF됐)aSBE!1  QjsIU MvHhw;|T5p0v^f. [ cF:PD2>g9tGcf%p{b#)CoL70dIPe+('sPw^wy-| F{ QɌKTosB3@!22$#3j%$ R Q. N iͺ{[#Q& :ȦӘC6zEKjE݌s<&s0!3I n+S+5ËzGcax5^h$7zUzx_2WxBC ȼofn~I}A%Trp ߻EKGџagvyKQft` \材Hh"pjXIh /zVXͺgȮ%F]!։O } yEAJi8%9*,prWZw,B~3'KnӶyo4PLxBÜ[L?we3 "dGLaI@yQ&ڋAu;vǏrq!!Jk%^@0\ņ̵eͤ! .F8te6RXOZJ#K fnߓQBaCEYܶdR.['BG܍؏L#.?~ Չ:!@ BA2PN*ԯJxn6 `VZI8U2zҨưjZ7 H50RX̛>;=WHteD ÓF0RH+x((18fMl2eX(&M#rҨǃi)d]"!2 7)0.BeIe`^t5  hǭ76PC9[&[$ȗta+bڞ4 !\"ؔNIеI5CwEJ"“AՐC{ڛ^wx>2_{_y'ߊڝ۬o{1˨!(^ҋN6J@A. Գ[  F~Dhh+a%U ]E;(̴Qv FҜ.D D}劌W hyEl9W "4\~aT *d4(#. H%d'l[z !H:xCOh $=B.brЯv2ByרFhz'7ʤWBBfFm7l#BkXDPF"sc5j =#+ r'!b;N%[̌v'WXK&OK9ȓ&`nHވ:~r z0 p‰ $U%곓QӶyFF.Etp(^Do%-Gp^2jcF;bDhm"h,CfT'xB24` ߏEaj;K #p\EA9P)H{ј^ڎz{.eA 6Rj45@s_di2AO2Vl\h ww9pA)q#yup%z!B8Se>ȮnOȤP*!p|Y*3j0c!ˌ1B8aV9 $E0`52Rp !H8 -0`7\# KD}0aÂ<^t`.#\8^KeHЌQXnC~i==L,pJo%RGI q1<q2eyGU^U1RA1]vV[c@,9^0X5^/PdPr:8g1E a8q\;q e+(pH_&11,¤ [EZ@cxablb^w㶯TMJ ⳌS(DTJ%8~t;bMN2ǍNenC@2u*,"Jq!0ja ixzN%xgBq#U5J znERI";bXh /̎a\ -K%j6E!tP,J XPHB($$pc`8'?rcgҴ_p-1l]Z -*+1<(Eh|BEH!Bý `pp*bp*Q8JȀQmNWY3J27E3$G0%D!\(LAT"(9Cљ'y#Ad |!-,dNB!tdF={ F0 YҤcBf{:L {ZRۑgwE`o)r!(0KnοwoDPT7PoKΠQ=A3t̨=gui-ANDhe,3 # ;'K W VI s &rxe{ H %%ړFZJ;=3XR>M"hV:hP&D_,@Dgj!2H %z#.P儵=D^#8t@nRPpH NTg V ZeBA 8o fC5X{ 3AS0B6o BK fkߪPWŒnކ].2H |u+W3>-_p9@f.E 35 :PdP8SÆI5_fɡdigq :Q#hbP8Qob)_oxA KW] BxB^N ϸÆ;u0A܋觓԰]Ahaڨ+{P}%J~FwE4 hB`P#D'_ kEޑ@ɡO? p\Nf2yQ>Ѣa=H _8zk4^w(sk)'A b&PA8v*NG򵼓͜QժjBIw;bp[cZPf5k0 5 VUT l"š@pSXGc8oxZBP(ބ~CsGD:Qw=+<~ >1Cb˜~!4ř=iL CzC#4mȊ1xJ=BzIyt! |A}~@p!;vPI 64"6@ 7 JH!AǢ%Ǔ9OI )4BC`]骤H)G"xs-CPĆw0x 3I’^|qV1LoiK.TZE-+ ܋VT"⥝d\|H% H jwQAE࣏"z3Z"(ɡp| >;6p($[BVKV6 7!CA 2)D1R8s/lirDqoQE1,L _,i24iP(5Ax"lS4Ad0T (0XCCO \f.4 > tK/V *od@TBhڎ4fp͂A$&F kjG ?CUYdcAx %D  ǠA(=ВJ @v%7!Ϡ1‰Fyɡ.PsE’n8a) ZA (`] $o!N( ɠ  ,PbO!O*7Bz.|><|!U o/^^ͫChH4Z7*7*DV=6蠖ABP!ppUwaI i~f2(bADCjxw &BeЮ !ðClo߸W/P'.zP53x4͠xa0dP_1XLDPB t h;<31H _$\ 'zF, ަex:Ű` SуbRoG?$X,!g.b10 ,jͼÛP10TPϺu:,1pёBXO:4|r?dpAPF ;A a5cnP!F!H nHJ?ZC ]T3[`X5 )/HBh Ԝ.\)669n޼YR/Aᚍ #55 RBqfP4HN{ a04dT0OaPAdJ%lq^0(ɧ:uw·Og0 T =ς?E#X&aY]ڑdžp ptr 2ǀc28,T g9[>Q2B< DD_UNtQ`RbZ> >=Vb8I6J 5"(F`P!XI gS.;' CєXApЫQn0#E } /S14f2),*'(X(8% k?MR(Z?$p+8o _^0A1X úڕ]ٓ=#/ %Fku O()TZ5IP(ÍTBD l4^2l@dC0&Ǔ ذ0 T 3I <XKZ RXҠ?+(BO KAc*}ջu|-B%`c6֕](?#Bx1*I| \dDp"gSP OCsƀ>ܼYJfeHFPi:A ) NU8Ċ{>!,%vuRFT3HBCh(ӧ_:RX,`OJ(MZxz׻8vmE:Cx2:( 3p`[J!4J !?!ehE1|f!(-|1Ft]_#e0CG Cs6K<589tDB~HbB |8O{y&t"SM 3Ch>_‹3Plٙ]ږw)  0F [AljrXV=i1K~MB($ |8T2`#?Ɠؐ0RhQhşP9{1'S(J Q0Bp1ͩ ~lh^ }%b="s!Qᰩ {);wIwB5JX22B] :E O*03/g!  AAzX71Q zňy&Yb":lB2)`аzڔFN?}fEOtBԨ ~ OuU i@@D{ e>a--ܥ>IRJ C r: wuږqOj? !PF;{ԄY. {Rl8B") f`2vh8@a~Q ;tQDtHr(OP !)aA@wDwaKZPR᡼""( Q!8)KxQ(W%Cw}ϼ dq8Y H"n0h9ETvg1 A% "[jA {MғSBh(8M-nYBPD[Z4B',L7C!%;w~noުP/F n!HNtƛoV ] ^t8Q*ČQU !2T=4 5DUA(T:{Ԫue0W b124I 2$.V43ɞ:mI"r 9'֣LŁy])Tc!^r SI }j|`JƴPʐ/[g#4 .]$a'juu:G(O גg,W#dJHe _JěB>040 ul(CC[6>5Rn V9Nڀ`ab܉2eJOCCuW i״b)`ja'.Δ)Dž" @ +g@RE AnEɉ !Q h24^ 1H"H=N4/LiHda%&JEh^ln7"ADpK-0)0IR M񺩑` ߘ/Ο8d&}3B84ljj1B5%Z]ne T^DB 0_(Q+8i Q }Aq<RMYbI*1S*(uP B2- !4ܢ(4Rq 2p:LD=j{:&NyȬb׾t| Y p5njVhV#3 *#:pRftBcrMΓ'J /+4l$T%ʠ MhNel4Ieb8R QcG %`; +p8m:E]?5O7 |70IO~0Fy}? }>}4 6Yzho9XZx (ᮭ[ADO5T UdGWXc%dndNԪ Z!`΄9ق* e@( u3-ԣƛdGyM ڿ'ީ),\ Ђp`g_h}Dd%M]'sDSSInaT'g+ D O"+GBhň`luFb&E-DjʊAljv@^4{R+s] BDo8:,qe:GZNBz-l}8 M&ϴ>í<;Bż, )AaG}48)o7:tK{Q:+_~UX&-Gf+B(3 Rd9QBp:lTdZBR hEOzLT (qwfoH  :X-f(bpcQs0Yd)(B(dOK#/*V Ē0ƚQQlpEY( ʴPw ♡P&eu ( 8*ģϟgfcm}^A,SJsp?3%D]0eI%Unt0 TENoxRIa@ LF/z;A^oRpk>-1ˆ @`HJ}= 'aRY+(~JE̐Zí\DcV1ZE[-s >`B .Wh :*(03-:b-ϜYDSKYTR&X ޓ`KcQ*ʰuq C+Y0ZvBv3)GDB¤LOFܻw/ފľ'I((,BHb4x־gBHj%BXY92"\Ž(a.LxJXNJux~)ϊ= ]د:_/ͱڽFI lC!$+ROAy\W%(xQOdQp b|Y5T)sgT?k q3g}zPPٹY ̶)S;?\4VB*D2?U!NBh2BBRŠ4% };ZW~~d# ɐj7&B&<ۙ+uY[9Pۿ4\ ёRU0SEΑT &=C!6*?yVdg9BRt)1w7Oj Óa(;sd`oJy!kjH{uEBk\2]de=KLH\4,++V+ I! <̦r gBjΧpļ9[@ C]T:ZBTfdY֏UZZ!(.!0 A><7yH9Jw-l–tMTўF!"DGS3](!@XP]]Ўn\3D)I++x ,NBh2 VoߏϼΙ{-JvpweCt|hO2(̨q4a0|Pq}1a]D %Pɤ7rJs^wZ8&,uR7Ѩ?ѡ)5Ht0BOcZрBx;AFfd>*",yU)?x ^*6=Rv-b};Aп1EF~4\B!j JaO@FGW ':Z]h.>/KbE!QDo eR !ISķHbFDŽ+W¡0ƄSmZAa'nMy}CWGm )\j:Aa aOWJ8{\PF{ Pxa& **Nh3RĘP: TNb#oPKj+PbI!3,Ֆ-:)#h[L0 ڍ U1XTto!C= AtїiV'!/Rst6q ώ^' žP)${^ub 4EbGi H)tظWo+o !{^JL.23ed%J ynv$ ]%D7W=CBjb$-t0YhЏz;A/swQV2> @ÃMi-zLP I I3ZW'8ʍQńuJ}B3Ie;ƃBo R ,5 &f +L~bj:,%$Ŕ0)"<A =%z,/:]BG |An BZ߸1(xc;߸YƓPb}W4Mfk:O~YV!!%tRNAEEu:a]EhlIbCh1,t(&fO>Õ0Y OsI/mJ8sÿ~#et();ɹ *} tg8E{r^׼K@}[:_;R}qÁ5#=-G\ PSWVeaj"`CYv ܨaU ( DBuB;S3 BɟV{`WT% ҎL޹'Rx//ҽ|,i;.3!% ~ɖ“6X'B!O{/RP=of|W 1k=++vx>gc~jhPLXTE@!dCԄ*FNuvJ3VS< hRVd 75!| D!5H9Zro9;jɹ%NeٺFR“q(jQL;CfaU\ ٓtpBFI T(fQºXbFnMgrVćnM(Ȇ pAnFmx2F Tů]BM6&!cQK7 tT}_7&snLaFhw^px8O! QL( 4\P@QU.Ca!s!) ){߉Q !KRƽ-@Lq|gh\n›|D%d *7`E JS)#2Wœ5!#*! J0&ݹoIeUB!Lۨ|T@S*LB6& 7 {8O7۷3rB$?VT$)#9$y<B}2Ąn[c Z _Qy.\8;j8Y5嗁USBuTb&ᑌ=<Ω3A3@"Ztp㖴5o ̒9w3IW'd\iƓ_1,?33…xx.NBd/D?* AbQ!&*a]ꭰ5{(lR|8;+a+- 4ǷJH$nITo fТ0~)BmIvNlEs̨9؏fwZ%P(.Z^j&A&f,ei!d/j%)1\ aS"Т0B1'86ZӔ0SvTݞ(sfi1 “`P HQ6?_6*d&ܰ=Ҽ,՞{!7Oaq-x]ݙ+*OAö0LO?Nɐn5ntH%s<5gML*a]Bnj/WBy, %=)ض{AK2bB6 + >'R{B~Op(p&~;3hC (ܦJ ,ͣE; r5vwb .?%S 4+\ IDAT)pV!=bӨղ&h2<3غ}B6_]Pqh+p3)WXEfS FBu"^jl~FӕnK 5U#oL0vʷF<@--=PP(iTq(?<pE( w *d&݂ Ia !`DCiǕMTB5cPYSU CJ_eG U*oK:UYoʗ ![%j-Yn7&0p5}V{SBVOsv(ܧz /ieYH(w*_ձǾpGKm/‹3ћAaH!C033_aB SPk2aa((+av-D3a5n-T['f<% odFw&1 PBlo&w.!Fss33 Q,P*Iڻgd@E oa ʌ;]% 68,$lJD?z)!xQJ !%T ʜ 0lrbFfG+2Ąeuhߤ]PWJ rY.ضf2t'w;3;Q#.* 㐴׻P/l: }5'?>}yYC:PVfnuh|4?zVBPJC^:EƄgJXf<V0]v%406֡DҲp:nt-lvk0Ǚ)o;|>32AXX1aS A^8(ѿŅ(dgh5b'Sn{eFݕ*X曗ԏ7: MfBW !CnJ>Ы>lZLy f.p>1&Ċ&㩻>J⽣|~.!CvTꥤs hɻGxS^h1\忬C!Sjx2eELdE B5f/ ՜hgx ;za0 )!dntRQYxĴLjh{;Ѻ: !^&LFҕ4SiB}w:\$c7)L@XR_h_yY)ts3q)nDOh:p}33CdnjCfʎrLp`ʘj̖63\gCX؞B*QЇ۬ߧMuB̅_p[F,mrpF@CBXcvcf& cKڃZ"853*PѥKu~ Sڗ&%w,v4qkzoo.;F"YTh!(̥^Bp89*GL DuWPW4!MJxGQ-R(9/sZ>GS!bL3$SF[LJ } 3*a]Y?uJXʖh.aN t\2T0Զ$ܨg!VavI'vz ).I9f4 EH SB)Nj4.]2iee ݅0uuu%|V®3 dp#c-i:ao73 {0:h{w@#q -njǛvR:f4Z |//Q) ;M1;juس ;C$ftdX߶ f'./R F̘֙ou Oe0hG3Zˌ&!4J͠ubkVLh]ϕ'plS`+ oߞpw] %flfv̔jG!ax9,/?$?ԤZ Q8pgqI铼?LRPJ /2iѬHKxd;Z6`@ڪkРDqb¼n>Op:_ɛ{Yh;! w8t>«CmV U(0|I*E,;^Ϯ~=׏ y^J#cBoLh.zKM"H g;f=gvL5~yДbvC$h($ġ}5wCpzCb=\aoފƴp`;񗒣IAaD m3 aPMpPRfmv^fGs9gtLU ܥFԘ0aEƎs~Ί'7$޶hj(:~уr>Zkv:DN||ߛau\.<}EP[e VB7*!JhzGۖ$T/OuBO֑_+y3v;;Sb})nM^ro$wKqkҧDIW/~yG ̚/-Y[:ZY9-X0󌙺1:&,#%t |ˎẑuB6W#t뚴:& )ad[tksG^OLޮZ*1x|ɯ|NUpfF,6?0Px4emIJahikrZ]l!L3e[go BM8P'n'b}JffBa^>oat䠧2|37'!\Ln Ł2dbOT^&-=!OUvtݺlzxKI̸R #(8v:SRwQ𞚄9{RϨI;mw๣;*iD(lnȰv4<3Teң7YJ8q+!g9.i^Ƅo1!/„Z s*CEcfvSEmy2zGDNSEbŒ`w^{İ6- 3(1W Gր%2.;VZKR&fT>ƌ/ul aJKmR2F,-x+Զ +gy;܍.ޫ2k ~f71yf[x[RA7WpBV<&\%&,˲7͒J7JhRV0mXEKRf$)G+2ƔQ(pV[yQEI|,a 0Wg[Tayao VJPMΞ-`?nu uBHczhmqb¢ H{, l2,b>% Bx-ZLl)&5!Sph󇗄k5Z ly2k;Kt?Cʣh SBXo1--0;*7Ƞ-n\AOpmV ?2!j%oтpvr>)CXm͸&Xצܠ=lՎ&t7/!%$G.t!-90M өn K3>(ySOs EGQšߜ?(Aowp_yT0 .HaӫeM S&'0ݍ]&Qʋ?zUFK gń!),JZ=T%|]ܘj &$tn6[QLḐA(a4۝1^;s8g|޽xܽGԿVӁ RB23@V(!\QcYe VhqZ }LW{ם cG%$+ MZF,QB~) Rkaljq6YhBy~44{%t_]W,0!#_ +7(EvffҥcA)̜ˮ )1x:!ы_ec)!eҜ}M?6p5J8B'Wف1EeQ(vgz NUi|-b%·Tc}^<7JᏜV|m[3Ao3 !$ +! )f%[;Đ?NYo+aQBGۮ@!,G?'9v.neb p%oU-\/l)_GOue&4 r]+)vT?<;!CJG0\W!4 Z>^Kw Lp}0ƣ,K PBdLəM_(eG/WG ++ݮ5$B");JĘ\w:fւuk3@Y =.jfRi{ƌA}; ##*:u VQD@ |hAu[OԊ|X8|pkkk'qG_ta[.a܍& Q ˩.'i!{킰M\cJFNE cP8_J q+_B׏Ҟ^iG+;^|7ʋL kx !`$ll/=TS!a`LxC^QBo^ǂVOvBXZ-!zpE<$]k:JB9d7 {?T3XV(5H%,'fcºĶ5;C*İUµȡCpй3?>ȇeaـ,W{mg06&=*BߍJ â%M~^S3sX~|p!lX-7JeztOA!IR@v Dik)1aNr"ך a]gw~ylٳ_ yD5;gU't稭Dl[ o8) 7F s/sO!pOЍf\PɑT?/fzXM mT3NQh!lyӣCBBQJI /[%fƒbǎ*%L,ZӛBE%JɎ]aHsAZIh!TKB$6vDž(nS=dm[j# ?2{pt7˜g:fl!Sk 0B@QrJL.EWbP(SX~U Ąy "XB6% )Tydw"[`d]`F>QҖ* i}6)< :2xZ> 3ಥT`j1,&>?։\nW~jb  o (xmhr1eB SZ3"oPt93) oHpvc˷YT n{H B{z30uP08GDh!t&9P&KO#Gk7l!B֘V%nt|* !7#)|Vҕ κdަ=_b ~Xr1_jZD1ĆҜ0׍pڜ IDATRz0I =l9߿%>X#7 .xO^ |jexom= ?pkk1oC=Fhf=9Wψ4 #ZJ| 0bm#j( o(l NsOjX0םq\鏸 dp B& CG啧}OKsn iWzB5_f@33ҏRz0\ RcK 9P`Ѻ2g'ZE))jdvm-!Xp}u5Rbw*_kXBꫠ@pjW]H("xS΃5#0*hG3=htlO{|=X)DAG}~pA3NDCFBjޗa&w&Gx!!g̟Ϥp>(!ҕDaP ˱\hJd:{D$dp튵nh#p/KjeK^3S`{ Y5 %bAO?Ɠ%}ꞎRÀ "d سC7}_7ɜ B,S ;J5 GۃZeii.J.1c~pRW2 ?@H)ӨD%1!\[+E M3>÷Ű3օҜ=|ͭ R08hI`E5]-9-zcz5Xҷ;J (U%92{ uw˜Do GB6F ͩۚN9D>b&'W /.P1cB|P `GYڞPX<,1=Sg(2ȝhp #aZ|Aq^Tbx^ړm*3XZ%Dgo 3 )'_7mza{Ή>Ŝh3a'uBüݛm~ o eq}\/0P]/x7(!ra+|tǏ=z&[Ѿ}GMFd erԻ?AB(!, J #E HIa9ဤh%ZWF U-'JO-1$QذA6'E1 I͒8D3 Ϊ+ZS)I3(^ ۨ~YOwbx÷~  )^6Fм[s{~-Gng17N%O0 j(֣ y]y9kIH#Xj̏}ULh|AqO˃TP0xXW`)KWհ oUp01hj֋0;Qǟ;ANW윅AOۺ^ ZkaHAN>jS_ju7,:36]!1a,9|)*&$!-br) t8C_+xXYbZc# 0ҷW 'Zʣ&"i2;b;]rی?x/25 )$5D1 T e+Vh+OCZ`o-ذA> 6.x*'_K:z 8F k@QCAp|KNI &}"NK)W4o]Xeዧ1a#*}*Sv >\DM}|*AkqL6]kloe$$$)bB!Fx rk'4,r1lPB A wxG?W` Ws +viI͌Q \ZpiP M|cCq4484{F-]pD 0WB}e㟫@h&pwԘ- 51 BɏLYxC-E  ~j%N.dًT޻'QmßW|30 S v 9j޻I Jj6!:rR&GXO./b$ TIeːFl"\ W] La> Jo{ wl4hBȚL!IBpnFTJF 1tr9@ϷBA M ߔ.e qE8p++C #1 go;%8Om^t눴!K%+1l!:F+l=g'`h>!W?ѳf ϳ;F>7j B%Q%~4)ss7E'X(/MN W'í[-* = )0+*$>XI2 礑]mɄ { 8FB@iŠ])#Jg14rF` "V}S<+~ԇ D(Z"DaQM ql9G7C3>}= 2L@&*j."Be8냁>ۖ/HST#rH>z0d ɄAk8D B* ?=c "{' _`?ο(1gЛ&k~y@U$F@Ƒ(L<ƍ2c CaPUhI* 9ZWdX"yIGn" Gt*٨{A؋L_&& A`NH;/~%BdCo}JwM&/=0M#AYa91*AS F!`JESxbM}o hfNkK֙5GU.:FrF**]Dqc!C>BHjAqል!"F AIG Wj ĕ?# B1:"$^pjAۄ7QyFMA1X"+Ya#6`H$ CgԒEo$XtoǾ}s私yۈ`f7L8"&b7C~4i̟^?FDDŃuG @ 0\x]]d pNKş ob-FA(" ?He(RA 8 eY" ^1 Za!DP2QXo <]9:Ѡ&7- A2x*@LB͸ᯐ_`1%ry<~T|pc3BUFp1Z(!舐QƐ 89" \qj%sh(&P.".G"wI'M>)(?7Ʃ(ބb&Ճ`A`lbaP6PP-w'JpW? ŒthC d/#0X;xGn*R(npDQB՘q=NX" A* ] 9#e`xρ/Y*FPH@}odid8," Ż@ ո @n`15H&\iPLxAb=8:J 󃃬B`MCšAp8v&_Ah*G'ϼ+}"'vGǠ$K# [PꆖK(CsBα~Bqh#1&DJ@>:7əB7!5~I:_:M=bM$2!$ ,p\|p;߾(ͲdX J9"B ShpAARl0"Pbl z ` я!C{b|ҋmm@b7:_Y %913zo0 7B>f Lll (p6AGCᤪ ùI$q#!H/2 "?< \#?f3 ahH\".\TH"{q@@D8< j4~Med5xE( j4dGyp!F 80@!мH8u\&5F!MOCUBa6;*y\dbMF&KtU}"d]tS17iՄ*E lBZ A-G(EW" wq Zq\TK{ZV}P( / o[Fقv( \ jh ^w1.ż/~KK,8ڳ{wV{0Z: Hg ܙyW"X2(|})0$ r8I*Hah8wYQxY 9gfFn33p&\T(= x,׉2^|,SHr*5a#/p6 *i:D w66OүA'\4+KKK+C= uB8oHK?sio 3 փ;3#ki@?tDK bf꭫ "p|M.O)...i5wWU) WHʀ0V,/F /YF:dFރ]. ., 6,|em{cӋ)vi8 `էU-׸?gQSp[ ܙhMc8v)Ab(! 2cUWgpbp%ńH!nC _Fަ GV4qQB= AAT|!аA7`p܍vG1B ?ʮBb aab_kki(^(*g &!ol\}dFه.ݶ /㾬0^!x-AS L!8.\ .[\rXu\(2(A^O@. o_aZ ji-a)XBpanX x˂ሒ`;ԯ=ż0Q5`D|_0Ҧ=L#fWDxy2!PxMIi* iNэ$v͵) ЃxᏫ 3tg g\" RUbPTjA 2|ZȟFж`x7!xV#RtaP@DɆH]!.SDNG`Q`СĘtl#~0.P>|㓇 ԟ Lt6&$ʠ^G Ń1~-[i95!bMh%˗vY Ze9Ʉ{WUከP/ e;.ঊP# j` A+a73. 6D"+ r]9,)A`v ޹7mz/Ŵ&U" tk p+5f؄oi` 9VQa7,"Ն6䔔Uȥ!3KՄN 'DѠpX!12l b,5!Bx\P#1JttԈD`8[d" -1!ݻ#m[ $=d ګ/W3П1xf Xl@[f3" i :iaM *]n\dخ1tQhpFMhjB%beBH ( /( : *jMŅZXrMț%KXz<)A"";}( Fc4`N 5 MZg֟(BLDu7Q&Ԡ`"ά(a*"d¶9C Sh0dqNx (Ό j0D *5؃H9Fp%l@8"/X T8d DDpjj !U)$p7 M0bb]1p>Gz &3臐 Amk>ݶ9?sN!h̄bGF4=:g9RUH&$ Ba7e^_o,Y"p0pJGń&D Ʌlšhq[f& FJ cyqoax.@pxHdKAgKvM9($Їa|~dd}KBapӏ>궍9:o \`h`HHɖbQIDATuMa%¾>( CF " ۯ"x#gɅ*"r.ZE"<(DM8P*G  )bq~g  A~M"BP8 . zSS%% %l?p-}$pXT%9`°n^{lRmkaE^3Z;&!!d^̸'g [V) '[ A Js)lsL؎DxlQ(Yg UT0"H+BoUi#@r?,C. CIR %0d& /NHT lI<ħ%݊ii Esg0B^/p 3+ ~m/C1Eܡ5. ,TF-#Bu(C?B ې9"0lgvۄkin HĢAVABc˄Z_6kHue N9Ѓb&diq!nX"% ]%'(uX(FDF z! 4G}ɚs~ /I兇zF) ÌQe7; *W >UBL\jP!8!`ٳe@aij$ !7v"6E!WķX#&SF)G0kӎ(ZB_}?9gHz^_3zyLh)Ë 0^KBslD2d iw[wE{bY*HC2a4(}* A@0qDU~!*Bdia`",- {Mx!z\S N֔ܧ<"qS4_.ZOB4Q|>N`*n~__&{je0qaB'җ> E!YL(3.иr!RA_ фYIFk@``xddAah G\"~m~A/ohba9%HL&Ѓ 2i&`Zd ):ɿ S+[#]y'`WD|( re^.G}}}`J8_} 3oB:(9}W1^%8"T \vw L!v\Ā ă_OsEH((8z #~d#a?cАLҹj̔L)qHh"DEzưu UىѭxE<u04@?KcbO ,toy!v49z-R-I=i@t>ʞd#4f$/ZB/s- qT p%!"h/[\N* eBaꭒ6aM $Ph°AtTp"B d"rwȂġ 8a1!$dolBهÝ-Ý P6X٩),Gb')̆F}slOt0/e2)%ɩC*|Q"PF!wfoD_%;ex@  m/]MM8k10\|t\W (sWs CDCD!ldpU'xTYtE8QΝQPD!2 jlSѦzV!n: bbTűD`5{Qlɦ#̠DŽ̫oլ)ssg](Q w(ČPB*ic:~oטF"FL=h0gy](Uu@a]Oc63BaQK!y0Sa%BC@o X>Q,/5 BD&O4qMX___Q@ˍbVܙ'>S4ϒ`a*=r_i2R;贈e 3^2!e(PLs: ݰvj6 /Z8hWh,X REH^P\DT2 ChUG fYa"2aU=X& :@4aqNC;};U+̡,[A/Ck^"Ck>Jœ2"t5pL5a/.!P{i1au'Sx :; OiلA!=&$ 9% ɅbB`jT R6␘"f`Z",M)T"U * rWۊo-ueCf )UcBnp{vNeWL+  O l((&<0ۮ5.}ݖmT*-QCG!AmL(bX4e^W.dz2T@zCZZ@m d˜+ %87ǚ10veOkY-]G_%?p:*e!&Ҁ"ʜd(_ufB"Pj!u)X]DH$nV ۶8%g0]l'iLx'a/6ET}rͅ ҄Hb1CPeFBKo_Z w:LSH&RH}&De>2kq;&u>B",LG3&*BfP)63iCԷ˨В!zAJEa6 @Q TR2}%!F01dė<}ɋ_Do9zoBR+Z BXH *s_`+et*zOrQ u6V)E!)p>ʩ%B96MhcX#° #$"D R JG1-*Z-\>rq`ad7@? aT_>s Dw'O~|O}G|?-z!DbgW /QYL9}u|;pj RxRǙBBPehBPmT #fڃk1 O155a1eV.Q,h@"tѠ[5}դ L*o]#b#8LIs`QxHP @ٗy<-?zۚ7%F bKƄ~1!an!קMH JːlMD(0(Bo6zeM\5RE(|]'|K}d1a͡"P(@_E* H`b^ZO L՗qk⋷Ses~mᡠ LsָB CA5&E䖄ΐ - Ձ#Z3)L0>NÄkK|_~Z2&FC CCB&1>;J"t(fH+rNJ>~gUEEȡLHEa-eڃvs4XZmƒteBas2aM sȹ !#R s0n BE=tId(nNnn}3Ӹ k.kky8 6 q!!3(xR?m{PSJF@dI[Y̠p?BIF912s[_UaT6 V'rfX(=fk;[T܎y(HD asVQ9FaΟ%D #]{ "|yBKƄVMfBpZ 04%Q9q焪9zce1^xVUUM)<䦣P1/!%'j$8A"|8,]8,NIi˸ĨZ*^kj2ŠB2`saa~>˹5d6GA&\g_jg^v<`3hЅTN ̔0j#, 9 ("<]J 6uVo4<$<\ Mhy͒5JĠE`ިC`S}D2j'AnT4oo8$Y$'fµ/y:}3B($> 3ܒ*tR̰ /p^.󮨐dծit=X\70ŤSyS`ї0OÖ́kNsǘh([U:J3ؗy`WL5!ks 2--3VFx}+gI>V\k؂_ڮ:{T@ﵟQݺޟ+17:.=Ҹ$ \r%Ru_u14j̏}_u\ԯd'=ԟG_}6??= 1G;GּFf=}Mݺ'6oK]/&75C׼OQ/ 62lc =x%eensϫCϝ5{Xî[k~9#pNfa [zИ am}pul'`'yVgb-W'lkֳ|]>\#7E˦OՐ֙^:'{Y4kdpqLOZ^ kD|}x lGO,/;"^\ {5%4"w* GQ%Vڔ''9h0{Q_/WWjo 9~'P4OԿF=R3(C/-"!x<'0NUTWt8]5f'Xq^Iq[ /3q'1+7iqKQ@ݲW?IBvxq'Ƅz8e@,AJ?gE-\fȃWj/E?{)V:ڤ-!6XJ&:"_=?" !OxٜD.NsQV_8ko$5.FRwݫ QkbnANdBFZ5^A0VUq y(ryMqWk8 6s/{xrKOzx/o(i/Ou[bcJտ@@,OVs[v^g7Gp/ "T;݃\(m@CfW@0ƽ^|\D{[z  ahA !6SHa,O My wOllld/ E]umtOĭAYޘpH#m6C :~a 2t>O]5\H=c5ݎB*ԙ'e U')3|y[NMNe}~evŰSxfǽW V^bs=mƐj[M=Z_9)U>bqCo-;w˧-D6sp@z\1" %@ \@8 8z)1^ʎzU"gLe*Y|-N!rN'Ces/Ў4BʎO緀=,N d#`GlBI"O_cczzFX#B.@lOv&5$nXPM)gdyt+ ĉЮ¢)e}hGDM $iv!K%q? y1c&NΔnm:?ڍ@\ٺ3ry>X[jY00yԆ T(Wl?Av$s\_7eSv>Q9t(.;цL%WCdϿnLE򞛾.tσxt_s H|>B V|k# ߑ{ʥ| ;|B{WNlpV$|Cl=Y8aEs${:<@N1nRe \C^3'gb`JUNv[[/@@;eHd3}u?vvyf8|$kZ Ԙ2Z5{_YlFC앓XP[rL6A~*s6Wd?\ǍY?AZ~s=c3CqwXsjMM["ls)0$3}$#C"n͓8Yƨdwdry ~%5vrg)*ӛ3>aC,Ȏq[啌`|{@+GD `p ЪLSm4A*.pt, ʛU`UșyeRgL0}@^Pd8\N"0Sҟ]y["kUI)u=Alfu=T ݨE1c>ER>DbpR2J#=(M7 0;5$Uߜ5=n;Uԙ5KmŒ8!_F_Š5^˒թOCbg)os'O/v}11 /wZkn'T1/x:r1]G2U|#aMiy}|rt_⾭|vGfxn&kcoRPHf@g <9@xT,CG~8k9v)D⨏h KNBS3[tp[ #$%U+R}w`/_L$n;'>[w 6iһ.ubd%cӯUL4رй@M0 sYFZ'AIZ<s2nϫl&n'ym#"@ą}Yos!V_BWG5 /Gz,;or MW2W2 z xH,e:hԺB' >ߒـn w RSFIyy[dy.]6Q#d <9d $$7` O?tfPcial ǫ`~|&X}lJVVF2!ΟnÐk1!ʽ/"hX)Hx$ z_AL/@uHuBi X5a/߻EjR EJ~75HVy~!(9 ]t.-T(di{5^1KjuHO(.yuBNj`H18Ud̎UB-9UWvǶ~=oa "ߏxV%>-{hfŦb_G [94{dyr0rgip_D/X{j@c'JoPU_{R!08T?[NUh+CJÊ1Pd(3L{rr(lט}5" I+gXȀe"\B&`^waƏbe{;yϝ{!p_m?yk2D@k;7WxAzej00[ᔷ$DJwEV:-<|W,r̳ VE&Aԡa'yedÃzP$I{bQTֽZ=/ʵ5;tsv J9"&"ug7?|Eo/Ph/4w| W 8 `$E=pO@deMKb Tt+1 d6M~QuDgAe;#jcAA4KN kX֔Hu?72d1H;"WQol2B8\JOy[!,gryB$!S[N}vɃ2/~.17䶶ܖ;<" En&fbs˰j[iVpm̐E;gJYx&׽L_=<:g}ܶs(C۱Vt%`a}5g\NT"kGN=6}|-~ ʝBVwyOLHX9JFgGv A 'Yq%'lh[` tIX?B>)yN/hSeci<3;Q8VvC")czd6 ֻ 66XAXRWg"^VMbXpug[akW֜gu]׽X(d_%dIIri#`Ogd R%\DŽpO*{+ؙ܌q|dӾ[~:|seTC[r522D^AM>Fi͂dBs!^I\Amח[.].{kȄ>+ A]W8dbe:_`jLgjڱyhx B(`d%@uRfqeŴC' ⸓ZGX@''\Du1zE<,FKk19d 3oB- ~hm& " oe8[Ò'}۞c@vA2̧!EMDb}E 0lnXz{N #6z<~MoӠ"eE\2 <.mEnvT4׮Wm'-}yJʬDl16;4qJx)Ua yEjo[0]{"c8YR^{ڛ9O3^gBl"!su_O[Y{,_"^'w2 !{)_8iSJ_$6?^ ]I 񶶈_8Q ?bA L\|<ϝ]W2< r;jv{ 87~fOz64dnRW2|yEg/v$\Mwb68eǠB7exˍ?\'ImcN2 i sȘ 9FD딸S̺-pꑸd(& \-lgg7oq#l;ߑ-ĭ/F-xP'n|%U3d^XN:Njqp2'[M BafIɺK ӄ!]?֦ȁh'y&$ĩq|%8GIQiOz%!wI3؞A*uDY8b褅 1"aI# zHA{ +s5dF:ٗ!]MjְHERz5v`Y̛k#-z$9X ijsºF}ZBuD8z8!@Bcws''Kۼ sHɱ6\A۹>h$7dۚD|Q놈:=3a8dV#I}[2=^>Zo!wv/r/3˭gM<0&8磟\#t +ayBmW#Eg+E=Z6Pն7㐁^vT;Iv\2i(YŨNb"16 (s~+ sƷ5&@z9l4r@A4OXX{ĚQ })1nڑĬ&ӣkpnquv<[X#M|.{Z~U=ڼcxEe?TЉ^^-p'_ѻu/גvc!|+&zfV ̏sr&Y0wx*5oHaM,e#0o(}!qjb0%nL܇'@s*dA:zdP*"VHPمf kTX Ӯ#1a^3#.4)~s#a$sU&ZM4BEF$i+ 7.$'?%~mFj h%V4Ug|/4<0= IDAT磊N=R6W~q z k mpf}Z_ezקWk=N#$}zgcʜ^ĝ˽Sϗ. Q$¯vqmXk;+fAffyYO}0Muf7'AF}!C&30¿ǧLă C@b$^vq+~:KXW- Y13 D_4vf'tXWean.k x6 |!'po݋EVB%z2oȩMq"0=rU2X[~$6ۡL/׿[vՕ(eZvV_)qle:Ggf762w'xqnȈ@{z؊~b鲼La*67^"ˬ}cÝ?o[0_Z*Eyi19pJ{t!fH<3&ِ\AGa9HB2$\PY5P6l,ƑP) 0|~ L/nwīٳ m@ʪYvf cV#aeilwos%I|PYRq oEkk4(Df×S_0g`'F&ĝ&g@oXP[K?v;ÖD0H@cV Pҁ .(;ۅ6]hӰR$,,%P0gIOzx4}y;}F=DtǕp'60mxiRH[UJw!C~kv}>O|eؠXoV.UvSdVBV@=-zx1<H}yPdxkZ0Zr܃lf.9=NuVRvr̹+ޞ%AWp!쇄E3hs:$ss Zcى֦޷/.?<щ7NgsQ.o-" _ Zy6q3e!Ji Ϭ6B+/46 BgזLOѽ#ї9{ ,EBh@ PgFB d0K2ks+7 ;H;® :;,*q黙Id ͧ׏~!@`NoJ&C뜚<<+l2ȱr(x; YҖ'ၼ[e"%N5o* AN|'6Q~ZdÉ-Hp#שYPVv۴.X*-$ Of[H顖ÞLƣp\_#'+Y3'O濺 P|IRr {5!I/ 0|7; -,YrPEF7; (&nw-8u [9rILՕ41㐕Vo [*U@~`{B$B׻,4 }K罡>ǚhG29 }a ]0T\WaJqh\GUwRX65F9Fv_ryYݏ((8*Klz۩o2\8LV%HOuׯ(z=9ߣ Yܲ; 'gW7r3rEwB8\;|)}Y v&q_&vOagτaQo01CT{;]OlK Fb&5DŽR3sWwh,Hu376mL"$[o2*^Őe$ogR3H &Ҷ@ W!uӈӂת/I>@!G; nSaytC'3+ZbZ- @{Bd}< Pz!i} qٌ:q߯2:F=X9?;S/4`u0pOɏ" B=KمYr\'?ށk_|:o2rO*|3DywMP>SGә^Hgy\w P a5UP*'@1`kKc:Jw\ f6q_9>vw<;u*8Eg)mޖ[K;:T"iJX1x @g-S#Yz +r`FDXhRVQ>;GH,m@$N/iy>8 ]cJd|_/vo Utpu&H`%#d鞱^&YGW`m*T26̳+-[Z=.5^lPEV#@~T^^;~" '_d,^W쳤0ג/@?s;JvSI/ҿv ?Yx 4aLzYd,Y+Z^ap^KY!tZhaULF~$wm1$Ǿ=HEF'Cc4H$0 v3m0P$XhYGOmiY$`wk[=5;${>t ,:#6"f'kiňr﫟2:aZ6\v6;Ȩw'mGnPMIJ$ě"UwW۹'[dj͓La/92Xck-tks{gEr'7-,?h3kM \f{ha@y>3β#F?[NQCDπge]=5ʪK}o&+վk]M.VDvp-y΂ |f7UUJƑpN$0n:<כG#9:Yb=;#":єոr ,W:`* .ȯ%L+&Yj -.fnk0T &0#hO=[yu2#ެޠ5<`ȃ=0 w&6{jH`W[Nj̉`}dW#Zܿo57q=d  ʟGyaB:Z-`8]Kw w:Ik^48@iZ ZKߔ;p4E*yyRn~ gTǕG]P\rP3 kCJ͒C&$Snzk[ g|# /J"3 ryBF$ q/OyW~jvn*SIB Hc>7%NDֽ$#~et"wS? h^üEb zRUgK{4OO6@hu&LcPɈ%v͈dm{nseʃ}g~oU峀Ǎr\tr e /盌nD_VBԯ΄T1r  oV'HM=87'@oՖDHPVk"f71ae<0&_(4] ^S"qYn[XW{-Ebj2ޒ: %QXlqw]^YAsнo4A#|fuOt҄=]׫m<"}ƕ~9yZ#g8ZvԄp[61h_Fu])60G|ZOF^&K]]iěDoJL`s3 l;:bR[٫qmƍ4>]{~WTĜ%I"ccc="q"c0OʓL{L*, /򞷌5.ndyMcW;փ7LoOSC5WIvHPS,Cu7lFtV14H)~{>zX9=ItŝҙC6\-7B}pRS6}S$ŢJ7mE cgwrΕe 2A=A}tNHhd3zED|z1|'sxjܾRk}5%/$zsϹ ;`v':jH%.½u&s:r{as^.;;mYo#~%`Pĝνܼ/E"GNɄ2K(}Z+.1 @:3? HZ>v!B w!zǜȀO/&A83w"΁v^J3s"R!sM,! /ŀn23PeJⶳbR%B \"+!1߯6#<HR!@(}%m1C9ފ`Sؚco CaM7c,gMe5 }q_y^4vBXn O++?D[B~w-}l|M8 ؖ=sgvYEo4^N?alsq[YJpܨ.!ԁ?Wn O[ |Mj;" T^UEa)A KueVy=AA@JD;&T;)9uqҷLTe h!k kK<*m9HXc0B$wq| 閅h9ChP%q,~Hid&>pXl~CWMGXrϺ4Q]Cҏ-&+sqbHfċks^QAOn^&@UQo7#*9[9weA@UwWڈf˩{S. .w~i<&ljk3]m0twPJʗ ݙ*_ϯ_ D6ԉ[>^"c$ F.,$~žs\}M9ȱ}![Wڟ(7TcgԎ]z,@\R&bY^, ?;@Rk fhmc)tq/M:Il#= znIOۦWkJHad%!`5uSf!յ=ϚZDʛEH|CNs\03^mk0읤 =c8NX0Wca63x&uC2Z<6u*1UG:n s7{Xy3ۼzmyO_1(!A|jocwC|P?4r [d1 OUMD#".K,\HAk=ef!#Fi$wka}"Wo`#ˈ~"?K3GD{F خgl lPA)d#DȜA[Nx#Eveq-6 8qg|<`/(_N_`_8}_vܚ`l+CDdliBk^H>4T/ 6y.R=猿Q35y[>8 ٭G䐼ϙ~R]ձaJ g2yzȒ.=.Nm Өp. MvqP3ߋIec](enP~r 1^OId@G-1R!E69AaF͵&qz_IȦ@]N꟝rP;ט;1x}&⡲ar6-8/Z c;^+k H#NzM |.2&d\<Α*R Ákngf(ϡΗ|P,YucmBlӈ sA:w S(lb60Ϻ3;Xr#h\& DLeTmrn 59O9A> z_l};+U/M/bO+o`%|!Bշ2rEZ073s: 0R|Zp0n6s-lG6Fo oXEZ ,r"QI gWa{ܚM&je+sh坕|M9SL}'>8q t;4/:Л5`c5m;ttEV.3B A:]G*N 0ķpiNTOX'=]:L7"Pl }#'ͯI߳d&=˻wfn1s ɍ &)Rh"]f*E_ZLJ tLDJ{YVL#pKŒ;){ Lk5Ҙk!)]ܭ{)nkMq#!k'΀bGksaګ@!4Ly'*r/[ 8fg߸N~ۼp?@7r,&OgN<zG;wm( lzN7-֧m_\Ed]$DLRtta23GMiD!'A&cFV]82&ۃ 痤#ys1꒣X^vh+soGχóz,o8熞q3urfS"Pn;q1WyU;ڗSv'~ws #$BV?ւL-Gׂ5^ Ч}s*Vrܲy_5nMݐHlLu T=dVXO)]/v!Wlu2d|;n4C^1$D"`;/."5Lb@B|`HGyp`5!фx {| u" %&7 \1@?@ez.J>g[ͣ>cX)ݮe.<=1T>uzl`s#VUj#q`4q^vMȎ L4@~uW(pMhI07'ƨŤcϭ I13kϢ:LJL =!^01O5I[>1F귀&u[џ~7;W^Ss307Äǧ?|9ABVwyqC+nmiwmOÄ|8Ǚ&+-e HSl}U@{_d *M\ۓffMUv[Wwy3nnFroS Gf7zK+=udxokZG vPD;\L+cPgȸߧ//}Ww׌z &6.JV| UW772= M?Ibe`YuNYw)'ӈ>1|;" a8[qg7ޑ-쿗{O4u1n:`Fr4's؉46$7Q0)[Ts}f5WNPr2n1Z#X[8F7S%#t\iY1U{/.DR6WM>5}LW! yFS@`zHM~\P M %i@[=wxEDDg͊\Ayz :j3~B hE4րfB$[f79qb(BI$U$HL \` :fuiۛSzoRy[2,[)b8*2ۀ:\A]c wݠEķ*MI'fU'͟,tcg)ONc<+)R3pv卌sx53):ګϐ؍j~A8z@8nX;4bB&"#Ayo{/yv{#a!ͅ+ok jAB/MR:oR[SL踾@ ^cG̨yx5_F 'ev}Gl:"KGnX[{s>[QYmAl&k}qxQZ*ƻYYh$Gmîtk}s+t=Vav,7/~C ^TH[I V2 ] {;%.!X)#s`m2:KKԉS! x 'Rl#Ї r5;-1e ݭnz'. t-$ZǼpG^GFJ :q6GDL YQ2l(=N_ֈŔ=޺^lᲱ}1:A%Y.Axкe ?-=xkID>6^r7enZ'[^s.4u{(Am\4 }xnȏp-PP@Rwly镃侦^6wBx/+9y/nc`' D8 yX̝ TN-9vŅENBO$7L~ Ӵzu,c(; /R{*?y֔ڭٜkB w1:ØW8]2Ŷ\hnX>Fvs#(ҵ }2 sh{fs:Y2gc:hyaI?ۥʰ-y-IS3*aꬺOG[]md23, 3.SNdn!8[4.^%_OC-vTgLBFtW=N"_+wayZs)>$@k^} 5\z7`'Õ׏C~ޢ1-9r;YG11Kh4B'y>WVTڈ[%`GPQJDEoOґqSK$˓m ~]D: dnT(I*՛D]vur͉u P k1=OA%Q]`){ŌƔsv6ܯ^3ҋp' e()##9=2fBHg3 `[C{fmg^Br%N/XWu-0m="l:GΙsdT.~-GgdϺqnnM׀@ⷆﶧO׽F+lSɦ~jeuOVWѦ2 ީՄ3@*AC@sh30@>}oǯ>[Co@מ8]_ Kn/z<;tvLO'a$VAi &}̹:Gua<ISD|T=q=PU#1;N6/}DyisCgC:ОY">g`E]&O՚eL,Y6}͗>݆azHEc?C;Ixڬ@?%Z8pqfɱycKvT@"3|Tj&& eEp<'᝹˽O_>u,T{(H?&T""CI]ngBH$Ё[ zjATU@\Xؤϡ8 'i $z1pT*nz3o_$o|;bh/b==8X2T3~^!LWɨOH6ˠ1{GTOů+=;C)zjwEKR}qRf:bz4wÀ.Ghyji4ÃVlr]mwSmkw7!G RE׸PbL@Z Sm;Kހ_UۉO]4ce\ ?Y!G8ۏػgp.wϰl c+J3FЂ6 Ɇ}=P~6i}T h~bl'RXA6^G|NDiy |8Uk_=LPm">Aެ)![*pt5fGz^fϭR'q|xVA9o}Myn?YF/wzGOك= {yn)8 6UxzJ*3Tݯ *tP=!ZwcG>N"0}$,V"N2 BehE:AxT"[EmGb!sD0gW詔=]U6(q-@3 %$[Z2059=a2sle P>M9t]e#}2r3U Hd?iXj(rͻ_\icXPf98fudnf08 ¶lCvp :G];9۲siTKlyG JÐN|PcەZN-䐏1N\c=%f$!cr :=IF%m'?#[s&W/F'uc`̅>\j1#^+kh"֚JHc{'<8 M&W??r`^ĶipJ#*{Q4hL2Ɵv!¬3| Rk~>-W]Si&KH.FD^@y<$M YCJ+%EW@WؘI6ڟǍIlZ6Q+\I-u%Iv桇ܷcN Hf%,K>]:"(K/%ziwЏcllVc d6TM2T풻`Hhlv]Z]]+/dQV|2!AYΧ/-,Aj?ec㧗HD?^٦]=nXXd:}h"r61>!Y:b>ٖ5$")} g&#u9Dm IDAT|Ye0-$ MgZ -G1ltS^x4%.uȻwƀ*L͉'-{N\"3sAwO`dӃ|fl^WV&q dRîLSi Ar+^nF+.U0H:Y?jC"ogּ詗Z/-P6?֛JШ5vN׻a[N֥)Ru'B0kxQg&Ng VE0M% hkωyŪI|^&7|TSW:ws˟"[ @R^ ]gFNԃ8J?tN#| n]ZEpS0Y^rpuwOIP=at٨q9!t"p$J  /"tVhO1MxzPIVe y'V-S#^C(G,L=t(XGzr 8v!ʣ >=L'5+E0a oWq+: Mv_I܍ϠYsdlgM >V# 'C^eԢ@#t1"anTU&f s~. !ju%^1uyNIP kgh뵄!:n'M+S'vp/幾b?[n܎e{h0\%3Ϥx٦lJ0ٲp$ I$1VY;U~crG q&㨶]MlQ7Rs˯kov:l]#JIJ+pL7HxH7ZHhFf:Z=Kr,".PFs#`{ͷKnndYƺwΛ\GKT+Xl !#u,g9/dgyp],Gxj; bh̹@ok|</Oozx-k>6-z⢙u*"suLNa?!m-֭mW^n9n t͞5vA}7|.dkVgvs%̠dz\czPvjwԹIr90Q$hw0#Qqx8;:45Iď^7[A(k/7kr,3O9#^(x!vH~9`p/ɥ98~{Ɉ)7m d2#ltd^/0@`ᕕ|$L*r^/tySz{8ٶ'XQ{qeԧ􂾵9o/ٛl@(%z]g\66]uR5|햨7p=ϯmc9CE֨S#~ћ&ں_Uf~^9 57%[;A"VR TOpM};_DE=>!6y r T%&=feQ?" p WIx fhsB# IƑdG{[譂ekzCX%uQⷄ'LG? دulFT'Haew=GrR)yf ;X@ɑ}JJc7kD<݀ 3EẄaG>5v|ZXG4>.'kl3m.'}e5(o|Ǽz9<'^qmW;ʗs {KATX3N7t&2٪Ig˞#/#ol$"q՚*\3͝ˑyyK9O5Au'o5,Ϟ7n w5a^s|O#U37o6oD_&? YO>8?@To=H4tĎd-+F${Q{(Ith {HH^81+7 <"t򉀞x 5Hkc@iuB7q4ex'L"M=f{{= Y*Drٽ5<^ZW`]L@A86<u$w2 bgq|=1lꥼ%˶`#2.h$|{LC*TW &{gkB}8{Wܨy49 U-?"\>^/@.}Dh,뻮q̭qLIG-_ >7?^זϩOk'n-7l~R-|Θ50/S#|d/6Rϓw~8n@hJDىB@e9 lEepA3 ׃z1ea}Kp!)0oLsA;^s z -pLC6 Ftkꯄd[@*zZSn=a$W=Eb͂Kok6MA4I؎d.|ayk$F96$ yuHֲ<͋Zo G{FwjtF.=Jp>@DSH|x~׀:Pgn`D?hhy_Ewbg>77K_z=bn)i:ZvdDJ۪rҦ+D?_qfKxfW-_ ڗ9/RpAY -ocd9/O*ckCF_W>gKԇOB'y?Q<I|H SzI@Ι? _o´i"Q `xB8:5F&^Юt,Z^Zhk1FzRƖjWꊍ c cLkrۧ{E^CO>~+ו{ =~񶾜}GvYG"uHA]XO+s84#D;e01Y8-(;9!!kw|j@0~ڹ$㣇pD;PTr= &9 Fuf0oA{)!63{[cEoPF!^A?D [x(oɗ!E~e%Hy4ډTM`y&mvD:- 7☇"pĠ{4cl>K7  6M%Y՞L[ PJݫ$a#uU 3#Y]Ukd>GZk{yYhcWo,_즥w6GDPX*N"!.مXishaɩ+8:!p.H )d@=`MZaĎ A܄<1g/*R`'D-vz=,]<1֢޴ 2}l<^qы~N*u)KUbfZm lw'= ׿26~+W㋳Ϋ/xC^'=/g]P}xMp?|M|n/OOHqD'Yrp?քó)jxxtacCrݛ Lڅe@4cH?dcJHNWzkoFxFy{t3LupiKnP^SnCHC̐BDhuv^AD.:/F@2ɚ^rOpe7Z}ePUx! cC**C(Km3lQO0Q$l2~0xr}&ӼymvƐ[FK#=啇d8y0c^^kxGg;!ObE+ݺ Nwmɕ^勓X6>{7*Q_><[lp3, xZ4᫈ޟ^ 8gp"bjMR$ڋP)A k kpQQN@ +&{ s-$>[,{H>JjlglbdwNU+z&YW{,DI ƌ 1Ӕ -5[1IB W6lT⧶u}3g / >Zvފ Wdr= ϡ@"zHװ6r|lBg&Q<֦Ӣ$Q}g!X`.e].;:Uwҝy y $G( 82323z:2w;GEgu* $@$I:tWk~Zkڵ9_wJN]vժUU_kZ5b]'TuHʴb2n8oh}aP]Y HY‹Fi)Xŗ`Q|a;pݎi {GY,q3USWNޛX <6ۀ>Ol:iZjkd9Ճ>\sʜ+-u(]6OuWb"kgE4  vĻu< lL9IA 7F&D-=4'#AeL:X_{9Ǖ՗ϝ~];fYqQ"ZoSp_\iHJ±ըZdT&4LMbX9-(FZS(A!X͙'k 'MJk3chz#+?ҝ9$%(#bX&j6V9!Dfص}"C{%[;x-1ͅ)xqDvBoM|^aU@3c( ̆&Y͑Ϗ#lxVݳO'D&M;]h( ROMugz񗳂OYIsbiNpl^C\Mg摯uMv|LjO4|sus}B{lӧTAL^1[0.j;}}fVDe`n>}O\| {07q)VYǵ b$_MygJ7d` IDAT/@C2N!(ļ $ 9nt*&&5IB3P*U `*,EMC 2sv V ޙI4~Y$thXPD0x5ĸgBP<S8gN"2Y;~\uF OÆskJ3P6/)׍ml$BHz=pna= 'BLs!%70 >AεH]IK?b.U"_WB kr}|E$Ixj3υ<1@P8.ҾD-['9>a6'K]w//믾^zShSht1[@&jMr&Wz3YԆ>ѹ':TP pƼa}ag&'`Ohj13“' U)@`'ޗz> 4{6b]O4O08{/N#"ͫY' ƚd;,ѝ;6p; pn/7A93U5Sk5TqQȷj B;Al6B+$@άɛA *IzZ(Ơ܂P3gnzt^e;RHEaHkڪC1m$d Y':Zq ?ҦbNnuhSڔk@7qSܓq*,4lT@vp츠4N}2Iw8(MK38N='̫,!$hWW?ub GW4ჟqcɼ?š:I]'V"hzMP8Ckit N^˦.ٳ"%q"Gq ;H uNAa0s¢0x*,uROb\bE0u&ie˄3)!8jirloG mD5B@aN{@~*r/S2pp)p7r ( >S4 0SBvmR^ZhO+rpb6X`2ƙ;r*igl彪fL` JxL9[DsN)7(,qc2- @BȽϸ^+h_^V@[-6uKqZC*p9ORMM $̘W a'u՜t ;ntd\0&;Ϩ < ٕ\00W|TUJ==G0rrGUޖi辨%h:dc/9)u+߻9i8a8*Z<@ЮpOyNlý,{NHN})ub{ZjެDnpZ>7{lrZD鵏&Q;,hv=V:vX}x݁T׮2>r EU}¤^;tBt?hx*A]p{^Pv.7l,.h &:I&ss) \K@_䟏R6v<+ÜM Zpl.y37\NJם n#[r7I z9\4ejH7wTr`Z[˅np^fN>s&4u8,ZnՑLQrcJdA, ȔrdsW Cݦ#oiF\g3VʆG}kթzMæo@U"fbv坎@(4s]p܊<]*TCٝ9-# r#G m \4DBg9{d yU"1dב3> tFxlX]ܳF>~sIGz>.!;@@f:ǸH8u(+䟳vD̡C1;޾z'MBm8aRt2(Sΐ!gc4j$'9CiϾMC7$k,!#^7)>hzih«/G9Tb0gQ耦3e!33eY:q!`I9 [j8+'hC3.{ɖ&+²aad LR~d=G*9dPqʾNUW@-.N#> 4OcR FaѺCG #jҴ~xzMVƩjID@)d4S3,tAG\)A9ɬ|Uem^AADɔ^9 (#H4/f2Cdﱹ-}O8H`xhפ]o~z<"PY/@ L=4AMΡ)&s\TY=v.~Pv~^?=qfz!;k 6 bGxG msr V"g>.`); lgkB>j``7Fs>c/IEZ/qT ,%+hnqQYD"TW죳wm`i/TM)X5:i\E`€yIY )v赡QWk$8Na!ir qگҴ$rd ɣtO_k'-_LK[-hi˹wQ4jSZBi_oBrӱLjG|AGS~Z9OW7W%8pZĮ&Le}hBBk}ާA,~~[2UmNZ6tQ'q T[Aa.܍5,KAnwDw˻QY|C8%ag'yj|VX#rNϜ XgiBjB]JjFRf4)DbViWXl 5-H*Yݙɝ2bz G\εY/+ EaNZfquok@ xˀ x5pM'Jҳ 9!}z7"ippk[d: )f/oԕ}}D/Q `1ٲ0NvP)M:Iv}qضǏ}!V6p(qJŅb, w~5Ѣ\zy}G}hEKLH%wX H0eڒe(=0."zV"{:E+91taySM>d ixYmF#V#wm4_us(#ef65cZ6C1. 8|oq;ȢF͜[hU @O>'Lꨇ4;T]g0ASd` Lk>h.+Λ6HPr7n+r=!D3X\1& @;H\D<'!΃T6`0C|vVIHyMVin6S۸1e8x"k-ԅWSgM 5FSg+8Nx~htֳLtS+_ah 3n;YHC:Q; ϕw.,8MsM|EG8MszלiԽp*I5cPs_1?|jLzׄ([ai/]O7 iilv]F˻.#:G(y}}It^v r8cP(鬒8X)ux.tΛh˾u~W[G"Lm.-:vPJN}^\t!Z25"t۽CAIPϩs j$Km(/B"TuFVnd ," |W P@3%ChIICVFR@e 1wΈ/6 h&P,s6m #5IVz4qUXS NvB[qm.4C=psPz;1^K~Hӫ xDCrpQ BX˟%p&)+*3uf Vg95SZ 2VTꓩǭP΢Eg~TL#"c]mY7G'#7sN2Gj"5'@.^ܽ~R‘\H7gVH&Җs6|j66듚;h_=lȽJ04f >sbn9N^<ې/Q PS=n#7)М(Ӧа CP8b*d`C^GۯyJUx|:ew ^nfo).x%e^)AA (!hvsjK% BMhtiduWh&坥^Rz팋8$Ԣ鮵Ӗ4* 4ɇ/TTr\)XfFb$!*&`fA߄TjLC(gi0[aCiBC[J*dX624\x'#ogVOI?u$ҸuRh<_І~Hk۵$jrsr/)<g,MʿUY{$DaenxScG=]wgSN@^iQ{ Z/<ٞWuӜTST7O NN8N̤`G]SN=qu'gAhN:t'>1kȩ+֨~#|?I:Y{hBy)m2V;D{ܵQswd(2|{hVQҠM 1m\QODlc0AaC y }wK`¦E85 bМٿxkށ O{+PQj %8& Q5{0?qm1Ͱ=me.(W89Jf;*AY٤׼ELs?.}Q<6JߋjohYk `fMy}[yy]? H^k:4sg؄b' ^E.aZ=X7H)^E[f:|ןҡ4#P)xf$ǧǫ {MH%dV$yH eVE֙Jhs '^m>X`P@pԘ^|;+:&o٩g+901SAp sQ#Ǡ3y) @bo{xM'U;O8hLS4gP;P#YǙ Z@D[CM*@LN6T (Aj=g0M~ qYM5Tz;56^M.}3m>٫iqRL[| F J|M U,˺rZ@!r䓾A7͵zz{Oމ ű0~CO^Xpon /*Xh 8B䞌M= J\Y煳4;&9'^d-Of2I *Bj+HyTF;89:9)bYo0wƽuMͶ3ATBF>C[u ߘY"CgnCT?&B>cONBT2L1WٿIꫳO*@8/3ɌI`M+r}@.,o1'XzѦ3_D~ ;7L!5(`?($x}m5ۄiex̔`QD^_T85NK` IDATE~`瀖,'9S5-L +(yx]/ A6Kq4"W( +#@`vYd9Ď.*XW ;k4c9c%tjNoڮn|(&566Phv5A$Z|}8%+t,|AG\ aNèmgpB J]Ϙ3TU˟3+?PQ:B3~ӼmRfr$ 5e^w7r7ƹS> x̽8W˜ASl7jm6P3̍FfGwF3vlEHN6L59HXlnBAccG6`2kkMuQq8 @8Dttf`uL'& +S91̞&=Zfuim~lq"D[򽴼*:o'Z25b>Jqȅ`*[ V5^gãMz3Ϗ'3n*,ME@I>0kLӠLp+d ^/1\i)- m!2']*# %T&8 ^lפ" m.UӐ͙ AHFjEbfu', imrtd0-S) kuA,R6 L<7]ބx7~~h1 ^avc@j 9SWAћ#'dIO$21 Y:年6v^nJ4}Cr.jȭݾ \xg5i\c?Z]*H j3$}ܭ| mq~]-+8Paɦ귺v8sQFa0R0O*A^LHΥ#' m-MSnR_rfϲ9SК+?ZM ZJK'j5<1: (~ Dv<6mFLOɕpX_fz}M5yR+ʨOS#Cr7`?|\?60Z.FKd}I8JEl$+7oqYi]Xs¹:&Ec(n`ظ1?Ӻ9XRP56`6/A5I 3Ҹ0/́se#{[4pU &âmgHG|ny6F7SБ<#NKXD6)(w-S ,3sJ'*UɊaxLH,^Hk͖h NƝjIM/O01Dfh!۱tԥɄ8h;zٴ7ߚ⤁h8Pz`r>1`2nT/&~rV3P('lh Lma&PolbQIl>Y%v#en̈́)IL(ɀƣKY׺j@IVOX:}+x);sFٿF돎3$'~#wۚB vUDqkhKHg<>=CmH^lP@b+X3Mdt@MxŮMaa&T&q1j.TNb6^u }/W_dZD鏿 c>`9]yb1Inc}tΝy&c;3'ZgX>FFaZ1ޘNeǓ+\ ;O搷+@0ffԜIh+Ot?r w@aQGer׵590ԩG*a7&jedꎭZ`7Wmm輿 dΫw&R"' =i6_+A^R4NϾx͟6jL[nCOѩ| Rj@+[NocO΃r1 r4XJS͸xvaȮ0:?(8`6WXt^{ }wB{_={_ t">;]?׎#vr I:(y %ӄύM*4@Rh"J5 x-8t>:gkb{r+ 4d)NXxtY#st_R' x^R' jH +'-aiFD(KnP:1% ;v&h.ޣRY *ϫ˜UCzlPL!JG-K9+:86ºe9t\[M|*G8pț\#X*-tNS:𸞱lQFɨ/s}|!)y2f9R,80 a }<3)a0JH! |!~V+8u(G xm1Z`ḐQظ.=w?HKng?G>W6?j H0UV*1 %BZXVL1-2ދ撴38,+V5}SP[v'q9N 1?ĺ@sIp~>Bn~q 8 ƙf &f |dQ5oT?A::Orm)'L}IH =X,ejܹ$/Nvоp`Uo~;Kɨ )0uh Pe 3K3r9lwc*v4^&`I%&0D[J7+gMk =ɷtl;#8sY^hb s3D/0ы|Y 8w!D m#!CIc:9 > ҖgЎ~hVō.,Zd;n4ss6., M xrh&ɭI6/`ǗfHr V"w5/[6,?ΛϿ02bcW0.qD7XƪP6 +ڹdWWb^ Sñ;#uXӆu|$rWw5`О~(-m^8+[~VfcPc(=t4Ca|y`t){^ngF`pɽQ-[&.~i͒Xe϶ӫ"u!XR5G)"_u6fήEp S @,5`f*kB()% h5Jiu"k X:9"{6K8y/@J8L Vg`ÀsZ@)H@_z'd,UmL(g^( [ncA6:H5FF gB/2j ^I{f [8Ih]Ό}X$Gj`۰Llq4,E1F:ZjJ`I|`"0spbIdĠ+ A& b;X8Xgއ{]^Bڽu "L?Λ-j$չPxaF@C\@b IJwaZ}B*X>DP$Ph 69 '*McxO;X_p8 7ym>yN?3taccӄp6 a %jAD3F@it66;x-$&kG/rrĥ] awbE@,=ʚNCAR hbfBϫ[\jyWVE,P3A4I&<`$'Gd?+KgjpI먀;9A.ZA",]4`HY5 ЧpyA1 3v&TZ*Jz Ͻ35Ym`r綕V(fYki@YQ$Ѥu,Ta>ta힍#3Օ (04Av3P_š&iSʉKa^BN*8V d3_u?W~ϡ+=֒8p{=~C&5:@K<)M /=G$#ZY$&QnAGNfXb;cuԽgJګ-:MZFӦu4]nɕ^{woYp; d^\z"m:_s޺ ;; EYO8QKD0,+ܭO (sG_0VjkAI}ީTP-ԆB wֲ}cm2)D~ ѸCf $I?vcKyֺ{#KQV ?R٢!-t@f 'I䟼ukV# RܭϱޯD+B31-ūK=Y@J6Nj/B(/3д}9 ڼScljo{j g=I5`2Ĺ<.\S,dS'[ѧQqGdTRc@32MSGTg7(#ξjzG"lf.t[ή gy[Db|6Վ_@#6FK-noaH2m=bfTp]p(yXhGk2'3aE 55fo"p\9@7}[nj}ݕӕA[7mZ:w?@ԝ+nh6WԙOW{Nhp! YʼJ,&dT^ /U5Dq܊ *e\AOx ;Bg|Ӥ%.\Nev+~cMEohۅ[CNtѻ_CGؓ529$ ZDUqWט1W=vݵ Zp J=[1Z`RAܲ0=Y];AnyľXTz~P1.* H1bR`XDqdڹqȜ񸵠Fܨ 43W/~X(τ@Ӈtʨ!k/|g )10@pvT5KDۘ`%RvJy)noC= ^'nOBkj0n CR'dug;kM'^mtY4v~Oގgv[~]PW_Ils@5= W]pCytJ6eTINy\ȟ(zgP+ &SqdaF1^ނ\s 8?B#[>r;-D7II7-R#?|hMl}xn CxdŴ77j4 ~jn 1kXf($cnm=_q>iNDq୒y! c]/.]N?p"sܳ__CPp చ*'EO2?VqWC3 ~FV`]*tz IDATjW7}?ve"50]ncv@VVk49.ZeD;#Bz,U7!&;μA,匞yRKf" ́m&_ɼ )%r;A̦H}5fDAհ!'hK%74MLfR󄘣dFnxKD[3jay-chTj_aE*!"Y6mmrЍ1 w}6I c0w)(yE撰55Js@ΣywCP;vPkU2))2yͺq*DfbJaԸ . :M^M5\+a.ABpsJ V NO{S q=+1䮣4U 9U杘Wh#t#) 7цM;h杝|Vy]S *1S4bǥڳ)'*˝{pn#;y;<#kXPM!&n툹cY/? f.07lyVp\AHyzqω=: 5( >}9^EKcvM20C4(50YEZa@%QzPՄg(πVh3  [4V<+ ll,&ox/ ']:d((&߁yк~ý9.g1dFvuZz- œKB~K=Y`!\)YF*8ButKo@Jq7 s&nྶ}_.3M7Pq2*/f{Jq*4՞۵3a"?, #e~a݂ i"?8UGCկ-;hQ@I9<54jȣЁ/-:t#7diö+iiӖӮ{.g^CK>oc_3670W`,*5ӦQQ`kYBg{CaQ{j:` )wxnumM/"i ̟7ESbŁV^0ܴm~;5[lSJI_inC>։H;$|B"p4bB&bc N2M4--r 5hM(4g">f )"?QS!^YMFa8Q@#ZY*d<'zBPqV9lDN[''ƬXqZOA* gY@ՉN 6\$yCF6Zdm/羋4Ka3  &Q9/*b,4A!ܠ&>p.N6Y yDZGEh<"T4Jؘ@?@hw!mf=&3 rOlx-U0{hWuv(/7?;->E~w) ?~f#m9㥴ҎjH+ hȄPXa'Dus)A@M&q)sgm,qJ..,$V Ca&zg^MYsN"@fOb&5] d^ZA EP3ZQ` ƪҭh+T0~&PAU0 ̸}??[#@헌7/ ځ aw>q/9ۤ86XoCOK<j%ʍ"Nj;$ߑ'<;G's~;щ Z  E xaҙzŰI5 V@W ؜@sS#9! )qu='!6VYp`|&],kAb]){Bij26}E5 !/%{$YߺNyc f-n,l3NSȑ}'H}6愗N & #ʜ*{{Hߗ+l҈B;}^^h* 5[y4xLE3_?#y٢c-w}t[iS~\Zڴk#DwR+V:htXQ c6W'$Y5&H[iÎц注t5RqMDݥ͔q>:/ |d?Q>t';a:{X8yUAR%7٩gĵq{xk ,EDg$@:/YХ`з+ DiTޜ-otP y(0]㦝 ROSJDáy 膳vN0:J;m |&N_i&'N/%|5/h:s{yc}eZZ8XrdXơCӁ! 5hQj ;K{ p1Y m֞smL:d2ͦ HoyL!*:1j?%c:%p&/-mO;?Itڶ]{ھy+-oX mܰLMб:rV >z9t<@;@O.̃A&'sbNw<|nz}lqIg#zY4{g WNn*PiPS>:@=936OE&Otǟ=|ۿz5V?&z3oq? [vWGҗީA t*()Kl{(Z[vBL˻_I~--ﺒ=R"m W##|<ttHqfIξ0alč;B} )d&G#A\= Nth Q[ kl>y'  ɼn3 B#s6tNLd%@ei :a- : SL7rڎiUh$ac' }մ{9il;T0}>}˟O/wd6; &C8%z20rἚj0ho `ㅖh j0aV^"Wggd5kt1=+ϥv KY,xC'ﺓnt]cQ$r;C 7s":n:92yV:Nh Δ 414;t 8A\4FjH5aO058,qMvؼ2$Q-(`Qfo>ܐHeL7Lrl0bW,7^ UOINFK=d;wza'g%y6'A\( }:MSz[G|B&Hc58HouљSrӾN̘^ӗ?kt~pMex6zsҦ'ә7v^4t{~efÔF|n]ps1ח&-Ȼ5o{nfyH2CCttoV:q6\AhV<űOt{W=';?9_ЦCt9D+<<L B8H"Dv|piυN[&KŗootoTjn' iϻt΅/y󷿃nN k8[Pf~4fg%ogeܥ^F]bڽUr|:[>C>LY?Cgn`./M67̡ygE*;Q[6$rdGA\S']JϾz܋锍;&2$џ~#/5U@ۓ%ՍdJ^օ5xh7lDiq@{n72nq\Ls4aM(Q{^@Tf^hwWi'Bҏy/7Ke7zyi %BV~J66p]`(cHZם*}Ug3m'E:td>zuz'kxOWXF|_˾I\e#[v ikٗЁCL;/QЃOڎØqd0N?8P87ҙ7pqXy=t҃U`qŎ`GLQ@!ֻӬQc𻻿6ctʾWӆm(t1c_tKo"þ}sm {oS 7Fi1OΙ:dE7˾xkLj^vȴ6x{.zIFw @\ pD0Oλ;vomPZ˔#fGMU&U\MEyEj ^IW_ :- >rnv՘B{wq 86Q5ONDL$`JI9 3^p3W>ܵw!}0*~'?BĩD H`s̔ 7vYyR[FpMjx==pbc5mb.3-jѕ C:iE!qndS7];>gox_C+x0қ 5`J6'o#aHK)O^})ޗ Cw?z0gɵݮU VKSb5 Q,k" P<{^M?#=흰Oj|W[566!^_kuFϞWY6Ohůg~i oU:|ϭU<q9?VC8tv;YFn_ |>4ū \W% h/yg͙gV[ ۑvAʃD_9رCwdV@@hTɫ׎DkWfh)`~׎+Y׿v\ޗ|އ>K#̙ӿ~GXP["r4V1-.Q=Rz6_xe7|q۾4wwRƼz1lItm QI#X!?EȬή֥_C ;DPOlpeE˦7wmS-13WӖׂ?) k 'QH<#~jcǃt᯾=u}/o>qO(`X5@Xߗ!)ŀ_=5 0Fፍq;|[GaB1$dLkf`, $(- ZRw7d!O`|]}tf5_M{COM;I|+O4ASm/^LTKɼ F<47Z 6T8T@CeRG3IC͜"bW8-d 8>I]t@7&/6zSu}iz~6.t|28`9 njdJšaU̠$N]XƩY0b'uQW4Pm\`6 ޞ1:H2}?I|+4/}i{8|akZir nl d O%2p)*!L::7/ b䬳-.z%W+2G_tM6ɸrFSL*% VPJdq1SbZr8&u1.zJ^;Id=('#d\_BOorQ.ܢFMjBk~~3={q 1]unH*B*,s RTZq/l LN7=c^}$̆MٲwU >IrZd3B"t!K5-a_ ^G.v;G%v u64i6츒 'yN2wnPwx:a] UWA7.UJR60YmE;h+gĻqgʆϠP2z%3@> o!a Kۚs^2. ϧ4sJ åcj%z ,0l <<%{6;n|)છO6-/<½gқn:0`nC>E'!xc휑xb3y:'Wx,榼 䀎uVB?@P0sp7ٞ8d҈̚ ļZ&[ _$Gpmk^p1Y9Z\ڼDo3ӷ-zIќ1)$h;s DHA;JʫK? 'EU~D3+#-3hLq祳h鱻꼊|hk({bqIpfRB&Gg`8Wm>gK듶&ZЇ^FTMYRHvoys -L"y}\-ڭ͍ %8J0,N 0DcQk9A39Uf9lbg/D%zDgu|$ P KH S%;XU3?,V~]{'4-ki?}:|liT̶fpEqi P~O7_јf)p`0*hkA2Sg1[l*t9-ouZh&+!. 0Z9pCJHPd 7]MϹd^vk z: :H50ieLi2:S|FA̡>M|_ޱ7A5SiVN" ~IOϻ:sB&S Ee!WF>M{y]O{f,fJv'g3;+[|VC+f3;$4>g'racѳNm*T IDAT byWXBb21   +{ѥ%/_Ox0(.{+hy`r"Te2h 9hK~ep Fp,FarxG :!~b.'g nRdQ=V;ٱ:s1#5Q(c9ѻ_ Jz{ݯ6&TD E^i @8!DКs mTq{#a:q%u~^N0Su,3x6~6}:8MO7i1JU~ 1 KjS$Q)ѻ^Ta߉q^ptþ=tX }vV4ӈk Q}\qsM"'| kuIcyȁ/wjG}8`Ho>d?qA>/0YMmLS b;|m>p3m:Ѷфi9 $ +`6&`:FDC".ыw a`÷- ЦE[@^ FgD-b8&V8)sGGb FLv~w/cz d Uh70ju7};]~%'%Yu%ox&+ŠP1Y@'lrRp[ͬ'ъAĞP$ 䁧MLUaMs8#~"IraEl}Mn|ع\zϯ QuBO]#o 4ne,"#J 5[JlIG+tD%$-zX茹86CdrԐO3!ĉv^ݴiwvt= G9ms]bϧ שMH==1s`#̰fhVWZ@b\-e3gDw/8EA8)ϼ3.d"e'}Ϡ眳Ofab`ėTH0&5ƂԵ]5Z/hx= ^Ll>,$bU krI߶` !,f--l2Bdej ;׍>wm]pz3B{bO# _s\VPDL]0H/(abyn&I=|h6;'S+osʊ;ڗ;@֟ӈD;.'N)~h쑀9wW7֓b?Ѧ?> 2r ̜tg.s(mc1,+%LBL0" +L˖9ul @9j@ 6/tک־61 &xl@fG"OT!ZlHY7A.{_ғv=Ecy2k^uftF NX) a %cƘ?-Zٽh pxcsU>(m1j`U; ޕr>,,n|Nz/[.6 ϾJ:g`m (Q@zx]>?=Qg!(~:;bHapcFU+)z:e0LU]aТTo;zQ:{-"mزv^sǾm5'?j D@E-tw޹-mޱCέGq'${\ƴQ8\(OsZdwi=%:W`KŬYB} R3 9y_<#gAh{Ӧ=tU\\ێ4p3؆0H0 D'z 7Iߤe,罚8ҩ۶}Mywq?ؑxmlEud ų(+^-aW&Σ.:Z8v|JL»eJ̚|7!F띆wRC҆9wfzs/WO>G&)C3|jjߏ $+Fi@n.= 6K:bs%S{N>KȖTb2Њ(mV]g #T9S}İVJ,yNkF~zn(i 0*14Q)AW\iօxNm /ݾmjPypgDƌdH Ml囟to^xU;;jFm6ć ? 谸R\K"Lq5G'2ÓM6`7$*MN~>8} t%3BX@2/1e.Wh& o6Q8/=":muJt͹[w?pp 0 u5 >7#e4| '/yry3|}5-Ϥ>{{kf#Q0 Gm\a1)m6_O/<ϯ5 JG+M!YW,>1ӈM.vE_f01A+G?t’{BmZ9NH s4CϸPDmt٥_H z`Px$S@q@#\grټ߻4z'GiR guqkra2a) `plb 1-cWnfk-7B) m񐖚Do)&<pzH/&މӤ Ů }[[&Ny2 ʑ_M/}<űm#?J&BgZ;.6N_ m=9&?G֘D :$^\g[a#xY,''Kr~NHDGڶEJVIRgUpd=캪{>S5QuK`Z06Z/@x/_^BBB^H^%PLL5ccܻlcZHif4>ssޙ{$K3kf JVv2I͞԰`.mKV =S6#Eh) -M3™ 4ZmnN&erZ 5#*~x \HYy=8k.H=eSƓ&[lŅ^,SR kHIWeڧYu @e4BRhE+34.y'pq'qMSGjUoB+J-U+W+8MZ{$>J(~;7Ɲׂ|dҥxͅ諸ը2 lbH!`VQ%{ umDZ QVf.)ΌS_ 3\FB=9X= ׽ g_Gu}z~+F-Kߙ2e9ԗ OP:y15t"S!@g_ƺnYUW)Wm9 b%Cڎ)ԹH<W4idrBo$-2g@J(~%g3r3xo2nbW{ %(LjT B]ۻ'6 S8r#j8ZJ,žbеC9{Xxʉ:Mm`{Kx jb[2]ȢEp5 s8_lHy>B?6`*SjGwUr["AN?u!&0$4&=E**HM@J ڛ؜4>sB] էfIoV2wʒZ>_h wTvr1Q_B(c#ij?(yL l<(|o*KBmɋWi/AJ/aR MM oBjV%ŒJԪ֧qJx{X5rrpAT^LSgϣk{@mHX妦G-$jYhs<`+AX^ܾ77J$GW'`CHZs$.A!>y%dhD )2i "0Z`% |{&-dٱ)3oXktl/uS8z*U4h%r^qڥl8ޛ:<` ~iFxbeFJ&M\BwO|Z0m`fuU'e)g"܈4$4Jyp)UzIuG)ɥҊ¢g,~U+`;B%i^ySeGl}h-;? Zq:Rgl6ۘ+;EyJ'%ii]\Hbb5s%;aj08ZfڗBR*+ŧsƹ RWɧ)k'Q:“\;RȅnP8XRxT e~G&HIB:D{w؅M[¾qd?+OW2Z~*N?"]}z2I"Zk04=oFxLPg~ã#w#ØDG[;::vl?Slx !}be]2!*l;kM7HBin*U;R%ZMT;V80sSS9/D%DZA'&鬅U17-Kudd ';p28ug]H}Oriё39_Fo+!2=] ߽M4R? \DGnS*`# $J\N+8i/DuAOnp-He;Wܮvx++N?hes )5 Čee*Fm_ 4'?EJpVi*==|/9*܏+5^w^t/Zl˻p֢40`G+kYhV0cJhhN@+1?&ldmdD ^86^fl+Jd kLQ\b h،Et 5)2Z}*49 [g{׬mo/;zX8E polOC`?T< l/!?o^v?uR,daTT pw{_yBnhE;-{khދ=wo,rS{DZ{Q{}յa1  p8wdNJ\()K4Ү@,LQrj6O㦽zU\u}=]d >Ly_۾"k( fϚCjmmuW}ڤ/8wh}b]ۙrYS|{gV ]~MN.yo6*򕾓i\3b3j_:){ @tSˌ%.hbxʚCL)!eR(L0E*SfVXTg~}>\7 32޳O?CEӟ+z)K@)KxeUO7>>?h|Z׷M7''=ur}Y7ZSѳ49 P!XUuG1B9>O`mm.l@xׁƬfkY[L .4`=4BZ{Ѫ0IiV<n{6D+gKts@pv؉'ݜ(<!(T0,mę_*5'zY8*ƳmO,Y*U,.]ocɩ1ӞJHޕ==<1PrR\6 k]4b(95ZMށ[6>l3֩"!?[qh\d #Ebm]\7aHCQ\ePi_8S` YRƧ8ulo> X 8\F"%,OV(bc)t1:ָd]wj<>Nۨ5}R\u?keI>ڽ}e$؊B:=^!ߏQHNDj-)ݶcF_F%%|;1.R{{ٺhݴsxNu wΞ\9Z^ }:/yO<zR!&ʡoݿY,1"wYlx§O3Y PqhB6ͼPU>9QÝc:!B*iVThh9&A4pO&78+d}2&G681pɽ84܇G6x #WLaYXȕKzNirj ?X!@\7Ę`묹'Ou ?Q F}*B *e{|qχ;/mxR24.x|Z_ý[05Z*_^r%ѩJue7*VT?tJ肍1 9DF+bU۠HkϕIA'!K=$8v:f8TX@Q5cQc1wPD^aI[AC A8/Gb w-6ڨ΢s+$crsOxi֚Ɨm}RZ.P"VuԹ&\D@}5XLgT#RO$&}b,~ĺ8҄QvMiǙBxar(M=7r[bNJ jżoJ2o=7j}DVƏ]eb Smݒ/.cKP4kn]AUXn;6גE̹G~-5;c bVF\bVx\=Mk150X9b0i1'|P(ܽVeQNaj4M \^21B(A*s l"W%&YrESJ`cxsW*J KbU(-rP34t5RiKrPvI (!B[[D@8<#Hd@XkfńL>恩ו8>>1!T .d%y@-h7l0B ju**m)vd"U^9w*a1w܆iI7ٻydBr}I Sq=J&&uhL^tP} |dA1 Jj^| L_c 2@8q=kеer< 0왐|pN3.[ cS46!jPQoEkbz(ZLhX%(:l5x1eJE+)X b5VMcI 2{xqFsKa eR;bni&&󺤶|A0 qrj u\ 0xp YRƒ;㸌 ڶ =E{;2"m-fHXˡ51qnŊ$>QXʘR`TN0y0j Bb}iyCwY8$,OrzfB| TNI߶HѾ##bl</(ˈѦq}JsnjCcpV@n/h2Gq"5cR(7$"d#USKO{}pMHfmAqw`qQK83CK8ޜIMOT$i ?̾(w"E iHu-Y ) l9~fOCےJ"."]P,Q*#]<XT{@׳tO-mx [sQzcce:PyK-B{6_Vo6xFl]IB Ɯ?i5sJM[dگx1KS) I,<&ՃIO P{j.=9^%;!ɰbJ |НFrd`ct#ݘn^2ry[(\>$,'˿/]_c!?k,4OW*9$(;w:»ieyf"QgIh kI8J2ٜIv 4G]RinCe]҆d;NSk:&)6Bvy]W++aE32:C5@AB~P%@I49|`n X#ttXuM`o,0)  Zٗ$` :KKZG#*|]%篞R&^"D?`P;c`" a)"1bW*Wlϼ?,oPׅQ-P17JH24$]Y tլ,pZV^bHd.BnIIMJZWv?s\YSG'3cMd.-p<͇-gmys,qy\ %3 Tq*Z%6:[KSe s:(kkbϡJhiC Ҍ3rSWe FS6'zf83接5Sbuk(MݲyT^GNMīL0nC֌TSSGOeRAr.~,v/s1`p-=Ffw?)&\ Oq:_˒,fY+ߧDQ *[1s)XUW%&ˉ$|beMLR THRӶփ5cq"7C( feNLHVvXsv3;H[ ƖEm=j):!=ˋm]C +k_TrO=עe[ߔ2m%S1]tsbg '7EkC#q"v:.0iVn1 9¿<h9ZtgGҜ05 4>9j)^Pu3z ubeLSRjcEQFmY¿u%H3*|1è{Է'#SB2ZB(a'|fl(L/v[yԥ+bX |\*r=Ŧ_&'#OVܓb.8xJ )Y -b]jƼ&%Jj:@!>$qЦ2'O^fDJA\/W{ⱎ,LTQ k5sʇ5GDHOJq e{Xj5Y,6A\H ةRK ZcQk3Z#)BND]b]hYfV-P0M!r: mr<wc Z܋T,F@?5N~|HtO/ʚEe6}GmkCqIq5QZSMY{t%I+v͆qyn +.+=-taEW'[ T{g| ͥ}Nj9)O!y eY,+`=QU|Yiaܵs[p8S)vL SWU |)\VY .32H<\Px_zweOag7juZz\c%u1pųǢS=nlP[z^&_F z%}nQyF++pbA͐55OٓJvsɗL=:K^8 PxV]1?C%ǡx`ݚk(/(Vv=/Z5Y*C}r'|y){@A&O&a"V(8]W6o^~9ͷS CҔળOZ|5/&q`XNo,}y1N g)Yuh`oߑbT&]R꘦NsҺ:_@*XJz#4}6ZvX|{gzAYBN]{)(IIhѪp9HkŪ sԐrhLma._(T k6q+*2q&HW^zPblIHua*+.RZqm`Ⲱ&!s-P}W}"M"«m0*^q7/Z|5Yse -pϘiwozn=[[P* kƫ.,RIz8m15SɈr1sRL|N ~~EiΊ;/]x&n~𢥋Bu-02) +iiW˼l.!]/{-UN4ggxXͩrx[h*J߼dJ{!^~A̛ 4%C[R@X7%dZ.B V>߉%"-&xx]u OqK0DNuzGD+kD4e]Hjw- z,z!SHW*`Z^lHucT 9^θ hn]jnK rNܼAr2~H l8qJeJ IzmVΎ. #YVtoo!5cqFgq p>Ck-ZD1>U>Z l `><Ӿ ͷysr q;뤹bE;- 6euve8d+G$!y *CE,0:7CnEk. 7Es^UÕsC:ȾYhuF ,T۰E`LewVϋCT޺4j YS hh}*b^S~C}k ֞RvUhniRjI 4}ϖe!%mS.TgӸWDKx Oއރ{TU+Og^ϸ(Y+$; P~J+ڷ-RO;~+q͝Sad ._KBSS{nYl ޺Y4MSg)a/Ƶu_,J6GW"W L6{T]d@ZH BŠq ^zZݫ/D./^]tr* ;J6v~%`8KW=[PZKU 7ퟧwĤg5Vٜ`Nr{mr(E4SU7^Oo|Vhsj-Uh 2#UkJG@KkNveoHCx9.=m*.Zyx*Į^q_ JT>P r3 uT/aB)v;W}8{A]+jnšKߔ}^=>L ajbb,IK{涅hXEh^W-vB*0x7^?^;sZꤰdpd3yu\q&:Kugm*`.HAT"ؒFkNNѭ)4E kɗ`ㆢNP9Zl:1ELy} s7JMCT{>~tvK|L@kRRKr#C*cA$O|cK/>=bs10tãhinAE8uZ[{ŧl|Ni̬ڒi?T⭨4vjNUWD_vuvH$ҷq'W4D}Pk+/J  U[كx*{ >];2q57aNuR7NYz[̞ȔJ4%q]s5ah~53(ze|t!.}`>﹋ry.)-Z} Ar%VI7f[ڗ}b3h-Keey>K*gYQ6V⨦l!cw9VX E AZc|(G@};Ғ:pGpх|)"(H®ªixn+sa>G U{mH+kz)qWrSq{FW䎩pI+qxI.\/mm72;iA*u`o/jt>/ǠΉ5=#X}K>-|q9Z,_~dWmL?U;L̜_3- ROp\I kU`G1 ``wrVXYc>ޛ8}Oab컌)^RĤp@5ԖZ EgB,enE@fJh,4|>av n Ў G Eҥ̦@h\GŘPXOA͵ez>3ÖC;h61R;4rY[j:J@MHh))@*^TiyPx Ye%z:~]xoثoXC X𨓪"?jb~<UgRs7Cײ(W<7H(olSܾo {+gtofk]g3WbLO*EO[V맗Md J\?BxIhEh{VeɎ*wblDoGkwBKe `<gʝwn|xonx) I|&=U;Q>/=%7̥'>H* c9s#*+ѥMOK2MP+|wósWc`IPNGբ!F'w0;h.ߌyK`|=GyJ\1]u o$͟Jj`) yU ::x76 tlɀ a- LH 8ĺ <?QIlN8 I"r4CJ&[+O,j5#Gs[7bߡi#Oq4,ڒ̓4:pr#ђv\3wi^`7D*޼^)*qHY>Q悲VyP^}&c+R|mp t²kdnW%o&ryז=C{gyxpcoX%ў!`^hEoH!Y9}\7GA{@cpkBp*UMn%*wI~]ÕpCS-G#ϓ= ?F]>=* ̌/R>r+JN7hp|G'hN>Wˀ!!PRb-u\7##H"(kmS庋/VOtKUJt*X[㮉ZET֯x6M@ u3s[cr3"kt מUrQ#f7C7'{?;"<&>箘 e*(|~~]8Ara $ε_nL >>3 ,h~M FT8S xcLq eiFG: tް-$d15\ ]^q㪫!ʁObǨѱAb!6@eZ*:۶'͎?p;%>a|އE[c'6w@.T^9:emv|hw#8(XpB9}y1"iŬ:;ޚsfƯQ@woc/SH)lj={o}3yӽ//X*Sʝ>KtZszwswFNlޝ<(Z4r{ 屒{/O=3 FY T+(In2WPUMdOKBhErs[VR1EyBwQDЗa3,xPOY㱙]5+fqZ)^"ǜ Tٗ5:9pDͷadr:I.gmZdϽ3G)mNK:[[x@e*8A|d>U" ;//ܶq ~l'gAӢ %6KaJ0J Y8 'hҵSF:q|ja! ur_CJoRG1rhVb`'oJ-恭6))ڣud{hGƥ@cL3b#L ?p3RW,1I]$ouvvmW/D3/tk+vyOo:A8xuv"A"[M5ow+_y7mŵY e4{ִؗ@[v1VS5&n [Y|NZ|!IVAVyg _'?{;_^S<QQ"}YD%* \\7Y3z3v}Rk?y9*$ `Ӟnhm8)e,㾠Ŏ+&M;~"*| MqhN&5QIQ<1J3qSd]Ӣ ͟R" cϧ<0aB/Y5s{|jB9&_6n>GCqwkn?4]ɉ T9Z =>`,/y6!s+~Sn#r)l0[E WC"Y׹",jKhE I3QU"q(b>`T|Tр[X*fw-GDܓܘ9IPH&-~kƤ<ўu\*nl1i);u37yMU{לHYVB8 PO 9E5[}ԳBL{@U?xI%0$|E %Y҉=z0ۻ;7-JΒA#*8 *&UxdQ9"Q9SHLW$$֊9(Jk. 3p R'iVU#eS#T"fR,Fλ!1A~'?266}#8|&NgL3 (֊R2kZqd| `+@g߿ٴJIR!);.(cWw+*uZB(]<,5GEYtˀ 9d iq I/g +u#o ;ن n_Q06Z!1S,ZI5U eQ(6}Ld4O~0veg7g5JyZZ7aP%{k=<0CAZd=ݵQ<}4FD"TGTȠN>O@Q++ւJ%bp6>4ߙUhh0Xr)%'xh3S5zSzo'?;j@3[7bb"ZSi!`yxw'YmFL1nJa=o}?fp TG(C m(gt#x`s([·SXWd<&؊z eʎHs -В NJؼP7IwPwy}@*HB%}7'E=Qm&x_)j=V-!$JFW\֊`:<+m3+*&]a㵼k*!n;/:^0L'zWa_V({鿖"ZPQeq֚:U1x\NXEYi0yCsMIJ\"f6_X nxlɴAk?JcgPW#Uvj+y7/ 4g23k>u>[׏W78 fKmgڗHNv3:!%+5ߏoh{[cPSGuXqREY-p_$@r^=~̓}Gko/)vy2 {zjϡ<.t#zo=J|.b3#!` \IZ|Wށãk^Q}ұx5?6hb}[~'?۔rK1 VG{ȯB}p>'m5>}'{\ 7Bזv_΃3L3eKAJ_iv^EB͎ˬl=E%}QTJ± ѸL=E9tUxp-.Eنb`%Tr5(pPruˣI!3ZAM?t/`Պ $~Vp5>2k!ɶ`7k9&@h4mFT}fzxh-SEapG܌I;:8 @Xo1 3 6>׮ekHw߿ $m-O(?A3EgLe ׹bi() "3Ys^|/E1[ñ܂(z'z$84@2s|͸ޣŀfW`O j5O 6TTy%* !V\296-&t<ݗ+ky}Hb7>wX}`eoGU=hb}ơM7k=ϙ92ST/͑mÛlv`X=+.+hn:{ 0{c[["61WyQtQlBgaE4f$WIm($ +GD'n9F@! a*̝bݔ"T'T4xcxq楿$go$l}kwsM܂r|+ɔl!8A,J剼X!U--Ǥ;?A\~2V,_;5CލqHyl|`dB=XhWN0XGV2!-&r,no񞗿o~ɕX#NcAOڍOǸgc69ɿ[`%ý!1~7y#[7rLO [t”^ ŵ>+JŌQS5n| ) ^ 0,f|7:󰨣m6 W8\B[N%:JM@(l6nP@@s?E^s9Z6;6߇8nS<(Б8̫Ѿ1G6|?O!dž#<(6| "!ڜ [!޸==pC7bԊEhkO-q7K$~N "X%B@sss͚Fp7; Kp9_}Fyk)z > >*ƆEVX|%Z[Ϸ?OCͷbPWјI9 =̝lͩiʶkVV)8c$FR\rN^dNio/~횟ɁS7SRH7؃wS_xϦm+=)ifZb m `y/{zRp?_y%]h^TymhpUk䷰?JFc`",p8B!=0[Bȃڶ ټ]qoGۂsooώGϡw݅-{AzW>E+zdp)ߟ.Q@rA9>zwGgӽ)X,yeX|ƢehinAKK[6n&3 ?}aێe㘘Ϟ³H*g?m455V~g4 ae%`k-"h'v6Y>IiNZrOmx8mߏ{z~h@kZ;| C^vk4 Zmg|R'MEdEb/< t-uibj ߼IO0S|6/7ykCt% ɕڤ/ 5E}-Ǔg_ssgTxWI eN T˂-5&?dgVH=}Gp▞!k ĹDU>+NټA" ΗМY_1z}HJ`;@_!NyQ5` su|7 ckxZs!:WKOb`o7Fn1oF '_!"P! HD^'$2C ]2=0VR!i]E*NymKN#M`wynX߭B_e[be8wېʟ*'y'!q 2ĩvCsT\?WҮ))]F=r2{׉VϕVB^-Ll#=S)8cEJAF_ J)hJEQմk|'֟zX{ጭwa{鱯cW[ZK9bbvL@$)2ֱ b8V)+@+mAfaR\?`B R[y?Z?'!"z:ljj9A 1) tnwFZم?Gn$v~N>Bg*B~;>v>rSlY֎>Wy^u)]cǾxtɧh>gd~!x(^Zxh Cl\ˤͬ-eS:/o,\PS#OgO=Oݹ,}yk6zV >.&m#*ʟ%qj54ֶ_W{.#aLc <Ѿ0v|9>pQ1T w0 _TqmاͫF\2,X*,X~1ZAKrt@sbf$ͭPI ?51 !Labp&a.Grv`r Y8DT-  c $RI) VBY(IAFH 6 P8~Y|#mylK0]`JŴbګн2,\V IS ZZ`rb c}8ܷ ۱0rd7:9Y~J1u BqKZC-Q ilm,OdOmmW+JInBCkϽ@5jc.?yS<)͵`iJs!q CCul~m yMV-E0XMZZqI?myP~ϝoN;N3ZXH!HHA" $G(63tȀӉvw{gz^OSj}Ϲio߻kժUϪZ}{ϿU[}Vȓly׶+=^} /gE/~1w]l_<M b%/ƒa$IuVV"7}Po|{%['@+.W?^{㫩>{{? Y(8Ўe Kxp׵~ ($;{&zF~Cw{䉛E|p#O%^K#7`"=]~< 4.?K輕w}erG߹#~&M y!: p*g*xwygiJ#Q>438V~RJC.]IQ%)_ DUv"O(s+6WRҨn`q=(y)++Ħ$#5ݾ :ig{^)xVfOtU! J.& ]^&9-Ɓue cp޶O+>M]MCJ7o5!f??_S",.pwо\X]3S%.s<ϸrdrdFEiW7,&W%<FNSth&uSC^$6(,߇898V:kFP.aY5"]$$hLJz-c%xL sx(ilvճ#ִ̥So2ԗXXR.PwDMr)J;bJ=q:)qK Ids;\ypI +qnf)\F߰^|q#l慀 awI,3uDzORfN" ~Wl yw+}ڡ JVsØ,ׁ `h\I/Gѻմ*I1)8g xO8?bE*Jߦ(y ]-ػ*=ې2?,9 ͊)+$y1yxX R=G IDAT$** lʥ(3#UNt| ŕxs? ]X%y,ZrW-Gk/弞||yqú,2 %u9 &,h(Ou$eiZBi7#t;@FY9u$,Xr fp#hʖY!륆Bl2qU+h :Y+O}4++Iy*o ܄cS%@~1+@T >Y4JEs~shӟ[ yk# ӹ`|x1}[{# !YR `M0G9^Pӗeq Muη/$6k9 2T%v{B^`֝z Mړ,y7xX`~G] ^c@)o y*2r\:!SOGX ~BsM:dzoArfaBeG%}v"CX7ʴM-AC7&YvklK2Nf>Pq~WS,j+~ =hn,Sl[tVBӦg0BRZg˟>#E(/~4Wa&9,$qaiNvyauo[#: 47.80?Dn+u ߑsF].P+q0 .?\E$۶i:4eV>1h.6R-a 󚁗|~4mʳOU>_'~˓O<-o}F yA若vKt(7@~ݷzZJ{xg9#.P~y Y4D;]O$^΋+H@\h7__#Gkgo*Sxh)Ue,u "ݵIŜ}rޮEE*݊Ko z^)@u.\ǰF\VYOQ] w{E•=-5:sGR#oL ", 0C-eI0v)/oV߄e2ӏ#i YAPs"}&o>b,!'VAQ;ʵ<}]yڙԸrԁ!>u-Ef̛u7*l5Lg7^$ܥCuT^2Mu}/jߊ-)VvM骈f7LOWkp+9Vq_~<?h3-+ ?,KLޱu4[%& 'm/؍zP~8]1ֽnwͻA6͢6h4m߫S{k%e4c]q5W]&7ݭa}_O`Q?p}8H+F^B$@,?m?/k==ӟ] WQX|Os!&$7 A/P C(L!6os;V1+ בfa0|o , j aea.G#HRx;`)1bs.Vt64QWp:bf!V6\0j̤rW"2Y+qQ 4'e!AiiUٍy>Lպh|<,UBw `l|Mٓt`<=sQWgr=cS뽦EY\)NX\as*&cFEdYJspGkӟUVBE0 Ywc}=ƪC 6@t26ŷ f(MTYZ:<U[ůa8R#Z qkeއ} 6|=rCC O&˩V{$k%<8?YDLzPg4˾q Kޔ=ncف沒` }}@ro//^"#yls%l`(߷C;cO>_?"olnQhn%P?_+gܳϷmx>#3J|<ŜYދ>(YBAa")-n? `8.qE+ߘ!+/gEZX-#TZWAK WHlkx^|~܅4a* &Ǽ՜ե:cCpƹaHָԿօix4شTeg^H.IQNTM+$+LB@|vכrG:ȴEIJA*z_zpN%Pw58|Ves\iJi* H_wȊXdy[F l((+sTꜴc^?(M7?uȂDyL:=4В3tLK p'E"=J1-gϻ^ߒXw[>eWmk>[w}'|'Nʉ>lC'I.bF 晅.;`6ˍv[9umɭq d!C4$r]hIׯJ敬.yĸ G#-(,z/NS%+;hFb^3yD# z[S1XSo]H'OD|rezbXZ}(/ҀU@]Dž35 7PhԴoT娞ڏŪt8֗s2.?CxX*wMHȂwfnA&Į*Yw&VOy:sR BF"G&f^J)򯔼|`ZQf5 m4Ѽ91t` E<.7Mhq׉QVз>վ;/Oetg9Ro~X ǘ&+H 4I鈨yۛ,bA_&t ʶzox$ ^#:mn 8*qϴfkκ+zxڢ6+oCH3Ĺ)M\eQF9h @hny+`J@ZqՆ 'k}^ye}L>ٟOOg?i /|Kg]x= _oD7|_7^?JY1(04m:ϼfюs1"D%vq.i!G`-RE}n q "Bpg%'mSIr&Dv+|Ʌ.j6(nY-X밫sEk !W-҂gBoi;$i.y@G',&Ң(-bx ' wU<ՒXyҧe.M]*d+힬[y" GmEΟiKi9AP)]].by *u!_}hV=ɶṠ}\"SOuAggfY$8H1&CYo||IH9;$ eחP3(CNBzZHwAo$U|~mBXQ*o9BAqMvJ 8* y%0>D_M}5u/,Ԣߝ%) yg=VIo>ÒNLw $чehpPZ+Ah"g~ǞDO ɠi:nhn?vC.ԍhRtu׮XB)k ڷ`^ )GGhb4 4 :46:DgooSmE87]Sƥ4iɟos'mnZ}L\ Ɓ =Y^o?jÕyX47rd#tH.c c6e<+ƒ,6mX( Өʜ6z.Xr]+;`:uS0CݲX&jӫzV1WtfBeOG 8;H@֮R7y/Cp- U\&BaƖ(D.Xb% M,4tOţ.d + :\]K(ƹ_+K_ #fR;4b F*;;ɯ祗_ɏ- ?'\V:\p_< -R2$ c@mGZe~7]{suQE6W)|6 E[-\Ch"u^y '@Jn -\kEKh6 ]s LkY]ỳ2wx!%w 01RL͹ѓBR_`H-Gۧk8R]GݩKt M7 TEty ;(i"YȨ0dIm)fĚη2 ]$J+Ivȡ 5V_Nq!ԗB I/LD^Gj%4߉O:jdMycKk7>.qdi]Dg L-zNbR7ZP\!å4*s>7e@9pGGdqGIR` UnrY΁2Wa>ysߤ2aOV1kz$Xv 'j{~5&@AR@F0 $ K \z4P@a|>|ch47=٩:%>7OqiKX tBnśwyDqԮscQU.N|=E(598P. i^h0Y'z>e5AR־+:Wy= ǃ'h1;tZQ hw܅5Pw.&Zn}w2TE3]R.|g/=wv=} yJ}9Fs;VA!j׃Ev %)J[cpXijW(URXd/IpJj>z;.;P@f@jd&2 TF]Ir |Nycv#~Һ4w<"#+<<U#Їӓz={P>h;{@y4q!={e6hm4reŔewʯ6_5p'f7@(Y=qy|36YP>X̅Ɣ,ezhK1䃆˶GWe5K}fX|C=2 ?pALhÛDwSIubhhsH")Ri yI* o*,֗oڔ6H ~kK#Hy%6nv nCI7#0(j)C%k2)Tgϥ3)w{yܾˀJ+j~(\bu( >%v|uhy!G١N@.i^p-:kHmi6F"GPdaq{Cn; %ޱA$I!(xb#J>|@ɽ IM? Tt&565wZdF|P"9MyS41xD<] Zw.M4J>)Mr-5邏 r~/r_! ^櫓68551îMKr~pKX" @Ʈw=*,qk(QH8+m&0#g[\!_I xdQmMg7uwXqD${MF.]C@[PyG^MQbG$Z<*0$PRdoq>{+WJc0E^_2?V /}E܏ז~/*~I['1&pdQqhj[58seug* ṕr~V V|i_tM}&C9BFA$L^4jg 0{ l7ЙƜMgs`.rΦ>Gs_?mڼHViQuŘ r8TlVo;_s=xW!v/;Av*Ҹg\mqG$Oh!Iah5Df`JԎcD@a5uq"Lպhmq3"C䈢w(9mTG^aå•S? :aY"8hlnq )6aaI#3]xD_ϟkQ+âaJ_g`0|0B,4݆h?`Z@,[H .d&f~ UvH򰬆rqLb# THW,dZ|$(R*}ްK&J>~66eFhXtܢ$fs>)S)"e 4Aз|=FySkDKQOE1ki'^=I >G7 XiPfpB$ѻ]F.?ZlRJ+tCrVf] mҠ]~YOt6{{{{Mr`T `4wJoL^ VvVЃtwLȁߜmdai*L* MJ*k4'ZSpz3Ma`)~#Zi^%׬qsRR +/(\Q Wq%"!  `<ŃnYBK5`?o-"^@"8x[VãU-?UwM :[åtZWU܁KA1,諎z{]~|}o p?Vv+qce!$ [^sVtyRGT2wo`&'owdנ$ɽ~w&@y'P $(}Aˈވlf}Fnh TWXZ&&eV c+)h`^(0fhGbݔLkz2kѩmrJzF7@RcH){_/okUys@|MW}:QݪK{ͥ G!4!3*NgM=%wgW%nZ^KL#y\ف*bke3m(l X';%0W.F6cBnV2:[ao֗I7ZNy#qҞ}/UejpAwIvd[3&N#XaQiK5zWߠTUEt;']DW8_᝵Ӛo+m XAk netf;P%Y*,ct~Q,7J}>_?W}< !."1@`q-1N Prُ3y.Z3po+MAK rv̅66FK‹Fy.t /꼹"_W,\44ڠD&t4p.mTySbW2Q؝ˢQ{O[[{*{Lƪ(h_rh${*BsqMFJQk,cT[ôxt}x 2hcܡ ;wM[@>k\{2OQ7)(üӒg,iI2bċv`9{VE^?7b!+(<|$HV+MS6v2]ރCHs[:6l#d'#*s7Wc - pX林\ܪJV<ԙHyI+Pt=h~nŕHfy_;)Gao si1Ƹ(#ɥ]0:ud,3x0ݥ4~ļ{Rs}o-J}^~/J^|t`}a=1wȻ|W\qg i7!c ڽDܣF`)ĺez@TTX]-yCb#:C~b vLڐ}VN#E6G/v1b)q (Š"A%Aз4v4G*vHle}p o s{jD>hmaquN ~PSݨPI=T+G s=]Ls +PwGxz |Tw)iӴ6UF {69)|ZvCJeңJc.lN~#[(DwT MD# +]Q&숀JX=#(]zMwm4`P4V~M:0L1 ܯBʯ8s^YΠQutgYqŲcRxtz:7A\Jv̋->? oϺN@2P\0SV6+Q@M2L]ΛJ$V 1&P: T7'~$PiήK4`+.N[ROQJY:d6-V=D fZo~.)imW*BW~t. k*(yܗGJZ(nK$*y@#+E-@t}B#0hԂئTݵNJiwF.eNbYt];P,,TuS歑E9]{"+pmZc0Ա Yz(Oh=]q PZxB& ^ MTԟvP6V%-4HQI{|3Ws0 `o++nYrK^j+%w|ZSSߜҲyr`M/߁ 1J7Hu쀇Q K`( h)%(1kv8rR9`F3_ Z[rU[q X):-үhn㺃wG~wD|SKJ>/ %z7|.$<&y)Y˃'(?Xc^=Ŝ[cа+1u@JљK+`D"AkȏB$\t(|y4RYs4f!zrs_Sq/ToFݵ}N)I>qm\d lG(Hi@kUT8}ҟ>v_? tYpu3][)(,RczNuD LwJ<_er>KRŢ2MVd4 |*8G= o<|(g2@ e>)`Ea-j#" [0q\ vl ! :&>"0gbN gy-h䒊a1 Y 𗅕c\K1 <#-lҹd 4wyrVc,@/1~.PS@k[%ƫ°oӬ;0+tFKWGն hJ0;_9(GOpÿ~w]E}#[W,7Zi3x4pvD߸<\IF!n +,#R|{Gm"7/O~LO~Sd[BP,=75$[¨$mq]* aklRy.xh~3Ps{:5`XF 0.aTr턐P}t֪8uh{hIQ&tRʎM1n][ԩBc=i+jZ |y[)1^Q]׳EѹMet/r#Q^M9+X%ם$פ\zu>g>2JC>e?NP󡦿ִVZVW:jjXUGWss2]%iX%6ɭ@@a]ޥeks+JJ!Akbye?up0CV6(@a`rp+u8 Y iRKuM KJJ E+%L',`Ia}m~V2ϭ5VC,zk1\d@r#-Ͽ]~9=g?+?Y~'?[a-&tpÍo|ҢʸҘC8<Skfw* '@v(Ő-QSg}ـrǓ+(M>YTʩ~ 1-\6u2EaR G>κLV @|Ckr$kkKCZ5n{%x[ /%aHnᓥ?`y.AkYe1/os,^捡F6L-Isw~[7(2l<ӎTI=ؤ*\Q.ӷ.`ES7 7#>Nyf=o0w^5-U*tt#RjHG"iIh:geb|8:9nӋo hD/k*+g7rjzb/ w P)\X XD/VHã`3)Fqcf1[nVA#)ZVPPۡw6&6Xi%%++>}(o[#v IDATlKȺk ޭBHYu\ylX7-]?u.;~@[wϓkܶ~D?1`碒B輬 pgh .spuU< [uXg1o[?Tњ6 CaOwEY K*Cu)n6$A5.ͷ2)tgO?:gV8ۜ,,4#ύ6< +$(O2h zZ^Ԕ']&uv Hti0esf8GʼYE9Gg}OX%v_pZry,M4ޠp)g3ЧB:oQCvqmJ3L[̫k@V~*[% T{fV;\@)$"\ncxwۖ;ſBӤ_s/լr̍ehKCRʤlE e'+XVJ _l ^B!ܣ<3zPִ*60ಲAF{3:ꖾۈk;+ш\g`s1UihNE劔 /d0 l?VTN&7KrqB٫+\#Y0v4"fPGW:G9VPvs q>F+ڧduXJjgD+ϸUy+mIv}1{X"3Gv8?8P%ՊЃO>oCw_}<[䙧Ӭ鞇ʋ/(_yW$ɟ|\ެtٰglak!&A,+AH#~.q6L!| wLCÍ5x' >!b X&9h; (߼iAUz! ˩+d3Ln9JJ\aUl"](~{&HVf1k^]@MIg\%i;o_o'QG+D' hL r*.JXGPR;Y78ԏVEpA` Pfְ 9l#>3{ۮ//v=!>O?<ԳlU<[_}^ė_}E^|EyW0@CO7F-قAveCm|rM/w\Ysy<\߷c ~VYcds^)`mn~>mt/)cǽ\d5ĸ,p%H\9 ,!@~+[(&긡3%p7Ux) \K#2J݁,v́f.mVAVBewf(gm/9˛J rwPzU=iCJQXsaM9e:wͲa *rSYқs:*[Y z tCF7/[7RvxMEja9'kx}eAI"?qf2@q>XB0㢬4!#!/""n"ke ^kA6{52pFi )5ϽQjp9:~zǖAiBg}.k H~n.qs->t,E THY:j{n%}jy:6NsS!\lq]燣~$ȸn]K=oq]𖶍\<@R0W41'Cn_>D(VVD PoQ=tnZds !#W:"5.8X# @}.?]Pd3 K;I8'icF㕬i%8YVM`1v# qY!qn7B7E| }KwK.+%a9soǒ2IyƝ1gSiR(xޘ dy>S L%/"SaN?;hYVhpQ,|XЛғJnWi6cs;gJ{c~<->ϝ87u:9z,+OiSHaM:> Rg" ;)e:hutkxjlI6 iHRːU+:u пNX]r,oCSCi$@mF0 $[m0Pyr %LC!#()|v4P\ήJnhs-S=-CgqTuVc~7 a`1l!1(cЃ," yAiCA2 0nu@vrRjph#V{&'oE-qcX۲/N17߮/ȗZê\$-Xe /!AU\SPIW[$ 8 LsPt},@kk%Ycw7U^$ ֲb |3p^,lfύ4nR,CiBTHr'#e$)GGY:Ӈ"OW(_u8fķbQ̋BC!>ųh.;?1+_s_yj& !?w֥Ώm>x,S|&C9ೃ"jwjY? ܤ4]RnRҔѴU5O3ZѼdGJsԮ '{9\%GeRk{-ʷ},AaIC:A]2\ )1P&sW"+ eP\ a7c.}wwۍTF\e_ײcƞwct(ƛ ]YAeC1vаS4>"<bGrUC-ݘYC}aR,~"/ίf2Jؒ4>tJ ew\O"F|Gv#`$"OnS1&J41lݛ,yRg%+,)Iݠ誉rA] }|waQOY%,giSqi6;)=ZұL ')&>_+0x3i)ħwKvʻ:3w9NʊRUߓNs4 ⣹\bW-gs,VY}5M㢙d-$I. R?@*рt NМk͘tM?ܧn_,V2H%ᆅ` iϒ g<"VXƉwUr[ʒ:- )ꨀQlP$L ͆AA y΢Bۙ 6!WXnIy5@&_9gLuWlWM|^n2 @2lHv\AqI T ޣoeN)+а#`8`[R=EZ \2Y5̵o= ݐeiByhskU .I4,BF|׹BZlv98MGS~HGWLU9- AQ97lh'CQA;g,f\ZXCbammCWXLKx5ŢZ8oFmVAs8ڕ#7V_s'NS.I-r* Q}M_m49ݿ2ڌ},W|>w,Gngϙ5mH/fYRC=}*ŠO FRybn$YsaʜM\r]%6oнt#p[W3 gf꺃ZV7Ŭ"+pBG$Hy8 K5ZnQ/Wd Yb޵zvşq;4<@0 )g@P jĴp_.MY k>l]Dtۏh$.)0GELc).O:\ &JgTȚ$Qn ,@aib*uͰ2um㥆{"O rM,v:soI=Ppqg;G V."4 SFF'bBXۿ-_87?x~\+ qv6Ϳ%@ >t{*5RAέ#o*yR367!qvyzr `>ZI \i^& 6OiiYАeXJ»s7N-9:_#kt-,CenN&E+,c`Y<,S yJ53] H i}l3Mx`]*e E hmwb:X=WJ.1+9q4\wKڹRPZѨ=qt %]h3Ww[XXa [PV P-qa~iR~ }W(:2~e{u j :-4-&pẅ́hn.#pq"vVUe7tQ LdP1=~nfH 6[-,?Xp9;,NV!8v?p3&A} ,5rwp-NW18C2\yw(*y19_\g\,yS[,\ q#FXT2KyeFAxc\  s't5{Kuh@%g'ES˻ Z\:/Sz"'%e#IAvJϺK_LˁrhsZ__CX k\]QS)Iٙ˜zu_<߫6N:s:)0o*k| 9qJ_Izz  ;*k智9U Vq۾Rg$,b;KܱE`/Gs1"  "7ꗽkLu3h@o4mwAzDG뵘<BW>U0yPw'*Cx< +E\wB^G4^cz+QAUR\ՅxƜ7|4+GXA|ٕTO-: %9[ 8|V[ 2o(Y#Ihu0E@M.pw!$iu^wj 0`>oi|u|.qg/bܙC:կ31 AL.Ayx%~^(QwoO@e'!ڗ6}8 Rrϥ:ܷ]Aex"0/N@.iOueUѹD&r+MZuZYM'USyXO/9Ri,&؎MYjy沧1jI.{XY+kumXfkNEbd] 7Dw7x|/ 2_@twdzP\ܵOYnclևy+;mzk4F Ta+cVdaxA h` A-& sJ|8u0װyy>EQފ`:8Jr3ihʊ+Yc ܲmߒ,[ DK0hj"pٝ=p.n)=֋ j=PMw!0pO\;Pgceavґ (A- OL`*A|!tYAX _}5M"RVrlEe1Uܼ֕`i P6E(gwTQq׵!i:= KÇEy<#&le'7CybS߲y6'7zc/˃P.n?/Ȳ"!j˲ަ{i*7˴.N.iKg+َ!tsoU˙d :SFLEx:klX:(WVEZ|'D wg*tRqMy3~ IDAT}FV,_V31kv~!@R(%ς |i'*Z% Z?ĺK ;@JԝN1XiarRb4F!Q@nE۲moY`&A *DVd9>Ƙpk3oؐ2@=_\fnc>[U=?>Ah,ݖ0 @Mf>ӌx;m@P` *+Q13PIs<(y>Uq69͋ƕ=M7x#(`E9Lj7 ~#:mc#29q6>1]EjpoD(YNNxQ2ʽ3XiI9H;}3)\+ISE8W22'ѝwU؞@smSA"ɍ_O[5MęKO'//>mڃwouyJ^yu:8+eܞe%7o;8_ހo|NyS?'Ͼ3kg_ zީ辰> ,SZ]zi ˀ1kFaY^F3eϷX) uYxP.LͫGպ ;cFG{l-LPVz&Rmj(Jyf)nI+R,E$0H j*>ʖ%jNcp pp (ǘ} @kduWPRC[\a:Q\Ww!!yw]*JR4)J% UBV*p{F{e%``:3bᨧn{kXGPc@衢L :!C~>8$g(#PǂHŖѽc4J\iSCգ. /KȗB%dz-T{Ď"qG_=:+"4 >4 I汄1ج=!C*޷At P~1A+ kvt@zȦGYZ4$0WԢT;*(0/:]gyp碵q>}=~uw7^_wٜ]^}+Of3%/=-w : =zY)o{oL7Wf}i,>~V{WjVm=p͏6d)&ͼlIy,?j<9W[PLy:PS m7Cmy0m]ИHJ oW”w"#"'].W]BQ]ǫ9\7 s_x^()HA]@@AGB :z,,諤y"!-*ni? k-608)W|u]^c&d-3 X!~W5&,7,%oVڨ g,@1VR'MKS|q? ͈1lqcX$3>7PbE K7Q1btDr\]$yN|q;+tdm4 \X(!kKnI) l={H|S`za`YJ8O~ \ FmL@el(V%_۱a)%М訬3L4Y_읞#R6CkMߔis**2gL<ֆvOSwKW%f7!٭EFyo/=/O~< 0s߫+/=M{zyYo%>g~Z{H|SFt-AFgay=ٛ~@vɮ9>O.O[Nw5iqKTrߏ\kJwl) ?Y&R!M:D4 {(PСq6(*ܖGTRlR"0ARh`h \HnI7裫)L(*C0Z8]S3s% @ S_Ȃ%=՞[7F7b\YN {gB6Іԭcc MoG~釠R 4hp rfTLA:@(&~J{t/e 04t+ ({u'e4M\'fA(↍l0 h <ⴻbR.΁Fm¤͘VWx^GݥdZ6j|^l55\ az)Tv`)f\ "HmnԻ-gGCEVTVA#D]h\`|m|^?}-4ƶ>Vej5 JNj*, 8GmYaT*Rݽ؟'gKx0Qv O|ެ/>/.f;rOy >6' 96 .k .o3XGrਜ+`Nu:OiQX/OeZVmo3Նz/ָA'@@bĭec-.>3#̗;Yf6 #Jb e@` Pj@e7Vhz 64(A8@+/rn/xFzK}(9J(_@GgqVWܶ!mCbp=l] Ggle$=6A!(")E]坻F]^x x n:w.4n| R@f-S^߸`|CEcGKb>lc0XT>䍁lQr׵nkx&Uhu+.] j4W~Sd[CŦ#6E7rD'K(1хچ苒6jZ/Ry!ex0m a|H U y=']]HsXϴ_N=QrO4LЖtz}@~?>| =$H Pͤ2?߰1#CBBr" 2(J" & 2,=wtTfs[u}oz۫UYYY'ΗY3:ؙv,bYd~\_Ǣn/Λ IU`.^p\T|/\v :4Yȁ˕!Wp}\1+bu\^H4-ILGh b'7EYDk3H z-9 Am/\U@0!1Sa @ +)MQ<7lQ6!f)/[Dѷg @M&tP32j59}l+u P~ t 98}cZaM񬭖1wʧ`1Y]ɚG J]D֕Gi~0ޔo0N@g| E)/%4t!J]I_a|Cɋ`UE G\Qc940^ I>u,)v5_eLƒSWߡ}+am:Ç WSCU]{ `ݢ_Ǘ_V߲>_Qd:?'-\HK-7*CSR)0"C%JT)͡h0]*0&$X7;<)J7Y¶eAn( m}to@+@mgDe>s1sTWgJ񢄀Pb\?v 8TNXDfi8hC~mMhdeJtȤgH%`IwY`g3ʹ=YeE4Z#*`@h I~זVd,!-4sd &qqLaGztf]2m|GXϙ@ P1t&˴te:c '3$+Ae(ީYE"zNYu Х" \H]&ں7w7vnQc:t:g/gqckh?{ P-I+v ÷ 8_]@zl ={ iI Q$1V!`FCtc,6̔kR*WSvgiTQ|%\ik[]ߧ)jN\}`TIG' Q[$YO}Ҩ2z \*njɮxE霂1Z1rP}ҷ_&)l*@krl&%#)* ܀1"`[AfTIL}e%_Ph@!2cT^edsTmTSjQ1@e^eL 3'w_n/qY%e[a <ꘐ ʸe'5Py{s9XDyz%i+C8X7aMUZ"!x܉szw8c[}zǖFuhp[;V)G OR',Fv!uwfٿzN99ܟQ7Tgρ.89~Gߝ@l7M=$p(IO;GpnS9Ṛ+kCeNYUg81Η .e)b:0Amau)R*UvJErYLfWVJ5<lYR+_*_4"p fj`*8m5RkiVɔT;HqE>9ʝ*dt<+9ʰH6OI B.MYDoI@!EȔ8D>yl!' |i !*-pr]4vx`1coTewZ\hX!Y "eiv | 84?_AA0[b3,#[h"dAWe~*<Ȕ:Fy``ISZp7㵸^q " ZL4tzkL^)(OKJY#ڂ%iʂ^AOSx~ӓU@ėQηE.۵pz%\JW6vŶL9[cg WV(DjGo>úNEA/o-;6k_ ٿ#nC ݴF#O^ [kDp:.8<0\ubb !}s0̳ PX))޹ F#ȔԔ͡a%%;ٚu4Nf]Gr(H Tn jxe_ր4W?2d@9:dmyU82Cih szЕo B`goN$^#Gv/QXfM$9U2 S,ߥ>iK4+5c`@YqXTi|D?5Oۧс SG-5SxFp1 7i cj0CPp<"RWO" ASр|gWA <ƶ9c6-5ț18T>$  )a=Ah3/߂S}BbrrIf[mA6 pBx"fa(yJߺXo9+>x2q "o2(T@x(rֻ^|g;t;&uÿù?QK1${qt}2:wٽbB =ržu•rVBHVabiyIaPS@R+] T/bnX!6 x sG5)kwNJ3+jBEM݂o l_FbURc"0+}\(y) MS'ӻ.WS32#`JfA}9 I&{>1Ak cNsгccv(Eq1s0F7h$RHU`ePC.ͻ T76<1I3~NpT-r 2Ү` n従y9Õ,TG&Tr5O =,>Rs;,Mˤɮ ~ˁX/lBlqJ`9o *z\ڡsxƺ:5]] o.m; B}ygzw,:fʜ IDAT^dիN łz"TV\ WmkնT}ix-S9.ج ,i_7.% fx?­:|(vs\IŁſߒqٷoaݪqwm'Ǫ+.{^U>)B njuIn"xF|ً\4sO?h6j1׵dі"N`.B}z.(t0C%,)plD:-E 1%ϸ1fkEH}r{=݃ȮmTL}aNu*@=a@EUnP_ T!\L=wb}ZKc]0R- Q云{u2!h7ޫGMB&6Yڭ9XO1_JWpEZ_< i<'f % !U"s*h>G2͗Hl@C5%;,>D.S<'4]!>@&s=`BA y/Kv7r̭ )zs ɢ`kԿ]}cXr?%C؇9$w/]ihg*z}o86g?G}v>&JesZ2G,'9od Z<Ѧci۪}?9 ]L5i P$0W9 *Ht91O>>jZV1F ETB\R^)di (Z'L{)%x"S[s'L-,ALKRG?V0|xa~nE`g P<-}&\_ޏ%$dͯOdHIPfUn+rx.ϑRx_|\*ӭm4had =I yl>>t$XܢȕFԲ(h1#$ A=T6/u"o .XV` ,/j˳|PPsVόI _rQ9ZHfH[/"0.4(EJ"rTr'[D`^'ѠAfc)"$(h<P,larڏN;F|An8GuT'd)4$_)Iya)e""̀HI,:S"8А}cICiTש챬 85/'\~K>x_x`y}[oWq;i{gUkkwlP-\c+8(/eV_ 8sӬ\8ZiF53'KB)'[{Gt 4TE] 6u%dnbI\NBabsd`Rʬ|Hi#To2[hQ̗6Q9/X0X*Xo*@(\bH +J 1+@ByP== sӮʲg2z!{n P*ۯrA )Y@U 7 /f,yR5nt&/̑s7=5? 8˜#QMLgЩ XR`E3"6,^)C񫦑OH#G&sR>-磙˳-]r*/} .[ htvW>gw(X9zs }'}\ WŸ-Q e"X=X P~ҽ/XBuKL:z(ܘpk}b۷6ioۿW5|ˀ)KqpY%/-e6oʅKfѕ Lk`##O/,S*(ON>Rj֗SJS9 !Ij(LbDXسQ` m `j`d T75̫ΝhFꜱ|WƦ/TmT, *Y+ e\{eJG3sN=&}HHԜA|Ev8Ru `yV_Lx29.LU3shr2E %H8Fq1@KIaqߠZ 'ȴp^}qArA@zܘDI[cc-PʲXT!fJ0uȜm]rA~Ҳ`Q/ ?y΢,8GeAlu .ʑɕ"C UфԐ-4d~ B@tAln~9mzk]p7d1iU:׸~_~)Y`o`s^^gyt;v)+q'z%l+,cuľs@Z \7(_\,h6-, snuS0pRAL sYij݇1>( C!ǎt("ʼ8*p`ITpų`CoQ H(kTt;gl6%S{eTu&_ѢqR@GLMg R=e|L.0r󽆊ur1cl )e:BwBGtfkۯ,̼l8GR%?QfFvB œw3Q ۙ_13x.1-֟p`'h/LNDzQ1}0#ix\V+?٘l ŕU`n[pPls~Ӡ%Lpѳ V}'-eLՎրT EpcWy5X-=S凪9:vDá*w,ڒb~پMmƋҁP(r [e1]a4a^)%—xYEeS.QO}0xQ +ZgkS6aUBzn3srˉB LT3(AfbX/!WZcW25 L, RW/~@;9__^11ewAƹ#6Q#Vڑ6 |~;̿2^¡XpQԻby׸N9X}R' ?zWȏ 䖖[\wwk̓Ksn}RV\<~W{E~aG[5t߁m=[B6\UvEIʼ'n)fF⻦J?L+ Eօ|NJL3g$L _4 9> J 3_*ȩV]S֫٘ҭZVN 1wRHshxjl5Gu }J|{B62 YBה@b}B|m bB Q*l*Y,zKH@>"N˂gj@Ǫ:\WS(1̳[>VeNORdRkcdt=]|71Y`0z\Pi^ޞCdṡ&y `Y@1CLa W y)&lU4@2姌n, @&\/ 9@ϩR66^Cl  > 8T=88\B յN.}J5.ɶS@xi۹O[ʶ0[W5ls]v]u@andN}睢ta"KǢ(aK~O B9ULYc=Q[T`e!ks"bQޞ2 rbԜ/n;`",zA%)PDtV̘ 3x]0%).) IѳQGr>tyCan`)$F ,?}"mF ;a3]87.=@'Ʒ>ekZ O4"JLA‘_Ge2ܘ(`f4,'bjfĢOZ徸"J``A}Aw}ePbgj}e4 _sJsON}vL'#{&] 6'CM9:3d?\Q!)>fA~W^b9]q~GkW}sCU~M .kے]OY4٫ ,QfV{;H{SºOYsߜn[cw? Cj`ܼMe \(uz^ o:$2\xT@|)1 Of U2gȄш*ˆIRGi+ݷLMN:5@ՠ-ܸ2q:scgxvU<)\ǨiMć?4x0GWla멕:=`NZ$+xߒ@(w) <ފmc_WV%o0|²?wK*b]<υ0|yM7"C' ,5EtPzXg`ҧh8APn , hd 0o:*r䁕no܅oFoϱw%,uDZiUUFwW X@d.*> 4X xUg) usp|#֋,bV5CSXVm-`ml8M'Ow.p QlSi|eCUqj>;:pQR@pp!I a2R(I9/ٝMDP[ %-5E!S)L}[15RfE5A=AtWroy\W߁{ guvlзf}mSdasHߞrT4O-ۺ[x/㑻M8:0*Z ZAV=(+kȿߡY։Ų]o ʂEjfAnʳ좁`FO@V$@ E5'Ioe[{6|0.N9Ii,ʫMHApFa.pw9gl" VFfy*8 E~!UFJNP9)\s%R˛ߠS%,U2$iB8@g8< #~BSv.#!$upCgg I!GgX`6zl Qeur?j>E`+˕C[hX6g#sdjrUF[JAMu4qe"*D4F/eL('m}9J~#0mpƹ)?P. ?b3cVX'協@8 $T(4pu^!਋LPsúe Q56=00asGﻎ=bao)w,)k+B9BU#$,!s.cbbT#'1V#P*rXqϰuIW;c1! "ZR[}9^oo8*^m 5 0F?>PwYIJ z1A_]Y-\u ]ᆰJIVXRS@x}{o\QpX})[s{&_ ]#Tޤ>1EA_z=G+lV8dNm# )5TA#Z,%jPtlc|? 1p4`uP`uuVYݲ} ;q(́s"cq2\^1׾$P l@ϔk4ut=J9g&Pꌅ`6Wi:ǩR~T-$^ #} L5 _7IDS+43Q3 #aw XΑ]Kˆ&9%%-Dl IDAT!޽ZyY͎D_u_Fڑ, % W29d3(<\ra& 1CqUEHZ=bbUEz'ݿG/>n PXLpAx&x{8qضz{eu[E2a}gIb@n*WT*̤M.VSQKs\zwEuK qn:O?ybkt #lN\‘k 9Ǝ|4'@؁~v^x{f+֠ àN?{]/[} ,2u 7w2rʾ"P)9 MAz"Uy+a &3?,pX)LVW^SN -[]X`ǽvߎ?6ch9& otU@*lԩh#SYO{x|u=#C.WTE~Xc $I!̲'5@H DR߫d`SG:I@!i& 1{\ k ,q:),212 |<=L~MHѧxl_A'#iJ&:˷AZ,} f\cmrs% <7 =2HêK |ߕG~ ӧS7c#gl6 )@x؟O#0wW9jR6*}vL6p4ʕ>ׇ {'toҽW tQPUpx=+/SZpY]@2=A tqa\Lde5Pɜ*AT?yQ8aƔ@aTQ|1bB V(yxR,8Aw#M;0H<L&1MP}Y/evJ]h:: v~W_Y Zyq=@] iHYv ϹH|~'Wȫ&/ʔE.TmB;KW},?،<2hՁ ><^8En_CDv &0[;}󶵺e܋2^p=i5f a+Vƌ 4CJz_2eP# 'E(HY%A82IB&9(/"sVa P*a] 5 OXbI\oJsc\w}hٞFRcp\XKfڳ0݆7h9@+?ܸ,!6dzh.:Fwc;@8j\`Lv>l4cvpXF{&>xkq(kk`8KeYQi\(S:p ص@otv9@LOq"`&(D;o-P8t]*yPXoew30'FM >]12 l (s ڕfʒ*0;T"񞕬rU_|~]GAHsi{ >Q2=|l@g j06+\Қ9_.k *(l_am2!zޯr&eIx2:3y@3!t&-ހ;ofB!vZgkߋN~.D(/OO&cirs=*2bdE$b?ɛE\Is0+SC4S7ކ1D4dSQ1"Y4Uw o\*@%LbiUE=/lXN8,+D5M00ʜPM4Дb}!@iR֫2` b٨Y\x(# J4lID\L,2M2ų\cdUW0Z G5,/З<}fNnDCaOoe-4Wf*/\!fG]T>d''uA&Ned~G!6.@ s?K,t{ vFdcn7 69 FՔYvf-"ȣafҽv/?\I|7![7aa]ap6վt{+/<8nzp`\.+:c5A⴬}:Gϭ/5J[D}KpROE  ygzJ#![2 jBIQwDD7U:<,7wp 8̌<38O"1MEc}SFRF9'A!V&AfFɧ0iO$EG;0~H@#>%x?DZRIʏ2)zh9,NpgАLoaN ت1ww (fUlA&{416h~814VAR^3ݓiB0RO(l?~v4_Ã{Ep A}F"N`fI8> IX *d@!Cl_Ȝ] AY3s墅xfOKy2 ]Ƌs,g}CCRT:݄jK `~V}o4yק;x~Sy:&:ڂ#2)sEy'uAzW8ޣJpwA/Y5n.DR& /"ٰU>oحyI@" nG݋Uj*Q|Kb!ͦRƄ)"zP?@y#YRSQWtkF0GG"6m6LC}d:MAB7 TuZPֻ.hG|TMI3k؁|(z1h3_"^zPc3cST#bH,ҋh(|3dY+ ePH@,pJ%{;5z$GMٗb c%^AB6FL.4)lԄ}12kK_-pRO~$> FEҕLF 2YTaWB|W D]f2]͛|7kPKD3n G0Pߑy^yZ!}F3mG F'07os+gq7ܱ\,po%(2w $NXV`>eO!LR7?oOҭ|7Qu}FbBfNBɁOPvNx}h):0}u > P8t-;gp  ]"kuCKM"Ϗ)lL!3s-@&,޽QLqDK:> vlf I&BY$!}.\vBH4)،.hcfal0~~{WɓrCT0ga:uv vl`(El.MCDuo0׍gEpʮɪ?) ]aT_vH`02 l~1Cnk0+lR* ~ P\i:PjYX䧾hXE , !DE*SoNG ^B ZWۦ.sXeR1 eV4&p1Dn#BKX@gȿ04&q o%E_ƨ|ʲ́ /܄8A<ł _쑐%YuD]c;cӟv\A FV tRI$ "]ΦE4_.B1#M~@L @lay ֊AJeە:m΁:WmY_>w7Lc?6na|g#4-\ `ܠ1l{9Bؘ`9lw~s ?IJn|-Ǟ2mc ^x[Q4i&[@qʾQPzZzrGOeɾ2["+VݱiвAW}f9-G2ŊYBiCl~M;V00f`Y9?Jc)J UP+cc\(@K١&J[^XC 8>j/ ,ѼM-(LA>SR ΀QZQl9x> pTf"XI|iaON~F)Ƴמ !EM`0 z - *AP#^a| 'gJdV\ sk%ۿ:cE\ &O^#ق'bIdfJ vMiٟP',Ņɫ,LBWESj#/F{k>P>z?N?0X?o0hd {WsvsSԋ2H?728j[Hyփc>4,` \w/BQ? 0F1α4H@iqhyY{tE_w ɟKxMH"k8g(]DҽlR߇e `Lu@}Xe/Wױ171?,71dg:F5ߘ΀&.`vaqxiwpx :&ƣ|[Ab3Sf;}ͼ O1xyg\Xaɜf…WPz _sBA9ϒBXQ 5D.5J==S 2p>wSDH@@[; &ИOP vC}N:)Cm^`J)ٸF=c`3hčsZ>8Ia0eV0~6.t8&A R_FG;0ߢCN՜C2&wE#c|IyL$8AJY E~ŅzaXDǁiJ?N}Qk(+2$`\  ٽ[þF UkuQ@D5P2}{9q|IsstABYd magafe{?pqr?l"Z$o*Ƨ7_R41Cnb1F._FZq):,bIv>Ez~HΈ൧q2#Տ \E!V&C XX$ bgkl0;hUnvd;M7,?I\e&y2-Ũ;}htvka緱,gqxa7vgc7'Q{4G-6D(-Nx۷\}+ Aauo$(dk2k u3cPM/CLD\s4 ($Nm&.4|)6Le6q"\Ǡ1#38O@9h5h(i6##Z;>틛ؽ8'h~9@ѣlBځ5QIp_οBPb20t_?!;2-|pyw(<dmfXӈH"lvM:O&V\h:#kGs#DkQM"* *{v73ۣv۬Z01=lA_ÐFc \а{/+E@l{s|_(ѦXj3P%b_vVÙEY({gJ )ԡbe\\ꅅ(w'0 Ϟ{ע`2aI$"  'M,h̸ύ(.=>lgU2#`9hEllmZ}IBNO1$bJNo!E#qt~'<,7'1-8Ii 6u9:Uѳ;a'O\;†4;'4I \]e;پ6o0Oδ5&ocs=8:٭hڵtL˹evm>ڿ뿌߳_}n[oʾ޺k ` d;+Ϯ1}ҔK9KgơP@l12dÂ$Sqi? IDAT)`2 |s v`4 9G 4h>3yl =8?SR-ʫJgW~v8ǫy{o_.d>$Ba %L4M^x fUHa*9`/ʷ(|RCKg8[B%01 zKM&$)M';3~>΂F_l^#A5 %k& jx_nhhXp?[ S"iĜc:=g^ŝ32(Ps\Nfhjz„TM9MxAE6 LAD il-22chûI5feEh%yc)ǔIN#v3maAaLSa[}vp~[@=4rR0e1)@u^}nҵ᱄}"}@+^xc;1a2 ɗmD'#̷:iEj;ZPƛ ȭc%s$|Y7씔Vχ9 [r_^2^r]_'D1vqȡCW0e?y2 NPsS\~"n;眊I?nʗ04=_| ;ҔwIŷ0ǰX[YrXUJ D>PLeWn:@9@A<ؘ)z "ʓ*M6n=Gf0蓿`\vf݂ALT;E5mMo fbZyq{5'׸J aC<=:1_7&yP,?dzdB[46LN zIXL+MX(vvNn1@qGwy?~#g#xxiFqigGNOBg_xD6һH -+.'q@a@OG?l2^|^L%G\O("@f\xYl:ZfdΘA+C"L/ɛ16ߎ#kf9hL#|')X,=dPHJh2¥YV眚b2ܣ7v7_v.!% r2[rb{1%MfxXBa 8xnLSɊE0sMr/QJD[SgyBo+Iu <헲^|ձ>v*o>E1-hH+MD]dhc!G\N:5Vrz]#P&4dЙYi#y %AFNS@Vc4١.Dy9' )RjXr5j;ld-5LՒC*)ld]k/81ϾzCy.p1<)ܞ̨t, MX-/f W:YX7TAg) i1&-;zb^w@>ut%k"3d*\/xs?5!uA ?sG'8:*H$Db'`>7:Iw?6Z YzIcqEl2.lsVWi*:`8R?c헞eʄt)[ z k6eXpc2o \HȦ341M0inn&?.bGϦ`6]%ڧ۷ց«?(8 2 ϡb+7e\ʠ*e&wBA"@ [*ZE@G5vR8 6::O~EQJ.?c4" '<'[җ63gqїO^ l~17ޯȩxz\mܽd`(Ag$2i 8Ӥ;ΜtH۱E%Ž5W?| ۯ+`W䏩ʕB( 9h D)! {`\Wހ$kxӺm ̝fI~F³ GPLŝ~G~}>>PG'n(?LI%]܁ M쿊#IAU't:&9eyO\漂vLiQE @s)"b.4( Ɏt<օ|38R&<ݨ1:]18 Q( .BUm_,xbXCfů1R,.m{3_*>"`/JoOe Z~ ?o#ϘFC3Li$gf].Coy#ь4puIa >#g2[sti*Ik{e[[Q~ >%?lpmC5/1ޭtŃ. GK8|,杹i7̢O"X9ݾ._'xA>@!q1F@aS;elT,!Y ..#[Ry 0#VITrȎT)SC[T%^ʕaOpїqoLC3L_pMBqdctMȡ[xm0YA Y{oZ7]lo_GI4i4u Ɯ $܅030lN[n>u ڞ:H S(836skN'R=9t^0>p[f3<mh'\9xLGPF$ ?QAoɨqף7.pG:UY:q_[@3 ߵ:n߿[Qv$E,8j>c8yH$P)PHiG5Z>gqH8 6f{r̃ PtQJmƨ1'0(`VF c45ȌE'la4'^qCQQ_;o8#mKd` }O.z~> AY<'63__?QlR.AI!a Bbڤ`1b ߄"`L{~Ojgq{@o{`|[>nOY9o0Lp\4Nc?W_u( 2 ,b@un]r O5f."&<3yg4,agbzWpƝツ'G3ƷhZ*XcЫ76k3u P_Ad wqqEPzk\xS50m}W9M++т&6e-,2R ȋLDv w4PL4a|#lh4M& *6>w\4*sE53 | :{↬x:\)~n/|- | D%M&]&-Kr{jάtãqsUQzf,rJJ#C'9XLRJuFMEg ]bs B@_1:fY T`3I 34OPXN÷ui*5?z K4:(- ҙ,ЯeG?gB,y EœXanL^W}f-lAc<#=NfQPIV ,|qŗ1ChRz{ݼS'k74E1ׅd$!eGG5&uP;ȕ{;+ C7*`pGxe-`z7D?{8Xd]a F_2p\oy g?V->m0加0$pfDƯ|=E}@:xQ.:Oi7~[¾-wH.c瑶ٌ`w?? n{x.ϲ7n˷&_wS.&0w[Ox`oPZdPX37+!AQܥxJEI[q/ٟ"iwJ u|[GB^| N" GMd5D 3补`z5]q78T6H#0d-#dXR.__St Mc(ѯ0c Yi_HWDDvFpz>[9YA c \nn>}maiN%'b'9('G2q]V l ^ey9ޡFax[IFP(i+W>'u-}ڃa Hh{v7ڏf[ܠ"y=HLY>M2 wSK^}CG)f9<}<& )8< )wz`K׽7Oy )E&qh84513"7>}ZDlAXB5A~MxrVN#qSO c*6FdV^ `oi o`XgX/,tJ;04ο=Y`ɔ)loaxgPaGpe,_0l&WM4}C0}ΝJTXNe\+n1: Ԕ[j:z zą^|.u=o2(wkN%WNo~5~ W ;w/z0qO} t pbi$f"1xϩ$<3JvwQgA:@'žp JA#28cDܻ55! 43BRV<.S^.C$WpݐHφqܵxj8h̀(,u@rVg2,2hYp/ث\_Z /(1=6 9Rs\q8/g;7 ƾt)K٪g_5=?x |;(49K~McIw6n~~f9 Yd\@Kl3Y踓ySe ;vqaЛ?O]U+IZ@AzGTVw.ַd[6GմqxywI߁ﻊg0:8h(c#7l;i|ϋv&ª[ ͎ ;Tm\X&@WMl+U{RIa 9GP" %Wʜ4GXOe<柜D|%PW'1޾`%y^w~pQX >? ^NvZOE H&}Jd0ABlf(@rd5AX= v6 ~kx)$r.`8nj8ˏ]TV3 9DFϺ1߃*AzA숵|QYd]xəacrvQIevTL⧀˜H~_OfB[z5$*動7%\!kH@,1νwAIw9TWWWWg:0&e_(]H*P~KsHGD4䖄[5Xxn@q=Z8NB%sh8QM"IXNδI.oPE/h. %+H'r;M0FoF\}Jԑhc]hc e?}% i ^kX^@nX? &(japwl S4'bCVAGVQE Si$4JFB 瑼Q1 ܶ|G" i/^\ !!ᎅԹ2nbS gJnjc@# MَQ,!8ٮϹo ޺Fb`V(іA>\bH[#Ԃ_`5amQJ}sE8u'C\uNW%)"HKFR :P.tBJ:'ހy,Xy™ K'Tn q_X@ ^*J؇s o8YSBJn_;c"j('s~)K`Hd %x(-}'E| yq_nPH(87Zv@$NXh('v YiMƵKˠp7!yxH#QVq8FXA5(  shʜ`5;WqS'0(mg3FY5׎R*v4n !vf%/r|X %#$}:$v ; IDATREB#@:gd$Uߴ䬫n0q29y< o޽Ëi$k e *Pju~&{g<ʲY$pI# sƊ:){֕JR4&@a]IP+1<ɮʕCݹsc2s  2, X**^7@}Y»?cϠs 4=g{ *"xi$YP{FQr adFug#:23E&nBC% _u B83iS&fqwqN†D6}%$JkN|}lR;R$8}{P_^KPXTE z\Yi<-/Q .^2"8+u+V3`05`1#qݒr)fd4a$ m.AiMhMdPgj;Y"-0#MJ%#cg#01Hk %rH1 q"Vrk!T ŝ9PhgJЄ3:oDZ 0L Vr| ,"݁@8$Ĕie:ˈ|.u *(@La 5؎!jY ńx9,7HB0nuƜ,iBILcb\i]DtF4q 4S2HO^ !u'z i2֨ݪLֱ03`l m$qJ%Ԉ(~EB;} ޘ!=>"8CZbC5]UFvȽe!ٌufZ7U-2gbvPpw|+6=&ڠV81"HHcb['8M#7mr5aqaxW)sO=Hm _IgTTX uBBVX W+I ,_b\Oz sSC/G ##] n~'u??J(Ô[![H6YZ qh&XVRoA,Mb Y|md痫L[y2폽*'wb0@4HrLf;3ju#s5" p˗Ͽ +|Z9Fjjt{|}ǃ<0]7O֪XG <2Ƽ>fva8p[<06iY`bwK[&"5oLiF}UF@(,Ocez Vn J\N1S[!VN6|jz, &sY PؗnU.Zq:)X - M.ՔU{ Cqyx<ܡ:1y%Gh!R7o>7O1^2s 36,gE#/8ߋ&G7+3gI1Dyŏl"z1Tc e0a51!(Qd5V)g_Qr aχ`;wvem,37dF߁BD!*3J!)ѳW,\FRZb_ud DC)BT'tuc.+]\FegpZY$L2h\EH2<1WE}DY<>ǫݿz:۵A-cWF0@h^t)p]b X'4U='DnpF.H6{<=p._`DN9B"#2Ćވ~s13'tUB2 nh[ =cG$}cׁ*X9FTT"^pV}dsmd=.u-%(eY& 9a `#Z9uk)* AǾ>ڎRW/hʴKq)f=^/ œT[F2Cnѷz/^Jb-_ (38r᧰uvz'٪ivy 6A F,:ya4T~apO3qBdM {*-JO 41*ɼL%4GH4@sg ۯDE"VP9a-ȋ ʂF1a(>(ԻGZԡ z)ο|+=ǐY[MXj7X +4)'HHR<29"z~g)hngϪ衪\Em`I 2xHJR#ccZh(nfR%"p7)˫.u^ZEzn|2 mpFUr d VGi^W~>BZ D|ŵ`!5 r\^VmYA"$Hovq'ۢA6DlQi9FV%yNZ-#-%dՒL!r46Q e\sZ>*n_"9XL*\2Z8ѯP).8h~#|GYGY =BBd8א+ bAka報a $$2> ÷#P@i+ˠ1+P:@( ǚC Z6qx+yBi[x ĐRht;~AZWZjNι7ܵ\}+s̾::":DDFH(K%0n"P*@`?{Gi1f,8'2|vjG.$k2f/]Dh]d5Uƫ0E.ֵZټq =7<rzzQ{<@i{}E((WR>0||ƸR$}KqK ;m,gr1NB vԄ+@ s`0bsL̹6[%WpYq-rs.7Փ'ؿqj?nnMc\-c;0&εpδ™!u`~ E0̼" ;K0B <|P;ߋ`gl ;[4G>tqy厴 0*um`͸j0V"^K+I%acm#tV!"$0Ec͞SCi0JcJD@$b:v.w/"Y>t1:kJu5 3B3*- 2%40c)iRoAap "XP5;ip9_ǢhXMB318މkwK$8K *S>3wsj"#/J'{ R6ҋ+Hϯ =E$'ͮ"[Kxɺc%KЄxނo?"s  x7Z̼kĐIuR̭~fK˨_XBJ] *(>AD}X*ri4*HjU$ ut3Bwq74)FFrY4#į>Kb)@J,CRtZIlI=e2˕;9|hFhÌ] A6Jj63fB}q'@Fk_ϕ;U-\C+2nP ̸J02>DJ oĮECK,@7^v=G,"|ѳM 2DyXaj7zMSCnE~Gs6sgdb{B̲4D3q*JQm!ݻ8N>f˭|񁸑r"[Qd񂣬Сc~Ө]R5BdJ٧  jXIk2`q+v) g*+FF}9?7 K# .*5h}`+IaPA6w,VA'%E:P J$ʷL˅ZֳG:FznىE ^CY mNJ+W[2E:v Gؑ9 ՀBj 띰ؕKʕ3Pj09ƫ:6bjŶT r X2dx!nzQK$uEQ b:z;5qtw;38zSudB._ H BmFw,R8 #y{BSEVTwáqh:/wq]YzS Q `X3^(G3nc­,M]ܢ ;('#֜̀$ Eh}#(Hd2HKd^4b0u&azK\~wc$ b2w{}恱IUl9PM `]j!}Wn[*UsOqZ*.m&wp9,] ;Z~+Zf-U+ g(igXtTpn4?A&8Rǟ^ޫ`=0f5#%71ri 3>O~ l*9ڀƒpt;w'X.~-S 0"L8(RrJ"c~,E򘴗 [CwB7P?y? Gz<=K={ "w$R Bd\5jviG~ ¹( kg3UhV ^a{&=/ri Uz  W*!훕YM(ɍǏh,cFUnmY,ww<=)ciUO50nʾGg$;0!WHUpcYd#ta]PDZrϝ[C̢-Vӛ\ <}~wvYdj_pnn?J[zX@d ϽL6y͈Ŋ;p'NU,0ǻ󢨉Ik`/ 6Ѯ'1U4O$#x_mQc/bCs(`<2QL (tBqH~Z ĥt~P"Yvq\zueJ<$ wڅXR"G IDATıǪXxccj,YaMI~[Rr E"?H1QO "h-L!uit /VfH7 I Ag؞ ?Y>]x\麪epPl^_WwbNQ4s=+V}l;W.{mfr'Hʳ2'#q4p:k+ |L3f!1C#MN#0zYD-*}J ޿(kSkQv׽F=>=9|v6txV{H?=nD/$kHfU|+`" c8{P+>;>DK}(W1e7)WrN)P DtBQACWZC~XSNԯV7㿁ܓ=?a~4־_]FuQ QR$OT G\>`$['J3αaY!oT(37 q8uZDx3T bM@(v{[$Ú`g%MSԪU4M[fj PVNIHIT*w͠]Z";`yV=I.Uu4J@y#o 9\\[84|%l01L=uSWvTZD_dC45׮|Zw`&A!DW|4b{CIrW/˗N:b$*zS 5eFaMDw8S-xn=U) !r"}LV$ V2ܨj@a0pn?yV)] t}dyjwa>6+#APAWw#F gi *5OF7]Dƴ5:qH~ UP&:LiY? 緩3 O ұk@=Ċzƌ5>u&?Z M4[Fy[J "p%nZ]F8Ј+h&t)P"¯CwK~߽O~c0t͏y3S}7b$/>yo\eQB̅yLCl6)\^!'O^!C3m.(K5()њdA4N-åahSgқxZR3޾LR7A# RJQ#9iZB #À"Pc5VO zR4|2RM݄Ok. /XAC=ɔL:ݩ6QŞӈxX?XKCmU+*Toza1Ji7(~ B-*Y 3X༘O8CA(a4 @%p"Dq#)*l-&w%7Ox2rA'hbh\|-!|$G@[R.4o~ (`s+/|qIގoJZUJš&A1$p?Wf1'\{KA: ܻgAa>Q IT!׌ztMw~R2KqK.>.ְu`Ch&G?8/6[Z3Mb/%Ɍu&*#w?N`BCrU*ׇ‘Ǵ*)࢖/ct#*q~7|Q8E #<56ME,bGI2y% !Vmĕ~]NCd 7A"Jı*$T,y}!t Q(cum6ip[v%VX "=E\F-g~KhA)vbœ> <֗_ׇd[1 "kx Bo1Ы=ɓwkݏΜ=^h{6P kҢ;}$|w7o}Z&VVWZn"y~5߾շ߀ト*KlC'j{"xIR5C6q"XsW*:FiT L 2`sV[ Lht|l ͬcg!H}ȝ&d1עvo"ɋ2E~ʛS<vP!2ad@dzJ8^?,@pXDc*ds]6q`k۫> uzw[N4n~Ƭ_"ٺGџy#V Yˊ\@b^۾r?Z(5H|VB,H{ p<+`EYCY5ֻ$C^֑.VXwMZfxjmS裏OSsTk5LNMؒ,!$Iv5ma޽zxË/y ;wҒ=7礪KHO!J)(:Xc* #A=1#o`jRqo=˳Hk}-!5-Csx bgZXq'؇$5 KG\+8JhVcn $|};ZU h,gXh m UFRaRF(7d&oXAkM]+tC20tm,hˠL!Cv/VAcdЀAaqy6ѕM?ꞿ59V*3bX}#HELZz>~@6G dR*ҍ\?HYw+Y{@<<U¹@0+^uO#' s3|SS“OG'@kl ZEMAA.  z]ė^z _;>/~g{.\r֑wF۔-1joއ-Soچd;Պ`erA,߸Oµ[jsrxRAV;`o{Upm`mCi3X7(x[U4*12&`z{D唈'X%@aqz B%9~BF~OX<2U@)N z>cbt)Ը6VsZDu6h  ,ء?L -^Bxi|-h4Pr`2B4t%F5(cہ1̾`F*+CEY8^*pa/8׌Z};iL-pH +x5,ӂw7 bUh1PY+ʨa9p Pћwe gߌa9*y0-2inxOt`}9dQ%b8\%'ʟ'3gsܟ;\D߽.Nh1|!pQL)i^Wvl&{*oTlKTy+ )&d&/M/q$75/:_"~^&Z.9,`0pl*W9)b*E 9+t\e ~74 ~ȷr ֖!lHU efzFXL0EYM;wsg*82F.#G~8poy[sf'W=K1~>I,,,`Nx?vbagxeEEXfM&_~i4 Q6K C -['{ 8;1Do8(7 RrMH|GvL\Rr4=FY iw?lf@-`r'Giq<@ $2 %&;BL-VtuMf:7 u 7/ PwPb3}NX$$i0`mX,EJtzNqOa Q,WZ}~8N@ui T)ciM21r/nPxu0b0 bDk!*jfכQҶ}J+@' 3Jm]6Q@П+9v_o^Ԛ醪UKX}=VhT$ * o{W)0tLjw`˒8~AR|E֐L[f1.-T^>:#$pG}4;x'ϝLQ`A|/ik FLEīI)Gw:/>Dį!,8-}AS?gsȭCHIw/Ϣr)J a欺L|VN"fM ]I ᚑH PJK1!>WibsJAҕTBo=z!c G=|ޔ{q}2c_2lV"2UEz7!Je2OرK C _ȢPZb&]Ew?!.qb`Tᚺo^[lLJ_w=5TX[68N=8B_Wdm<86<>|2kkFAJx@YFCpN^4hbNLN;, 1j~ä.f.7cUNdoBYc8:D Kj7\`3xY:oi?}rL_?o!qɥ ̜PoK I̵d4gujX> JS8%sK],ʡUv+WaCPV[cK֝8F+JIhQcտa]b#7r;Dȉ :8'@m#007;|M8sƼöm4E֖ҏ [P0߉\rxܙ[:Û8]$ݟU$Y t"t3}uvgU;^nYTuii%5/8A?;Ε})+ wsϙ=Y*Zaѿc_Q'`"j.vU \O6tT9*+'cu(x_u<ϣlT)f$2ư]b~dMBYQE*kedoh9h_L*7+\YiOva\~n9=ۛ8s r.|;؋}c5,RxfS.<@ ,MbD#3s.ag:Fb?Y.3ni'ft MIJ5Mj8f#YCbr zÛ]̥$s3=aPbA眰 }6xmUn؆/7B舁Mr'1bt*(cΘpujV5w'Oc˃}]6ZhAbRq >e=l #kVbr s9.iF W( cdVEQngƋ}Y4RL'ǻ "@ IDATxݷֱ!̧Uax,=Q8ct|ysx!(Ё .t滩JPW {?*(KpUjߩ{nX#r'+t&w> VIK/8#/TyU|np:P{<b⒖Y'$ȢR.W/=_zٳMO>9v-}LԩS i]$s>x7Aw@7PœsK .7LK؂/-vEW:z}RO^+`Sd??!9)j,>XXv="n?BuvIZczLE2߹ }x׍;pTcIDرIMNQ pVµ>|xAjq5}텱X%n202mhY24\.Sk=dk>T7,wC9 jyxB}B@%d6FVsĹw%FcA׊jZN@rPP3 hur =EC+[5&8Yif^5>2f0qL0]ܓN)87A ;|-4Z ǶzD oLXu,yd`5!S#L mQ( u:\Oi(o{ 3 Ini,fF(]H~y0/k,CkwJFL^B6Fhf)&m/N)ƺ'b௼}3=R,Q3,Ξ={`0 t Ϳq'z:J[2an<&KEY{X_#fb(# ji2CT.'2lw0ylz'l稾>j/+1)$nC/MXA&#Old?˴g8hrWMύ=gʬ#"sڸת(Pm?V.{W ɵ@t^}ZU=XA="sf « ƺ8ˑWO 0\0h v (_0ȓ$'.=@hCTm`Kyc1ddҾc9ׄm: exߑ^TYUJⲦ M_'GP:8*dz cXY^sg$21Μ9?'~oy133#c?:qSS?xIiܿ빞W$(!er$ze%y)>w4DJO"Bh[TQM%c@8P1yO7EKjC:Fv*s+Hί"]j$Qj"g4+ t#GSèzB jrOR:W ?H f CicڡYL{Z9>(X4+3P")tU")l9!;Fϡdf}pNwUc13ő h9Hk 6L28]]~A A6X{Q 5ck6Rr nx`VmsҘV8y QZxvsezBAs TǶ8q}ǧ#^1rNQfX5/b1?|j\ 3j >$P.$jB㚷k` 濄sۗǂmKw ܋sK%rK ɱ1oyɺh2@se||2~wqvY<3| &&'E\`eygϞEr`#Tz 2UQ&Qڛ"Amv6rI )+R825Vabi틡L&Ǧ{-#=23KHέ ;rsfFƚeEEUP]Y;mŌ\}/ l[}ddꬄ޺G w?;Nef<{ՐEACx ̡MQAZ7ib/~BcM.8H9RUz] @Г_h#UL036bKo,($]02"7ˮfI_I錌thEkb% YM#) *;9VX@ H ][S1̿e1:,X1l%*toN;ͳt]ߘz6Z%#g†W(?px ߋ>u^쩏oY4MOhƽ~sf;F a5pXg!4A jA׵E&><{ޅ|a}?L k0k|#׿۶dn1,'X%݆*{V?7fsE|'9^S^*-ye+E(EG-ϯA wz!_jN$lZAloHL-=u[JtP><"\"ڿCiw @[rdt uepo1G9'ZxO*7pz*R O-bplA*SH/wuI0-ą\KLS1bDM,g0wPI]`/.Ftm aq rLpB҉ +G&`2njtB+Dfk|Q?)jjd(JNny?4JfQ_օ*j8$E6oln3?6ub}w =nDumt"ş! L+%(2tL8zrJ(jǨqP]kT?}E"Ts^-Z{Kt][X5m~|{sc=U_l' 9md݈ XcͰ2>s ͈kc礎ѸMMtOr R wI>3.vҧ_y5h#[f1UtNfCArߋ\u޴?id2tAxkl=[oY7 kk?JPa\w5pjrR  Vi$L*Uɧ:r_ul.%Ѷ*"A 3m\[bu7WX>2aueB m8V_<ık`-Y4I%.B1OaM\H brb }i%`Q{)b:Hy9,ݲdۚgm:/bf}hv_B +at0#m U`h&F'IcezM ?! bzXZM zY73F<2"A].a, u&#6!e^]&\,YSEzbg-$'~u#, Gnnv}ڇ(HzmP8 =_x?EO^w!ăBf!IƜYaƋyֈ~gHdD\G=pw"`Cgn{Ǧ sw=n}[;ȍT"D"4g+=jr ; jQVaYWEѷ%]9g>bc\+o=n4}?%m/}Y0GpȪS#'@oW6w݀o/({e4%P0~<1sI7F6UP<8 }-՚$ynkUF Bqtعsr^D DNļf`Podsm ;n PW*3e\.lJf)YbE2HP)Uhv^mnƚ(L|j:tW0x2/͢,W^\E2@RX6C,"]!J2:*  *3_"-=2`.[;]Cb*wIfe/Cʆ g s5e*o\޼u58|>8 Y0,!`V@g\md~PmSNI; '*0VJj,WP"b4fN|+}$wEJ53y6[݈M y/m4e--h;C`0lWnٖꝥ9$Xf|V;]C0D%k?{ <6P]׽f_^\?|OdwφZݽTw $l T;tyv>B9pЉ(Fx.ѱ…`0Wm8T(uE"TwGKCX~72c$=}?a07 j͛`3TEOh{8`4ү ȆTk?P Baiϡt82A!ᵯ zOQ%Yn==RS'FYA!ao >xVU&1[B"1,$=Ou]GE,Dù~Wf =yڳ?z@8dC/kܓXz'$(ܬ iy=(m m7hӈQ~,zߨ$7p% dX##ZM 'Fwكo'VWh4W9Ga/囿{.b%j% -w|A"bZ?:4?t;x/_ njJЗ_~ xǏcYa۶)>to-x{ލ[2VVVq!jRƚeGX+1:ciqG΢q ]z V/Kӭ,"Y*V]CcO#N]B*rrQ*ĝ{ޱym0\ 2B2.'+Myb]k"Z(%^>TIݹ0i"' kKY@XD~]G* 2O'#,ndf9}x:7 SU[0׉$ΠC3 3PQ4!, [C06 l~!A5B &͖Km;r@| NL<@eo =W8;帾>|VW?)Pͻ?ߪ軡 `':o}ǺڬDW[N(F450^56>:CnzvUtُ[DD]߆ pA2AmAڌ׾ .5 'Cfܚ8G8B+,ݗw_0SPIk~V뷂"eM˹, ೟,~JY.nƂ6Loq|뷾OZ xpŊLeb綨C%Qk<ݩ^Υ 10(ujj _~qث2so;$Y/_~YZJ;_im|:>Mƃ../0J˾Ho!\\{`Hh|->{x?=!GS5_٢JD>4J9Y?Ÿ`r f%{-Q\Ɔ>TƱ[K;`Ǩ, 1Z{l+hw=QYM -&ȸ2O s䞸Fՙ_;-[V@"H" 2g==q`l0H;1_}Ok;؃KiT,L3vy[˴9<«yp&]03?駛#RFn̒o3o>}y-msdg)# ή;/AA*s1  M`7|EϦPaW)+Qv_^.IAAY*J%7p}c~ZM3seג}_N_&UWHͣ{xNh2-,O|_;߉ĄCKh& ‡| VKE\}o~QI7*' ܉ٹKGAt N"OgbsJ7xߎJ>Co'>IeP(3b'}{?n{7?<,..675ˣtۅ_ O=Oޏt⊵`a!HQ {]=Ml9b|>!77{y oR]7k9r6Uil ]$UQ_̢ܳ@U"tҳm: stmjk@ Sd2Mxi;j&+.Ĉfrx\ A.;cqQ7ig@qO?Jr˓&#A.KnN_k֘mC't_զ1k2U;@W4}ґ og؂ f j IDAT}IPiyZdIT[H뭀=pY`S|HA}{^@Ⱥ\`}ZqM F:kڱ$mJF\}c(dƋ _1yFWӑhi\][Npj% >>8r$ȷm38zi8}C9t2'wK aFXx}b3Kw\I@"4z@׫0&`lbvv^yfQhDGrhEdwa`F W!wHШ<~[(dկƟ뮓f_f J}[ %e ŏ~sw >K:T5D*“Ȍ1WcC7"e|me #-ƚaT6# R}Xw h߻j{ vΣ=7,:l4W$Oh;~rM3~fZqvcg}DPMDHbcOI:18S'#WS5Ns]s ʴZ9AnMY`e%H OȍPä\<1(I]v-Fd`=yIyH3I/ X%o;@(n;g-<y!f,Jgdg|mSJm6gzLE T-G3=EIaM~5`W622GV6_'2RƆo<ڀSqho< 36uE}&V_ͺCXѶf01ssڎnJ=(@˭AiCPnU' [l{܎mvb6ڛ!?zM4!u, i'O5W_ş^\6+:'H_mWq07-[6w[x[~E$ o0rl~ B@.\`0R]EEaQK|_Zf!c9KKwDyy9q_h '&pםw=^9z## ̢>$0KG=Cyeq̵&*P_3#X;s rļU5 Im3->7Ϙ]xK OyQBgѺj^&,+Q&a1 ,@"CtݸTJdvzJǒ,ն- RT6P)U&πRpzU5gT@ Й{%ܤ[U'C˜LÐ 7/deJ2vF@^{t <=qO:̿9{cT`l{^3ZEPCn kT:sՊfla0GChyN{Ʈ;`,YvRiDOEW7ϝKmbT>rOiZ̀g |7Q'Qziʪ}hoz&9Ʃ۬4}%駵 t{$;M繟V+"Si1G0Eݘկ/e ʼ.")\}Ufff$8CLksiq 332L-܂O~x$}z32F[Pߏ&X)ۭ_/3Cf( 62/1:2;+eFqޯX(`llmeZV4M1.bOZB W ^jc(DXڶ ֖yv9v]yl2Ď@$n+4  ^BջS*JwBKT1r,fɸ&7.Ҟ%r>Nr, {Ր%z1*BsC{9M\ ZB8h)cVLE8ऍLL!WLhWuV\{jwsq&}p%A6X2?= &?Ur%Ra B9`Gѳ!xU_|c~w[lAPh$"m޲ox|>q<ףZ{ `m ҟsw>\;4hC8q8>,%+Jl{kӧ1==-P|./ӟ_7$쫽+t@3ty2}>ez.ڄV)l3aZhdWE_]@%\)&UlbxL)dX:ApTh0Ldž#D0:M7873:jL?P@* xFEEl0z!1 3>oz/?_ 6Y_j񜞛؄;VۿcpI,//"d124u8q`MҢ2MblzQQwP$2t$ٯx-WN=VG?ݏx@ @f/dOOx5nK/~泟 gOOOӷߎ?zhz l0rWCY`O-,m%MX 59`AfIP-EE7e]ÉK=w0ԓ|%uly';DNs9-@XrڊL=HX+ isFCt0x`&|2ذY=GEn69,l7[v>H=y *Ȼ`Ȍ)(M7G$uM_Rx625U7^WvPbҦ >vz$9Dy@:#yP^s.f7J>Q{/#cѭcj3WMl3{ߟ=J,`:PStphk5]SQgZ6%Cſ-qE z[9C1]\>ZxJe?Ӝ]id|qj*?Y]МU>ڃmd$n7m?rLqOHN/wOYlk3a1|8qn$|;a.FMl0!3VI 쫯]ZiQTCJCC3nB[urjJȾH+ Pn,h>>#5X&^Z['y*t2K6(3y33`D'#Gݿطo~/xlBzA^q%[h .<{7u}V>dž dV8dĘ}Y&A؎yd=&Zo19]t%7i( 4L?Ð j'$g,y, !#S(7g|TzcB631rD)A5D Wr|J9,/<8S0^=C+O*! reR&73`m*Xչ@JxvbܲSZYWѩ 1nta:3NFz*0 ")3-QYn /U "g(wӷ4> IIpaGI6\o:@`ƤQkZ(S$y,S8;"pC'-{%6ɮ,=$:T}%NBuکۋުOs,\mN(7:rcz`/CRؑfatJB.WVBϔfBPde3Dvqo< C<goz j3>?eL<ɢ$VK36 n;P+wcCytSxbK*Ha]{q)^ii2rũ 䟻#wdE|M a&\FˡvEVZ9T'PnwE(ѓ$L Z{gr#ZK6b@ڂ&Po4PCѶ D ۘY">9r% 'ԇ(rtYjiCcMf bnf,$MY\DF֜u:7EwX|ܗ^REEl%S'*VBrٍ'o OV=dzv~Yaz"(ʪQY?G~'dj݋Xa l$VʀW}u<_=wl%k0 Xk؅CAQLF⼘WQmC}*_އii^3|mx*q!ETyk6Im6ڥAm6×)%g şuJ  Eš*LEa©eG&k0‹P_]Bvsl\ceL9Rq3uTì~ag_jMYZpQO6@,{;dDJ?ĖOg|l%)-?ȃN2XT71|LZ{=&wԘKH"f@TVJ uEa"+QZMyhW!g[tҚ&v^<ss6sb RZB?lbds f7wUz#]:?,pȭzv lޗL]Q9qJFF{z?$~B¹/%̎nGcDn.jZA6:@KЛHވa se£zxX'沃QX[8;D<̹\œnGf4+^M PCC ,dra_g h<<'; B %r.PQ<.ZToyC 7DlYЦsAANVҐe"@.P&GV4fݎ+̬Lg[ `Jc'ؿBB @I 'NeSN lJ>amtaoB_>1P`~3.wMa%ѓkIo> Ƭd4ﻍ9bj +oɓ_@WoAs)8ikyu:M9052YS\A J6jfhlMlCnHL*F?3t!GTC8__#yh h]8ucR & `٬B>$&hOa=Knr OHgsӖ-:NdAV AiR,t0[~G_(Bd3+n6ʉʺýj(iT&;Q^R~7s>)Y NPtQ$tӛ4QhOI4 $4ڲ;SӅHwX10:e7MJ8 eUB"ڢujm`'Ի4CNܸ}ЫSi1'i/B:f>rJ5IXn*P $IPN?pM3yǹNzﺋsl=!Ovƴ+fֽ 4, 7N߼u#h~X|نrAgڗ#Ӫ ۚ泌}nG?^bQ#3m dFLEwiSaC@ tpMMkK817Fa8i {ٻҼ2fijggY.<3;xg?kz(:8t՞jԟ#k lV:U?@<2&>p}ۃ\o=H|0v8nCD S+=^7'iWw"NybR3{T@y-̛S2e3׉We.0KZg>G 2)gcs/btCA-ȨwwKd$--|G֒!'F\q ͥl"4ipGL3}Y.*D̶43^G] nD/4!Pl~p{rQm IDATYm>ΡŶg{t҉T'd '4A|oH[>_S{o;J3i-Jh;<68Kb]saMZ3B.NV'B&Mva~[GwMv|U6.qȘLm1̘8թ-|z-& ~hѣrR קH8WnŮ~yl@n|Δ @bm`5n_;O7Z!r 5C8r(&=Z& ao)¹NlRۮnbRHp07tЈ C,cB7xsGRl:Z5% ؗ!?0X> d{(W9 C|х8~%Ȋðt'3v )o~H/ ]_|).2OHe}\Pc]̯'=P|5'QשݑOcRm`~]K0SmļO}:_19sXc}Zc7|Mr!'cĸw*<ߌ;ڝQp*q9if?wFl8> >fŘC-綉ɞRݫ~:P-ӒsW)]I^a;q]6;\`t,sw\%OS8Jک' V!8 .xB(nKv2< QYFs8}o~zp'%]gUdưk {y~$g2~y*{e) Yɉ>w| ?Q"&mܰ?M/ K -)4Do~fQv=^s qsEXop$]z Z|~F|\Vm$'D1]9LCsA98Es@KG7 (+7_ [kM_T`cbo~jLTջ ,i`1=;R:2OҞ_rhs̓Z{yHi $nA\pϏA&#gs9deo䟘X"DRA6 7܈__+_[9U8 j>:?F B=繹*Z,8}9Tg@zB=YΤ:aN n'ڒ˕@~5?{P"^e%Ĩ<Ǝj8OpmwSU@ IxƱ7>1duc:Iq[-)cZF><LQr\bE,|eL+WxƮ\]/YQ"WB%7k vP7Q &9ilryӍ{+8-e"ՉMH zy9osoqbђyYA.M'Kr䦈4F"OvCêD+ܚ ><3G sJFb݆q4&Yb%\GP$޴ïͣuFi ss_zǷ|_Ã>)ԄZ V+vfQ*011+n/exK_ڊb»&`B峻v1c%loEVx8}o2)BOڂ7%)fѼ/~ZhX-'?%#gHwn>7P͂2JN 1.9y#TʛazjgN8~6zoHLwحW8j`;&!Y b!wWdvuAZ'0=QGIRHNb:۵ێnIuǔ8+vёAƊHgXQ7#u~spm<-V$&.0WҴAO:%qDJOMg rΰՠ2Ms6( *͙ Oj!.kȭt2H:_qr>no$xfuz٣OgIu:" x!WhT%ض+} N}33wHVNWAm#i@'u!wTN]]y<>/ƶmM`Mǽ=t7GuJn,n}m GG [\R۴9ցh2d[6ʟfZIARsqo=9}G6\`;Zsx-]w0wCRѺk>e+ՓA)5BJFښz bҹ8pzZ (W=||L0 bo b1 A&c# AP\C a&+@ j%4&JT5 Tfld2YjrJMQL1in)Q^^F^ӎ˨#hlCR% "ٌ8?XN!z~\ߊ`([0ñӌFid2y\ve2B;(F\##XZZ@REx $AXCs{zL.Kz5k/V_5fE]/9_,Q ֍X2;i$ΆܺJzۆuzJ5 = el!# HˠigE:YkبhT\2 B \jYms|"_֒"9I P@e '.9H"E4LJXUB}bRd `,g]VSvpA>zyJcX 7ujVLl؊༁2*r3e4ƆT~}+11Dvz  aPa._KAy[6`8g\L4DPyȠ p+,4PA_PBBebDc}y/*_~=ssȣ' h > -[_ *RD;zħ)]3=GN8Bs$M pĤCwp ȐԷݍm3J[+Jm &#gi;1졄F0g/ȹ}׽Y6^aDZ, o9 BOVJbf0zK#S r6b|bL6KV8paqzg`xPx4"`Ah:" X@e/D*L_j@JS&ArF|c8G{~m0J]= /yW?_s=6}r*K ,U$P[?m}䧗P9飑eL!+۩~14=̖]݄>9p -4lV0ajuMEec^ (JZ!|b{Nu Cs$k5H0=x]/CesO#q~0Z3aF2i1H!W±ҾckO,r%;t~9/K8=S]]u,7V-pAƸT(eĽr\C6UU`N>g^7 %liyN?['d`3 ZAD=QScnˬ(t÷p"7yUOR엌o閅9pimrA H=mh3T627Z{[c:Gz w͋ H^皏ZcO@xꭸ~、۞rDŰA5`_wtZ>M!ϵ-ܻ+]N3ax0'䅆zbo*s bVJ*Mڅu]֒ KE!XԞMz]o@t9 [b ,ޱKE 8:fbϥg3:$tD!c׶*)"Zu\cPǪ_XZeYM 6l]wzkeuld¥mqǿ9RBk(߻f3{# h>1ʿ=vEҵ^Fj3F$e{6CVd3ތ#bK01?4Ө{[%P *ŻXhOt{KP8Ԣ22J=ڭ>Ԗ]XhRu^HPҀEgmD(+IL#FAaI@]U&zU|Z w]EA DG=Ú QrFG4fPmGߌ~;T7^5d>zC>okytPlX$i2jτp]4O&N>PV3_6L3.'AM`f=n3+9}9lPHpg`$#I) 7ݎWrlOÕ ѣȈ G67 i94Wy@h?I{Ξj4ه[,lz Z91>3ڬ(y?КNKJ޺%LrGp؋$v:_^%et< L!K hg#T0L~ Gqְ|NbxNT>lc f E40c]?U̔ Kj6qtCޯ܎*W0 .UwcWw0¼Uųø̈́u6 eԾ}oDP#XS@e lEvE<'_lőjɊ{NsËESWP Y"\ATwqfP#/= (N-w?X,h۠v^%cd IDAT6@ikv.~S$)Ꝕ[37|y֚duN0ſx h.qK{%O( H?'ZjZ?LjeR`Brr1"lV s߁o4r` 9;yl9p<ԝ>}wיA(M Z.[W\pډyQDƚU:6i)v92W óhmZ;X7-ùc}8GU[p쑄*OvK=}&ii+@$1 ɂ33>uayGjHN.q~9< =˪4=d%\FҬurƪL}0E>m"3~zܭnI3 ȴjۇ5ӏ`d Yaa`Q(VFFq߾C; 47u_q`׏0֞sssf˨n nYrFNgZ/%wGj1ȉ؇@ZY^ou4db.5uK  :D*3WG9Hۛ^FcoG^,&Q^AI5fO=YJ(bh'Kmìp "TEC`F&1עwd1j6h/$kEjG{\=06l88f7HP)=U -NfEX mi^۱6Ъ27< ]+bwn zQi[m"n {'1/S'EV1(tQ!N]s<7ҳN˘d9o;WﺘNwS]E@  ^XKU餁E^z%/b (a=`1Ca5٣i?Ot1>nF7l,ih0c~Nꐢ9sLe\gR3LP3yʧpցax(Z" o2|3rj1w֝?Į/-.=El>f!+"7_5Nxz-__$xˊV,gkpc'3:=O=` v3mcq|`vZ= ]K`1IwGyHsܟH;(n[8JRd141vd0ヲ .>![X{~,`ΕKE\tΖ3Z x*wqޯJ6aV-VP(O]6} XxCCp& BA{noյ(XaϨC'38o$&"fJiEYG" ;,6wSA ͙I D|M5g7>Iw™$z =f-1Eڟ1}5r*a.imYIQ]m!JrAY Tsh}V}n.u=(k {n{q$kTSP) 5$cj_"M7u{#s͏_Rl-Z\ ʦf '.&=g<[ϜueuZhְKz5s^+v[G! atCGc=%M;3  `4H1e:CrYmSp'qd Gp/a9,b 2? E~h-G&$r8ښaxb e|2uFF$P1sg+-Uӓ:3D> /j-3W@XK9J1[@,̆{:˕>SȹbY)3:^( S؊6LbP>AĹ6md4>7N4(uy`:=06{F<%a(Sc-F}}M%^nn);'B絰=՗99uy9Ό P:o]q/xN$e`"9}֒;|ew{!mӴį7}6ӽ3Gt)UuWµP2ʐk@[ew$|29q/[ڄK9Pw걯|5}-ƭڟVd7 t uQ7cǼY0( 5u^QqxO _PnhvqJ|l8{Wf!2p+ȟ^Bm0U/#f2T6KmanR]3ZxIņq',mW?Iy Q[5RA(ZpyW4rw4W%O@+Qx,.#Si)ȴr3 #Ϛyr6z",Xʑ >81XV ).xtm ߻})%LP(\kH KC#.356poy7>M=mwM>w\4K~>{A%+L݂شvtnz\w( @$pcڪ>3عv9+WxuЅ:H~i});@A#mToNSZf^^ß=g-ܷa2Xt{l6SN6_Qbß U9dӵmk{RsfG1ro@PпYa.%E25Yǹ<,w[pRMO(@(DV <讱Dߴ\}yx߯{ظfՊ1͢"#d4 (SFP5j{d%M k(L#uK(@h(x;]T5Cz߮O<pV<,NOq4gB^Vrt wlW^ǧXa 8-52<8PՒ,ܐ uy\{^a1@qj1Z샒F?TuPيb/gXTSq c[3$uh-G0!Yr1CF&A}FpkK-oj-ݱ>`l8+"z1#DWmC5n4n RAe(] FqLMͳFNF7 \%#=7g03;I$uAwu uЧQZs+|w0r_eHW:mwG֏j>[ K8z`[@u62(4/-ۯR+7^1/>aJMs"5߅Wѿ궾**>p>lqޕ8V fE[Qr[fŖ)}U](;˻TXڳO/V|cYA?0~*m9vCAA_X cz%_]|!vAzCgB:x\iJx&!H༣CJ9-Q*qE۱sp5}>NȩӘGVkF,vlۊ/J,Wor26&a,چL@A\RGF5ngoCOc챓}Nt|AM|\4+]|9Tb/rI4Z Cy,]2瞋,7D AQ]ڠtf gJ$MwllnF@bOά(pJƨ%ZT20#6iL揮 qgQAPB*/\0"? czʸRwfI`B{gB,zXLTx<يSFTʼ@Щ.Fq?Oyӕ{M#u{.sGHHAc-o ,]mC ]\=챣yӗz=b$$ dqy5gZBJbP"(Gyߧ6LF'kjWmş]5pQSaݯuY<͔R3:W{&qFC0 *DS6zB_ _tCs߀˰x%«U2wLPR z~ W$v{.F.y@%(-=R;؉@7C,yX,"^}v _Qy!J-S}@j{ZP]viC f Z66QR8[(ad0\ct:i}DMB糌KϥfͰRuKZ!GqbZ$JKȴԛDTs'm-؍H87vl9!;%,zS\ )pumBDzƪQ,Fy*[V<OiÒYgvlj1L0U@aJ.׿)k[؝Yf6CrsU-,ֺboIy?Ux,9DEkε&f C}O. R/7چ(H^,!34.*0{>57z-mMn?ђx5 d1V(M)tsʮo"kZ۹ ifqҎԣNٻ)/sZ]7Tm[._R'tg΃:'iZO0 D\sQ:CVVUF轻ۯ}+x ^iL`eaĜ2'\W@ZZ6mIzi<`N$$_oqg ,uS_isqi:Zr.Ū-ʻJ{L3eU䚶qz^M  ]JZ?]g|&[B,XDׂO|PuR›x윖ICy_;6K-Oe8cChV$؋`+ XcWXŚG;P;] IDAT# 9j.gC SZl :e)DAI=ƥF3`Ȓ<sa($EEH(:Zpu%k;bWK]i7vpWH$ksL~Uz{fz Ō~UeUeeee|KX|j,mE,ϐqH-Na!\sTvb5M(]@EY5V0V74SȦu\JPlϷ"Aֆ|{Qf|80Z Hd5awT3NRhoTf߃pF 1,'1gT a[tP^M& e 0vۧmݽKVaW81vj#=p"9>=ӫ},oJU[tyۭ4޲CIdlGC)!Vo( $s7u+yOwoggQ,~Bmn; H. }~S?sOc%#(ܗY}(ΗBDLq%l?8BNjFa&VrN*z!KQ~6b׏qvY~g|;QRR7e_CZ n1vR7?X=t?'Mf_]F2|%NZ|6<;E35d97)`Wqէi&h&<\*=]rdoi= ֻkj_P\w(A5Ezݙ*07X5"PÙ&4Y+@,I)+ N!iTr`mP">B =JݯAAZVy{0  cN S,L] LP@ZںSF,\,'Y]B$0쌌yh b@S;l TClo&i5J' XHʉb~@J1!pv- ݵ~D˄aԋ6r92Vfj=s)GTʉZTKF/| 1!ˋS}|b1MA-t;"&6' 6 %.{aHwQ0~ ;Ydg5QI^pvYXVZHP5t/VT{Go$-/W^_um-,&N#OM^xD6 [9E3Gb仼:"ؑɯtC~IxvjYGE ô}sU!L@pK^RD-Q  8$j5+u΍=z[|c{\?zWOR=5ԷE9G—1䒍Ԇ ?)b(Xg'tWh'Gi>: 抽0XV:"(f̊'d^p0IQɱU-@"8 qJDY =3zgqű#D yJDif a9got$A,~,\5*1IGHnœE^Kre+n朡fvB Zw{/|܊JX.taх'eu/0Oމ9 '~k0_[(H__\+;hS2K*_>(<}_#; +!Fg5b4+ p5 ƻws<}^_;*ܸ+hZq%zZ*mWd57ڋ_4}@)VK2;h!a Y d[ |rm,JrF@\]"LvLL7i :/.Zھ?qX?޿ty|IןBe]w:~w7Kb ()?-R %!:.ęus`FzO?ߜ^l4D6#߇iA%Pj:HI6DVm7uXY0q9VJ!e.rV`=)4 Z$c Qc;zÝ+RЂ(ib+5r+lgl=Ep ݥ f4]lbĢAQ-nx$A@܍"}!> +Kp1тI.B@EW<޾A˼㬼?'σB'D!P@N"iWelL7-A?:UZoSyaꥎ=r~>ĿSsm սHӠTƏk)r*>)SarY__o ,lE]_-Bq*㪱 [ ]*@wBBDroDž-A)Fmqؾ=Kq _0`< _#"3 ~,%=iL d~g7{a]F_3@7ܐJې3w3(^":/6RH,~y-*`9Xv$ ̅kz*#\ON@Yc}Id:D?1XQ]b̾ps_Rۈ\Y V]k,a8n2!G088MQr7--3'8k8|[, Blf)x.rF.n&M6F.A_Y%(+.X8A$"*X=NtZG5; x=q3QPXnBb/*d  !H0BT,y6}01[=Wӯ]Ժh+7r@B¸,ȸF~~ D*Tj d(EVn1CցPr? A!YӇ)o\̅K\sW7{sefƒHH[  »0[K6]*"?"hKZڙq2Z2BHRˀ$.2M^ XnไE}J~Xh`ɠ+s}@#ӣ:k;}lC2O̸߽ٚbUL' נxF1;3P/}j%>B⻥H0os uWy+Y%^n떭%ЬK`A܂hȍTbqmaig-rvn9."o^# }KGv* zXNKEt\ ̟oL=X"F͟qytzo`̉ZE$%v\xkSZ8 QiGfXxth\Pp1}fՍDg{q 3/_/ީEbݷC-Stb"*1nk"= C#$ۜF>F!Jj թv!͹Yag^`{|4B`.)>]T#m܏ kDYz⻻̴hT[]姀@=2bR uОϱZW**9NH.%BeAQ4BWLKn,9jKȠ\hc61WX2v޹R-?(y˸+^.ɞ3b' VJFb}+OuE>XQƐ>hF,41g+r@1xB(#@Řs AnQ1w>V}zV( IX4#, 2o [:):/ GUÜ5#G㑮FG7PqTخFh,݅{3lqMdrl߼7-V3 8I~lОEoc~.pʍ Aa& nPFH^L/tpH /L,bHԬ#T\Q\|  WNQPyd: I#SH|31neʖ@ ^Y"3"nX#Z|%V}GT$q2gG%cڮB&/T~$"L)+ k*Oap@f_\z mОWcfꦓag.`8g}Avt<|b 58B!0D.4Dv2Psǩ J|9z'~el^x +o>) }vnB5*7VqA(}MV2W">tYCCNqZeoAy=¯~N b %'. eA[z e 4PVHJ423FyCй{iq*{blZ)KO|~u\ULw((YŠy/Y-!\oy=*beA1&qI7qG# / 2iK!˹M5!OHzIGQ9hKNwҘK\>\U().'bޅCEUXjT]E}nhM̧LB-yx0ut$/>n,+]ȜVAiuAM#"0._Ym )QjD8b&A4pe=$Y9dݽ3.)l2%W?ßDe7ފ"yҫ2_cD;p!o-{4L%Ŷ!*؋+(R\0[wZ&’"Id;cøD査o+WP]i*j_D*=z XINo(hD#D4innNG)ʀ+i!8u5PVq䞇f.t(VG^D TU^DE"Sv+;fU4响ypx7w0l:!)V*{roSF]+Յ˹d{ˆ,-X=7z,HrOƓ ^2&7ɥs})49T-˽hf Aԧ^p4npdbFq,cN'> nV>,Ey7ŧWy*2"%0O8X~mF@Fr̜CZf3*VZ]B+ G&)=,urfzY V.q8fpJ:,o?y{3Exa7 'A&/xqHȳp\[7i:e^j|`\C Fxv}:YaK#Tz*czEWp0y4l!V0:4tͰ9T3O/$WdqڜWd-]G|`Rcp9־oZ78m;*'eZq2Գ< 9Q( u[PZ(|I]<lZGsZ>#T9^yxS>`D m|#ƌ TwmJ3AQv95N!:B.<3,<3K(Xф]~c%2s6$A}~ NJsID^ZU:$c-"(}LJ*rd5U]70FEfs*PKZcBID>J׵7:r +m\exc;O^3_ԟX"|Vn8Er74ɇY*QrZB ^87@}<. ѿ g;NjmU/y`(,U92!Wj lgM]W?jHX5ّ< SE7SnGyuL 췰PGˏ!]jG?G:`EѿE  k-Guh}"quY45Ό$ XMK۞CG_KB\fmA^buvN'y[)UAc%LZh5GjE/}!Wآ66*XYW2*e6YyԳ (MHkȐHV1le|J/mS@zӫ}c;{8CD7Hd> :GtQ>Z/<$A>zDAE-Fd^& MMo0:ܠ/1z(YhH`HLm1y[G/Gۣ09q p),h%uELg_W,ظI!+Iі1b-A" ,=i^ͽ[^w7Q@>{/tJ^ ̱2YzHOVA6˸E6bx3H7_/+O`o#x[w~1T%L|VW5挌 ut2iԖv_h[{N6B~(X櫱iy<]RNy}PEZFUm̾o0unU8|\K& + ?r̵²e}H<90@=I!s6n_j0^&T1(*-UbDe`-GZϱ%vcfCPH{Ҥ3ZFcmCQHT1B C*Dd.LP)R''{73x~Hq{ظutv3)0z䬂-ן>0I we"Z;H!z 1+ )1ܢ/"WpH)vtcmZ;O!@ç,I=ƽx ǤQD`Dc9x?r^z :ct԰T> >He~A;$`n\Es*:>(OJY3_@o4f+=ThUN шGgE"*Kb ɕ|e@o~dcteXOtI CD2 j*]B瑮|Adq9޿Hڨ>R+׍U"<&Qq:(cY]omrs ${4.:fM-)VB藋!QI5+*0eto^KKmtUDި'%20=й V>x?t !jQkqCRxqc1p4#+;x˻[#jr.[~²ee\tkaHQjEXն1\O鳫5k~rZf滎xVDkrJHp% 58G#&f>˦# }[5+W>S~tc|Oz0aB#NCe T ȎC"Pӹ_SY0IrAB]5Zo€?5)~9A#`e ͤo=ȿZ׀p`,0VBi-D)FRi-ԖBc5v3UP8"}q%,6( ,t(s%9=1m!xS;P{W 4 rZ4kq䄵L]DcR0Y@h\E% ! Xb`o?TVV;f#xl㤲*@X % L@"1P$1cvR۶ F6k'x`q?t|ߑ ?\LY½t#]'h!0OXBWU *y#]BMB32# ?ٻmqq:E\H̓U 3)Cwwy_x&_f}Jc*=m0P<_hx1)ߦ ,gr~pt q#Vn53$e`*%1 _A_ X JFI .WqW5/7.Ѽ3 *f0! v No̢d;l ѽXzrR'!—M(Z \gq0U2oT5QPNq_ڪcc`}?:d01JfpX$`p*s[z> j殍Q{ܭ`$jEka"9_uDLqD7@He !ly@Ƭkk%9'TPa͂Tt' G<צV0"uw rtTc%dR(Qk(]H+)7VC+D@SFTGU3 Ks\1W Վ^.E5q4kL\ns{X=Kx!Y c,n U7(]r` ~"2NhƾÑńn h;Ok&J(V96D4r冩ΥP% /WF,'QNb>֍=§mxz2w_)h\ L guMX[籩bxiFf"u7 @V7sl . OC.Bǒb݌BJ.*V>P'sm-ix=] 6ȁ~>iyQ$A*ڵh Lo5'`0hݴ@US$4 3D.8 wUpz) p{Sra 0 e/! !miYʋG_P´ bY#ʤ0VVB87Rc14EdΊƸ.>\Á ֓Rѝ8 m fE(nE:dyvۋ7P9a+: N( jrJKr`2J`L~P{W'7Vأ2~PSIŜ"+N[ \[PTUύ+)g&P)%H>Cӯ¾(/Ll@@2: MczߡV?ywh {M@`a  xdfg&ټp]yp h丷FNq́<|I\ńSZO16QB2:j-aH8YNb(4U(vS"0,c9uYLe"bH&s~tl (ތy:`IeN>0 Q;±m3;qy©xF a*PPY aX0 #Be1:|7CXow`YlkpYݰ tM8{hcQT{,s 8Amʼ4ױR\os_P@P)ڌbG 0'(-ƈXN:_12(F-8|}GdU<&p=N \.ͼuF 0,yA H`s*Aձʅ`“,w`||.#NJ7"H@`j͢Zpy.!ƿH8XuTг*kZ Ő6RfҰD="\Fm_k^qG_f+; d].*P6fw[&Kh.(U<1/:QĂnV== 6SwX 呻+lI D$I[8C±P(UZc-Li4_?dRQH7R!c G4@P$"WF6!*ޱL- sa>~ȡ`)@AH Ef#,YCMtbyXAײnѱ1Rađ~0ۮ`|\гM(.a^hg~,ye!;2b66LGFU7nc*`l>0SD3&r!M`a 7n€1eq)2P4!/0vNM_V]dP C[kLbO@gqLr^YZ5w'ѱ+gNȳw.$l}1y_`]Ka h.% jH\z膎R~S)UY$iz|_d9`H (Z s)wp~m@Uhoz {fX~~ TBpbtd LE⚀=$+sdͅ'Pi0h i/f_¡G_7ϣq сil$|>:(S }tcӫʃs"m:mۥNDmK#~C+6nwP#lЕqI{A4C409˙f'c%V)UnC&]vk]_Ɉ!W6zXiUè@ު#zyZLg0f f:NpWXx/v}D2O| ߟS ~ēyShH_Z2B-Ҥ3V%q'L zR|7ѢnE)+QI_Ey*CB"D4eqZ^@M* c*:%Q54\,Y-$/9Pwd`0Z"t:8q9'U"T5iU/ƕmZE}FhL9ݏBڪBi1c;M;B v~h뙌ѐM`Q&X( iԝj,I41I \x&2i*+&l,-΍T^@*ך]9m۱EW "7RH/#Pϒ\(~4~1Ζ `@y ^N$m]2plV3xjUTɷPQ\}J kIS3Jҧ4>й裏>t-; ұ&|} m` ~nvz0x͡=y /Ry;CPܳGLjP8ThFEM:#-ڍ[ yi|c#VΤLW&-t)Q`0f=X/`jbSO̪:^0h`DSxʬWLm`pNol~~W}7@(M% ]m_: 4[.qJY1zP[ H-v0>u %ڵ+32Ҧfqd{J{w]ֻ.oAuV>tU\8dk+vUrdB@# #zH`D#&A͋4U\|qu m=1ʅUF6gbP$Vܲj< P~֬ E7C3-61i*Dj*o1z~?Y}cn@XRgW@H^*pWx:+"´gЛ0.S!ߦ^d=bShwtͷ$~Rfͷ`ĂBFjp4C4fN]PeDEQ.O1IRk1LиBH 'ПjG]e;Zh1~.]Aaau.c z1>r+o|̐ŘHUOyk 3[jQi%i+rBp[W` v<8; f*=촜tN Xhp3$ˎk㑃be"0 Uk-J q<02#-5j7OiR10a+#_*NpEDw5w@X^hҘԸ*#ab +4.SuOOKFǙkN2(|HasO,HiP`fH3и*`VSnş^ X0p"{Y'n?btS)D/ѿxL(0't썔 #w=< PGtGCE"\TmQoiՍ*>*[ԶzC)S1."̹vnteS*ҤZK lC_7k m57+HjHgd"eI#s;NՑ7LtE:PLhQ%:AFYn,|%Aqtw*L "FV;}$[Ԧ" 0An@V&UeqՖ *ӯ zk'/N^#vI\ ,x1;X]Gغf;;SA=&nsJcoaЃTzY# IM!HKခ[CC`oD ‘IKab X 3c1:wamH28Zֱ):9X3D+ZAL6HA1EB -l_'lrOX^ŠO#ۘjKhM[YXa,QO?~ Ȇ e. 2Oe %ˊȜ㟳L}8e@.6ZNAa&NXn1xMkm2Bm&`vE6"0y(r, Ma34Fk] RO:,.Fɫ_*6-AAby8 v+C w=,]CEItr6G|O?g$84.u G&q!e9jI\H%(L+|U|ad mzy 33Sy9ƍxZQfoc@P9TZeZ$`?4^E<Vmnp17bJXš/u3geXCJ:8•އGޡ,X ܭnH\ů~eKsJ e];[a4ҸU*tIec<̕EM(#'%Г[hb8lSj)jyh='d$ȓ@*,gK ?Mđ[ kqG5~ ~X;k'Dƒȍ.Mvt 4qi9(Rk+#:QJae'?n%"}EiFQr nnanͥvb#Io+kM-bq|Ku ZbAtIwOBȭx@sO}\j}NbfG@&J 64*oa>cF FjTj%sm(0 AэMh(h _̋B2 4/‘(:P EFkϽc1{煮HLmιAq]*++ser$R/$9cpu\zK IDATr-.INM~j^T\U[]xp;7{h'-b94# L回O)Qct RE@3p4o6Y 0`WRJU ;UXIr# TJ|X߶SO1{>ű]/  h[7zP&U% ؒF/O| )@0 o 1|V>4;2ou,weoy@b|oW6| ױpn`ql^= mnmX6(&#Ē+'`(y+i8 K81sV0X}̜'bIy2(*RPR|X7/5SV) R3‰4Ik@&wHi{,9ܶԨ_ZLXV!Oze8 13/Z,o\L3D@M,&1 X9]V/.H ,`u]F@HlJH}.C mTx Nw/ti'<v߹Ŕۂr)৕7:]$rwsW`p0wTbZt!DSEb .d`0vǁ;KB`n#2eTNA*@,9V7RE1eKsڝ{I&FJuXZ~ {'^$i0d#)oaI]\Kܶ@wS_Qup9v U)\vwtAk?2M;&7Z~Tk2Eg"YEDPBƨX^%Y>Ɖ;k3(a"BXH Zny*KGm=bd!T:]ǎpc]q1I.i;z?Ns>jد,>~gpL R\!ea5" tvTt8dZ!cv.-N]_O־bsFDДXDӋV/߿C=wtnz}ߜÙEF]'[ʚ~|oB6w[^o`S&.D+ب Vt(<8ҸS-x \]/ou!0jV!gN k)})a9􂿭E L;.j*I쓥)1"0Ct#@wR,ۋV{4+mxX=N&l(񚴶aZFl)VӴ!4RZHү]*sZ .W $Jk5q\W#YE!ckG.>0w3R%!HuXz:6V00 XEw #b!n&)A&):Ly2zI t{" )nh$ q0_ : zK`'Y{A,<)jeABrz? Vg(}?BJU +JU8>Mit=i Pr0M4otFmz &A]DOeC0o_o1NpXk;I`p;U9\؇3XՆ̴m@80i2(|4X.WXI}@9X|,q$}?-vN .EWVq|e)y LR)ؔ[Bܠg- c|( .c{c@=c)%Ǐ3 X~K-o4 ڨZ3%Sm2ONYʇJF#-db4 X!*.=%ehc%> .EIk:;jNVe1lE.˜"И RȬ.E b?KO tA@hp m4TJ Y}nJ{L,_ҘDwXl~;FYJu|ˉ3%( 䳤tz &ꉎ H( oV(F].ș~ $%WKl4{)gar%ThLH J%&R'LbVcTT4YLdV.&8A0pt) b(f0B:ux?`B LѷP3Ԫ4jfpR.PSC h-_˅8Ug}KX NM{hQJ%Q$ 6~_Wb{T0H*np塔ipb}$-, ym?!noO}ZV2Nz*WWqri1זBzqq_ǘ8J\SL&u[7T_JR|x['q3 )P&y-~cOln6yiqu|;b}MϘ4blZEoFNcɣbe 27>HTD3?ŏO#:_!oʥROP@Q~ך.V@w#($DZ"MF:32!܅IY-/\z[3E^AA6hy7vM)$e0z5`5t^+1Ormd &W=eplq7΀".%%8Xx\5@,\JeߪKWçR|M.ѝa6R-;扉QB$wRzOV.&jmAhaL#42]LVv ufP?p= b"QƓ8]HGM0 ${N ˲JrN׹s0^m@HGRrN 0nbխ`;! b#s1{HbRS蠷 #˽w¿^\??S-sA^Sa5JK'teΨ],MGŠQHyRLuTL *[`NY(\G3H;q@)Sb,NNޭY`J0z`X ++ }\a%: mbʊ0Mwe,]\r0QW<x8w$v/ AAaT$"s =x (7xSw.J@0r:. yBa:h$$)./'KX ө,2F* HgdU'g;p2걕pu"NBYN* D|nd^&=: qoy1Moפaȓ[X G)^+5/p}N#9E%变@1Ҧo@ {)nUi#)uu_`/'c \֗p{a/Nho]-uB?׫pcqk8CLnEF_'r3KV2nlZv]۵uO=f–xc˵Bs;8w >>~'cB{T$a3f`ְH)=CI4'ϣ>~R\floU6!FPt$k`+B-AJ,O1'!V@41Vk6m>[#?7H,yT0ɮL.⫯pۀ N.O.cOУ|P}4R4)sow,;-7O~Sw "m %;ݣ\ )pH8+[V,} SRdRGl9Qvv3/2nR8Dro"42c ,vaK|`)չen#Yn$.ubfI$$ai1#Nh #u\:'ҭ*\v; [ cnBjsԍ$x4!! r},gP#_0;h"J C-uc [ |V%Gj4c;O}{ a!> c[ )=Db{ՓR5o&@ iw-aM/S~ ), m H< M; _Cq[Ё9~D_pX Į $jB6}:O>#mxp[ǴsVîN%^%ɤX(6l%1qsJ" #& #*=ϰ!J?%2kl$%YL[,\$^ѤBŘNP Q.e=>V ?wnt l3| 6xG1I O8#^ͨNp;f% mG UFd"`7Y{.; ?|0>1J$7Yx%>p,#z(6$6s*+1[v,,wDMȮ6Dy'ӷ(6ˎ_rv>Dn-|EܭKK`)1 ĠX'2t׿N2NAv%L I!@٩XASㅋw&keUƁAI=]9,evʨfeJ$:'Ʌj#-n9!.(9(bRQ'\M5?77p ^ Cz*ru26ۍ-LFąL,N ]y=o4MKk񄹄2> EZl=&ʤ6ǴbUz.zxޖұ{zxvxra;Z٪nz#I-:.CTUkC,yZ-Wi|)͎x]CSN9HcU: i$NV񹭟o9@:w.`P]VB[y[0% n,7[X~m+ĭO; uyvO;8Ffx?Z<qxAoq3*lg7:f9 nY=+6[qE7xBlt:CWbM\-}6ֿAt1Gſ~k_WaCh}at_ Pýg<5kM`W~MV9|6$#iN `[^D!;:UJg^Dj&FLE.遤ǐ~:9O|c2 :"Bg ;~Z&x /=5͸g/s> ֣g䭇NH`Y  Z|6HdAj"<``s`7@cOʼnI'V3t8Jh\nѩ"GLyl?3BlEXw@. Q(MC."HDa6|G݃ ӭ t(j 91c Vl#z*%_VoZSSۖXޤd$ѿ}LDBXV埙iI2c&PQ#.?t6R&#!N)k@Ƀqm\Crke_R6m8iIm\<*^<07D2r[nx (mH􂔾7*J )U{xftol`@sm;Z:pՐːu`uuo#37 I$,Vļp*#>8Ĩ/ IDAT|R*XƐE#Q%G$%f˜/aN#q>N~qGo A,(=k(,>X?f;8쿥aHs;*vX]}.ֿr_ō=t9CJ;6)Mx'>|>^Ž1Z“ǜ}U''X|UT@xkE^dD.sQ^<נIe- n㔅ũg`|RSl zb\ t@,zʪH[#_픰jXhS+V8V)JU,*V144B < DFj ݈5A8h9$+!U+}6"J`L %Mb1x?܌al!S~ԈdsQ1NMt#&#w)kRB\JYcR>7v;5e֙bS!In9xp T3{4xxp?zGճ2i:(j^tdÖI$WP#A[ㅵ=la?r@ՖY&ۙd>_cޱbҬ|RSXFYԨi UÑ^^Ӱ&a-Pl\Ld!ɥ7>Jk.ew=+\xA $6Y<^y_mQt_XY\o4'A40~[?tOm=VLi:4p a3O >_=+_Isu:X;X 1::D'Să\YsMyBMNCDD4@O%qpF:}vu: x|߿<^rLGUϼ>qn^@é TQ`-q k]hj׆(=-[h(SRcKV:)4p BjB`qκrW1f0$'7nJ4A:Q"]u#l7bsB1d@V$Җi+$jȸd'i.sYlt{)JIfd.M@ )7&ȕJ65<`^]7OA?H8 1}JhoR2{_JU]39;)ƨdL=j&w0TN?Fڟ''&t ALpeH7=dZ]_E>/qts 1bUdT`$^lG _ux cgJB$gHgyEP 8chHP T 48` 5-6pT6z2=K!?1 ktN#qŽIhƟ/>I<ߎ L_i*<i"I;d3tFפ :5tD졵6=qM1Kulb/YiI βx_gy]w͡dؕpţm ꅘ'.}|sxk߼WtЧhzЖbXkY ; 2pd|/ڏbǿ/vvtǛ/!aު>b0/ tA' >o5K_8"i4]8) a!zrqw[K;jp* +FJwEu?LRbzK>1lFEr4~rGs)^~kc7C?wiHhXI= tB޷[e %TRY ͈fs$@1N[ѿaS 5"F@@+62md#"m ZF@bLy):e PJgu  }t`Jdo0 3ڬ\@8N r~A AS=3Cb"`O(zbR:p[ߢ8MQVVXfY($W4) u@ˤ[l++Fwm-`VSOBPrf1&J3L ^=^pؽ-G38[Z@^8̀\cum ':O\]\c)  {fas&-)o!W7I[LuJ2O9<&c $Q|ƻc~-٤kt|ۜ1ӂASʞTYg򺖯sP _tdQS!pr}LYcWȨk9/# _Rij;=_ qDȊ<[^%šYGz%44q9&gQá6@ݓ^cMIJk"e*Sn%者!_&~_z_40 4bحkjIhJIҚ`r=ŘU FGXy"uP_tm8.claF/$b H5?PFF(Q"W6NFŕTKMg^ZD)<^4]wpCgizPVsۻwK ,̓@cݯnDs+K+waц<4TyoСIAܵC8X7~xqXR c {f;/| nkmƼS'ckU-q$1,(^\X_"Ra*JRHg=־twF#bM,Ydx>=YίEV9/TlJN0Nld! [3LY7}!6d^yJO QA^bꀕ %Uه>}OXU`!Jؒ!'eh AS~1NҖ`{% ~c -89J?j@+@DG-Qr@[xճ]iϔP4%ŋbX/:_\ 3yL0xgEG6uV#IOc 0 v ^X;]5p) L Xc$/NЋ |ʪe/LjC> y.^YznK辔+{64r{‰, wQpe:5WgvWVQr3WȻ4 Ҥ\Nis 6J 08 M;ា(­=휛|ӟwٟxv=/܅J Z mt0P?qi+5[L Ѓ2>y9ײW1 (}Hά#0S> r=vCqDz}|❼r-rc9`׾;`O!=r[,֗-`h:Uw0~76=NcQOxUO>;?Vť p/oDXPW~[eIuʵ(k+sVXb\&)|Qb Yn83D8!˂XG"A1OV,KE0D@r)ũnh*Fyej&܋Iqd'b)Gǧ)k;&, &ȲCuLLq!|:XpHu";sZ.HWV_1|%MXUB :"ɛT#F2*^0pI.$Yytқ10V0h`8wTMl_t/>ݔ&N܈xBqO"c+ư/9Am,hˬImA_$$⯴93l8-72L0ngd4m:" 5hu 2g@@Ev-~lAAqWi)ʄ҉~݋56=]GMˤE;\K0 8 P_[RqםZn{nT-t+Yo~7~nrZ]4XNVBS\GC]|*:d|ceü Nsm dh ]b2PF@0hTSeudFE[ D8cRSJ@*H8HeQHD q$"%8p8jE7 ֯Rq1sE>5J'6{*|&n L츬}% , r9X^~0Rbd#ki`LviDE}} xʟg®Eb,?OzWQ58Hu|/=6 1ENN.QR$n> a&#p c(0؅֨B"6q+w a^Do0 D*3~y%7X^X[B,AimN{*awGڭC|lIqW~7AYsnsQ; /.Oc/]߂#|S!drY0F+*W@3sY?sE\}crTeEA\XfIMo|R [HYkTFGOR'8rk-~ JH*X5A&$".__3O`/P[# myo/")wH"\ZĠ9gg &Os\ 0ZV& J.Nd1Koᢋ2=K68U&ce2hH k_PWeP6&L#,x=HbIM[ԌxBa%(e s;ZNcY1hkjЩ@,Pn &㬨pp[*K+&;|$o.78ͤ82a{Z>x7N/)=KAˏ*D3 tjLem`,bgbaϷb1bPڃ~>RyN%u3@y~\z?uUDQ V j7OTI9Y>FpJo!xҕF%5 SCk,!'zA5Bmjܯ+z٥P's;i{٩sc c Wl kiZ 4ZVݨ_ށl]ƷwҲ9ADrM\TN  ;  ߔ=}ԫ}tNB,+_.[ ;@):;A6X.XX,TX\03a|O IDATz%vG+!ױ}?~w?Ü{Ja'p)+iӌ1JR8ceyI}FgT8BmEd ~I~p 1-p=*&J#dU4bU!#*IG)KϐZ]l4TR  WF2hMJRH=Ȇjpc @s3AetZJL`$5SYPr)n/2h!`٘|S!*S,N_i"@SZ ],ťO`mCbrF\x k >>u HFuҷdE*5uد孅CIO`xy `+w?y%VG<58M29(Wz\g 9ۂ7H `y r-[LX% d)SXэj $~I@0EK\#u{7:6Ji9 q!|B][6$$N2@D&$k\%r 1X?MTb 5/|L˓Qq@U icgc6NT;+Bc) 6#ԣugrY)$ K4lQ:ǛI[U[NypԆ\P lQK,炱sfprY}! -_\ZMx<H^92+qMŜʒW>{M{&گ5Si \7M. v/ 4R_?˛NaJj??6`ڡ ]p\,,X.Y-U-Z,XOr<G’0'?ĉCk],.Xܼ;a}!Ϳwʯ} ?nK]t\o17c$L=\<>kŌ7 2YB \ eX238:!OT^8V䊤@1yuf2\t&2hs TD]WDJI) 4k]?Is54{ ZiVC=uz~f (<33dg `$w+vmy}wZTc[9d8s>ix/.>b7O#0h##hVuԠ ׺"shunbҳbf-INl^Xaq[F`˵!:Y}Xnq|mݣM[61SAch)NrVqJWR)zc:+\ӥA N 0'(J}PR8BO%.4kb$r(\hkDP9մNNx wbkXtI 0$.a,VHn5e 7hw`c%TE90Y $Bq@ː!`ОAlE̢^0 %Θ3IQe $eq\~8'togM:4f1j!Zh@,$# `hi\/XK "vԽ1@,,?*SO%㋚NJrcWoDMb.dYdʤ42a!I`iwXՁP|0$w^#K̎ }_ )dlV?ڪ0κglUגpe1LO3̇w 5TkӬzN٥h @&u=-}m6Y_[-(AC>>8o]Җ"OSEqN|y=وlӿ|ҢOuX'5:>F5X}~x*n 5o~=' ݽd!UxX9_ߔ=LC1MDdY0’N3EMV^'J ;a֎F)\,||"WR .A@Y\C"m@1_[)¬\5ž[^8:MC׋)TFz/ ZR>@wjCÀȈۧD&!@wT/țR-B-eM. `(R)̒RkTA_+r20,Ԫ @F :*3S 7zjMW46s&T,eܿjsZBҶ۪>$ӱVMVF[Rje5W2nb!3l1ӳِ:9&e}Twp $s(NʜCF!қ>zʺOWlZd@E*-kԩFd&;P9 k@ڞjx{Z7ГZh|RZ1 9su1OMT[ϫof-Z;U`m> ;ֵ )!^O馊W#L:m iO2wxH`c <<>F1 K `g 5^X n>_a%52W80\ʹBdpqK. PN! ]_Ɏ3%`T+Z[߲Dy2VPDNp8PGQ͠BbX$(2s8ŞZ@%7ՄC& (n+pn Nyam4:_('^(lVp<کHΉ}9PDa2 i|6"[ښ WI"H=J[Hϒ< P"d!3(1Z+YbqehV Zmqj]L6(S9 2n44 Hsvc~v<!F>r].mMtY}d@KyL¥= ^v&>, [j hpr;MY>ϡX:N:ŽEc.nZ ఑5c띓(Ҷc0ME^?9dpb4i=c}o锩uJN/2s|J+*\>e|K=ʪ3 ߵUt޻=o> W< P;$je» KoݿXm޻$=mP8ў KTR~du*l#Q)Fߠgh+SRX1"A (jTVY,`)AQJ Z^o.ZVE>#PAXXE"O\!@.@YkD9 .Yjur~Rr\ \n%Bv d,E gK/+NU:-m,0K(@M&jiL !Nc ߆'bnoRQ8}Q{= #%J (|.L,_hoӮr*_@)G+ ǹBˌj,pX4IV}8&Wγ^|6zg/8h?')zEkR/Nۗ.vXֽ #PI~/{!\YFp6 iy(kЧ"s۠FpLkzZX$Yt|O6dxWZdxBVOFIŋ_AE OA",sD&J;#aO;@JSln=GƓxm[G)D9RMriWtH=\b}6XR㨸J>ɍRi7b~4Fn`y~}PV~{'<TVV[VDz嵀Ғ]}7xjp~,DܞG6fYde=mV+{΄L;l ZR<è'Aq!`eǴoASOwg }p6<0p2b nzwٍ`10C`GJ=,-V}ux=:q_kx(n1\]Dדg3oCHez>FT&O<<L% ݛ.$vj4˻霪7Y'٤_=#+2`슫geࠞnԯۋkk5Xk E~1:=v]uZgs1/8,z<ґY:'TdRG,Z-t&QsYg{Oh˙M|N}pN8WRCΊR7h @hQIA_Wע xSraޚYO므}=amբý#ToTt 2[xoֿzӏWCB{9<"; >WĤ,txͪڣ HHQdEK{^|TTm+\.Ü5#.&~kd$(T,S%ڈȖ-|OIQI ȅJ'[6ԑ#j dtG$TW#F';zJVZ~mRʡp)E.hRAܣNɋwevd vP_i[$t#jp#.l},JynL)A&ɤk.=׈#B9NRYvQĤB,GcYdv(No:jSZWor 081<27^d]ڔ]osI"Ƅ,ٜ8F1s9EMYV\}yynU=ll0gRjn2tQEikf埓cY H&(Jgjr91PLnϨeiKKH$%P+=G ,G>ZdhZ_1EVkݔt$3~ƜgI݆p 4  IDATѽe.zSns{1EP),1qP.^YJ;ҏ> |3,-5xnx֨G}'־Wݟ~.,-wa~'.r4αPWm78%C۔cH \C Vh4+7XR>I\R9a/1k񚴳]L" A(R4%vƒҕb4Qnj1XxDV5Fq1Mh%1wYT-`<ϔtF%1ELUqTq5%*FBIBNlӂ]2%AZ jD$}GqN7 $?]t_V`%K5ym KSO)+*YM(c4J3K Ȳi8dFʀl1Q\ɷPg @ltkPbD%)A./]'zIa+t<*άHR5wMwڎ]#f^f2K#شa`u$녤=!P6NOd@'˫p-^DcLb䆧R!rL!1hMV2c[풁1k /JoA'cgkXƌ7޲`8%9 !q5vQ ߴcf4bЅصRRyZ%4GU iyFQȒuO~n)6?&8JBZwrڐDJ&".SB2kOZIBQ⅍&;EA\ $^z쐪gsJ,2*R=_)DFYKf|M5OۯT"Z;̈́ @V٭O+2 9SsjG,]I[pHEmn$҇.\˞9 aԥ?h͛ /j I9%e+,pLf4-eM"r":ߠl.q3?%c dlH?˄̤>vЌj(6ۈV2[SKtE&,[s T`g3^4:-lyɿR:6pV()gf248wy{{[]kZP.p[}Wt^.&$_'hwEwѪРOsR*tӂB#Z%˥A+Od+E;ji)&Ube'N'ie,gb!aݩz)ڮՉh |ڥG?lyi}uoH΋so?I9P% 0ʆ / 7?b/ ۰eA14Clr8$qΩ0*#⋬sιIGVfddf|gD]_=u%~<け2 (o,tS%6!0۝p u95Ɂ]b6i'D/6L1otByοYЗXuNO $S:1OtOCܡe[ Y9tɧh.'t< tM4NF !?R^? ȋf&zD>ձS 0/#Di/> JgXu=3,!㨍@ {?޵аyD_nዮsi:`?<0n"qnsؿe[oZ>'mϏԷU㴳QC@䊰@VmI~U(87-;TvʖC5噸w>FR9l>OaP6.uٗO8H굦K~v앐 h )B.9 j#%EOB}/kDg>jEO_nH6]8սSZ\ >5KJ}4ĒOMYНǟЇ7/(YN?^ٿ_ܲ2>oU^޴ 8 䣋3 j.96Wj ;$4r(V2W{D(CMRУ D6Si[af`rem|M!XR3h{J_ 8Rhbf9UBuYoYz @ T+$0ƨ Z\pR>t)fdoFh1`dL1hx}!W6%YwiWS@ab͒ 8\| b2gL pzS${5 -cPy< %=hH5Oϡz`@ Cf0E6o`?Got|Sdj"0訅>T Du{6T'aPC2^%Ŏ%8Ӏ_}K#o'<.c7k T(XST Է+Se'П+[dkw?ڬ^C9 bAgNrl)y||*ymɁ\>r"Y'_y l3(>",ev%O"ܿ3_}hL-(Hx*t?|K.`Ġ)DgE 򯋩Ilˆ2Z 4Ĉ`ͨyœhS4E &lz |?{ݥ(Q߁j_mH_~'iD6lF ڌ; U?%Zm`VԱkV.bbx6Ooi:261 xa*  NVaj}d2'WO7Ŝ^O}M}-%)` ٸƲ#O(\ B~2G=`QDmbuhMX-{ O _HQfㆼGcVV~hgq Et?rxSbP7Sp:SmbtP롃J>Xj`%cۇ o&>/Lz"@*e 'ˠsp}<@mk+7!6[d[tkM4P鳩杳_>LRw210i "dAe 6Ô6 5#z>?̝ot^Эя~Z{S ˜q_-D ,<{-&0b%#,pZw6W$S"@r aK8PPY"m@L F@K""IN]UDdkd6G _wu7= %T&@-) 7THQTsG*Z2P@@0pVĴspv%LTvZHf[ƩΞ>ca?[S&.5~u N x#O$$/GCZf68`@S Yim'u?R2@iLqf$ROuY/R*ȴ48ȇ@Lt-jD!59C7:s=ːp?Жf&H5x3U}7.LgVUۦʔÇ_VP-7CV֯5O(d@rtDMߛPIsV߿OtN(s8V6DBF99I֒.>~6tKZ^1z%]hx.5? Z62Ӎ[;h):}Ä-k`MM\Bc]`.c_`dH"j.ZA.X|_@ %:`B3ǿPWǍ xLP0x0:z>mG@p[]̶2Qِ@C4 1 Y}- ?vm2nm{|sJӇ*q(œUXRW9JL_4yZ~K㣢r؟꺡F:''J׭h(+ߚXН?-Eix;4eVIt?xC$G#cn[oqC+i@j4 ҢrȦ>Bk }B[L8="d ׅ #̚{LQ`WM:)#I8Mo$Z/X\%%MQ182QyI |`eʴa '6cBQ:tv_i`&aЩ!c.?*H5E~/ؚcN\ 2xa^跥ˆNm:I`T{|?kADZd_,h)uhfҎ^-441h5ayP.kA+\ͥCƷ 5Xo-cBa}Pg8riǍncmFwi»Cc=A:~_1aK"pE>C פMQ9vW䛗IrESC+ѯTUQ`JeV.G3v?|Dl_T'B@Ĕ.״]sxzߘYޣG5m;‡QzDp\w?'}m4!E( @`AIv E@#`2辂>.Z A}dq.gL]c_ɐژh}v K ˬ#LMC0&вMv rN$5> ((7@! 李P%r8Hb$>pF96Ü6փ7.`MѮ+aQh-67ȧW#؅VIs@Wи;GPBjWh]XYZ;7>g@kn>9`i{6pLX!LO}vP+u75HjF;2&-`*ܒ> jm>j]"+-!׏mBeI{PIs;]= RN䨞9g.h'՚胻Dߝ^rٷDW+S4i!^wNz6iIs5l@،h[EE*CnQF!:3 XA@ Z;SkHaU00 b2i&* .J=Uˬ`=MAxڮ<@KbĂ6j&NVaqT+}[8h+A+AИmx2 S& t." ȏ$lNmg@8t\`uLߨu +mhKATwQ~r`0Hai< @PPΧU,ʹ:4ťѶA*0_%\T1>(j=#3!-kz8dzg\͐CB4٦V|iugY[?6\ ~4Q( |*]a{ EO19^ 8=7C~)[_ZoLWm t0/ [=&n|evЀ2˹dtaY<wnwtjyr%Ƨ*2ejiwNQ9hulgtt4A*hsJԜeB4ZZϗBv,E/zXM@#0oz[kпFQbNo-b3m $L@ TsM t fD>dR5@|ϣRyԦ7>1諴*H_u;S` IDATm4@ꀇK:|fa1+Ha]5R* ͷj!C>:C$cSйk gLP4ʯrߩH}- C*" 劁zN)o!OLB&E;s9N7VgFTXNgD%ޫ;!ȁzG٧:e*hڴ{9rޝ)oK$S?dpn:/)ļ=5Jp߿G|z$y`niOGhu~B˗oG@&-hhp&Ic!C0$ ;#6ùW <լ@ \$^mߙXk8>2(7{gfa9#%n|@8 K<@jo^Xύ;Eb_sI.1{qso|/Is ?-1lj JuCo:Ws@lvO*F|{h[Sx`cxnH*OaU7 cY5  SaO15yƄ r |nȂZ ؠSWFgrDp䍇`Ej@0P4.Pfw}aH}2j8q-&qPCs :Aj% +9>aBg f)@ۣm4-i3v@ѵ9cF0 PCd}RCA+|a'ȗ}t:TJ6lxX+g9?41 tla&8h(Apgh fՃ2׆@, vֿYQy-M%PV \7| *ʌ41X]iܚʁ ξ|B쯧؂`19^s❬i(?E'}3ZxT\22i6{);b,39zFU '%n!oGJѪ 8Nk`AV>Tv +=`>ʨ# Z[Аg\b' eZ~E'`[hhQ(hBD'GP/2UZ%AsDEѱ#gZ} U{xZzg*5Xy;@a PinL 0V'\ñ2)Vj=x{ǮZ Tɂ@Q`sos58x]r`["0huj ksXkiߞl kβȲ=ueۀ20J 6{wgnw?+Q}:|BoaxEթ`_~xrߜEu۴Z4ԐFпQF&e>gnIᔁ<͠Dh=.W /s ٿSŜ*耟R!  h@Dxd f 2TcX!*hWG}kxAVMQxK:Zl6jSP|_3;­ ր.`qW+4`J?5q)6nppPj4b)p҃{F#]sJ6D&%48ٌ/IOEMP-pZU KQyY53 U09{QkXy\#+ kphNtDܥdͱ,QHL_͚BJ } T*f ansp!NvkCۂ=Q@V߯1a,C06Tqo{dMЮn7 okMk{toi#ZYȭd>o><> :gsәyi΃rIGIDWW ]  5G.>zǔy[P$:Gͪ GVDDHa PI5}Z6Qrڻ ^hÞ t E ѾyB@FV4`j0Ɲ H>yŅ1vRhU~&tW;7G%l> m B?xn:&7Y Ă<$7\ 5wTzҍ &~+F95nxR0lhuJyjw-8v@E5OpM1@c5?e[G"73zF0H~)jK/"4!HlC`%6c3fyuT>"h4][QW&o/@_VbkMijeҫ |tN 8-ln"%:z|Q4: )'L. fy%YaбLF]o f޴VŇw1x;P8]@f=i2k㟔20$b:B cl>vIbc'7ޗphA2↠A@\+꟣A(<}}G rQLSK$ i/84U֧ tA@@9+s @YD-d$4d3s I*~ R"@UH)ʬrzhДu޶0a+y Q7FwoV Ya9ٰ~:u|bB(NʼR ȉ5nD>-V#~mXG=xoB[gv畔^UM*>`ߓK[=u܆ʞ/⢶Ցll{;ڹs|QAvh+91|"u 1bggtw9B+0]В&[6xvlUxȋ3+m *Z }+;+2ʄoH7W3By䠉%hmPs$ǃK9uyݭ71hܶ,(:q>Xcl)i +`hCoKf }TTkx iKOఃmCDd)y Ch0&РAuCeg !C/9LpYo z3wn̤/~6Φp26coH)r'ҋrAtrtQdfy7q&O 1!]vAj޿Gyh%/w̴^6beR^]~' ֋.- k /9>ɒ( :DFJ馭sb WT= fc ؓ)j;u8 :D}i ]FSXQ[i]&2 0 m[# L@H૖ |5Zi)STh7!p'nrn/oŅM4nQEXJϭRIʞ?ij_Jy9F`x@` (-[dKiR5H> Fߚt<,ȋhƚPs _7WφdVpM.TV|hpa5b<~qa j]aXzS~ FhtYmwk bM s4"9<uH2Suk88L\O:H {v_^٧(]]Sʦ$LG "ҶIhٜdψ^v 䳹jӥٷDMז &9J5b7Ek fmO;sO)eAt}jPqs!@O .]ܧ+u!O%3DGe[y-?OܨB E&][2Xa`NQWZ޶ޙCK /֤cb$ BEHɄ_"?ɮB_. t ؃&6QRSA$! z |G}#m*qZcNm "dc୎ReM>Ny0*j5ql9!Ėj%^ub!&9j0F" tʮZ&TUB. HE흚Jm`=\EC$Cԏ:v(~  Wҟ~hx?c m@ȚR.oy|{p19Feb]ݘt,r@DgtcZ\i昜EsʉZу0gD/w֯)򱮴%|N ƯoDGDNwD׈~7:p7|KpFMNDnj eVkj.?ێ-0:TkZ-o-ߣ/?I1x)ԜM?x =q82b,]+9Z s5׊B-Tg&< =պAab@Lپ į]TL/K`PlCP [>h5jTn4ƴhV˥] %n ʀ(F%kx[+ _@$5iF>gU'Kn]>V;g)H8ff:WNf4 cj#VU5hCJ h1 i_f+FЯ'2 Q|Uczwq` 8^J@uV:s nfc;`\y5cdږ >lH\ߛ?m/>;uo8 lNt1|XMm~v]}P(atT\tf~u擤!:="~]ܩ קsD߾,jkZ*jΏ2檛pit}t|3=&%Sciٚ[}2¦\xWűV 3 k|쒂8/b,S mVD[o~_Cڜ *xN,I{}- ;ℂ[_S=fpO*\á EhOW_הs1ԆGO.:A=dӓT"ٮGj>ꂹ:/Z'4'Sk*(]ՋDy6YK@\s.r`Nξ~BrHQqXT ΠIDATP)\4w[uCR'l*(W!S{p I -yk2DaArbYGQsq*7D"aA=eH2?&NR-jUklF ij_&J'TA.ϫ &@} XvP0~zUB@GwOʜ4~zO<\.HB[I)nZ[sЌA.=@mU).ycAZ 4E+7GiC՜/ 7׮.7 )-^\,oybǪ}~];[^(E]4P>nϠtFڋ!^!AZPV;xmTx':~KUFQN)5S!c8L[uhja7&{O\(*$y;IRZL@`khwL4zF\W 04вz/AأGN7<S'[Td5c}&J}堙aro< rDryHB Xi|)@ É.7bК-&ISJ!n cZ a ߨh.W߭Jtva8+]S,WkKE%8!F=g ~ۦR0@[:[\ۈ/hz-hf~gZޛ`yA׏B8X9Pݞ {_Yj\;xa{kȎ n_LwSncA!eJ[wܞ st[>W$ ʜyRfM[ro YTƤҦW9LZf0 V{- jCU _5K.>Gۧ@Ҧ?/iugFٺ,W9bMrW2'*z$BZ?D@`Z j` jX'PDQ|2P+taUiYY샂Mp$h{Ag&忦lq52"_9~t Bj2r:kGJ?VSTQ 'A~|O3`q T` wpA` mO} s'ehU:`@ScRMcgC3^-6dR? Vrh~jԀmKϤRM2ch;xUUym -_/n2-W[1ѯ7ozJxq؄͟\ (}Zv,v\:A]9]SOGEaF'^ЭQs6a1^0~HO9.hԲn"v\cD-ю 'Wvl |3PL@![fhWmW fT0Q4 $i <(i00i3!l]3XDzZ&yenxF[M3h1֮b\3-TX۷)r&^}Rkts:EP͛STN7ےdl.>|8#L6 +at 3p } PfՈE?[ x`b*{t6mgp0+G Ͻ%4B#>l U AU `Z {{,KՇIW8[9#4x!hHh 5!8yb5dC%6Hߑ(Е%H^sն *X_MO(LuTL=gViЎ\O *&'V'bC@]fvZ~]Ј۬hΧQs' U~ $EM d|`vA?2w-;vBzP֟X3V;eb=5[z̀_Y)"^'޹ *AV6~Ճqs[0ͦ߾Ӝ]Z,yORf\||;9PfjDm%k޲Zr:yr!lV]@nV#x]|Ny Åt;?9?~ٚTkjV4g[\-D/W!!xAx!TLGeH LԀ=DA ܋lׄ= juԮ28uG-D͓z^5bBt  uxP`5hR+J^>ݳ 8[ש@vDRm50h۠;n`jcY5~u΢.ӧ L+5P@= FOlyVBE5VL'GL;t EA64ň)Fk+4"Sa&c VŰVShHrڗJ)`%?tymƃ!W?]7 J5M5Pwo[CLg><ҡ5>Ztl6BZO>O.Ahѻwgz g B߿ۥZ/珻wۤW^@li!]Z9mG/Wt'_m(۫_wfZE 6*ߨ/A`^ FB&r@X;DA@/ (h{͂BEr@LU%h !M/8b>{'\XepM& WyjX;q\4q F`EU&Q GA@.ffD,"'ܠ(*Pxj7/$5TSA=~^ -qlivY|dɀ~M{?1y6BӸ/>:ki3耽8E j-n16Y䉸!`Gn!m[K#Q<б5f`ݗ*3mJ*?Qf)9:ϽAl5J Q;7ކ1&Ў|fŊ.~.?{NbNN +zNZLh祜9㗝fn]Pр2fsѹAmhinHcWtSwislԿE7YhٷA!3o\ٟ(в0FmN͑. JHp nQM Ƅ(uVzPfG!a4 /5RL´3Vc3o%Yzi0 IpܩojQJ(c ~v`h2-.kCiS ]+$q-k#-w~jS65wb@AerIT ]@#O?0)~@>N *ClFGСpB=T{m.@ H+ɱ& n !OdIENDB`hugo-0.92.2/resources/testdata/gohugoio8.png000066400000000000000000002175021420147000300210050ustar00rootroot00000000000000PNG  IHDRQgAMA asRGBPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖ IDATx{lն]j ;HM[ \(ƍE#+b6C 1J/m B( qՓ7?~99y6cY]n1(]t}9fd36|jkylkK-6Oڦh~j#1$cenl[m朙fXnillĦ{#=bQj \[RXYfCR8b8J,C0X,c2j gBRgpp``x?,E\AIc |% [5s 3`I ZaIa!44 GRʥ MY[m+:VO]tpUB 0h0:hpTBZ!80 p'7 >h4:h4BZ A"!lupB E &QBAPX"lcpe`8jKRCe9Z}D!\p"Fy!DG0ިGSf(a  gtƔuG)/b e :8 0&:J9J8JDNBH$K #C! ttT "%` | =%,o컭!BEB>e;(!8D p0 QJTAVZ)4" 2s!FV C:X&f&!!!:h2ތi ( Y$$iA+ޯa Jh2/0B5ΨEz!!:Jb^ƀX6\)|N ܨE qGiZf<-%>˸J($G 5Ajt8ҴBB2LnI*%tQ>"TbZ? aD5B'/c1t2m@8OH!B3*p"#cC%|:T ̈ФFg%ɼRg4 /NZg du5;,ODBQ󙐐$el}""~Z&G%% #lZ&Zgj~D8nQBPtd!duI<G P6R s3V Wf_"$5|SN$ N8JdeH̔Fygt:<:!A'G 2TVf T_x@XVo̭l~[%tCB[PJ軣l]:o2Owɍ2umATopHmD8Dر6Xs0iT+%[!YS:>57EeHVꗡ7:Sx (FìJ  uύR'+3ꅄSfG mh+RQAjY1!:kt h qF!ѻmubH8X+*!ײfzJHR†A/BxQ&5:Zn " kԨ[`naV'IDk*aع=u ,'eĨe;ڼVor׹}땡\떱{`T@HpDV-k&k%JH+\Zt ]57$" aʼnVoRS$\tn} C75ez4p6n;YIaZ&,3.̍: t0:nޭAEa:}y+mHobr˰[&앱ik* 5:"ڲ6+Pm//z\^f}?1ypލ&7328?1ay+7sDn|~S@cF&_ u:m,$5Nr0=O C~ 'Y>4ːԨ۰deՎޔ}-էv3c-]L{"YN`BBF 0"pFB4x5B?9RabF )7MߐՉad1FRp" oJdFi@8%HhUBpeN,ㅄavFvРA› 2Y08R=i^`4g-&fL8ZFF=kNFiqF ݀bn'nrV%#"FFˌ2[ꇅ!!vFe a4>"tr#b#* OY`]oqDzԶ2@+7MLdEI8fi3fLf~iwiNۨܶ=k^^:Գި~I ZoOe&:Y ͝sXX)›EEˌnuɎIJt'[&#XVftL!ezghCFSF;֨2S- ;ܩD`;GL˸!ixp̘pP&fLb9xLh|'HW깎5:i27b FѰYƙs(ʸjS 5=~b:”O8N`πi[Jxx|~3琺c"e[-[oMݎF}%2.Ãʌ݈pFL9Zp pm kR [2#0XLD쨏 :'˰kL›,󠿉LD8=~muu0G#C-ڔydjuGoi(75w괌wlDg#!3Z?DLY S-f&7Q`XHO !["TI]JL8>68 NK;PO0kب4'cСW#}nGG߻{&6[T{y[!BulYhf-y輠_-42kF^EX{,:Z 4 eر-m+{yGǦuz'/ÞH֖1iloOun 'e2efd gF kHBYy*B8 [!9#QNjt=}ϤF8kԎ5IV7:Czxzam0Sa`H2SپAAN(oU?~R0g?= ۰s'af^w/3P9ИfécAI aAoZ!)??2v{3w{?1'&uJgar#!?ZGN9#}FLBhbBfCcn#isF u=[!k J=}Ny ď8-ҰHmb#-3 n^NOL3? ͖5m ]y M䍺]#B8WDap^|ZL iZflNfeƥk$7NBH;k61Q4Oxe[d}+7iZ'F͏wL?PG2Z֜f?7+hNّ5^ Ӈe\&y E[mK1 Rw0b"<0qJhOx5BIe#BIU' OLNX{̏ 3- Dq›NS8=;p:-ΟnJF #9z Nс3x'[f?v;&Vo|w83݉?| w_4ROجaS6ˤO"BzDT0n lLaRzu\pA5͖qv12wNlb 6ˌKm$TEC`IF3(+/VM,9^ӨaF%dNq4%匎3ws!{uFYo{;lQţtӄpa̟]眅FyS:=?)ݦeh(?c-!0oHhK3ݼnpĚ}b?lIHO%2&Ѷe22\2^ύ2Ѽ ھmwLx:6-O"ɓnޙ>BFzO}Onyr}ü}NOSC`a4$Fh' OF3pǂca}e\̣ms-F`[#BrDLP0_V 9! -3"E(qa^8'L؆5u{r*+:%AL1LI[! 2zO'ǡŶOFٱэde_gDT{Fۓkވ5/3(;9-f MRO0MPp#`3V#6N1!'R|zPZ˔A-oQGwgmbZ(2(-d!̻U x:?L arF̼CAD8c-_"'B8=5c--3uT>7i%d2D ˽q[ ckfh (tJBzg75:"9gc‡S# 1=jvP [7QH8?Laka~6 Ѽ̘Xj4Fdv'&Ou8:1OJFU@H8><61s[bZ+7Cjt]P4ose.uQ}iѳDp̃$$"p'adG=-%GQZQ!5jf-oVwr:ւ2b[y2pǍ:T hJALSS=]L?fU7bL87Dщ# 'F0m3IROXsOI$e`okA vP(Ą6nx%G#B8,,vO =%\6eb3"dS۳F s&&rN66P8nX'ZN;@X%tH$eD#2cfaN9)<Ӄ|רSIG W#FNuw$h(/?~)L2!!>$ff{ټ#(/zFe̘='Fm=JM}lcSZ W&!0LLQʼnl\KGIo׽2˸<5n?b,3-cFfNAˍʈpp(B1\puJ mKwZk1[%'۞ g,[QaCEBrs-mYQAC &Z#4.H#BD(p#X\(浍N  m[SEJaM;2ʼnuڋ7_݀pTx4oX#MFcA̴щ #E~ ۱6KI sC:+ÜͻH\SA A NE%\-#*&\!ܭ>je&;ۖ{#n7P0gӜq3C|]kJ GbT(S3C#D@ F -m۴! ,E@=l/dY[uĄe Ø0r̼7QdFIj䀧9tEg22aP"DPjjq=&0D{D B%BYFaFMFDPY,)=l)lYC1hCj&$1j!Pe2LVAR7搜KeӱÜ" !P (]Q|.qCC~|PKF["h*rXbK2?淍>?sZ8u{bj뎦<%̈5`p\zo nP? 9E23*mB"="(\jkᄅo1SIӲC LqWÒw$n V8,E& AOTb8dTp{X{ 2t{}H8Ix3a苎w2c2A6}B NZ)B? .4ѻHMmS ZA_OB0水a^Pr׹(EXZ9)Gm&CȘU s2vDK[4TbUP.eB pM@)M2h6~N%0x0v9a d-'uB|0tj͌L<3n$Dܬ8f6Hfe,AkGΨporGU~TĄw2cmDt 1Òia f4BwܐŔ¥LvH},$ dޠm-O̴B8 r[֘dBc[$zJH (a;/S, _|İT$. G\!V^y r5 (/lneZLQq7DN]!Jh2n\>W[]]AB0n`),-!,AzIS!4R'GHX?4|F s;S9t6,2zvv^Z h> l#d6 [I?Dkmep.X_fu#[-kn  ۴)\Q^} IDAT*3(r/,lU,3 dipX0uUB<j?q?+|D8)zF=w QB^ԩlubPJj XOqi%HqB B›|SsLHI0,& n6J8rEGZ"a*"aJ3A#љ5)7*pH|\. c Ca&*DnEh--/鰊C0 AK[q9¿ҙM VaD v:t=~?X1tlҮќFIޝ=3CL~ ʸ!`YYp-&`(D-}R=ġ.X Ru`ZM ,g: @2!(`G {F'f^u{2?7Yƥ0r ad$owDC(FB:nK (2Ρ7*ޭʄPTSz'9$]Q :9$HbVwV չv)=vޜCgh0u Yk43-pDd#ܮd xlfal`Z" Q)vm(",wTڔvs@C5I!1|%6Dv8W"5:#[ P޶'άQf #zfLY&D;MyYtoǦnLM: NCDQ׷(mP([PH22*ǰX^lte0`wmq zEG|dOd;yp$p|&Ͷej/RXjt"w !W2E)>s-L33l@LfbY.o9h)Dmmط A`6l(LL#W466\vLx3::ZX<FآmO, ]r =(ӏ l]Fivs8)r,Hv:5:P%M5qGntm",[h, [ALkVp1 }-,q8~i1.bE RZ8l:1*lYf<>1neeئ!t"B &eILs'e⦍.r2BzYnl1wAPƄ*,ÂDʖ¨ 2AK"CaREtwEm歑O1$„n>j!Pa\R3RHzęj^5y k@1)znwF=Swxdz!`#ՆQmj&f2t0_rZUÕ %AO*]Awj %ö-UJVBDQjӲhۯƟ?vr2'aC™  J Zs.=xFwȘjwC Ҧ k-aYI0%W 1}I;Wǿ8gYMknGW1F(_F5oun{'NbGFs-LI߇&{F_]-P" *CR(cBG VZ J)z^++تÐ*R3x-L]wu잂I@!'.['l?/e˰MO~_ru).5Ws<6>Y$&e}x>Bk=(nYB,-y!HlS%An(kU7n7ƴI  k+YޥА8l(OK! tP`-(N^f{.pBKp_o Ǵ;Xs>32fČ!0~ϚwE>* J8 n݃nQ֦yaAR]\v0@sk9LC0݁?A>,o|2%otl.*nN @|fe 1| =Q!s3Ԃ;<}cJQF MqB؂;Zʰvw) AaqiP(OX4 Tno(+ª#Z8$І]-aawZa}1?ym6_okJ.U\?+b8fZ KAy sDPJ!*R _#AAR_(r%G(bsPо6:]PX<\rutB )MIݷ\rآ1!+e5Ma49a?2g_Mʠҳ d-a?HۿK"uP j ޔJGYIpF'*,@P/)>> )<:Ee)J83d9,)r叮Kih Q ׬!H~:xXkA0*,[ra B.e[_9 (өhIW @}+I/ÈP(cٚpEgΚ %r _T)%O2:"J$ăQ"II㨄 GY*~l\/Lvn/ tFWQ?9 7U 6W%^EUbL ;/-SXVB!dK} ,+iL $ʚ3 {9ŇJK!I ~gt pFJgc[!\dNP,R D)|]:"-R1r9<"<"upPBAcJA?SB( f `O(!\cє?Z;H!!eՊI CgԼk`acg"s3&4ʐ~)O  R@9"A$祟pPeBhQ JyIXӦI Q /)|JHAI£ M(-T鷰o~cepAx3Kl`pܖZ"U\% K2>IAAvFQ Q.|] G ACEA?;&*ZĬYd? \QDp̉*?'aH8I/I-D)T:(LRk @EGN9 (2] -~- XP9psAqUV^!Ji¾]vŘ =-g4R!k)2yo@a8wQoJ1 )>+P #7*ĐP4"`/C!hT<4$z6E7xAbfP۳R 5@[J HG<ިZ7ڷo_BPxQ `,䰙aJqh;v-v從 Wu3 aYJ 1Z(JW=fpY@uP '*{{^u*GrD"& xggEp Ay+tEéR BP*` %L׮PQHk/͠a}uƆo4G $a]t-sʾw"` hDx?!rxF0+/kH O)w옵C2H=דZQ߀{O)=]T!@"1z89v #BBm^ 21|K\*䷂90L̬ -:-ޜӕ w({+"R(lljj;iamJactAd22׮vtLp4Y`҄ݕk]|ў=˄PZ˄ BR“.D5H @q@ 3;X |Po`ȠG_(,q Q2&D @Ïx"x `HWB÷VhwTFo{ UFxi␞bQa_ A ;H;h۹.jOR shaj}YgJkAhePިưWm:ڙ{ *+W`w}}uuu}+ݞ{w7)ݺuYnI_TH{j޽T?yZD܁*wH)OPr/i@KSÀZS__;e$7Gb@x]#!N pxbe'|x""`BzK{d ih*9T entA%#=}HKPVTX%iEjk֞O{UfAk\:wN/0إck~^'edsH;cwyJ5ZI]3 DsCK@T KcO?Mk@D xO!pSO4XVzAQ2޿ i;B4$Z;P{r]: %|? *!@{"f)6$Ġ0bD H)E}7p1İ>3%Ioo{R=<PN)3vnR"hJK!^LngE}7! 6EZpIR*+5 ocw92( B &ʀMcܨGA +/?@~BEaB#x7H߬C'B!lLŃ]XSFl!vOy9ƛ^B>3#cL-i_|hc?@Tpۓoh)˺I@#*(<Aw i ߁ڋJߒ :QB ss+*B~ ~bDL؜.€{%Qjr(^/Me<84aܘ&\#+:saL@p\9*4>I%UKjPTr (1//up[ _ NpPJTj]WU !L1b>hě9UC_ c& !FC!LAe])EItY8Z| B؏&F&"딂a!])\ |% ? |1feP]lP4g  U·3:FeHbL BP cr?sC}b5Bx-i!̝>lf f7C3bJK:.ˡg D$5KፖU+IpE5} hJB QqFN5 $9R7J Fi'!lM2Y aU `AHT_khhȨ#{{vj)%D!SW aPB@r(S//\h ?)P@`'ڪlTph0VESerTH|T&fr)! hu粞AHa?ZkWp lci#V(,)NtWшlC  \ٳVS%]>^sJo D [;pǏ)օw` MO ^S TǼ2\\$f$2A~ݡGi菲Ok`†NahC؟7Z}6vO2hŔp:& fH@jR!a)k2P,ÅJ[/z6K _yFW'RWaE3P lAm2( RF #˘)cY!w Lr΀B`@XuB JWwaM ^;šv$$^\🨄MF//㷬P,덢?ePw¬ :]P@vJ"-s2xzh˽Z 0-ˋ_{XjZVLmONVcZL DDީˆgĕF:P : kJ+po*BX(wOLDU¡67#-Сԟ-G!Q& aF" (L~ܐhglA w dB#^g ^&(|/B4_}B D-L|.|)o|)܌ Ks{* 7:w.(QB/*DO ikCizEx(-Qh6-aCح?DD]B1:2r %dL| wG-Jp}MD^XMiwȟϿ< "o+Q`Pչ#;PPx *=QxF"QiS2]gt[ wPdy#5K7Rwnw !'1[ N"pG߇}k2uDb:H0J7oЌ0+(fGsBHcŠt^iRπHa-! sA7@ح?C 7&r8W.d=nj%DU$t$?W ³bmٰ!ᯧ|)NA>>R1$x̗z܍ }uHmT6˨j[ sC0$&|>gՓ0?l+]\> aY =,?GjΩ.(["1ިPj "C %? ktD((l|nQS2$Jy*(R Q%` #vՎJ-5"#9zÇRɉ6Bn a ݺ% $,i[F e$w>$PY^wT!aC<}Yդ6!UA0o3 Z及PKfQިb=RB phBݮ#y J ),c!Pb;&DPujaB nHT.JؔTBK:>KAbBwnQ]%\5ʼJ33ȡ38D{&xm2!ݓB0]%DSݚ TN%ZJ3\ws@@&!$2X kv/_\H@({@)DWD%p-UwC.M(ot*'5C0 5f-H<!-&<~>g 6 ºfC)~w) TK#:-}Ipl5_#^:`mZ/7*, fP0hP $" sG $ >0erÏ'F&w7 Bs!#QxC!r(SQ²!OCa "AI}ΥB!,!pne(\SIhvL==l%TZŽ2{.nл%P%f[}b%ZM~JYO a*1D}/)!Z,6BŠB华$cn Pja6U&0 JG?BCjQoo ;vb̂N@XЩPp !3?i7h-i  JO@P@aZϯ}y!BHQsq#Œ]Ql#/a! Lʮ/5䇰#s(gBڥVB3wsQkpGmtt05ׁ~d:C /*ׄnw BBÑr@Aٳ, ]-̂0C250蕉W _#=W_Ѓ#B{Y!$ jz !E)%[u8((hku |Si&5GʵȕA\¼JHaeqΊ+|_O>1!T^ c\Мx~'a@GZ = 4&3#MI%t5bBEJBV Uv4?yj1̎0iSz: !NPX5锂Q͂.n} 7)w\˯\͏3J0DV­@‚ѪdLJ)D1C[厲JXPB*hUr*}( a*`P7| vq RY&4C I+A sCXVKaS­MT>\R 7*%5fI*) !`*&t),˂_/J -sC dnL@xMj聘;3ᵀTZ@xJ#(9 eBh 2Nٔ ڀ,%jpkxL? B 7I%ܤA\F!apvFpGOeP!Q =VdC1*0G@; ao'j,% 22$ 4~T {GUy0Jh0(cƳT*%-Z; 64CC k 0;ZBaYt+G!L /%00QWJ7jvQf&i BB. ̭ 7!<4M@X &!\J( ܄黀5Z%r3.h>ysL u0Y"1.Sq.)H i; hfLxF59cšP ]ۓO> !A-%~*J8S:(RR ēMQ{8 ɑo^KC`X{vv4EsCX_VJA8&e-lLde#kg%PXB5WČo\>W[_]_{Ƣ5T UFphJYAK$GgAئ;[LAx-/z!j\7RܓW!憰wKf vU2%LM[sDAI/JjQ ]\MWyqܨ|JBoqFO'AEB@x.vL-k`&^ 錫TffCxIs.e(!I%,1 9!zE>g4PB_ k`*9Z!R(QH{/f~V^7 B8Ġs29v֫+LB Ijk%X2=z)wLS ~ɑJH5Hr)P[%DwTQ8jsԈJ9᎞f0AVI=P燄A;^IvܤTS(İ@SMWVU2aGB!R|ý&`d|g1<כL*;6t'/NfjEqEV!,X:1ffmJs uζvɱix44\Ko -aϟu\U. atG{)qPwu&5*bgÞ=v]L( Q.7]x6.*?10J6@@8Ђw'gp9`H{GG7y {Q \-+Iw J;( R VBXXj%#cBaSp߁kS )YP84ϴAa^[!*a](aA.B[VjT׮z2НM1a;u/*j!DGg/%@ev'V (ƄAa>("V./"$}NZ.%B(PX?r5T"(01*a!܃QP=եp7KPߊ<&! VX!l;:$l~e &$uBPRJVBa%#Bx 1BG>T)QF '>)˩(NZX3k2YE.= Q̬IAb5qG*7S&e].)5̥jv)Q/S.&0a:d)̐' +Lp ~h!YX:~n(a'%|P6֗Bɴ|#w/fB(]ѺwAh5*%k HRC L YB08W`imE>!yTB|wE2HƄJEJՀ|K s=` tc~%f,WK 1SR ?j2`RxF2 (s2QY)7*ܐ0aLGBRQ8_tHa.Ő3-@j7K\Ra6uPh|i`(TRXC"_?JTn` `%̣~:ڠG﫥09_O[C0bKڣGuI%D0/(qեPP%<[߁/*\ʣyQ+!,Qz`UE$$3<%4C gݍ P%fTv]* zpE z(@Qqc#:zQB\@폲J) (O^*EXlph1aVZT1%,B{2{7R 6AIaŽ]9OQaL%?3JXd~oQJb((4::J~^VF> )<"R rG2F>];9IvTff«- af';rg= Sq@p%!3:XWwf+VMk {dLxԞ(a~t6_f<3dÊ!m3 'tyh5J>wT">jˆp#^I!@u͜-r'p7\{HLr%#RegЌpeʄ(dPxR{gMa>+.hVI1[G2a`MX!4}k!̾/ ̴5Z2rC(JQ`,h˕bCXK!jTSf~Z;B(j /: F:.GA4 y jER Pj_ԃ)PPNCI (🨺`7r@Im5'M@(PBa!E;!jZ!͜z9ks~Vޭ?^h\Xu!/!B RQ) sQ ͍ƫu2e3YgEᵫuugp-XHjD, mƍ6* SR;,VwS4֯5Y ٠CBTBa,fo_dAHTJQ_,;PE%ܨL^LEamF$ia`h(73$4fCAІZߑJs\j6iq#풡 'MBONo7ʲ(GafzS|h&Љ ȐPD]"jq.X#C"T 3i+bF<.HȎ ]3:؏@3* d`(D[K3tMOR<& IDAT4j-xb`QPh0L+J!@&3 -o{Q)GŽ9R :w"Z?7j!AB{Diյe0Qט"h&{K !UA}L0"cG!*C t02>i}a'\qDoA4J[Qù?Ccp o4aJx/àKo޹ڐgeuCw#]-6&J6TmëռZ)Q ÏADPrxYeC7 kdA\{uS~kmm}}}퀦 j pEj}? B^o@ϩ'~xy[vO,SJŸs**Q8tsgpPhb(CQxJ?ژTU/;s!~N!rF'9=@ԯ!"Q⍁\FP Q PX𓤶$? m1l]c2gB~q x^ @h^è Wŗkx8!\V'[!v]%(?_|/Y٭6' |0(sdP??ۅJáˆ5y&Oe=wƦJ=jͭPf׳hph?Y=s/tcP௳2D#i _ !Q !OeG:ng0oӢ1â>FdptF惺!vI)={Byz?qHaFQ˟D΢10iCn!/z.1@Ώ(<|]RkJ CpBPB=B"Nj*g8!rHQ?~#k]%pS(C_tF+VХX4MqAzhިQ~^z**y`fOVdr~BHcrBeb?O%@|)|APbSΝrΏh! aYZjcÌȜnPۦGa\FeA/:i?n( MpӮ( R’PU[0t|ۮj0 ~y^žABC)BEDLR 3 vCc$8]&\{rȧzBe)!pq'\;}">KˡJ e9ٚ$7]R⋂µe%F=_6VJB)k]K 7Q)\jW18tJ Ê90YO' t)H Qhv!SAZ`i," 'Nx.PDڹXR1\ Ǩ).)5 ,qrIP zٺJ/Sa}B(n  CcϏOKkxl8 B;D;@ N V‡F-y1GrV VI-qQ0*\o Zo4H`d 0Ri\]B>>EK q?!^EmbQ dN-@Z oBm.aTuFrQj$f̜ pPF}MRJheY\@8%JT*(OAmnZPA%P 䰯¾$MWmaXQOuᣮ`)'12^ˋ2[ ЕQA@͎' +Q Wb)Sf\ѧJnf1<{AB%ȰBM WcP#2!b7A!iĬoͩ/l(ă/hў5 ?0ԯK|#Vo’6`p&пC P P UzKTkў9ZrUX "܅踢JcΨ`f~ya6=r_8HHm#02V}u _g}I0\a\r%Pr' >]')o%vPPK(eP[/!p("_.&dYYIT!"*%SsZE">:KKAP"=@$k%>|SZ- pmZo\rss*+iֵu; J rQG`33 7q=NZ0hBB5s ~X mrQ[aBW[ A0L+|vI!pF*!|sAA\#D'*|Q"PxJ|4c#P9 r:0%Q{F,- QKa[ )I*zշGLVM3}'$8yҪ!Rx̙r!~r)KqW:ڦDoJ w! yOH!{ *+TjT;@>S>U~#B4TA͠4R <@ 襗O"j9㘲RԈ*I ar(s.<~E-A!-8bAOo1C»׍`dWk\i+eP\C3F3J_|WH DAᎏ(:(n%Cmz? ߓj/%,T&Y"D%"hT(f|Sŵ%P,a@c epUJ3z=^p1 qʧSpطk.:!/07{A3#j!]ΩK.kDN95?&T̆=#(=xh;("g@ &U+!\v OK_TbMK6@prHQ#Y03J0oEG:P2(t7JR(SכCC \kB!D1\B`o ^l7gЂE$63 &21  vSʡtL{vCA?dv&z ҺsC<8;^@P Ae#}%BcCk@.G qiCĵL), [IM A )0>DàQ٦7*׀nFM1. (R %a\zuk4GwedCH\E>l8tjb/_ ѾhQ\c2.M=0yJ`8V.JOI`ʰPn3z&"7*_aW(o5"ppOkfK9* Cq J AઃĶm (g/Nr-iGr2rlaRȦFlH H4_F{wm^ݩɯkCiAeYT 2ZK^PK\7*,(g}a-~!(_+n  DpXV AA b=[zm1(qaP`I$sBv#.AAM7!l{b[!s}!t_}Ys)K׸{ZyEW>yxX  o B ;mJP>>e&RpI.AE? R R 1pCq!%l󻛑5*W!ÃU@[CgL#'e(h=-UFM4ia˦3K D܅۱cT_2ȤD}uwa?BjO$Y;ڱDS i5oO!/oT (!i1*(krpi ۤ}LWB&'Tv[ڶH5]Aa]Ac_%;S 6K1!h-:#;2B~ks=Ü(A/8X Z,PulJ$…O crDbXggr={O^#ZݻgYei'vG ⫭TjZ9)_::?4AE %!.6rQDQPZ^ 2)(! Q@> #Ey|I!!(^c AxMHJX]13 Bphˊ>@x|( C[ NV7ަG7dAyP~D`:]}?"*fHoigO&`Hs!Lz xUޚq(:s(;nR+o(p}z {RW,%!m)|Bx -]P(e'gya .a 8c@p8SB)% %7s5: U+ A&3`h$g2 dEx÷yT̨xd H4O}ѕ~UgΡ~Yf'ˠ/h&R6SYt`KLxۢvu.%i Ɣܡ84 GD)D%@I!J0"7EcKVB >i pE@ʊ ׍w Ap&͟?FpB@qC@#C uM; QZ@!.L+UD 0 7.JД/!VyQ;{mA6B2\a%EZ\^A82,|P||Fk}Z Qax $@pdPR T$6tO@Nw2gUaȴp&G xp4@T䩨S !7bpy(i}$G i׽2.ζ#e;; Zs`NB)tb)CA9!Hs7]H8et+e%ġP%u%KHyxi豔P<ҍx Æ URXZXsQjxzC= n0 S7 DA\& Gg2P%Sъ2GGב >odg/+g5v ,Teb/U&8 ^38Ϭ0Lb *HkCop^a‘a:HT.B'^K+ A xyiHRz hG!/CB!^2 3L3G B`pp:HEf°\`٠2J AQ ѐBPPE iL~pz:kg#s.,_ {WW0 }e]<%kOw\5B޵)_d j/ӎTS(0GIC&۟P GaA|# !4B(P8]*a5<"BO&qߙCQ? s2Fp"8T j;: _Ki! 6G"]nPf̕_$j{2(!L"/F&%p)/ ˢ"P< ;BTG r)9*1uaTabpi.cçv&5CVK%\D 667ܧa|)d _-19G9B8Y$̧\!  0(pԑF CC$kd#*7*Q~6vV5!MwkN^ս~FsF$h( Fa!RL(IBMBPC8H +gh !3`)!"óN<{xwcԙ'.0n0QE`j!pXG u&Qy#I@э*/ `PQzD?:uuͨyuRawm*{0fPb2x^N ̂EO > I# ^ct1W=/K?L*%;Pn IDAT0. jo[ CsFH;j0f^3G@/RB`PQaJ̈J:~w `(!,ke6Xyѐ$&ͲeԙsA A:S<:@H@$2 C{}V"Jp{ S&wQAK;<#,^`0}e ~^NOO\T" nׅ)\Ɠ%@!;v8B̏wB\ZIӣ )eN)a5NDP:Cup" Qg@dJ/%FщE;7|od>xY1MӨb#xlj׀ 2 N_K =ΗD+oaxBg\in[Bx0 7,!I!eJ 9ktAGcRs"Qh)!818ѡzRu;ב!1pX1j6Y 2)vt̋*%@#Gj;*@xdݣ *_ê-3ڣGa /sAv_ƈ0 KJ`l#NpJ\$: Ckxv(wW$bt$Ё3vUE6%A٠ AخK!XLj K!O6Juup^ Iw̎VnԋCLyQ8w!:HJhp,QLfPHRH^P Q ]3jeF܍AWЩM^wG:A;%& ?PKq aBb9҇a3]BV%xPPnƋB^fUWntVAa gQha1ٹ-edVq$Zi[~#M<cƉb0CMM9yј^;!A-M) :e Bc#;("3~ZvKoww9:0џ)7*h 9JEP % x-e680$4BH:88WĴBWtVp  M4 U4hIU:BUPO%^{1WƦ1c ^L.#BI]?I{o2)Q"7ޅ@FßTB  i% 1"d r;@ H:$$3vJJ\!Jeη;dרiY:`2A5z;54dA v6v;k1h8fBϠٳwu@OoصkUi"H#ѫc `PɠNոRÒɋ~fWF\O!/Mܥ]nrTsmF!$D! R wUJF l/AKB) dA@-k$Tz* R~$hBs+$K - = F}t knniiijj*)/ym2Q 8HZF&,"KtP  acF^~IRH" !Qa J2ATBĽZI ɒRP(Q\Չ vUzWB8P? pmC'"45&DRFkST!%Fc(QAyv:2_ ~ P 0EQr=tp %FtBx5QcыR_m*':nܞ4kކ;*53YfmG̭qv\N6WӁ#]p8/3~MP af}ԑ^Ņn]R!r? $\̨%N#ع .?si# k Z R!F eBܨQ Ͽ[:H naJj<+ޖΥQk&0Կm$3*U}HJѣ$K"~\&䭣 V=pہ LNr"mϖEDqvzrRU8_-HFɈ ØQ0:xP9ę&%$>Ar2kHN˘P2H1x R m0*HseR7UzsW!$dB=H28wupв*a߳W&"vJa¸](0l'^;,_Hr3f !( \7~ tzL&*twg\]{/a@nEAXD8EeP8=*!\GBHZu &5)AF\)d%B$pB9fm4JaPu{F~T"aB4kB~.q1l#E U %{@Ha)LP T(ԕ+^UNdfK|!Am| VWE8XHiQ<+Ϥut2%ldJ($nx 25ʲ2P@-t0* 5sapC!tKPtHH^k0nh֢xALvW%c͓bf,uLxd.C.%ܨx3 9~mQf(dZF{dbbBDBPJ!$Ѻ@v4Yyosk212dz9Z{sFRyhI-螵[r'v.X&df2a¢p}sEQpxyRh,2 kFJR+U:@hd, ./ɵ/Jy)_X@(53.Oxi=ʌ.#ld1!pB~b3˼ ͐5UN+ ~TOxJ+UtC7DܨK5d:2ROژ#=( `Sɹ?MBg'GcN W %O`F}mږ#]"} Oa#psan AcFC$i$ 1)\2/ʄP{ѱ>=hԾ{.Q .$D)c$ (pyv ]c⹙4Ѣ|ּnXF "IKwt1|iB"{R;*&\( b(ۗl%`[I|bVtB:1Eǃӑ=`#h"SH:HfTX 2\ ouca7[+ @=_FOvQMk&S2)߳0vP y‡6|8I«읈axҨ&U*@)#s%8fY U]*PPI E)|RNx_c42% P$BF: \R!iL܋G!3ADmՓ' 9ڂq(gdĝN^?lZ Cۓ&7qa:KRv4fNH)SS3y2ѠrhOV{t7+.'[Kz˓Ӱ_[QsmOvU KzщF )(\ȅpzvkABpmm%Ñ䜵Z3v^D0wi6"îDH%R$\Ob\Ja--2YaГ) )ZݾDN8n%oI/j(2zD\ /š^$-T0)JH!p1\ _ʌ;LcئF2U7^wB Iz 0X #\BR8>C{ 2HCfv,&9Q1 pư`-AW^Z`|VQS8 1dQrz5gvvP𽠉7#8bj {]; 2 /ɤk2i܇F`{'RlyTAGA bv)jAo-"(14$3 P'Vsg a%ed@6Wy%l֢Btb&ɠ\ *Ρk 2D c>@TCewKi':2#݂ #,iÿ1!E+C&S-H3K̻"j)r!(0Mn.woDPT7PoKΠQ=A3t̨=guiANDhe,3 ' ;ǓK 'Ց I s p(AAPCI ‹VRhzB%b6 1=iAz;KʋKp9=7 !]dzK&d. j\IJ<#Eq@3i)zAvp1/)=_mk{eL߸lc):&N^ƾSRB,UaB9c5-A %2Dk!9Ru]<^(mhU>&rxeg H %%ړFZJ;3XR>랹DЬZfAM[U>l|:8ZZj' pلr zA Z7g!A6bX~)*I GQ*P0G8fqW'ݸp\ĐBP(!`8dApvzl6 ƒ1/B :aP _K>ٕaŊZ^p 2HB(ӢRm{~[:#x}-+|s@|Cc9p -EhpBUz qӻ"HA!18^SKv1̡g`i}5C%jTCMb=$1 3/@A^W`_W8Q 3KBId&Ojٶ}edCK-r6##8$虡0J8΀j76mN+AJfZ: NZBHf ׋P"[UWJ+pDx_a~_Ν\CbzՖJ-Dh6P_P*O?0U S(d 0av1 5X~%v0%Py $\\rڕ9˵.3|p&[jHzat8+Q lX 9,>㝼PUS B'*>qZ ' V=p  1810\}A/VRE$=O#d0Pp=BBwq?+k?Æ9w%82ɽ\] -1lc 1aF3:SA\9ܾ_Ke }ep"PJA%5Gq˗%]."(A)f $I#ӑAAc|-D3g(|ҿ81\}~XTrE!8zj* A~t'u5:Fq(4=(C}$7z^liܞ,Dp=twwC#WÐf0&{!MzyfOоezlmdEB#LP< A%j`Erdo&$<6T>utJ 8=;Zao[? ތ%X ~cL1ȇ㜧%!pHO@\tu}{#_x˿ѹ!b(bzyF;׫p($[BJV6M7!A 2)D1R8.lirDɯoQWF1,L _,i24iP(Wk%& D.hP `$?<tg3:1t/ׁ Zxofj8Gz5 !KZj\ܨIbX۠Z A}B!=%571 ʠ=l 7 C^.r b ݲ}^ @EA N fd4A~`1[3AM !*b9D'xp8Bp-`?|r5 ;}bDphGg}dBkU#e#uP8ѷY0h0$0Hr)j <)SÄlF`i{|`BY"' IDATB{LI}}͛C= adol/9Rqxk1GyeFA;DAFS*53 RgJgJX:IE{6s>:$CPnA!dIcbFrHU55ZzzdD6C pHnV0d(f! dDA0{$Sa_Y\':t'N4o,6!aB\!pP|M 2(#ŒbɡF @z3籙Ǟsp//5>CX@0KZhR+DC8f~d=FZ ^Fr$ D000xadÂ)L¢GJ_K}=~`$FGbab1b?Yx}A +xd U((< W}BQB")"n=!(h 1vtLba$d0h1&+28m@&ƒ |E w *~x8?bpd{pi*-[x`!*B4Q hl6C(Ml3G`yeȈ*$r)!'UP +xJsRspEhl 7eI!P%# CJ3H Y\C 9QcD1o·АyR`_@ )$ƚm'{Dv) >aX _ø&R7< b5ߏ`QR,Ygd^iG­c2AABˉ R,,XR|nqDE H T+}M9!dD=Jӝqha`XhZ/1$W!A`'%]\rOZ0a DSmuNn/!MG!00NSPɐ8~lO`J 44IHE*l!"Hy }`1C(+kWjBwCdONϩ^MfJu .?ţdPhdSihAH J R 1XxL ~ۓAO*(%c^,U=j^0$t?bbnZbka(, KaAZ,JH =1LN.UPl*˴  AK`XQwx83S&9p>UNYB1X>=1Fp)[!E|@z1 D&`8Ma+zJ؉^IQ a t\PL` HaaZH(=+q6i_on۶upE&tx>o!(P(1 Fyٙz֢P7 bzClr 5 Y/BX_Ԩ:XDd " 2w|?U҉xW&Na6) D0M /@ayggi[ Pܦ(*p52ra 'jaY,Q 0B9PɠFA` ObC°v4HE zpBDyǜx>L-W*-D9M> !O`~2)yxehLP D_æ(&yܶ :M*a\NtJrv>& +24l

    DE<0_ڬ@1|ttz'|"vWO%twYL4MjHJڕilAQ{`EnG3#Ih'^.935`Td]b Y?MsSSAbỦ ZԀ!uґΐ 0Yi>IAȔP(&CqR༩3T<<ޘl9a[6ՕWŹQ [`#\meW6 f\^6$F 9V޷ T= AjAװK ΎadiS  Lg壕j(`'{>zG6[͵ ɛ]sp0\'.GW!>T|Nv8c=&~SN=$̜Ҹ0o22{V~$oB, q=#J*RmJDK(AFSj%m۵ ^(k323Ec#:#S)B 6WjtJ$fDZR `C%K*>1KKo Upd m"K[[)K5BЭ{5׫@Oׯ^?@J_UO ,|`{ ®bX_-F=x!7PB/o4YYwO+l3.!^8;bןtW~g?Pwϼ ٮQou.܆nd VU;"GVuZYRQj.Hʈ(K-z(Oza[C:l *YsACa5L-hו{m!\ eٰ^-E* :$e; +t?у'~ku.n *VR2RX36/rڑ*`G$U"bj[.ph@O# itVpkWq> ZnkZ !{ rAUDj} ֆr N]NKw/w+<$'^9“6ͤ}k{z*-?r\W[M҃TI2׾hCU c+hZ"E(a6UzZW,zjx ~!bVbCJaVTu^mbB%}U- ^79O#a'Yk*]pV'+\݇i n:_L፻pu͟{2=̯J淯w>c.ZS*]p૾˦-h!C%FfogRC,aT%G&keUe)vyI\ShmK*n[`sՁ#OkOGmB53#"ʠR04Z9,jb5Q-,e1fXE$vWpB9ydcUo[0g&43<,lږ.Uoǹ! Dp"y0oJ k`z,Z,!gv !{^3$kхA 6.*LVxfGg&Wc%z!E=yiyޕ 4z~=d& ڢLJc*`J&edP0ߡuc! d`KÙ\Qki*#'IyTR-TVS6$ \˾׶jl.X:AV51~W֞(\:hAV 5Y>[gpH/"`҉x}Vx.<{O*/MԀz * w'yYTײzb-Qü3O.u̷qTWg >cʶbgty탕PK $̌qrd]bZU]cG)& iRWRف-aU>2wLtoapdpX@y3}*jXyȵPL=}ZFUT,>l]R~R*D+MIW,^8^ 8BZ@z|pDmws¿?ßzkmֶcJxz_0Ұ*v-ra\ȃ~ܱDd=tnxh"`CX M.vDU_ 'b:/ZYQ 9CZbOԎV-: <[CFP7V/;B9UseW?8beUĢԀ#܂V˿j8GVwA8;p# r nem!oUB] F/T!!;[ '*{E*ߪ[A=R,vNf+jôiƎ> `i9 <2 ڭDf+L 6N[-Q@~ZPhXjcVyǗ>B]5mVb⮶5"ގh\Y̬c=+%bc(20[i>l_k%w8C`N3mOc.Y"K2+uvMLj0>{;3=c>NԁbyE&xs'J`xwܒnBǽh4pP?2x-u 8`Wa{cHžځv,`wؔ\ϋu; ^֒+wA_]U&MT>Kvcʇ MLd ꞿg XcJFN9r|rQbEtIaYfֿ1 ]@Oy1Yi'ܸre6ܳf1mٻyMI R{3{c|yp.4R#A& tvX٭  51Vf)w۪4!8A"Ie8/fg6qGܢdTq #{^)_"Um8ӷ;@EزHzԞil36g& _3f t| 3RThUMω1%m&[an22/AS%ƏpgC#P.dU5lWcn/eދEH5{ˌc?^{8'UAǵ:¾PBt&fm.նC$Es܋k۞V@*m`dǫh U E Z[5ƏSv"TsZckO-{e!HV4@SC҂=Z&N҈`f&:u}$3EFk+:\aUNQ5pDŽ5 Z;2my[PUۍVq.Tsz>_+,1[PP_|epvNov6e ewaAk{ `Ynt޹qbć[xq$? ҢqӘݓ#oPu2OILvNWy I8][ÔS["=23aTmL&"$/=;0J;,K<:J"0vVUVH 73Q 8PO.mBh7=Rn?^ilIJ]Ch-fcRp F3fOCVɪC;4ov?Opf~9?q"(hvfh8Jeͻo_}Z}*hWxtuXI)j`~[5(:yٛq4y=/ٯbFu$/nw7*W[|j%ץoXv]+x ŭ8mE?w> /Ay!$j A"}1x&)ٻOzĪӶWˏcnaª,5UjX! &K0\?nRyS^ SۿN7Ⳝ0+FϞ|m;5O/X4fT'U.:3Դ^wr5nEa \BEML.8udtF/BA%SAW(ɠBĝ[Lm+3 ]M %dpbҪaȁj2TP]P7]UB2-zCgB=R+Taw9"b}o\zҞrAyxtiIFiNN>>ʆػy7\jaaI0eE0Ia@1}רy<Snvit3]fm8V{6u`tS==^@rJS$Y0̫e0{C/a %v[U;X.^(KyR#ǘ3*zpW?5uY\Z]@bi޽|!|.g8a^|x{9|SQ Gcn~XF^Dm=>TL G~c,"/!lpA1㍁LdݲMi-Fpy5(׸Ss;ICOlV>~P˗a! ]o/gAߺ&&=̼@Թw.rA_ג0PsS+1 S<szA''Dr!n ļrOH?uvOЧc`WS*gy7 *f"VRk =yr__>$e[5A~X"{?!.]M޼5<\ۇqSށcUַ6< 1" Up轱"AgnWmybyeto+VopuotǩΖR,։qUz;x\sE}f䈌"~@)Rў̞βA |cO/_bTezuB7_pXv תxGRa?,xFG Qn\yf? ƚyIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_400x200_fill_box_center_3.png000066400000000000000000001653031420147000300343430ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx u`%6 JI")ҒMY%9"˻D^/vVKr/N|lQ):RHŤ$S u`~uսuouC_wuuկ~woj=8 u? 8HT Q絃#>?…fo #Bϙp*9 `yK$`;?s~܅O2SVuƶ*V@~ૻՉOǃ &`?OSu~lLfR;(``AL_(I);H25m4$Mvq7n4G;p@kUI #qMo|P|&دk_0mǚ( 02 hR29b"i,(.Sj41LUgg pDx+B84AB8,O0><:Qq`4_ _i@v.y:_|1.@%{o |v-*aXh $J_fműWji<8LL܃pߩ߂I'WHiۦ3r۴GEeD%ŗ-sYt 's&Z Z`QeQ?H4#hDBDhcI܊d \J` "$jaAl@ 3<wEJJH,z1GJ9TI xIQ^Ȼ8Y:XéG9dFJPQ`eŘh[=_ =D[ Yhn.یh%<(H{-_I,~c i &x b#{<`/4o0Tjʵ+ (Ҝ(TQ2^/^AYϼNh cVd*yHxjPnvlPcitALUQGKZU!v%L lX;G{[>nG !j;G<`2+ UǕEjX[DԸC1u9E_٘hVP2ېTt9.^j) ,QCJ,2v0'he 񂃘sL> YKE"oѳZU*A>$Jkpi]JL.DZ\Ъ(9):X r2$8'F~ԎS30dp1_8` dcc`p.-^d/IkxPж,F?Tqa n($:ho{u^E)Om- #q rϢP^X AM{ v$\I2R+?J97ŤoLȕ"գ0Dzr gYDԊYԄa0 PsR/yҝUPHbJUyNb 0*K$ yKQLxzlGebč`?w10}@x"d&jQwLM#,oU % %gXBqAbP{Rz"ۇ< " :0 DsHdDǡ$P+=; .EPt8U1ԐߢZ FV$!Yăi ˁЏ"D2MYT"#@I/C9ϰ^EE!%-U߉T$FDXԖbRր%K(VyȪ pFIRDVOh*K^4Y1GG+SBs<WӢB.Iu[C8+e*_kX"R 2' k #Ҩ|N&_ F#<ߤo0y˃L(R$C*c"LqG|hK$6ZmKQ#,ظ3O~Xy3щ_ΰ("P\&j>%v]PXÄZ;mxoP:}jc]wl#P"=A€`e~13w?1=8E6 $GWBo[ФH7{`{륄}qY#T $*hũ[IH1jQF/h',yA[&'srT\,䓻2M*hFRߔ1x:7lHɃ 0@`"~D:BjӒȤ?eC*enOq^Fu L 3,҃k"Z8P L5;fC.e=jR/U1Lި46v\YP PawITyi,AH6b󏟄 X5`‡Eڝ(\#י-2X%`"q&8E %[07`LH ڂ4 BA]ciV%$yͪP~v!/W!J5 AL^)] &9ԩP1؀ ɃxZ{Fi}sX%W@DYP\j.TvviiUjPbٳпv Vh>[44󒡮BImLc/ET\,u EЖ>hMY[%åšG,%GSڳW 8[߈M/"`#JG/bSoːlV] N .vGʴ֜u[h"&C Y[ cSƙKhK 5b+ fdEK* +I߭r'`P$<@r}-**VQk >Y6H`1+v'{VV*"J+k)ʯXa[JЪ 4&r!~1 &Ў<Eİ2E ~lFL c#U0So,ǚ@DV`N2H g( ejJU'DPL6^Fhk]RZW|?XCw"{uA S~mda[gjҤA4GTr~`xAwQ^ʑ`Yd'Yd$}^ {$lJiFq \ 2(& "ai`nK!`\^gĊ| RkRXU43 U6T$BGhuUp%k<1HFXWP:\dK#K:Zmc86Q!T*sB%GB&p8P,t0oY#h'w26ZF%9[6YAd4 uDJub{qa6D( 5 x -S~8tA⇲v9Z i :0Mdq< 1A"/v]*Vmy)%&RHebmsd8iG~yy+DHp'(Ƌ\ PY IGϣUto[#, W,3&"|ʅDEW,{֍FzͩǏ{!=wŨ] q ~_iR<`-VXqp51Yb1i`Ə0w |;)@'Ueװ*4Z@E&S`eeȄ<HD.ƹE&͛:Ȏ{Vx,'3Lɴ`-+ߙ߶˟ʅZYT-ɗ8'QT)cџƦu\TCQ9DfBү>x~k 'fݲw]ivnệ(m4bU$IUVʠJ:uĢ7/Jv:CmAܜ _%@k.æ6]Y4hwd 4 2F@j-ޥ7L@. &[RU:f(yi:fx qc\(#ō K t5قE(teݏt2y/tц|F/_sG3=qӵUrr Ւ9A#wA+)<}V67d۲\Yo=yp-]nh{ tY09[5@%2|(yjJQ<҂euҗP/ W'I[$Ebh(Rq[N C\C%,3%{] rR(J(t:1K5&&l] i "7K@ar_tʪ_~+dcYBXz$qV"/VʾR\jػnTgڳG['_8CD/S f' [bh_S1һ;\gf['Of/iM?(Rޚz ](QCFu :Q3AI 1:Lؑb*VW AQ<ԀZBKDA 7[oIYAa φh늡C]{je|H$vIcRqfwlg `%ZV\$VaF{׿.6C[C[`?홃S/uHnPrqXX6AlTsX\γzV~lt;Ǿ필+?oU;ѿ4;"Xi3Q&0Ș{&g~&i㹩̑hjEw u(Ug8}s/뤳΋+.3ҡ[ Dj #1 Ѧh Y^+grNd|N[.$%#י6 crv9᝟%^1qڏ͏ݩڣݢ<+xI%PPV]cj\y|SF ?ܢvGgC)ySNm8>PbI5 QS|P$#m)98p3h2.*ER0$P"u`И༰Mde&󓜄I,&obnpW$.ޅ'V.(v؂MTzDgJ2na99 7sl֚.j]s[y=G.γԿ O#{fA+umԳ`9 a9R뗕%z8g)@,2A氫`@$Yx̾/5`D"L䯢P԰p]4!)Eer6 B9ɚ%wAbO@ƒ7 XF'=S^P$3d/3r0wUUm?4SG?bѢ_(gat #V۷']-(Y>:tk+Ax)EYˎ,je+ZLCdBͰ0]~ X\2(?$Lr@7a ˟ʅyF ba%<,Pܡ .l )_Ű 9昝ʴsV=EH Me)g8uF-Ԗ Pܗӎ-Lx 54D⅑b&F#֏ LBQETâa˪N:š8r[B BX Y;D B&'kZwvrny7.~|(`lN,5J;" TAJn1eR v1cU(W0y(hcWe nԼ-@i,`]ayT˴t\?Unpu@v DVlN 0'>8YKb;YϠ(AQdW-gL&"fn14$iA8ؤ"cyOp \g1 RSRxH{ 6x_<žtHlfq,Tʧ%"Hh @`bX Tpv`[%=HY΢F?.ۃYhYe󺱢gvd[UǬ y:gvN>:y_k%ZT$ taMRw@WKtXdc2Aˮ]hP:&&Gay^}SwDMgON=uE|bc+o4yjnnX{k` dY.&FOLs<49;67+Mdkpϱ&&sݍHP"c7 jeXyefY۵gOO9FD?xD ~[ٴ}uEJ#z=CW7n߹ءv=~ϋϞ_*œII*(~ʹ%IIZjƒgxm˺ Z<l)`uB}k«7}ۚ.\Z ̆z.\1xx߫6'|vѧgUMyj%LB5l_5{G<0u %zw3/?_!ktZV^xXK iCjϊ7,C=#;j766^˃ԋ2Qk41pE_ůj'%2nghW1q=}+{NbSW^۷˥Wìty\P e[kGw\9>y4w{`$ɜ^+];n/ڱCy>3cncQŠ^sx;f}5 ׭JU]._b],BDe{/\Wו[Ɲ 2KxVɪ6+d$23(JDK+O>s%RSgNTM*qQ_k ]7SKA+SӑWMRf}[؆5'L-P<D/!8 Ư,mnUX:.]Wg$Aĕ*9g*> "P]ٮ#jwGvG+]{>w}w$|cqXdד(VPKF(HC%3_ڱUJf㿿u 0cU;wR2v$19h/S3'+@HYS >(1f"HAKW6kآo+o~+ՒŴB!P<;)HZmhⒺ ZqĖh`pE*9Z! (5j`?{?޾z*Rmw̷ݗ}ʉ;s?vXd줓|m(h h5 yt»o};/z)-۹yj|Ĺkv#03֚ P9@{ j](_VeD>?_4 '>%x`).AjP3(zh8z?{\R wz03v.,d5 LEJALHKnyoZ 3FZ9= ucXr6*gE2+e}_gْ[a2Mχ ̭*#lT/.d9"МU7N\0!q/VR}x /2X]w\3uw?Ȭ a }`c(ND KMjkvpYdi5tt⥽ dܨN#&ZsƜ %DKlLϮtӴµa`OJK*~` ̱ {]fY#nK +ϚP}ayι\ŰhD}+/':T8ׄ kX]fL_5[Y$qgR_!%,gĽѪ@@ )~W)e_xHU-rRIiNTv-洀E5f6+OnM֤6FOvqL'x7fūT Ж9=j2S2}5ₛsUH>['a|a &cU"8 N(uzC6_x[vv2v Cl'R«;˶wv.jaĪ ܓYלB"qZW[#! j׬yiڭо a+T0oGr **, L>FNAijh}_麚$epfz/y(gڞe:+smUgpzV8/H)ba} 2"TNjU~} δ5#Fʑ (H砗|v͵C43?ZiV7n]c%Oi# qoz PVt5_}akj`f5303[+{h_<7ʱ9ұ/FGXm47UVJqW?'eI&AXa8V* &:^6^"N~-?UsO|r_Rk߸VLQ`ܻ ʀوQ\{\}v&djkŋO(_G6h I1:2債ա$Oُ?1l;݊\?2r 9޻9}Ɖ.t4VUxmqӈ&@Q<=Z4e>w{v- ^W]Gs!}5<[NEJm(ץ|ʥJ3,INj,)Os|j☜ c>֞:tKzmC8: 5YN(N(37>ʡ*Dsc{`ٲu˗WR:5>O܌O׺qa9ڑWhmYV!gf?B}_+/qx$&rހdV㰩`R#*09yZ0 :Ϣ5$S S;/7X]}ǎUpbtaAOy4< T* vg娔A✪Bt2.Ȳ 񱙹hFЩcU`4l@O&(ԊJVbCdZ'Y;+5Î,aSȰ|77Uatclc`  ~nqy,)>ƅʮcH spbLMON 9"OzN+.tf.b8C'NTp@n3HKb`Hmb."Z5XǷDUEn߮kP ƪ[R]qy2v&1lȵ\'[ħjחJ&ݕzµTL8gEgsm#5q@F3TʁJq\8k| H6e~aN3J!͹V56u @x~Sk6IGAwf{0Nw D)vS&{65P_;lɜxdBff< _B@I{kNYrY9`=C;S:=x$V勄&aSО|+q\ w#'&u?w=Uȫ~*zP>djB6bs@V#j9bX.%7`Y_OEBVV@Zh[vwGa3?"VP!O3BhXڞ@6&c58s=kzՄ>>P\:/U9RNZ5)$_⎎!+]ܺ dc[ m5MzG*3唬i# ' ![|WYJv{hHKКF ^?gN<PY1wyKqkuqS<k5{A=W5}M +~TQP+K(enu} ©#)V`rϼ]%ta}5*9=Yw_&& [Bdu檕yG^]Ld`}uɱkw[.9Cܝ6T{N *ԫ@2Z7 _7\就ߺ~`Q)` ~t I99]r#/ܰf̷MCOZ.=<[L ?R8e^G}КKV_30?iKxY+3;Vl`G͕ v~꘹`5f/%t)7SO58IY~ypY=i SI ܼ*4^w\Z8Z3reGwxj=:1zLȲ?xr~뿻yoToa՝XjcӪ }MŜ MԫJ3eOUeRmb]*kvG~C:[w.vz6Twg;2;e$ֈ%oK~ X~o_WV~v2W1l"{vi|`TBI]vݻfdmCWxr!W펎ݻn]޿|يwx]rU5o\56ozMyhifo~^]azaҪa&Bm|y]7]?}|"1<ݐ:'?u.߼}\kd?uö*/gو/:T=&JC0ש[UƟݿ5ìaO͞۞&Ƭl t`UUl8u[+7Nx?6}Tx%ov͌>jEqAAP>$(ZȋP@(L{aMF]r?˵m "JvNL>6bw뷾-?Ks :))s{†_ܸщنUnޞ'9|X\-Gc6wu|}'Z10$rEA],xۺVO?5ûG'έzǵW/QS+AK7)T*d^Deeais{}NWl_Q#:qʎAROS\s{+O2rѭ#Zs'O i@ms42`~xDT\557=:;uo"ߚ(8ns3͵}hwO Z=y}ն ?|kto>c!kX5%x3lY+|" pqk;^PX-c985so"A$<{O@*k&e2PuԑF^M/OEL)0})JZ&~yv~,>1euJߏ҃/cBMؒSf'Կ^&=5uAM#y |{~湄=Mzɹܴqbf-a9O40"N`Gy-KME$Z~LrAMd_Oӝ"&@}OFif?ǘo+b9*| zyO*@U; b6 sR (CaysGSVA23<~۱z+gi(u{zCEzP!(khFk)]nxѻ:x_rEaWa1UR*jmmT4V&齇ܩ3>kyϮ?<3xc~xa!,oQǗ 6|1+Thȃ]/2wFΧ&OU'l9ˇbE(f+|kfzkrhl;x`MțS5B|WM~QÕuD@okf[:]Mo0.e]*rPhWԣk|] Ry ) f.mBk}BsN9}Pl?,[Ru!,s3 <#{'?&pf(<5R-ҤES@ŗ}Ʃ@E8s:߽ c z{ߡoՉzS~c!X?Z5 ],a[HiɔšZrlק^\U$iMB%yab/&vͱ+˕eU}RUT_SL굃pt$q!.h_*@5z2} #OY)e-BQ u٦?_w~̇7ON M7(<>Z+ufŧh"BęP]TX^q@w󱗎Yx{tSq~ ?a=RV6n6 *jC.jyݚ^+SfǞs#eef4SԟvrNOjMĞ Qeq֩kvby]5N?D OCwfU 3|?P-U)Uvz{ϟ~=~~~*$9$۝ŌE? Hj|~t"|~';~j›}yJk͝:ԑ&~uw}*m%/L_\yO=b!O0箱g?yj%z5F)0$-LE^&pi jfogCN3N/98rߵ&?Чy]x}f޷l[[v_|>x6`TRPab"|}E /d$d6>w?q?q{ۺF/O=GcѠ(tO0:x+y"HYGa\@g)朓;$v۷+/ U hԉS:=ߜ>v/ЬʘƯU9j6uU[Z'^8'&v5K_%^!J\ko\vs♏玀[C믄\1=C IuMFT>8/Upa[j`M/M"|ľ]}?jtp1pu=~bcu}a|el-^lheќ?v}NNO{G79= +s>O~-ܱ_uE[,ɩw}ܷgLzsy&7>J'yz_|f#v_½_~,$hpGz΋.ɋGճV ~3-VJSrG 6dۇ~D WhNL-q_C@@NeqY`o6Z>|`h8Gֱ'ƞ9vr(![ ܺeí{ow9| v<o% C1A6ܴbh8>jaV^蘟:`aXt6ZR* `l7e2rủCEz ,eLˋ5  f2lA۞CWwKG%qsy%5:SR<6!3)]"l #cT!{(F^ _xr./`6}bfO 8۠"l`bڗC{ =hb'fVb= B={žA3)] 2YJh,Gg>^|\^6גv p)2,ED ׳0.~c83( #!>ˢ^&@ c]b9?}SM,CιHݭз9 #h_HxIRctz,y1+b(f`VJJ `RT/CXU!.D>eɸ8(4-)t΀|C`гyFa9"B$N))4XQ'z㻯Ǟo~3SQlLLq+G*s.-0 }L("Ho!_m DayOKe+^d)$({5KEd'%Tg3vE3'B~^i&[”RR{$~T<@Hqc7c'2Ce 2k $ 1m X <5@+̣C z]_d! wDž2dPA!( YX2glN s5(YP\$7^#=-7^>t)27o ,}I2bR'a=y])4i~NBp?cY5Lӫ`# AF ؅GGtv})&Se֍HWQ6V6sr֭TAVQT@dRJ3hwa,%H&d>;Rh6c/KrT4V}D#ܣ*0On e>qȘК4HW<0lciVX5#d4l{CWG]JFo]!VyswOk6{7ݲmWҧ}| 'z`r0 ҩȭ[yZT7 .&52q*x%2FUnO޽N2cKMa)rbfEk &mfBf, cO9:R^6lmJ ?V$~Wܢ*3vKϝpiI1WxтA Zl*`GP"]ѸiQav 2\ɏsaE&AHd,>L2x)Atbo4?Te_q}E 7!B a|̼|W b{ ɠX;O־ZW37 "73 fMB*TvM`V*2%^³ ,(!U%tB,*Tf<&ưV(Mf Wh=v,"DuFG4\Ƨ R:IBAwLSXIa0ID 6֕.(~:3+>F26Bd9;a zG:S0C[ggo֞fݠ:+0, n ͐cQ!1q\;; U$GIez ALAgQBe#]4vLYjh!Lbm"B\-FC-dvѡjuK3l-JNÒ3} A3=NAPR)p+,&m֙F8CYpcz;e5V$hIT=H_(=b)21>ˏdíyS % .֛}Gڟ^B9:6ر'CِL=Ѐ)l"XNC!DQ%8 TVsh C ,VZ,uU9l-jDQ.zhI`ztbFQ +V?fEB)i]DKG荰E%2ehef/#PښFWm,)CCdE4e?S0yx UNOJXp}DD`,6'B%)=_e;\O}+.iОOcG Sk) qfBm7! e,T!Y#ݹ+aBhBQ nbjE0pD7FI'R^Tj-+_ hdOOieͳ.HU !ZC7?Y TB iSA 'PYA5.\WHs4ymKV Ȋs,dY,ʐNrEVPo- SK۔PKvئ/_~kCQD٭;R }Q8|L@2n&sE#0QX3H'6bòt.`/,$+i%[NMQy&b !q{weȂR-`| k\+cwJǕU"tTRXm‡9bJdz4KsdB?GKi0Jd)ĸZ!OCU mΑAv^#_lVlH1gv?;?~)_sv^t>i_5BF̠UL(9^J$.DTǃLǦSr mC*r88ϵ(՜ D#@ UxA) Z>5pz` ,DgߢE- ZVrS+.|-X8BdҰe<8vn!&V>ҝ21WnWYE,q)Gax(ï s[ T镧Z-/+/ knXeWksnv~G=OM$ s+F{'P:ZU:@&o!S.CeeL >ubC^ BªyG~Ǚ\Kaim+&/ :dIh`j,~g n }r!p5+*mBXʮb b.iR@s 3-5}y а*P8cb)saf1 be"HykHZTC^/r>rе)*f[!4F^wwkOώOSgynƆB/"kS ζ)\P\̦) l=m'!/RQ| R fTƭz"NQJGcGA]RzvbVҢҤ c8o`h Xuq: AQPW<1QY̷v2ڹ,{ƝGG :QB$YPRA aC*"pD?m Y)P0,sA61$~!/مٙ?gѢF"בi1/^:#1i1.1O!AlǠPo{ =[#ӼbMA0azz䵆tyDb_aqMb<-mz$IUB,22|-*hCIφJ6[OoAK j+ 0H_h&\/3bbm;c!J (eq2A%aEyص4vIM\(qC^9w$Ɂ hp32h1a(>:յ"^\VS47ÎYWR>Ԧzr2GukXdWFp=Aqg'ϕ_,Tou ̟Hl=ЮP"8ޣ l*'6FP֯q+2u9(WlOrBBmKFń0W p+1r_ڴ2wET6=1L(&v aDKfX%>m/lst扁zM]<\3X3״A 7lOO{~x!l&mߗ%PD.wg]B&OAB2} 9NOkQElýSJ- tvC &qj k})$E)cfM * J+P[f;:@3N ]Lz.fe*%q!Q. 4G$d:FG0O [cy+ڡ,h 0jG2oBQTϱ"iJ4 g}HEjx.M* 0IMqfcoxtA"öClhy^/|o-{fdC i%>ĻG<٦i 6tM}Pג %O+rK"THr'=d>yZQI/5"`1Iq eLDNK`V8GEɃ1 5n$t݊ɐ@U+jǣAx6D1^D%5dMѶ rߔ`69pH@v AK:. &A:zD̘5lܶxTA0$U%`V+՘k&^u|&>E+KQUަ?ٞ=O czCs/52goSa &تDtƇBkKCИTgV-bD٥ľG9cvs>;@v?<0F]\REԡ[?X0Aa8Hh lz#*Fip~m!2Q I$#ѝJpz/9#orQ?V)!AX1>xWh_kt3Owh~O5$J<KW #i݄dz6{$[2_)!h^PnGϝ2CK8YmHٞ{0#P?jO'Qc&ͯa FT^`ѐ嬌9ъ1^l9rXymAQ@ wQ{׾uEk'"0t~f`o~Ddކ\G*~Ne6T0,*rs â0(P-,NocC7]бxI,ز&twr 6~,{*-mKpXX yVŹAY*b%oejʇ6!1S<օi?,?i`0=4:\ `Ad)fkRg(lܽ%Gy.Zgg< BB|׏`l0\ lL $ "JI( t̜vU9sF[,fݻCuu_IDh.xFv~hU +!NJ#_  IU)%)*e 7Q4%DPpϓ\Mpu ׂC3$ߢɩ%WNe6z.Jl XGZe<1~>ۂF^Pmm-o٨h4~8O PGoR. F",ɏQdN(-ƅ ⷼ0%&pGd ղb"'&P0 SS'"ڞ, -9s?aϻ+f~hs0PVo ࡰ&8H8!_vyb,X8ƑX 9 -(KqvᐆB gAb;$֗()tKnTgVJ~%f_J$>2!HMi3AVpJʷd>kf_Xy!'usWNK}/{i}hyW)<<va*=tGH+9 a2Uit|AEY|Dl &b +!(TB.v9Hɠ@Gy">+qHl!!_LSXޚa4YA&ݳW鼶iK;> ;G# /*jnRW-ވ A&c+G6% _}+Nbs^a(( Gl%D))rZ{kɊӉ80Y*SQ=H?Ud1zSѭ7Cg .E]e?LETB(sn$ȇ#PC% b;Ba;BߊHy O!X[&R([>Đ'PR;X&gVBJy3PnK۰Xm=5U{>ߺEn B M5U}*-h!dU4|vhu LPl `/Yx qsf5]pHCNRw;4P b㽟%Y$} ?H%a(Ъ:ۢE*&^jEm }P} ‡xFi!҇A0ab7+$ki!kx@ku@ A+\@&d +yW@'ˉ*T!B;+^ uڞib썕0aP]͛҈S8 O1׾y }N@%H^ Hr7c[B!~GR̗t MߝrbӞ Sf A 0_ww,9}8,Dh^,ĥTIDu@+I¾P p$C2Ntz]apECٌY+.E %2B$Cf="e`=!?P+CLE Jim; 0X0 ly$SM^"*bn.m2V)ٔbظ`QW'rfsw?Y3,{+MQ!f_gaӟrֿ5L-u 5~OCm, P+Urp4J\5:+qs7~;F<@THqzd)![ǎ pW`q4T]8l[a"K)F-v'J($05@[$  aA2 g3ؒ ]I0 e[Kl`1S! 8:tJf' jD2J`(@9d%B1pb  ;.Ejю9BFaA/_#$zB,=(ŊQ~.%ZGf+ݣ& ƠsrK{jI*Vc]jz8 EY am~E=ҔVT>Rsi9sRdqXa1Zp6U2E+_acf+}p)㶉[v4 DD+n"% 1 gpVEl^Aٽ{ #b<?$d ?ٚ{00<ɤ@wo&v*Zg5e)0BT8+T"$|JB$?"&V/9AJzD`1)&qR+ԬY3*CV̴-{.=oFI4Ǡ2 pŬ&:=+n{WK #q(Ip%~E5hǿH9+Ζb?fR~)'!*e#s#%P}M*1]`c|h?^(Z4LҲc= {Q)0%Z&m8x"bEgV%29;pqۨsPkKZA tGhkQ|FZomp9`l@z SeT o$PD ~tٚ_d*DG60'$[dXˈ!DAÛM%p؛v|sOyzXfb=ZyY3)3 3gVda:KԊ(RfW?27nL`[G;qd C(Pй\:5[=}`Ie=V8ŋ)bOƴ* .QnC2C.V[%}ډ1w lӱG'~Ic  &LƋ./x5ϻ妔\ IioDlQppƻ]đ L'|*kk3cLacu=H(F^Gh%KE>dD+儒Kb&nD ÿRē*^pV8 qL8L!,XdJAe f a]9x񇶔zE{vQs >uaAd|A`eBks̪[ŅNpc<'T-JrpVj5l)x2KNq ^2;XvK^ F/#ϤUUmHa(_/X.SZ;LRb% AHD9#"5) bj :=BLf˸^M\")Zע%:-xX`3, {BgkC!d)p*   !p(,cΎ%lCzP(M _. Y#ʁzHg\kw̆^dv;w,*A88)M cjD*󯻆ZƺcH+.RtL) ]<' 7tCoVž\R !P}DbYY|馇/{zĪ>U֜昄{+©0fƘ"7MֈXuLxaޥwb%"B]I 8X3W?35 W|le1VR%KDƯ+B*<G°Q8uNw V@]1_0IZ#Q?ۍ  L t@WFʃzuSC p x q/Xm̷p4! MOX+/lTϹ?âŊߣt4].f{`K:`u@@ꀁf2!_pZXWC Q_C13#wKqyx܍#8n*FJX`/Cw )i=F~GyWmuUWI$n\slҹCJ:4dNO8~Dah S;&,(5fOdqFI2#0a@wWXvʫnXkWyde%RʬNS8)2Vn8zXЩ;X]0rV{7gr_ZyS8ظ+u8+g!*Rwg_B1pg_` #NJjcG]TaURb4=Z6-VNך+6( q]6VWR3J) d*NXJ6bWNݱUVv!&ib`h1 :ub+4 4i3kw\_+X]l%m"f߈axEVBDH$\UEҪ"Ais.7\C F[ M`ɸPRHOhQxk3ZfwzE=x8km;ziĖ͍/Vʾ,|peb Eʩ*E9Ȭu@VR`+'|N ri.ң-|ry.Ye=_J Ī.m?dz MhC/B)Z#L;PQT.aIO+I%S#xE_77E20kHrWݐT>(^q' pCE\yEc0)؝5.3|agDP@&M@CǪh HO g 0КA%]%{Q]Yc$ zDV,p(0͗VRZt5\TɕpN |BqF9ŘpƒQt/NZ4Ui%:зtӦGoogynXfG5נeBm [M 2ygHeJ[ޡDhX[2kzt^ŌD'TSĖ5gՈG腫o&e\5}_Gc\vg֮Pb8C'IIPђH\!B."+gT5-1pGL 5M\TkclQUz%Z8<@GL<^*Ψt|R8% B[aoyk LחS[ &2x-WpW[mWZmJ"ruhM4." S<9! RèeaI64F`9&٦X .71zZeN%QOt2L7mz'֐٨vE-Z W/ΈbD^BKX&67kn;eϿsaOiFxj~IDAT,[*:@/K`I<|C!_) KHiߥC]po}ʕYy:JpO"7ՃPW$rJtjYQ\|"F >ktπajjFB,Op [>]ϵxnpar豢疝܅3.u"Q%VhĈ{'m(DU퀁kP2eHTʓ1T[HpE1!瞆\8zma ܠ* `&+3g]9$̳ o.'PcX tÄu:[!]|pWCdX-! hFf^Gk}@]ppI{ w’Uf!-wubFUTsKcɿzT')HVXG`R` NNPmj8,'eേ+xp귮<7b%^R̟.4M`'_N5R+ή)&ɂQjirS.xWTQ0HJC aq첮eALǮm2Z2 రi,IKC)NBX4 hAp+e-l9\QޱDd BE1B;+˯qq\7QU'=use-2km4L&/]eU|x^ eVOjeA+Ko53I'ʸICՎX lUh -6F j[FqyWx :+r{^M  ̯c찮Z)z'Bϋt^ۻxէ)cAqQo<5%|d`tz7ʸQ"v4h$ m`skA7Mm,aW. xq<2|Wi.zA,+ JUIqX+#:F]f`q-1 XԂp;2w*l8wA?L+R]ٿdG6mW?q-osOw {0fA|OG]hyK4AKwAz.RZ}f@=z hWw ֣ nhizn{򨚜4 fOhd[17)=+}`vCf "\ѱW٤lla,//9ztnnX,^|хFDOK'9!`$%ՅF+>}7='pUBỏO~"vHvYU bgj&LE{vpSch[FǞȽ.¸㿊,5Ny;MKv/H/Jݣ,>R%I(x i04-4m]J~l.@rx lTFKg_\F@P[cϮ0^pi dkjP6"gPz]gYj7rR~WN, 5m$ڂHo|@<`ACEm dTF޲kcT6YVw4VqWj2Ǖ{6㊄^Ҏ!oz 9Dge3̱v.-X/\~xxgAgc6 [{g?+Z<2aC(J_+9] ,<jƝws yk_^REpΫoS>[8I[%~{_lڛ]OWA#"mP4?=Pk8|S׼>2rƞQwE98u[~:0q3u{`h\g lPS=`F 8JDM Zu_f?%,Z/b"6𓆬}0)FuB{b+KrSIjtd Dt ,š 6Zex|u?5aOĘ@##X]Mk[ďnV]5٣4X8#0ozoM^d˴4ի~;Go{>z6EʫmguA*0]e;pAo*]5A"hk2Qe{X~yu{`Wҙ}H87 @k/]i[' pl4Yᚡw npCI2N5TF-=S?hgϾ꺎_7Vӟ'qPJR<cEsrw m#Q4ԁ")tih_svJN.NYzϾ`x%_:#jb4dѦ+&X =&gbIskRVHRt-D۞Yϱ^܌f;_r;5[eJ)Ξʙ; $35Y->Oc+SX1{ K4tJF{vڅڴiu{ի~ud0K|vgw]˜yꁌ /XO+;# 0\LۇE`:[NJCɻC8BaU(ֱup4R*F,o!#:cثWJ">|FO{xTk\D\+ KG<_.SP S""6- Hp^PBÆN D Qd=, |ݟ ͟}T5FKٺ","Jbݣ YשwAe5k`M&#S^~\ ̢^AsX(Wy~1^ a)*rexG>j)cǎBSBUN?ܼ3.>d3YwI2))븤YsQwzz (Kl-.{NstY6Z7 ^?)[EOWP$Le, aFw$_;|˿?q}8oCX"X)dVQXH;rS6ku_ʾ/FeYq眏;ik'ǻj0g=^]gO_zs(so S +[9Bo}v[ afG7CZoq8ne0jw01_91gij}5A3ܞD-Ohu9VV/F0o'Nlݺ5Qi{|9ݵآUE#cdD,?gy pj?QKmv6نh8XX "_o>R. `=cotQKKBf&B,$(V` Ki͒FtR])tsn6BrmA@N$"2jb٨8(r@"C!kgQ<nBd@O]H "L)6!s+2psNܿz{ t]WtIe՛/fp K&>~KRj- g 2$tH "jb_+w*6ZR>\i[~>&XK&更}k֑V~B^\b DFH   9'li? cDOjwJ) G)dƕo;B3P|L$h1 &* WD;~63VaNԼSUĢwxO7rVz' )O-5۫%p#ѾdNp 㘷+F%kA'hben! )ֲ<:F\\xIHąS.U=3.a~,w534s˳&_7yIJ2ߜl, &/8;_=Moەe-8xʥ&mgw *xAsakZlyT83# gX sӍmALg3uޞIa&;ìd5_"1䉾|<ȊeݻgjjZ=0 y-ؾudZ+ bSu)|X']t4Z{gej%_oxu1C##%ٛAT>Ul&3*"SO0Un./1CCzqi'XbĶ0ADoL}oD bou9汷AC_O|t+t2M/ɩoynFo~/, ;UFC{OCg[o'yfiWpѿyyDᡡ??3R;w~r=H7_:xa|?wW׼5z?AU{~w_Z(+-{' qn)]_pK_I8H4ΪoDpʇv1A]sjoI+~F)^NE5MuU2sEeh'ei"L}}bKDzP$gDI0}Ȯ?swa@qS8㭕7>/w.OeEU|T.9X/G͉O5;{rAݝof/WxIRtMrq%37] :qNiS/>tۛ+.|||lxhh~ЭE ʘaԮu'cv*#~ⓟ AP^.x0Ÿ4Y-UAO,ȌW(%X-? u򄒹k)90t(dN$g4 6P*1ZwS>B,E;Jd,6zI8^U!~w"b4˹#A8MOKtJ>'gxs*QG~u-U$4j+mꏰ{#rgERj`͹?1(ţGhf)0zyXb]1?S$<ēO>\,׽uO7af?˿7 nޡ SaGL0x(pjiO (t$U(-rDGLfyIE~uRUY3J&uHz^$&SJy A%!(*٩gfC뼚r]+fU&HɈWM E!䷬숶B Xh(7K=Wcұ qv @ؒy~Ͻ[!Lr:׏EiIpyclhq( X){/YHHc}c@1՜Ou{D@Td\uDÞ^ejt mP?KեC{׮r!(w8f8y/؍6[ cހzJO)1H1+9cz'8E 5Gp<}k9Wl2JByH#K$r2 szC؍7N腲i!fss8y @0x:1 e1 .NYJ 01Sqx'(R+'Gk(Z×rYe@R8o}c} s7Ƅ+ZrXNFQE2?4 8I| ;34žg~^KbX r.Y&@0]嵰ͣ;+愩-]9W'*3ZM|\NVNkv'JhzAo]}{ÏUO@<ǎePZ9@7ҙd 5, ABNҨ^~-O)8RcLو>Ou2j})+bHjvEvXr۩C&BWoZNvUG8eYS8n X 0!~ > gX 8!Sx3+j xo?x[6+[~Oe~j8kzi~UuO~cضU1:=VXk'jg( 2(V<  -|sS ]q" գ)'_YeDrk|UİX&vrY"L IXy=\Ɖ@^xz%Wɖ}/љW^vH-@r6&1 v80-?k/{Gƈjwn l{béÐ_a̋ЉWꊪъ[G{y_X>v]K?\28?ygo4o~LH2l?|+v闎iz۶m۵sg[iy#M*N';wt>d(3wld˙XZ)CXrS`Tcɠ-{c)3JvX1ƙ/8™;~Mэx縢 R`Yԕz4s{Xke} dnIHJSwt[!zZ0_Iʭ.58=gp!Udrl%N rh3T !LD⧴!X@p@RG>kj?MkEz?6Å]#{>ޣ"%e8#,˵E#u[}d¦Ƙ .ޑ'A޾&(4rϝpZMX*D/Zx"FRU@>*8G^K"C$.%b8zώtPMJ|bT>2HNey|_['U|E 1֏,Q=Q{4ۼ9Eˉ Z~DJso>fX~J&z=:8(@hʱK9j/~9%B9z/~«{-{?ẖ^)55w#UN< `#mF mݼt RTW{Lq†9N1RXa)@kҖ5ii=P߼H;NKMo KϰNw^)dKG^XBkv`NOV>v^OpѰϟ4~槀13.UgWڿU]/?tOK^{x`Jِa+ƻTVHt9Nγ޵Rެ9:~}YVY 驆e+( |2)Sp*2Aã@U?J-9'XV$DIxIkfTseT%l 1(ݷrE#;իߝsf'05<:?mϙǚAX_D&3ce6%3͝>˜۹=km Fޞ᭩QR)8yk+G _#"܃:>9޶矸w*+[kvrS'wyBkl@[SZ! wp&3-9;g!Y)|0*b䂢()@*(3.TYgnsB>B:*NOBpŭWd/ɋ+K@BFi"Tq4g.< ,@i ip_KGyTzJqϛSc͚>i%mm9k֍y/D`a^ѼW̷?훷Mn,`20K'+~o:^;F:8^?v:hUdxsO*SMΥvZJHTH|J/IlCr_X"۟|sTyQI~E=|J*L6^y [{Jxw_ځsfz,N|$B|iE>Yq8__={2aUn +&SL@wʃ;sP9c-Peل$M5cF2KDDz߅g}lԗqb]t*|a0s4f Zk@&@qs˟86'OZ㙆>1<+/`VqDkƝB?]ٗ]4 S+MH^ȩ\~{vpbgo8-w?A0*Nt)uA"H-t `+TjfA`{`IȤ ÎT~anfRz tPϤU%[,L?mP|6B(PX>̒OvƜϝ~ۮLuG3?o}e 2`煤QoМ'S8[y7Oe+ʮwȧq}~W4_si~>-=QwF$XbM\s'OX\U ]{WwLܹ%D .QT#Dp?{Sߙ37_BgQXjfZ9=Noe3Xf+,f}YTh>$o%O K2J9sy"8rgʊ\78Ej$|]e,<,ېVv 骓KO7k>cH:|!3~q&b|}d|G)b䢶&V3DQWDPO-A\No[;D)\2nӕu+nޑNpJ(:18G8\A߈8ʈ>}煕Q+vpe}7>Z;YTlUA}ێ%(=aS/cBmI G[yĞJidJa۫{q{*{ʞ܀֎''(̩ѐ%0$-B*UA7ִ?C|ADZkr`\,osac.]24#Ccsڬ:m~V&:]M> qhC|ާH<3PCul GG*/3mDR$B`ŒiuIY$,2Y jqfp8Uyw; -ۋ7Vo*oͶ+\&9~+x]dCW]S/o=ohCeJ]Z)i̬Tc%'p"H9ƁxzBs" ++b"AOCjW/l#wDMu{_o-h[WG/[.l\xnf g g}[{tX58=s9\RDY%)|;* H&˅ HɀQ};cm q/k 7[瞒a=U4M  ^0!]PVP`ϑːN+){f>}d'WRZj[;Y&OD[#E%!*C_1jFj!|Իާ.yE.hx{t$W} maDgς͵/\WnXmL""I%ֆX8hXu< xmWoךNVύO}U;0~Q\,t8ؘgUvӳ hQZqO/#toz*&oڠbAAHC rP'Ȭ@ oh.T=ar,`|MJqt~ [G8\plp*&)<{ovwVȡ%l1AoCEe+)VwxǪ dTR}iv0JT 8c%j{. ʢ,uahxE/Ͼ~dw8vgU-(B|5JHrE)B.쾨xͰ{N 㵷"H`*yk?WeӽӄjGwǂ5sHT1{O= õ63PKnc-?OwEt=\l?'*Gf~g}{ vٗ_xy W#ȭ'離k$Jҷ"U1T\PjBVX@ ,zu,5  x]kvX^Mq*mTpL,UgAP`&sJv*eUA я,^!GZ@sqW @3 >eoM;^5d‘e U. {wcN-j afJc7تGJZ9"j+n=~޶+nߓIjO5n;zճJNF6 /Wqa_.Ye+@=4rzA3NNm'!ޜj<>jvV[qT|%oYD8Bpeg;kh񒚧I߱$sU8'X)2wϮog ~pG4E L`/hX'pmӯ @g$jk?]5ѹ~7(o^ _'xkÿ`ʱx&CĤ"PxyAtƇgYm9e|V1|1LU;p?^TI0k&w_vLJE, >2\lq WeL<'߼/|?:O|cĜxA  D6.σL,֏mֽ#DD|T$F')J:P,I`a8lY-L(, m`<>f"!boj͆wӣ"i'Nv7{Pz.J'ԬC:fQޛNBZ9(bmUJ릝Ϟ[{v#~f-j_oL]%$4üBU!ubXV,fi"@If(a񒡁-p-aMۯ|c 'PFGI1YxPc^,8 ; 'ԦfשCoGִ$ U$lvREj0erSkw3-OD8[8),N)7Bˀeg,׾{h>v}hzn5#X3׀k\NɺfD7`lO\V- &E:`82;IEgH%G4ӷJ_%H Ĭ:|lyg9Gvg@Ub=9珐0! \#/G[%Eɳ@#Y"׌mO^INEvJQQA\#dK˳2|fZ Y/⣤PuuTHB@c TK>R1KlCQ, &7 X䕚!ĐmtT7WTK&Vďy7h~wc#[&`E! *[mE+VQ8.L +6զ ZJ?ϜzLgw'Ep6"Ĉc)G KՋa1M Ҍx*YQݻKr#/ϧ5ZY>l5zƮ}x7]Ev o;hf)e|G!1Cώ3Rp؝J* ra0ϧUYQjuQ˟ԗ6[x4(akIg!+VP~Hdk-\j9zS&lc೼5ˣa{ڝd?\싇2qH1V X`!}}!͉N^gYQҐl=KpvGGkGQt8 & K Rr>:Nps$!!/aI3k[S 峏~k'WVIEꢬhGE_@J*PY 7΅a;lYd[IP؉Qm?gl ԫ,,F4(*EX"󤗧''NePY 47OD۲#ߣsgE&fx8Ωm#Ě;ˊU^4AIG+V,?A~T(2J#4,B%TE@n> 2CH [&; ~<"n\9ThrK-XQf@7j*=$b[ų_FkOcŁHdч{}V @ēx&y4ۣ}o18H{?4t ZVU tҫXqlgۃ蹓${`oGa0|Ekqq)Q5QPt#b(Z)^2,p,"-,'%-ʐ8˻qIvG^^mX,Ve oUO$Q*K- LI]yu1~->JJB [ ǃvݒ|>LD NyXPdq-{ύMA HiVJrP%يBXa9#)3f|+?}';~Rh%%PA%0VXeR-' \`*ʵ mVy:-Bzk E9&!m0#Ke5lb垿(޼*e]xr2DE›pWM Jauc;?6Vk/a MO3$b+;,$1Qko TPPGyg?H{.9݀`mѫXJr[_|չ~nv&O턣yt4sXvnlJ6OV7enKY[2ύ-t9Nuri0M<:{7iI{}@ FnՒFnUg!oa?e׀Qh `t>?,bO,89_?9FS:m(ϊ4 b$!¢H;YɇmUtc/ IO=3XkU-2BB&481`x*,HC̷QG$uBK1I_j0?,V` H\hwb TEApaRd9Uc@)WE ; qlƋן\|%_ojx8 omHx1+!\ߙQByrezP*d|'b>x}A]P;(-C23HLړ$Q !dpbH60*Uw-$*/X+F\Tb'mDN:^*grUA^VPڳt2eneD.B~~ti7Xs~rtmB°s-xKKE(I+Sݺ`ZARj?kGO#9Os>^ɘԳy,m7?Cqƿ^.k)L}a1 g ijR56y x -Aоy0 1[|bK_ 9nuvXdΎdUĥe-v/No?}Gi̴,Рz']iK7h+?$$d#8TJ3 3!8([r#yKB2YIJHD Xrȅvyl+Yo\2OW0b@T63L9!Qa7aS-J;mqry>ch-G3i}HB,B^H؊E#p[{B`*ykQ]}gt.r/|M_kFWKxj+ɐ8lkwW?{'ǒJCY` Ff笼8PՁjk_sړSthyij?5);)J:$)%%*}Tת:dq;MK$~ȰjzlBU:[fd1/m\o^_?E5[" yD)o"sby&"e,e[󭗎.ɭ<^z;F ٘[X=E(5shKk [$gvFwcCfiNSU h4x˱:'If_r_d)]Gy TYĦ]ZiAKDcU<ؔ/su%ȼ(s?ON>JDpi%uUI(K'_<1:uxrB> Y U\PqQy;Y `jx ts!xRmnj>O2&fȣe`ϢlA~vWүzϰG,6WkoVwю*kȣ g$B{'r}3ߍ1d2jљda8J~r:8s?*<^-BJY'{GO$3D5ey$K4$+6+cuR E)1'Q/8w+XENa.exEldc`D{%; 2[)=ƵB6᳤Fz/-xt/?g&5KŞ0^Y"Rڦf6jn%x7qg(g u>U02CKy)ޖe]3?s kk[, x֩0|צk[LXV3YC3,DOՃ߹c7AN"A|c퐅Au'd.ngG<{><; ޵ sW_m]{'jx[S;jb hkCizC#X:cDky *S[{ڢdy^ڎ^4{}18;sTpݻn o$Nf6]hFl %rQf}XI Cj|=( ٜr`e"F5QE0s}@yd؉2u!Zi+`(ڙhei؅%`8¢5 T*l^MiުVYus߼tjӰd%`M38 ax-o- ;c Q KLέo]뿹;xNt0#y^u;3ЍP k'#β!z]O =^R-|

    DE<0_ڬ@1|ttz'|"vWO%twYL4MjHJڕilAQ{`EnG3#Ih'^.935`Td]b Y?MsSSAbỦ ZԀ!uґΐ 0Yi>IAȔP(&CqR༩3T<<ޘl9a[6ՕWŹQ [`#\meW6 f\^6$F 9V޷ T= AjAװK ΎadiS  Lg壕j(`'{>zG6[͵ ɛ]sp0\'.GW!>T|Nv8c=&~SN=$̜Ҹ0o22{V~$oB, q=#J*RmJDK(AFSj%m۵ ^(k323Ec#:#S)B 6WjtJ$fDZR `C%K*>1KKo Upd m"K[[)K5BЭ{5׫@Oׯ^?@J_UO ,|`{ ®bX_-F=x!7PB/o4YYwO+l3.!^8;bןtW~g?Pwϼ ٮQou.܆nd VU;"GVuZYRQj.Hʈ(K-z(Oza[C:l *YsACa5L-hו{m!\ eٰ^-E* :$e; +t?у'~ku.n *VR2RX36/rڑ*`G$U"bj[.ph@O# itVpkWq> ZnkZ !{ rAUDj} ֆr N]NKw/w+<$'^9“6ͤ}k{z*-?r\W[M҃TI2׾hCU c+hZ"E(a6UzZW,zjx ~!bVbCJaVTu^mbB%}U- ^79O#a'Yk*]pV'+\݇i n:_L፻pu͟{2=̯J淯w>c.ZS*]p૾˦-h!C%FfogRC,aT%G&keUe)vyI\ShmK*n[`sՁ#OkOGmB53#"ʠR04Z9,jb5Q-,e1fXE$vWpB9ydcUo[0g&43<,lږ.Uoǹ! Dp"y0oJ k`z,Z,!gv !{^3$kхA 6.*LVxfGg&Wc%z!E=yiyޕ 4z~=d& ڢLJc*`J&edP0ߡuc! d`KÙ\Qki*#'IyTR-TVS6$ \˾׶jl.X:AV51~W֞(\:hAV 5Y>[gpH/"`҉x}Vx.<{O*/MԀz * w'yYTײzb-Qü3O.u̷qTWg >cʶbgty탕PK $̌qrd]bZU]cG)& iRWRف-aU>2wLtoapdpX@y3}*jXyȵPL=}ZFUT,>l]R~R*D+MIW,^8^ 8BZ@z|pDmws¿?ßzkmֶcJxz_0Ұ*v-ra\ȃ~ܱDd=tnxh"`CX M.vDU_ 'b:/ZYQ 9CZbOԎV-: <[CFP7V/;B9UseW?8beUĢԀ#܂V˿j8GVwA8;p# r nem!oUB] F/T!!;[ '*{E*ߪ[A=R,vNf+jôiƎ> `i9 <2 ڭDf+L 6N[-Q@~ZPhXjcVyǗ>B]5mVb⮶5"ގh\Y̬c=+%bc(20[i>l_k%w8C`N3mOc.Y"K2+uvMLj0>{;3=c>NԁbyE&xs'J`xwܒnBǽh4pP?2x-u 8`Wa{cHžځv,`wؔ\ϋu; ^֒+wA_]U&MT>Kvcʇ MLd ꞿg XcJFN9r|rQbEtIaYfֿ1 ]@Oy1Yi'ܸre6ܳf1mٻyMI R{3{c|yp.4R#A& tvX٭  51Vf)w۪4!8A"Ie8/fg6qGܢdTq #{^)_"Um8ӷ;@EزHzԞil36g& _3f t| 3RThUMω1%m&[an22/AS%ƏpgC#P.dU5lWcn/eދEH5{ˌc?^{8'UAǵ:¾PBt&fm.նC$Es܋k۞V@*m`dǫh U E Z[5ƏSv"TsZckO-{e!HV4@SC҂=Z&N҈`f&:u}$3EFk+:\aUNQ5pDŽ5 Z;2my[PUۍVq.Tsz>_+,1[PP_|epvNov6e ewaAk{ `Ynt޹qbć[xq$? ҢqӘݓ#oPu2OILvNWy I8][ÔS["=23aTmL&"$/=;0J;,K<:J"0vVUVH 73Q 8PO.mBh7=Rn?^ilIJ]Ch-fcRp F3fOCVɪC;4ov?Opf~9?q"(hvfh8Jeͻo_}Z}*hWxtuXI)j`~[5(:yٛq4y=/ٯbFu$/nw7*W[|j%ץoXv]+x ŭ8mE?w> /Ay!$j A"}1x&)ٻOzĪӶWˏcnaª,5UjX! &K0\?nRyS^ SۿN7Ⳝ0+FϞ|m;5O/X4fT'U.:3Դ^wr5nEa \BEML.8udtF/BA%SAW(ɠBĝ[Lm+3 ]M %dpbҪaȁj2TP]P7]UB2-zCgB=R+Taw9"b}o\zҞrAyxtiIFiNN>>ʆػy7\jaaI0eE0Ia@1}רy<Snvit3]fm8V{6u`tS==^@rJS$Y0̫e0{C/a %v[U;X.^(KyR#ǘ3*zpW?5uY\Z]@bi޽|!|.g8a^|x{9|SQ Gcn~XF^Dm=>TL G~c,"/!lpA1㍁LdݲMi-Fpy5(׸Ss;ICOlV>~P˗a! ]o/gAߺ&&=̼@Թw.rA_ג0PsS+1 S<szA''Dr!n ļrOH?uvOЧc`WS*gy7 *f"VRk =yr__>$e[5A~X"{?!.]M޼5<\ۇqSށcUַ6< 1" Up轱"AgnWmybyeto+VopuotǩΖR,։qUz;x\sE}f䈌"~@)Rў̞βA |cO/_bTezuB7_pXv תxGRa?,xFG Qn\yf? ƚyIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_43055c40cb4a15bd8491bfc502799f43.png000066400000000000000000001305021420147000300341720ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATxz䶮4 Pd՜:w">" Rm{2d5iw%BO?}3$/EY^,gOE]}ӷ O"zL7Ig L+[x:ǂͪ]L\vz>sOxRz =#G%W}~1OW/Wes+<6__*)-CKwJxxЇ_/:~nǃS<ƀ,w /^!rK(D&%4>)XBP#`CI:}(>7_xBu5˰ǫn=Ipe01hR4 쩓ܔplsP\,ۢ>|{T'>4}y,XJd6Eyٝ1+}k'ю#\lj:@BJ^ئ? X5WgڃF1EV^dhR8!ZӑvCyz87e#0p i!Q6F\'|x 2;nmW,w":ʃu-/<~c;8-v#喑_NCaہ-cC'dI/11e: B QdW[s;*SK7`>^ϝ"BNl7W$x)h 1KC"K6 2{ʔxǿ XO>`%A*9ln+]9P+mUf>T@rME$ kbtKKظ h';Ыs3skGnȥ%zp6@ ǠF$bR|Dӫ Wd$nZ>GV53]N$r Wgf$*5Aʐ̼ow/xW  U'[ ͈;δ{QWDtMZ?Ry;t=q;F|ٝ;08:>Kg>әoe\qQ%U0ԭ,DzA%CCAlo;5~}mt'zy%8X4?sU%|˴RC[:S3?,+yW8w7xjLn}ί=QuωW?LBm/›G)!@C&$aЎg.'R˙>\jQ[ҫfe<9zz?? ^6C^)zD cl8 ;E)]dW﵅ѧ8{Od̲̾-*c>^J_)XG'=?§ئIX:4,B\^7:~`#< ;?~_ Y>Ka䧓BsҥVp'@j\VN? W/6 _v5/@ WDzX:0KkU?m4 µ?#]ɿJ[|)?\|6-lv˦S 2*50.`ϾD⒱FW}^]]ԫCɿNX'\?TZeF.6J7iAS>Ɗ?}˟[_oT^n-ƋݧkU"Ł^m:bPƚe/aa1(lk uDz%Jp)eVb3[֘[o%TZk=:k\H@_V Cb;$b P "|B=h}zE+pH$a%#PSd\Zdrjx R٘-7>W֢Vt*L@_hn*q/|6ôC*}/'4!8x\tgP: $o\`#,,!XbCljV"vX#0vGcP&"_6 U^a,_aфzhk"b"‚ec)qhux pUԛ[5.7hݽɞTzi_{˾a~@Zi:H9{3e%_;k"{[?WqauWwU4 'F DI>j 8K ~fByFOo WKJͧ:Zy2k ZʰjmԛbYiEJ+踕 g7D `} |::Ur8+Bm";@/=3Y S^\|:UH4gNГK@QvneX b%7"1bf1_0"V2 ն}Hh{(F8휘58M/W8 x=iAZ'/r~.€w_o#l}XTC:3f$g-. 䲔h%q.h@p;cpbp4 o缤W[jXKGގȕꀫV"ڍyM{\ ͟E+}||`҃/IV!ΧdUѾe|+0lǔL(S@|, O1K+Y׋$H|*|*nݰZ-lg6" "?z l``\8OWzf:yfXoo7fzӤWM-ģzZ{_@tpW_O֧sh6BU)N+oA_P@ɦTG+C C(ScT{?^AԿ]8treq6>oƩ4>D,ovX2{G~,r־P F(^zތr![^m.yBgT>0놭I ~Z5aA\xY} XCUo9+#3YK&Bǀ-ꔷ7ey,k;Q>>JYk,MUcSS{Ua<@@P7y]E=Z!4VoJA!+0ʦS9F %@*UϹWF ]s6*uN%r&\D]W\Zآ+@U`lX_#Oh/!s^pxQ[3+WiŨMw-p^0( @34۳if(Wԉ /V- ?pu>EE_>C $Ka=Ղ*c#]b: 8IkeVʖpٌWhX4,]ahq%hMx.5)@y2ӊb#SX6״aFNJG ]hU+~O/VLK2Jv|yǧx!^4SVG5~'zw'VE<~?o $8ifSPD(bN=&6w,l}:*G!v ZHr-ߣs*SdZC/ĭP+-mxӶGGZxV[ e 6mZ,gPpnv0*ѫ-`A&O󃑾 WKulu}cɌ-F.=bf9a_'Y:7ିE1ɉYQPXja6:[sl(s9Xhyb1μ"$v3pDw)/!4nf4-Hx~u )Pҗ(NyP M5k' \^>FAY)`+%ϓdJV@+ĬoiQעʂY CY?z,|.IqR>.v:C=`Z/vA(?-ʩ+)ވC'(VA`DH+3w~a՝:au6il &c~:ns8^ErhѶR@̈́)V&Q*\\ fp!H›n`3ʇU .j,p3u-[]{Z .mj X0ܵ$hO"Em Xv>giaqMuN&՘s'1jap]F';puBmFH5b ݝ#sV|M={zSA0d˪:gajR7#2i-R7Q$\MR<'DYʓԪ^'MxN3&ܐa!|p>Za̢W˖[m9x!MHf~Jv+õ i#StTYepd,ΘEGR T4?oR TGfI Ƥ=Q]Oڌf]fmFP)j pH/Ziewc.XkPFPr"G 0EXm8ҫźDvL}@I}CVPUZG4D-Y+h} X)ՊV+^qZM^ Zlng`^1+缰Qmh{o1F23E\kOhS S[G p#h3Lݦ0g[CgFV(mr{nW։I邺p*>mkjaЉ/60ym(k@U=RJKA6 F!8)w3f$`- #^QYAUdaٟ-l 4w0gD*hզqP["WUt̒]ljz,3DUGWGP d頋 8{)<|jM~ňm]uP<\qIj:'OR4hk*\EQzWbߧQyij@ȧ=ɧ&%}{w:njH5Юz~iކggkxc~qVۡ(k`fzuV$uX \hcPI\r?:Z -3@ˬȝ_;`z'< G+!Jć1/}!]}kSn31C-Lw xi ~PۈYP!DO bf1Gkxs&\t=#lQ׹H鞻b2x™': 瑩.?ha[-w{Ví1FdYV_ܿﻟGoHL=j,'%n q,aI@0" {QKv@@Όi7Z7Z$KUK6@4H!${jH h<@+aJi"X܍ Z@lbTr1I>nadb3GQJ 4QҶ6M?"ݢMLK-?̦6wڰ -azQɹD A`Sg*3yTz(b KȰj@4C7@\i %=?z21bYMX&atCaC듥`R ڰ7kͲW Z{w݆Ϸx;eT$VNpG7/Tz ,9;]uxgO7XC:v#VD3/~;2u#mLjkerez Yπ%]4lUSd)Z0>0VY Ҝ롂ҡ~Wbd?aUʯ':z .X\:Fݥ/+-~fQ `}j%<ZcU&FpC;S_N%z,vwÍ}xY[=u$3=QW0e\}RT>tF'umw+ Fΰzm.ņd\ (? jKڎfMAF^^±͇0ZLT/(Ѫ-rDLل2_*J)Oc ^ B6e9y-\!{Ѧ<hҸӮ1Z3qxN,sC(Ơun`強U3ae܉@ΰw}`LE^C+ugM4==ۂnKgV*T5@ZWj(TQ/Yc&+k7d#cwom NZKjжHMFdY0?yfSvA[C0Њ6h5^MyWfH0"f Ӽf17zư$!Ka}b[y ІU@[Q#fmX~^G$u8Dƿ^F̓CNĔ3C2̖Hnw&F+>nfZ%[ ʸyRṵ,(RRbJP7C_jX@/`,5\PZ3mH *!wqtR! &`6].4-2{P @٥e\ ~cp~~/g~B5ѱEIh7x{YYb~|Vs;b܌]l$m Vŀ]I;=vJC "h\9K4Og@~* ŠJ`*^Y8XZXK?9*Sexn! f>V-XbMS[pt6x4 +.19[Q\J zKe^g,I*nfLE˵~C8 ؂VRflf0-_0&|A a-#t)q8''V$w-=JNAsK<7`x?4Ե\^X6`$;er:KV;. : F־ˁjAj3ޭ(@MEc#/5 oŰ'h!&"_%~֦H&!tGJ%Ʌ:q<\x2 5Q=U)fE;ٷ*5B?)DBAv9r(˓x:ikgQ௭z=( `cե Y vA~uvKtm5XR27r|z:Y]d6& ]2gn`Rd=*3JWYbuMqUnEkX'F8uq9}(yd5d9 WH3[loݖ,aY ][Y(b&YX=Jxj43/bh(pG76bha)\L\ *Éq@[EW<$qt؀ g[%j͜is8 R=_c)"uWmN=[nʰO@@ ~.lafw± t]]@zU#fYb\n'aT R$kٗe_{ @9K}p3/5 kׇǔd(<{&%n5 ay^a> Z+) xz0ba5C$h2i% ]]Z F6oRB+w "|NZeaVPPרAH2D &2X3sWPS?@UnR)'/)-$42qHM H9ŸhwF7ӬG'E4CO%ZK궝gd-x(vSKO&ЇB\/y kX^²1 KNg6$m&. Ѭo\Du$O\E!`@ټފ“UB劇,eI$ ?ưE7(v< I@|;!@Lí[?2KEx1$|Â(L!&*]=@QTus+g5SxѮ (^P%ǖyMt?:"}-Cf#[$M8, GLCE07Z+:;qQ djOnQi g ƈZץt-O #_q }#&RZ$&M4jۗxa(ِ#aVy!-&BG& E{pUO=DbQEЪDy9k>N.NqB2݉ m5̣vVJv*#\)x?:drhHIZ,HtW)4r!`NVwgY QGŅpOjؓE* ŒhgVAx .%/*DƬ1G) z|YAG@ʴu/CM"VINZ=Au^&DTet0TZ,IGcl ҽ](Zy)=8ntÄIm0,)5o .is߇,4o, j',p N\ǃyS0ed 15š*\;LAeMeV{s2iqbvlgKѼτ=Bh~ciJj4l~1ScBѻi%A=>0G,Aqha1hj9*)/2%Pataiɑ2!];q]m*=\02OO*^w]i>Hиц qek7.T 1bj룴5K٨J#}D&i7zUF`հ/GvfZVg{wy2Vy+y\lOe}lZ@Fx[GtDm $:eY73;a}*3~#uy3yXqm$ǐ ]32+*@t-@cfO]'-/`$Vb{đ 5շ3 \9ɼEپoBxZ# j5+JӍ|zԣW, q̠Rz&b\:j=?e! ;-+#J`plwamfY Rθ/vYnV5ʉh܏.ݬCUU*b}8W;\\!ō? Zm*hTY'#F(ɱO?3PaC޴k ˯ "^I_6HjNjLE+SsjxXNQȠ.È~ (|6StZ{NA$Y=q^ctF+J\sU6k._.#WxNh(G%L7cg"coW:lR5K'3']\vx`w)0ْM߄r1ʆ^p]4 Xtmo;E R+r;C,ӆ M#ƨzg9(v5FUrTghmgefe&]u b"Z]S_Izfq{V|1 ضZf#hMC3jdylkUvdbօ[vBʰxdd]n\:y?qQ}qfG7u_ c!c1uSFv: þIW4S1ë]å8 Zt?nM4s*զQ}{90]3RיhΩ5p}Wتhp1"~xI(=iW& FuS:P4v'{)"Q-Ȕ}'ctIPJnͱ+1UӀPȭaqQf~ rܸ=JHr4߀6(n/ ;E>7l* Ǹz&ZhL$':=hǡ+lB5@!\|~,O5(O?PUGZ@jõC]WMLa}9ik0ԷGwFw_|ܷem@Q՞:}&AG/rIWh uЁ[5xsM|`DtYRr4E{`#uYdQ\ҙ`=z21U%5jV\>ե5CNTV=}B#}c<7vW V ZxmDBɄZ}<v6Ks) xVI6 Zp36RT>j9/ak0^dU N&a F 5*:ØOkthR(^6 k˴t9%ƅBO:W f,44EH D3|1dؾ{ȹӜX({UؘhuMغ:PN@ԫ-7*{r;Zu>/-x,_ӛ>~ȉڗV6?Z{{;l3:?|v?<ѫ'q,l*VQt.$ bx,KƓ3-.cLDz*͡1J*Yjw@#YS܆p1dDJ8#Auns gzz)R$WXv5njrT;[+|=r lZaAEy.-08P:ɺ'aԼ`- rWE2j4g"@<2'{Xbuī),: ңCG[qC2jN=5]M!m׈>~M-{Y :p{вmPƆh18Ngߎ7pwqh893BY$W$qVnlzXllGhemXUa 뀌\W~!X]p?G>a,o긧دU)Bfem edۺUX+ CG"U jz@f%hlztC"` qi7m#t]-I8ˇ!.A+er"1\[R}t`I g425d$GRi*:IJc[M-Qm(t~c5.8swb6I/dSadO\7*m>;EPr/!!cI\3v52y])+%c qoWom{ήJ B@.f@iv}W&4? f,}2kF`j5dz5H,{Cɣcvu=Ac&MK bъOOY.:( V_ 2*0)И(pc W$o0\43uMXrrJbXihЄ~__ Cp(7ДA0i?|0(@YH?b⭛LYDF:1\*z15Gzc; -EOB ~6y5twuSVO_ntVV54Y$k#ZlnrnuwaE]Z ߣYVҎMG;fJ6U͕1Z,4Lu1fٙ8D|{NX4SdF7jtŘF,e&0m!8 ?~Xoh{n xX6wXi+1ۛGטU2E, (C 6[Zn\ ס^m]GWB #$S[_uc3fRZ sD4U1 'riƴw=uRJz#`߸td H0DyUi>=#_2?^9(yY<nHD`U)ʴf*简;iG^<"ؓ=n͝F].ǵM2=#=x"V}o*'D0 <Y6 ip’%]O꥜S<Ğc, Gmu7e}/ T5l)P/8&6yB ߽ݨ_mQЪa`Zp*s kDwF&)t 4LM3I֥ib1#~6Jm<2wlIWw-eD hn;&K:6: „#`8xAC5%Һ g*'3|}M`"B JcIPwP&8 N JMsd mlgB ce Kdvf+X~<$uPT{tyx5Yۄȗq|{b83k !#Mvڛ2-ch%#zR S#5 ֥CQKR6" ES !čT00tjʤ4 A,İh#OK9;`Շtg|871VQ<1~P8#}9ޗC!$(5&RQΠ2o;ɏeкIxo3/7rlm=1kVMb%@CI8SkguY­"U+{<* M?}ߖ'1Tj{ 2& ,灲8Z:j7 7pyd)LWR0oI 3\&2+e> <./^SUFa/7e`+ PfψG&ԡ^LS#\%j% L\7eǩlU!G,TqV2H`d$}ry(Yx/^WX,[F̓Jm5"3d8wM˫  Ѷ)Qx..?$eF]eЉ QbVѫ^4'?*':?A3nGD=jذ .VE>0VbR7:UZxE8t,ztձ1)s9t:`Fz&>x.0Pk#ŠBf+..%CVՌ(sx Nz(I9O<4`x>Ŭ< lB8+ gЋhu-6%&eI?Ȱ2aHr@㹧#pN+GԲPQR0*K65$!Z)V֧Њ UFL*v|WJ.'F 1*VD6 =BЬVF76g Ds*)fhu!J\u͓r\y Y e ֵbŧGZ1 EkrګhW"*I%/(]BVG!ThH@z}e':iw : Hdw=ƿ>vXъǔ؝}Zke * Dzਲ*Pj'<)fGhjȢݦE]1負/Јa~ f<U&Dķt%bN>ec> ]!t|8AP0@xTD!QhE(#_ʩ#ISCnp):6^+*<UsO8DK= @= ˴(4 wQq]li| f@nߡUĮQ9-lc;_ ڳa}LȀRucWl^,ȼ8RqJ7g|@RdDyTbH_?W ^ 1އdAY^!ЫE^ yyBzx}"At+Nc't 0zADDbk`TB`6!*Gt|]׎/ n+}1vڕG;J"PRd"\[5sxmͭ؛d3:8C{ę ~ee^y1YP3Zp(cⷞG|`v 1X<_-`=2Z iW$ cTքϔZɲry鳑-ᶹ %z~ `Zz 2b|TAU(,x %+Iڤ*?U5RĖyW=GŬȣfĒ2T M;Vp I~T$ [yJ VV{!1: ,B.hj)Jrvũhj' ;1I_ `$EĿ|Q8$NVxrcdZЮfK#xMae~L!;9Vs /0Kpf8T <`]dg3:xiEp8I*X)R2je[A7$jG2IN2h( C$?@,?woYO|]-ȅ`K-D^p ii ƇX/G+lb-D.X ڿ<ۆ,Md@*oZbS!`8I,hW#cÐĉaCdTazOd+hW9;U 3l_ Xl$\y5}B6Şt_4 wJh?eٖKd TOcᾄMfK}AuڢP E{AOƳ^K9 8I9Ze \+fQX7c}KIy-l_2z&Vf87ܺF!+D+ w(0 #s:ːh[܈ŃWJGiG"tJƚ<ymC6 T!6q!#{6YSʑl= ٻ?d(}jo!KKY1: ,E; t0kЖc1*VlZ$ˮ͎kn1N4l"EG$AUH2`fZv& s# Qa/l封-i%?2X qw >/بXd(iT|#T۷hlnpbpx4#q :ŇZ𐩓ӆHhUyڂpا*BPJ=z5iwٟA*πq^!f`Nפ_`vÒUoV-oi4U++"N/vOh'= nHi.(9hC@Cp̱6*~f3lkߖx0w)^ ;Fpj&4< O`+^WHٳ|-)캤?#vsSXgqo pak;DM:E4APȝ%Ѕ[,dHeI3C2`(hJfUqAkkZE.(u:FK ܢU  8,Y;k [sS6o5Zu;UK$03UYx@{Щo })p!i"܊daFӊZ5 %ڮ T9m7晇^\Zluh+Srϊz|8a9p`#SxZ4y$N @L>˻@ʑ| ?Pķ>ngE]EQh٪Yʕc;BWZ- h6.lv͘,rN9"MCmQ |}">"P`9M1b iuxj"~q@Ҟ=j؀pⱖ:Ĭm5[L݈Z+OͿ4ΫV,{Z_I 3zE N2짅G0+fzwV<4)Tac^lovdzwҸ[{ *>w ZW]O^v䁊,UPϣ#@W,nsCb$8xv1ahљQaMc1e,?5w [q=<_5 y]Uʦa78>GkNj;>S#G=v'^Î"M/bD}+v-3]>w5p-X܎XޞWg+ކLX*M1Rad/ح4Cvo7.4OH)ʴFdLdus,B?knwH+V Í=/x178K'>H\G r`2܍o#9J'abJb8`,63hjṏ1EG`hm=kUUy3cY58u0qzv\7j)WU's%ڋ֪0v~!eH-f{r|G)fdYʿߌdr=״%r[a"V E!@R"sGյ;f *)0֕.w2NjUb7*0fA t6Aa/@…= }pZZX\ESLo N&=}IF Zf$ЭtrmyUzիU\W9j=:d]RKZ~Ӫ=`sYrlo}(0 o~C AIgM1ޗ:pip-<}[ɼ/rO<^</h);>Uⓦk!4B|]$EϦ$Ԧ¨MBD!D#zs6-b(xwl;m*#X% > BYǎk(f@tY ƭ޴v(7rօ 5zd) ņD}PJu 9xu:ʌ{M#37Z帎ԣW7Kwui!60|@-=}=QTK1s2jS+=n=KwA? eJF,3ҊG18hyh]ф0!Atk{AWޤ5`%=$OF\"%maIE'A(R!'VgʍJЌLf '}j@M߹VS'nNaN 6uW1Pk˧t)P1.t7}1@+(T0ZruQyU _z? =lW\Y, wx^RV,},c _%>0K=;p r@dNMA7{!8k_Px"(H9/QˈUޟM˺9=Z!ʿҦfp \W֘,G/k8\ߡQd,|Ү|&ac(u'0cc1)׈f>"jq0trҕUooSl WWUh(`A͎Zrgm+u#:&lmd嘔YkF},KDj >`13 =7,y`V/d6 Bp ZN^.2 jքh B]x]u[a*(sP"f0 UM@Z- VΣ7\'7ܚpDcl ~1b43l2XL h*UaoXVTi#8mXMx hP< Ad>cҫSϷ^Cz\8oqh ti[:vv2~?TE)&.tli&`o~)#kX. m_- YP0vŃQs'#fQ}!_!/"gQLU2!vFCȼBm _qu Dm32B( \ Π頚_nNW+mu*R&~gGPJ$zjnĚ\1X3x:4Y;+($@IO]d< TdYuaeYN.}{뀅 2\(iNT+I/%"<8tM.MPR3dKiO+]R`+MҢ1Z Љd,z)X2(4a1h,z@df~Ɏ ֐1I RcT;Z9 !Yd|߾Uj!?ADXNU8pɡ'LV&$ r[pAx. tuUAH<;Ӷi֩$Y]\fhI[ J5 !ހU0t5*|\?-.hepgH ^X ;P'HMdY"z) c|,>=$JYyV7!^FBG싄JRflcjlOx5-Qa2={0ds0-cJmłn LIzHs+J}Dle.,N,N @Cv|=V!kVMW2B(1%#M gH90xG-68HZY=,A0T:WwDC 72,7Vn;@N`-P- xW±Q9BhqBÆڊnjS΃q%Ҥ n+ Y`8 ]do7lIntdZ|rhj&t#CYF@{s0(*ZD^&::N'֎6ЪX7uX*aMxΌV#2т?96yQj-̿Wi8yw$kkę51jf 7~~mkٲ4nIA_;3SQ#lHm=y8ǔ kS7]9ANcm񠢕0lՓc+G[ԁSmadNQ;yLidatJ}:#!y9 .Uun6=;`dS >  bW@e`uY8 qr sDa3oGU=5[%zk'pP`t~b50zD먪e)AȒ7Y7%r8N ,!!eՖ si,,Xv7JݳɃ?ك1#c F6WpIͰئ' u{26eU4~u?L!ZWn d8@=:nLgɓd^Mau7ej2yN GrJ:59g d~"9< z|C֡,cNaXPT?Sq8+{wE 3gή&%"k~P뛗ݦ1MFwV5^Ư$,"EV{G>/QG43]bP^Z9߿++z90uOy(wؔ^oX|:|JEG5L]#ڕF<9=7"'hF)}($>㽼7xg41{FQpP%~ O :1@ cnں5jZ=Lb4@鏳Xz{z՜,}2墧x {!́tc$dΈIn_6{gIBDtd#*Aɰ`&`/HC`G ʢ&iR-a!2` vb9լjG`%Y%ݜ`NtZu1d&}Dfec+hVC 4 sư.cׄE~&)'2CRL* qaW,赦[aKQcrx׎Z& [ r`Uw2LSO~qkfx]]5^5ѐ!*oVvPofw`Ư5E2ѩF|X l磘4Fb%D^S3C<6!5Ij$xI&v? ~t YȔnjwqqp`>X:P:/1 ;ǬDƻUbK^*`C+)zp/6a!27+m~e#Hifn+?U4 JJ3S9l^. v;tX i9`Dv a)ƱfyfD۝@pRWOV*̿W 0Omظ3j׸ ^a1kr?gMxYP@9jՉmdžJ|\kt Gw˱6O$b.c`WraPF 2ҏ.RYV4 Yc \"Pw!F'ծ*f&R';S37(U vEn0,,s !j~xW .t<zs?`J&C$}.ط}F^jQ) :S] zO,A%$p .QGug5BѯID`6 eK]C0\{"95~A1aSZ[2SyN7 ՘ƠeҬnw@NӜ1D+WDq+\5i$Alƥ xkm9mR]HGv)ф A:a 'bb+NΔ`9n ohRU*U|+*(bӮQ$kUΨy 3Bjg4=!j_BEԪ|H9}#. n=.TYӕұ6N!\P_z9Rx$kŎiU28^vL7Ej)XVe<,my!1GX{n2êI0b{kU[մ_qRDťE} (igz+m>5qlˀtaC&K1v=ؾ3{FSL"TI$unPyy%fDfQ8+`C$u\qd_lpH3cSmpQܱQG8`%$' Ԗkڶ9E狗ovk dQ:@c.n+|1?\qR~+g̱ֆsm2K;/LTNSD ڃjM3z)U 齻*'Ep3s#e"Ҭx%`RUWۄhlHasP'm1mkT!7BBҚex<'VOD]OG Axv~K 6G0(}Z>ʋ^eKXKrhn{cO>S3_X.ui{Qt6͆_JgM=O[aP|oK=EU HKكb^j_+4UlF6i>S<D%_.^2~y?.V!Y/y7w:̹x>區n\8qej%v4{<'cwy8^d&a1EgsF_j@%y)5jЮAyU a"@7-JY!R,\y{<e(H00AR6+:EBN>P9점+d.>v;>FizaĹ}-jDE/sy -9={rBn*.y%ww n*W@Jix#88E`?6'ET,Fÿ 3&I3o zz k@+7 ?F'3;zs,.DN*J<1{%n(chn\;&cM60IDATux&a=XzZ|nyhB"S7(i]GtY_sH\ =3!tI!%Z'C0HWű%kfl[`V8P`j!)`ֆr3~j÷JY‘qN#DIP{ȯ0r5Y#8Dv xXq/İQRpūj\Is.4a.܃." hH\>Aux 0*-1\e \!P7ys(h*ǻ;ZefEE,:TAz5BtGɕ`(y0c > t(*]DýzT7lZh/{,.%S1>FUw/kZݖׂ0E:ֆc(Z-!j\}TaNk+SRֲwgU\D\Dl1^XT1/e :n5Ggs`oS@(K?]®(ͷW92Uw/%i.Ft 2Ra=xOxq0$Xpz)-!ia=4Kcw{æp\ r~ImN? ׽+c)GWOGfUBW/"V9=ڇjSsd) C~YV  [@mAӺm\@RЅ|VT"2(R":ˣ/BF!zilTFVz/Ȍ7>b4 ?WZda,FL@kuQًewX9rmV| i9vw⚟V?En/NE"uq٦1 N%?YIȝ'THa;}ͮ;,&^ azn#Ɏ}ě=.DIe[?\=c/z+!MZbؙƵXJItB3I.럈L(05.g.=840.4CoS؇֎[D"Ip\YF$ b'%4f`b,P;&uSSi0>NPD)уƠkͨ^/v"kk谺PXe[&ǃNb@)Z}sh?מhghW)ÂsVͻ&/,;۹g<1y:C&+_ƁgA И~ɷ`޸D'`[2M|5Wr9Dl97)Jhέ(Y.vɏ~U]۰{U!;aѓG/x_s|Ϗ"ֺ/$eUo\/K#Z.XǬ' m'(ĪZ6#&oDbjpbC^ČʹɕJzKJ}?(=-'Y$}*-icq/ޓvTwiyۗ Ȇgz^W/TʊXڀ-!؛s0Ru2E/!+Ii5Z]ן?h\.X<|p }@GvU*? \UKl1YEp'lOKoI`*nĢ(dEu͐_s4+)Ёnr̀WxN kA`sO(ĥc;ͺ2쀥?9U̍c$g lv25^ }#0ҐVeFeF:ÛسW1ck_ hvr ԄaS"F.?TI'TU9KxS?Dz[82ܦgdm@%zm̵BƮ:7P[ZYCOfF>o (kQPLs32W&f_c@% ZSs*$f,% K>ځ((*|;:rj;o5xB2pĈKĺEZ9,fT+crwSB^(:HH}8vV1d.E,ʬ#wjqP +N&N [U L x@ dK绑qX$@|^^\:ۯǸaayy%_ɼnU6GX#./+8W*|c^wߎ>-0oZG#*(S<+` h1ȍ=蝩g{>?!HBv]¢QO =(u_PUm94bohr! |rȴLFŨ~ieiVu%kȆ,u̐vKgAHtׂ^NzpZx{^m#4nk^Ya4~g֟Yw>L ,bM?|}u# V}i$"| `Ԕ+ ^}nu*Y{Q Ix](k뭉ݑuR|KG$]`W%YI8Oc@:! GؑEo $lEEc,JHVREV\5U;Vgͮ88ǀaek#'TϖN wc.hkv6Wp}a}B6u]+TxhcX&H_m5Z{_HmW̄ l;X]#ަD%/+?*^4רm 2' Ŭ\>͓3oy^B-Te겆]{ZK!{]S8[ jԣFĢ\,OeಽmC{-iD9Z @d!22,S 4XWlW< k)\pL*UY6,hA« C,L5U+ǣ6QvlPT>͞2uq?gue mw !KCD×1/ _s2E]%8| @ao%f],q=NŬy};*)CupMt_5X`{vHujK:qs+~t{p?㋝DA' tn,BZy3ُC0Fpy Dk[Ad{qъ͚eW'rKKKƞZQ&4H 8,uoT>]YJa_[yB 6\ry-F۠)}!7a5K0fru]1JKVz9]vMKf!抝N\h4ȋq^؛zYDϦU=$2VѰ0ADPo'XFݖ I4fA>;t=QS&S0W 3~ }=W;:)ibJ,ýHY3U2$I`i'.fGi ';zaG+RWkH3$+Q;0%f׿ӹSXɡDΌ<|s7`_uOϊ|E6Ps)SMN4#h ɺI6R.{lmjP?oìXf؃hӭ^x+1:\5zU8NNOI7}*,63MSon4nw`բ&0!=O px ldn4PWUOM}t(4Aj Z?MiWJLbŬ?ۤLc;9Œ)UFFUaD%x-0bȯG&aTse\e:v|M-qS PBo 9z_e޿GAܓR bXЌ8n۪ccW' e`g}"25?z0>Dl4/q27@l,a}oʝ@0+ 90+MERWVlLd*CwO KUА>$ t: piMYXRsm$-+&MEh$3üh!cD <=^ θ3&M05kqagjl3ڷk/lX8-抾Vm__Jo.Ex41C[ ')^=>?-/C `TuJ-KrWAmF$Xᡪ ˋd$!%Liʜ9rVn. dLD6u αʼ.ԛI`}9$DKKp[OLw|SNAX˪3vsf>OU6{xPàOC`"HLYTǡ8lVDl 궘M1´eA/ sT:@'_4e㷠 h厫PB% /KJRF}W IR\ӞkH$ Z۳Ĺ/k"j\` ̱Wg)镳_ x;\J:+l\x^ |H>kSY/K<\u tJ&2ʴĚ CoèS9+BQD[dcSq[ⱘ I<$^QJfIܮA45s_rVx{]Xg)oi]Eݲ&ky2y@LEef:re#؃0 cq̧=&D2j@ʱE~c@Gk&(Db8z6ےQKO/WX70>2)y-W VK8DPc?.z5*1OL؎!_3$@KPyRmv+KYz jBS,3WȵJ>Y1 p CEBY&jgo> )PzB|ʌl-‡n?Zys RZO1U t9cwD R VlUEM{!a4򻉾%T (k5e1O:IA!)xDl*1rO;{BЇWlƱW„~q1mŚCTxd"7ۺ*sZ4aj,2Vb̬xf5lwQ|'{paB47t5!! [`h,TJ&"$E}p5Uv!@3iקeI~:%#\9}ь LB>j֜ji}_gDV rU\;u7 %sIXèp3YYu2q2,#5(h1<{Xy"1 }y-h;HŬ:hׇGSȟZ^blK4uY^=Mlp6Y~PƋ5EZn8-U"3?\7;+beOœnW\:Ԧ~F? h,~Z%罪SK7ܘeY5?WU'Fn ii, z5_œ¹YrSi̔<-C7IKd  ݲ0ʖTk"` ȆWg&Gxgsزrui.-9ɕ1b5cWs1$+c[P,,i DH5b?1bٖS-fT_iX fq1Axa: f3C%E!2yնU˜2%d0i\roߠ~o벀Ɠǩsՙ KЂyz*jBlwT޽/ 9@@^a:HF5dw yp yNm\!{-8- Uj1hj}f xv9%YJ$6xk`b+vax*.4Bj+ӏGgu ?#n#ګ)F!8n +))/9 Zq܎7mUs:o)lD}m섑 euV9fyxV(@B8-2Qz xT{+״[c󵠤P[G,7 C䒥LCeҠF]Ȉйݑf\ |DjbJYY>кV{'nm qH:`T^ma<6_hmT P(O|DmgXΰf8R]&EYulIp1>O<%*4 qe=m&nlWg b;gj֢<+o )ߞWeD[ ]Yo,2%NWkBgKY>&={^n譱Ee7o3tT0=ZwӸHj=q6|8'jK=Ƌ3B?>CNhtx"LXYw_T`6Qڐv RYНcQ1 7V8jA—\qܪ`g"A3`jXUaK|\Q,׳\% Q'}9ǵ)^'amFP&D[Uo7bUhE?BX"ɷecp+ ;E"ckZd1O<25'7^$lRp0+VM+_S$qxlVmͳ:vpޚ$x}J?Ж;QPQێnnIaA_FsDlY 3L`Vb %Ǻ){u8,l|#_VFbYiIàj]nGb{6.*0/{({Ro\Ы*:HyHC6QCv(tǘY__㣩Ud`DB ʧ :ȓWQlu.D34bVl? ALV2çjUޢ5gSԆY YC.rN<63ƃ_KW CU_NWZeyiImҵľɝ`1,mh) WoJ2 C+ChX Vbfc>tAG AP lz]GY'V_x=D%J ueŚӝ:/w1ز(PTvJ>'q2hEz9>*;g[aJm a&F*SB'N", q[Jŝ!+e%k86b ]ַ>/,2G[$ R{9dU0#7 wR%]cRx&:+i! O'Hi 5W1,rBԃ7\T>H4_+<9ÄCpel3@IEB,jd`7ŧdI}';ۚR;["2(=xm 9_2L@g/T?!3U,JfZIWr_"08c6`}CjP%Dɭ}zstO'Դ,O-!  9Hldَ]5{_;C4̉LŅ rqSng_F5OߢU02i\;(ښ _R[ *U*q% 'ʾ^x=v|VcQ'>@sZ  | m< ȉs*F9Vt`an 534W;i$J\^LNݗlȖH:F=-#u}gCUN"w#{zB$7!(\8X)-.CŝIv|"!}50!ZVf~vԯ:O\ʒ.PnrQg/Yڌm>1X;R̕C"GAOεYy/=/{6GʁX-6Uq^ꃋ DiزZythd%TyFwA]{'EZ}c(&-LjQE0 Bc?oQ{#DP`q]\;'6ndCs\p;[;\#m7$MlQcKHĘ 1zq9T(YLͰBèH|G?ԿG1~őСidYT1g&nW{_SEl?U:չ  ~߆f?}N>ڠ6$:_>xD.:ӹw:5BTZQ~"IM&aUz4*" "&W23& 8=>,j؆퓞k[_>D70>72Ӡ'0@w٨#Nζmuµ3mkˏu#Jtw;M͘wYkn0m;"“~ςW;3;\Pa.q@Y@t/J g*Gڷ?){V$nS; o|'j=. w"v2ⴧ<77-_CV1P$cEySKLhXB]D"ie~!Y$[&'~:_G;.Uڌm#n)U'XոbM|%RxVQϰE`B3Old'`HNIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_4ea8f246299cc5fba9744bdf162bd57d.png000066400000000000000000000214001420147000300345110ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw "IDATxy]gyvnZb-dˋ-!{M 2p*3Sd$؁`f2b`oAl /͒Z[6U}.ǒ/<>w{Eg:=BLed,qieldjeXp,e]lȺ6>.=W㞽f4̫1gu%uȒsK EhraEqvXg`EqKDrpRSoͥ^K+ٶʩ>%S`]gjwA/]nzeˮ!aB!aB4+ZHӣ5]ms_˞h;mihCo#ے soXg`EqvXg`Eqئl ,\vӄ.hGvULve>0+e,mW  ! !@Wbfqs:i\۴[ՅIr1jFhƜKXJ|"8;,B3"8;,B3tբZN6 ێR0HbHi̬t]ك*/]7,B3"8;,B3"8tsze߷g/}hqzms_vske啶J4eU\`^U{i+ǺŜB}:جfe?i[2@ÑVrϚF/5oXg`EqvXg`EqtGеRKmst섃3EK^W2U>]:~KEx`W?7j])^h"2'2'ˤ쪴KyG|V= xX]K߰! ! gtm4GrR>8P2x_Iu<(_v=:/e ۬ ҕuؾIʨRTRfWLҽY7 30+ݬk8wJY &O픲ԵNʶR&Q8IhrS8PvhUeCpÁG7zqAŠ/"eBrˡI)w:%e(V)0K`xⴔY'0.V5y`GYʑ*'sv'8j4gVӒ/2ic.+\z 7m@]R~p ݶ47]v"8;,B3"8Cs96c˔U8fRM+,uR0x U>n(^y_C3!duWʨcI 6d 69ª "eOЃWM 25u5ϙqs\<)ضQ׹nXj5 ;;ӷۮ^ 3#7")fѨLw=!q9IUtlc^A luRnǏ|j ߰! ! sLwe\ >i#,KGPS$咋?r;*ZM4,jE\fUM՜V3M,oZjl)fYŊX= Kƶ:QhX9'm3x\,1WfEЕ])7v4 tOf1gτ! !)K6U=*VZ1jY| 0׃hUu |yf(m\|yZrȽRV"La jgN>>BYt-cuRjPb^O \t7HԈ'=gx'OA}#Orw7m7 ~%awL5O4nK] Y_ x mku&p? R>?U_{ 77޾&R%k\ #0{GUIp7k*+!?7,B3"8;,B3"8fLyUA*)qdbBp*Վ7еm Ke8nŽYx)SG|$GCk,2NQ*׹ր]UҦ= B>F+ךk}):aVW/b)_ƕ?_6G U1܅fW#)x-s3DP Q9)J=d?I(ɄWŸYe//6,P7,B3"8;,B3"8C,z3,YU,z^]Zf(1f2mR?S23D#9*,Wӽ\aO& : /|V хݼ:|Bڨ&)-{ĩpsVBVԮex2e9\AC~/V~~ x\=e^K|"8;,B3"8;,B3{_epٽ+BYu } #\YrcHWv'Yf:i,Vu>RU`73Zqi ]*TẗCH1_B)J929.#4q%e\:͠2pT:g7=w}u홐 ;*|W?B40MEqvXg`EqvXgLyVF[38lFN[Bt{Ҧ{jj$e)R;g)Ǎ;iY9myF:Յ*QسlծR<klUI5) $pəQ) g'gXuTynw8Gt^P`4CK]>]HjԬȗ+ #_-EqvXg`EqvXg#ߓrz)ӠjځaS>!>bJڅšYR\ deCK8.y1o}D^E?#m 0F(ٟ <_cX N3\{v]nh=doDf.{Zv=WF)ն/"8;,B3"8'~m8STwJy[!~Dbvb}unq-QVЬŕR{IY_?&)O2 OTF &4t 93!1ř R8Ґj`$Ql0QE %q` ǟbU1⽎iVLq:UA$3=Q>,\Cʡ")9kR杰gPj?9|"8;,B3"8;,B3JD~pڪ9dkbDٌ})?E\v@Ք72Vư196)#L #R\&%M<.bO6!eR>SHh>d&0Pl3M%s<P.t \WZA}Fppڜ%R~P@iB[6@ʛ<*~IД:4Ov GKp TAYăwaB!aB!?|2~:nuu늴Lc10Kyd\Ԁ߮ *U5Lwi*[>8OP޻ K75'FAnK~7ļjGgr$6m`3ϩuF0%@_vRU%FhaAM;5'{qi '<$e0q^F΍ e`7ᛐځ2lgH no?_ai H^uU7,B3"8;,B3"8COC5)2vg) ʫ~o0z3tG"lȾ]PpVf5c,2A#:~_෥R9Km oɝ N$$KJJE亮P\523駥\c;#\T;(aB!aB!j@ͿF{+_'e6ِ2=j{>u; !QddE> (֟$7i8p~sKY@9Ǡn(3uQA<11ƇZJ^`xJ(1捊Q fN3a&ƴ@|:6yGtߺY 9|$dj~|q<8;n4C'%p}e6W3+0~ۦ5gL)\y)nIFαk-!aB!aB!zoz_<&eॽ9'P~j|P<x rzn30MRP`7/e }x]vL`n-V0#}Cj֗ވ 慷Y݅H SPq~&X0|qsƶoIJ[çZ+ڡ­V+L'ixr%n ߰! ! Qs!dJA .'oC큹3o}GR^SZ~OJQ 0'^Qʃ7C9~Ϧ9k4]5nQR/g7% ZB̙82Ϩd>9^.Y)92 1~TʛW]l,ըZ#ݯ]g cWQYYcn--EqvXg`EqvXg'Vnⴣ~Ȣ)u\O)>&ejtk7Tw/[w>S0噔ck](}54mQh^eG레|Y'>,eiH5#nC0 m[ | 2C?ދP AЇC3GzVoIpZu+e< W#o`> P_$oXg`EqvXg`EqhR/5 Ԕm'/::&X(W`nۺPjqf#R񳕶jueW&eFZ~Pl"q<Aq[5SAhvF,7`ύf{ܳR^jbz%Qf+&(R)s"eYڿT0@ైz\㣧< I^ s# H#yM"N/S»>*a¨Q聑Fwpr A$ a2x?]=Mcp8a5(7Cj|iIxճVÕf)nrOFRJ_i  ! !Pt8Ƀ?zYVJYiVcO[LiD4)7Vo2ceVѢG=/j"FSVX듲`/:U=PD>5 cGWA7rb) F7Lm<RmJY-CYSv$Q/ 'q wB LZX߀xS0]Lퟆt,ōeB1>)4c[6@ʛ<*z~8AK`P%^AihEqvXg`EqvXgc׻Jr*^6;{Γ;/RE?  p#S)2}צ{IazDK{ER}dd$!e}t/cqhȉ ÍRz><}㧾h3js+ vA5^2˜R@O:Ѓ;( m8@aҼ[OHy: C0UBFb|:зpVj߰! ! (TʾKߗr a cw\uח @e yQ1fuNն!Ѱ$賖TRM ,4`cBcQ6sdxLZޗŧhQ+`gmu\.={>Je+ԁ[݆oXg`EqvXg`EqpNǼIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_600x0_resize_box_3.png000066400000000000000000003344551420147000300332240ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRX,_ZIDATx eu^UYKuzS^$Ynٲdc/Ā &<À fb`< #a0l)[%u%23~9s2߻U>^v9N]Iؘd?^Pl&JmI} ]o_rWk;btM 7^IKoYFU4<,S*T{Ώa{ii5*?Bg|S̽G # wt֫;yY?JU^ȅ*aj467[qD0~ͼalƜ~,oA''ܥvꑓan.nsh?gчWK7mެn&mҶg%w}Wb^>=K~&>9/p[%è`pS#o]Գ%-53t "6ND|'%n ӔWV10h"tq+E??GK8!+:ޖOy`\&ۦMLڤmH5Rne cQyD1r.c J1jN1g GQFO3.bLHJI =S4 uT~|K(01dBDd53] 2T;-&cA8(^9߯^V'WyyXGDF8QIPDq}Hu- "I+ۋό0.BL6 /pA6R582X[J/l< '[ɰ0 9GxG?;%PqИ Xn:*'P8:▷@lm\86ho(ѐabm3)аNڤŖ\*L6Tf.Лw=E6ڝ|=ZBQk"Fb{:4>uY%I{O29Eqs%#'6 ѕ/k|bNT;?<GƵ?G=!ltN %$X## p!郒<][G I4פ@8Dp_x%Qs?EpliUd (A] [SN&Ȍe8m"D>(O-*f3?gqDc8 y/Z^ !GBea4<1[#jiÐ%m&p&-4܈,K٭l}L<T#d=fT@P\ec#2}%q^uw'bUQWCH^-R8y\ LB2atjlTGJ5L^@C]bن ~$~٩R`88k$OMSa϶a6ٌɝjbT\ξۭMMZ[BnniEZ?ēRVbH@oFsA)Ne\P=Ki Xe^_\t |TZbD޴^0!"EPtYgUiTul`3.͒A,h^ a+x6L ӸNڤIC]5永3(QNō0hE5@̟ODQB}\t c{DG-gZpR,K TX 6%t?aIL۲ĮM92/ĉH8al:9,XDۧMMZj$\`0!&0hn@^P;0xI;J76 E0|-L͠Pц8(`ћ^]2bNH o#2exQD3-K6^{DsB6_tޑ½Y'AnO=P{? —@ [_ҭq Xi\+pְiH{5@' )WuL椇 a'.K 6U~1PJ&p&-6 q9Rp3)ӅN#Vve#fL9!g]_+wwG ?subbOfřdL 3 ̕B8U;P@in1(jnG‡0eN ~/!+ h.  ,0szG-4ƀ&3&(a(wa5mB@D8i)f ޢ<YQ,sK q*`<貘I XP#]Ο_}8lf-ns&. T  rӣ4Qy p.;D"e>L%vlj?bC(;N/ I4ߨ+QUMTe8@PWV0ar:1cTʒbFjMPǮ1:14.Uj@ZУR va5>dFI \i!e ^[Jk̬k<wd{8eaa-t` p@&937:ufg=[j۵M᤽[ 6ȈBz-^JLYZu>>unJR.pRq ۱0ѢL:ı/Ջ2n ,#*mWF߮巼v3 _$aL`>nwm'mLJ)6rN "0rqR-t]D-ɻrc q"5dAnEݬ XPp8g/Ia0}-@aX( RxМfSّú!󸐑B 5HN;Ș:g7:r!fTNڤkO6oGcB3UʜN&~@d[r"Xj 3 Vk٣-` (;Kdj0pCWx0\ߩ:0]T-Z{s2]t6?[M᤽}[lNÁNA&Otè5P{F4ngY/ iNMIg0 9d|Ѣ!)(L*=?/gQ#09b_&\bɀS- ;T*\>yruJlgl7B.vъ ,I، gԾ7ƨpRI_*^pKM͇>9I9WNœ@P*K֕a}<Dֈ _m&p޶-MT,QK&ΒXӆaP3fE(WZMhJ L&0ߡo]3D٪yfvXǏ6f7ZsvIi9q^ZX! V@8Qȑ7#0UTkުY.w6|<gb5D,0I'8~R" ^/=A[[/X w?m 0!i 1KZBFGP*E% 0r~DH}k "is)рs!Z&!sj=F~xX,\Ԕ2 pSng]#o\1мCwa|:ټA[䂄00AXaHFs,@rzBV^w'/D}#E֙' jX.X`KFmYn6AvlD(nNo^yd'Iѕ $*$ cV%0T4Z>͎6|/yelY,;e@ Rzt ]ltB11u3G#9$`24PwLLxͮ*T„$8lh"GqA֢V8#ڜ{TJFغ.m6A6lI`FfMi{hg/gNZArPܚ pqla 80sZ$k4 ?8$ 7ۧD KN|~5N6s^L`=;a4g5◅ >5.p&pnQg$à~(oBlJ/Jk?!T,0NG[| rfRU5Hu.M@ٟB5 R@f :M2-fKYB' _ l@ʼA~\R̠tL@v_P"jEZjn)ItӃdv_b½N۶~ev3DPfavFt!ukn8ԛ'j^Ic!Iu!Rf$)P)hFJH3Nt=tL$,.@Dh #7'.9H/X \nFl.V9m_K"\= Cކ[M᤽]P9 " =WE PVWoH )HAJǥŀE2Y玈HgHp$>]PgW"C$gNAc1z1 X\e + _'#, x/Z0\2u>,F! QlJ^BEH O xgyPP ą&PBm'm|slI|*bHTG2qdy2PA*3%?U -1*Cr*-H[;b.l<‫lY TH!;)q6NbN z+4NHʋ총DA .'fkޢ/rM᤽#]Pmr( &kcoGm.#f"8bŸCD"%ZoHWmRaMHϢgQaD(8HuC%).-7(t&݀q\,LFCh-"Ktm΃[C`5`D ŋcLjFEM᤽  GI?4g6I[GeFy]W2;!:]+|sa9ժx6gC1gE{Rk*VcČe<% AOZ!xlǒH2[b.=gʴʳcYs 8aGH!A2CNq5Ahk"W3wiD8ioVʿ/塁- w%l Md֘6ܣT6U~uBZ@Q+!)KbZ(@R%|'bMf[ Zc P(.GϹ9ϭǬ>kkR}Rm. I{;4ㅉrd>r8ha{`s8?CDh\%* BD4&ȨK uo <K"޼g(E 0qy |&tl<Z}OFLjA6U!`%yXXt^4r9k_BTyk "|xNfWaTcT.L0O `c+K8ә:.<ؑhm8+{+9p[eձf EĚ]%9ɮN] 77@\b^ $ qm {̅ |qŚuP n6An4c*|"r|-hy-y퓣k¨2*%,&+m!)hQ[M澑`vu\_mV~vBր L~.\$yLd-Mm߳si`N*ͽŒ$D`oBF}u[!P7,0S "J 0MJOiK*2Fg<@^D "}'͏!EО RFEB}&qv\i|Ϳ?8kjj\3BAU 1Ȍjrs>I/P_BLKG}erB $7LJ^ScD'L![xzx/-X*ƥ<^del=Cz L`kqX-x-naF86ic#t[Ŗ^Z }' ›c"qKr^b7S`77a >β~N1,qA. ]'nԗwk:hT &1,$4aJCX>L>$a `h?-֫ S*_?kڎ{˷[DGۙQ.u' .d]_緡\ky8S<_(٢]"X+X `NbEuuiit6wPQɦ;pw9k6U1eL\0ኁ*t(LvbCIYacҵftFB`⬡Bk)\eM*Lov0Mmc6B[ #o[$7S<0;ȣ sLm9 d>q2M"8E0|Q By6@_HQ#ħo AL5@ZsĘ|K,K?3!Ƥhax/$["R,i87T`t I{g)#*hUڶf_+A~݀c5Dŕ#n:79RAɹ]ˈ̞L u%hѵ]Ӎ,R*rXmWF,{_~kl{>MLXk#%L(n Ml5[ K1!)c 8^Bt8x _AQ=v,MO&U#4GSdABstH׼5|q&?ŹeO?}= KOxB*u8FV>FE Vɜ zRWSz\N _Gc|eȣ󂱖L.?ҳnE!mmm)7̌PIi~% P9 V_<W7J uI3Nk8&f |ba h)Zn7/,m}f'@|.VfwBT|yD'YfQQ IS%F.ƆGFfDll~O$ 2I[w߸wK* (~!pF=V̬F.엠Vjێmp6 }!ߎRBl:(uѤfÕ9A…U 6yUC#t`M˴,l1O:d&䀶¼<KYo<np0dj [er݈ fF;4]OQXdFe l*`ЃX ˜C"o[N[ $/4* >&np%NӮ( BlBAЛ1aA"L錈d=ڞ#3xe8:7KMcE{`N5wr2p*˃Ju|Qǀhe3B @>y~bfSrS8,ұ$5 RADECђ('=ڂ}[E2n =dxҿ谄m=oq?Kdt$.i4MkEn ڏ@]|2͵2h7FmA #tG&6tJ儃+ 2 4ip {BueI|^x+scQjezn&# _T/_=O*k- 9z(n/@c3i J%nlpf%ZV! % 8 [&X%!! C*WÂa%u|)HL8]^*(2ԖB&5V c!'>sg};?=LWWϜKk/~ܕK *ԲH /%6E|̓[4F8*l g"Nv4&cw9|m۩I7:j7cMcĮ (kr/"7p/݈BeSD^2X%(Q-qbgbWBVX;%"d<N4po$P.Z *52cC0INVPڒ_qYT4Sر#?p춏?xloi槧޷p;O7^@xt.D|ġ !O>7vvN? T{}8 A,!ޮiyȐ'nm`#@]f&bg)?5j#tY40 A&3aT:e3yUR0WPU+'Su'jތM=dIC=#z7WF `Bڌ0!URoDWI'Y}Tk ϓM_|1sGl/_  =?c7=[oO=Շzz}R3zZ\T-n m7& ea#Qfƭ(P#rnd \Gz\9 *xU@y6 b`F|peEV471bzD>w`lUG-q'hZ2DkKm-mHuM@QL`اLa/p<܃SiG'R[ &0%ʰ _1LU ~|<6!}D^;v,=Yxq>uiM`ÐPY`+ D(5|%&@GdSȑ!;".ֶѸ`+ lݱ-2.+[qa$Y)aLY1!e ֠NTCQUF5? " -uR.bOO3Hפܳ#*녁ÁN;Yws Pd %2)\d*7['\t%3@) ߂mQT;pO0]7/TJ$*ep~?|m?XiS?ӿ+ &K:>ҾI}\&{=tD)zC9Zb-f#raK 'O CTɨIVޑ\-Y-YqԩuukMt nlsZ.>jo> 1$9ETĕ!*edu.wH^5z~{FR 'Bdh>5E\Q ^ iUhh.X\ОE%8bqXġƒ mo(#+i9"]Ogwכ4O3Ъ5]rrZX]jת/(J%dzVBb1l%{+:d:ںej}БrADm87uK-0րMW5Y` s*>ELz}`CYUM#D ] m^l3ӢWN NIPjP+n v R`,T LhqR/…O[:pYmLuN6Ij)l&8rǯQ[gK0qWK6|"@_ۋTTrAQ́=zvAj?r$%LB򽙛VkKP?7幻lj4L@f0KX2)6so_T' 3LK0S+ƥBDeTM2fHy1ؚxY\yf`zTtW,ԀӅ,ٗUf/3]=k \ Yt %4I$r*ʨTkg }h`;gyQHAXPa{a*K~CבxX7,5aeAP$Ye2][u=Do4Gg3 ָ_8p/_@/N<*nl"M[QP7 *n-Sa}A⯝PvXd|3V/FXOiRKT"0$O8mBϛq] Y9x"Tqȶ"jL? J:sųxk3(4 FAl(ThiEf5ۃm \U=t 62޻Dy%BGuF]%N6o7/Śg3,h%L#wݔYL}|zSX~] Wa^;vN j}aSBy"J9/ZTT IbhXohS3${aƋz4KABH["pτ@)'1j˘RQd^~ a2Hr4K@Ӎ `6%ƙx0\# ?Z퐰[>̊54TB([7!jD@i>0Cs,!9x@%<H'y1EBD $?}nr0ʏz9a>9ZGHy ^M`t\y`2VPVB8gO}캍}6syjץ}Vh#i# {OU?xFS*Q#:m SLbf=(1bl\ZGH<>0 PMG.#cF'L:P:J}:$q I=0M)߄<1} hwd@ᨫt, p0*j=zK#CQe"' H `ܸB ?"O2c~;fu9w;wH1 f\Rpʰ82ƜbTeV5Q `h0,XKL{?pϟ=q7Pa ifߪoZ;w|@$gXkuD!2ȭ$[kLv$](XC2e# +likܩ>sLY#0Wԟ+qw)i-Y9hweᝠEʛ$T{*x 3' @1CEd(𭄬eTD=$M lOpa EBE$LAD2 :[X!:?ʳ/.(I( wQfR1)턃G bypbw-U>$%vuƩzq^a/jt:epmr]mDVhTr6.tM:җPPIsd&!Qd$bg]z4 XJVVh=WX}Wr/?wᖜ#FQlÁ'WFpX5G-v^lobe,L!Buل!1ZG6e)V|Sw /_zʚg{*xlf7ڰ(o&{ Cv84f.xc!ڤ_kE^|进ȍvKTVMޙӭcI+y&0l{Mł]e2+ yݞƟDJz2jW PR9ՖZZO9Aw-9/<{?p3///\^M˾"3ܚ"egHH/*b }Kǚ A/獡V /#xJcU^GNzZ?_AݭC/ֈj7!20è[X,Ha\gE[E-p:DؽI&ZB6 UVĝ@R@ofm d,rA#LnmUe#ђI2?/`eݫma PS=3k dM n9iHmK 2u6#҅ķQ`Pkh29N cI6\@]h.$lVϟ^9?Нv1]^^yoꅓ'V! p$3} lqpYBmq=5$#>cAk7 "%/py6(p .ܟAޖO}oKO'KMQ}d: ̖E[O`(#FC_[|JQM#ya&GIӍ#&?լ ̮Ҝrn3J1 pD!`::K0S3c<ՠvd2g*MEk H9*]5{RWKC> TUQ7Kxm~RJW61wDScGɏ6 "dZmمċ2:#R>Y{LG/ O^p מgw\fKWמ>yMM'~E*PKjw69F[C T^B3-M //psr NHv>2gK(Sd2ⶼ%㣡p f9ˆll|Uc?.2m6iF_%Uq%$"Id %*C* F5_#F&^ ej+>d.Hͫhls+#= DaJIpF|8~*%gOaB02tpbmª!"c)D<͵BBmW`3;:Bwn[W>wf<جݔ~Y0۱|$C\.~K+z+Y|DWN|jf׃~bw \.>%*~ bAt;nPuS;wPo'th %YR]=!+KODNg ge'o#$2Z(#:Y <%mDml0{X!_d7TĐ ڸ1fS\Iu곚y33%?7w{gwq/R-^YYY>}KKW..禩g',&5 dx `3y(N^7xpq쎹=Mhu0T՛KK++y++v! ,3&o5Tj5x1wؖ>21o'`7qp@O90ӟ{`PʠV|յ/|zeP^G4owןn]|b'y=?߿4W]=IcM+17],˼P Rh@ ˧wkЏNxGyjU3ZOOv\Z0"8+ ˃ D =[-ByN:_}A ZT>_nATG@ﺺtҙ//(C(a":x?Ǖ 2;I@sykZ©L9/PƂ*y~d~tzjvEk'9u/}ߜF5X__'S/~55(Q" vA }m჋?J1yoK~쩧N*exa#qݢ(*koJ>Ҫ#X{=kJ.gDL,OF,1 l%<#sSx;ؽ]q,}_?wWu+gqu-c֚ &Ѧb4碗W-mq>[6l7_gQk)q_Ys+o>/sĖ>T"sQ'*AHD|]wԮ{/6ZO5ǫscr_3jà"nGD@< LJisP5YCP]w{YY:u_[3/F($ z#gPV64BdeT2 1wms߱7! lZw~L-S_{;F)S/>O 3L(`./1=#{Y(3ٳȞ~7O~%}5ʰ6 ʋAq&NٞH%(w_cvq֗|3_xܪ-*3M͚iUp*n8wG.̌^f'E޽N\_~K+˿Мy ;Ng}]kK58vE$A8RG/|W߽~{ۧ r=x=ARtUY-  LgsGw;ss5q7?CDkoӿy;H -KF LȽi0볪 $Q2t@W$${da8r}oM2(D8ѹŽn?ʐ*ϔ GѫگfCE.e̙^J9pcw=tc}ڦYعgagem׾OWN.9fIr(ќ>zPaYϬQնQ 9+A/>xw}Ͽ[_}e{U= u0m?|;ou-[cc?]/~[?yZcqWVVKx^H։An2J\[:z%)l}k*ijs%X ? fѹ:LvXugWNj8q f|½mfkxP)Y b&Ub8)BtL"QC zw{OZG?oW. K,̀O2"cǙn1 RsY$P%*5ɦ63!qkݹ0sܖmTCw/y['l[>Vg>Ꝩw_qzӻN\|MDTf {\bʨ7uwJMG,5Mvd \inxjwtX{Dk0`UYY#dAJߝ8kaYInQ>ZVU]5l6y:w("xU:!Hp+q~ᮣO2h̽CsS6ըKmVkzٰlnm^?=޻cl/>v=>XgÎshJ^O&3_6uwL#F%bfc2(UO2]nX£v?ġ{?z?k=u 6NS&GR B}p+k@՛ן7pʥ {s3o,r\պ :p;cq֟;p^A Rrkѥ_  ̒9<+lbsUQlV5o1ɳ)I7upN-YIH j| tw?w<~=;v~{-!Qx&M)!6n}.ʹ-x2O&|Ë{N\Pۏ=t_x>. @FZ2 Ȉp UŻɔII%4U$!K'=.4*Bf`BFpI0hS=xs x=n?:;>1wO,};I*]hU+PkiU9hUk)$.;@^EjP%j ^?x_ ݏOQi~UQuƾ̨㮏^l @r:2ރ( hR8~Tlʲd_ HĤ%ml-nƭ޷T(A [T>Ώ?û vhqןG~K{9irP Iדr)+3oXE>K9Ntja, &LD{αOҎw߯=wKg.{'{m1@@ b)Lՙeg#ZbP,!S]^juZ]>mJ +EӽLb$ا/?w\;Ay7O&yٖww;t!$Au *@T*0c?bR+3_y۞6-lLiBB#=_c{λu3fnhBW2Qո!b4; ͈$REDw^9兊Eܻȑ!&m_X>nlfHK&a2svH0>/3{:ttjut}XKҺ iy&Ftv{wοp;ݵ@p!KZYwui:oJBCSzce$'/ƷD&!KBI5JUHp2$8gc(;wpP3dg]w|C%_̖};v{_}Wu4*G4k]f({<Cy8pdQΕ%@#yum=Gv{`vz[=ϽH͡gYR[R8kI,Uuar\t.SdF99[h)W՟K-kQH-Arpoqvc#mfwOφ?t7 F`fQã,ϱCԡ Y,T6ƈxqr]&WKY cӽnp_ko9C(2<^B K[X+%`fIS$΁+M}w7]ݙyLɆ鹷:pjkZ/4;£@NL_j|z=?k W/~p$cM_;Ąla[kW^8{A#XD۸e*&G̕sRpy;,ep˲ 6DYGr$,Hi{ܿXomD%*Npu{7~GN|ggX)e~mu`"kYz8XfeM1纃(Iy>˟w";^YZ˙ZW6Pngph ݴjR-l;`{f"F_o=n5MzW30*tnѺjDoNSVC::*j{uwu>eU763+#j8y^wc.V-ll^`%'sMLlsٶnԗమ`$Dӥ⎅CXⷰM};MFDʄEmp}:VUmW'!!_>1™ӓJ*ccb2ܟMȗ;)-߿(\=o`7=75o?1ǩ[)Bfܲ*D*qMznxŲ7&"1[5Y ;c<#:2 GoX_/O>6X۹c߮}ǎv\O$XTʈDYx[/S_8}›W0G<>wc?q],2b&yUq.E# Fy1zXu񇎌J۩7|s._] df]wtѲ~y…A=u% E&@?45Z &~c?ͅq1Ɩ,/^I7иr?wƹ:[F7مq1tZNQG7nU6傝4s/; ›>~&יy?Сzp)K8IxUiln>$08/7_"`q]sxtt.4qSX0cbs鬇EР gz8ʘk4gb.v~`_gPOO;'~3x'gƶX߿g؎ٯz'43qV8kEpX(V); Sy5A[ޚ*D"D><|8ef*?WPTɅePA#k~u[c7""6? w}嫫~>w?w.Ώ{ϑݏ޶% 8X [bF%F4r+o֫ipGoA_"@?j=Uhp;ٛ"xakraZfW/tx4G! ʔsffr 'N=/*0zSϿiHcWgL6l&\{g9uEF\/*Ź0+,Ʌ \F" 6kPGHafA ?܁ӊp@`6 OjY}PuդL/w>$UŐn;eY[_/'/󙋽v̿zue1K|n^,vcJݥ˟ꗚei\"Z+>啕qݳctUfUzsqRՑ##f*0 }}LZJB^SLZ ^ϫ:8?ӯby8|_<Ҹ}1оT/ðM\fݩB!9Ёůe?Z9ؓH+5bopG^>-e T.s*;AhePqrnME]t G-(x^)s %_&<`\ŒI0p"+iӯO;yvv۟;ԟ-aEQYt7HѡQS=4 DIB?uJ`;)K6)Y`17qaK $7jF@ r3o?ry> )ʾ/^>+i+B/<1ȉ-,4}ZJgT9yk}U66S>D- pĦMVG)i8WΐFoy\nu`ŋS8zm됶{Ugh=ݸkP7ZVGID9kK'6^skm 6lܟ(q[:XT\N (ɒ:GKN_VWWeK4T+OsaU9kfjzfj온s.n2XU|siӧƭ:KcQE,1n0^(3]M!QsWvvxSe`$pZ`-~!l#]`~CZ®֮v M=\ǘɘM-X`].cՕJ%5K/^~aܞ3;z;J@r7W*4֝bT]|;xx5"5j"Yq˗簘b;%5=qalO~3e_ IJ ʰIh LZb(PMwxMt兵!gV͞?,-H-th1?wjtqv*ȕ>YAr?oRihQnyޒemܱXgr֤A]&u[vuB~Q TkqCg~;74qS2SPȽ?5wUhD_^''ZQـ3NR8RD QxD*=x@755~*h3Z=AY9WI L`)&*",:wH pr eյ`#{ 2V,0,&SMhET&u&zfPWƎwO,Fx]:J鹓6պwkBB+]VtnV{ӒSM=w|^\>ʦc?wxozlD 5xN͉ZI|s.2V)C'Od2UU4e <;3ȜK✊O=Uy߅._A_e6U5oecG./D‚M:{U^,8v%,ޗ3Ҭ3R3Xk@5aU##*DŽeQ`}oZhvMrY̅>vݮ¸*I]Ӓ#Trνo?>:յ?Eh&eT;N Űũ鱽"K!c|mG->Y lJ@ !d6PtbP5*%ıZCJm>rVّ/"Fx[ƲR}mO ? ֩a?RUυөo}GK o)+8ˌ0Q sayJjo0ȺTp`j Lʹ>߮-1yX6ű8e/vN VbC=y<[$֬\|5tI:R a21STܹ玝{az ]6QBP|"ZW/eL,onW%́W%Ws~\FO |ݷz4_bz dg,MP}w#% Z)Шk'WZY! n|q#x/|cJR^,UkWX_{y}BW/97L#J㼨807&E}CDHmm-\s Hڜ0vxX~fw-tɜ"bQ"AC /LF  :y"MtH8),8ZAUe=36żYb{,N"֋A8`o5RUB YocA>06e{6|_J?Hyu9H$AHIJ[y%ԮU]ZՖ]eZv&\/ԒHb"A$!aq:IŠ {߽IWRgPe%Yi,z߲w.1 ݓI=j'O"J Zc֤&By;jz@Bf$X"S1 Amk=F5Uo ʼnBExml TqmkܣNdfEfa=lmDR$ߤ! Z24Mj"=oy"ҰîKՐA<U+X_ڽNMq:U/cvKpɂëv}fH +0 2Q(+5dUތn&5 MWyAa/z/`J8#;'+vo̽.Ag,0]]{oj_[[B7Z:K:#hGmp5Dhכ[UE#NZ.V7A첌t?1?T]]$j/wD;s=o4>A?"IFu?H])vKK)SV>[2]I‰I^7eI~b|'>p⡭TK]KrO}C+~^9ѽ޸-QH\_Yv[ѱ];"M$kddk8RoV-ݴe8哖ݶs='Co=2dS=2>z|ss_?B3xrLNr0vW,{ O7^b#;(J/P[dC^F ~z4(pMGI9_$ CxJ\]} >Y:Q|a^c?e_v*MAގO b0 1#ι2HǺfzN 83sٽ{}߽6ι_{wD-6##A_~ykN˜>5P}z4/ONKK{eX|0IЧcDbC8?OgZw6 {zo/fMP:t?~M'Ş-~nJP-XnB\<!`xߝŤ6;=[7Xr#NZAL_\qZeSRd˜rB}k6P` #f1-n_c{wfK"bM;;md˷1s;o{P8~w;ŁwȵlɹrzG*گ;pۺVBq(|ȵrp/=7#+vg:`|#wtՅ]=o|vt y&)X՛No ]օ"goNKxnknon;Tj'GnKlw7=w)Z>?n_q=»=/Im瑇;ծ/g[m%L"usb (t)l3BH[ u[~ۇ~g*IY~g4^{ƺSI*{v57s북ͧ#qtf׈>~~Gg.g۠g~C}}8/~t2 C*9qm3Qw f'I5I~G^?-x KSwh<)\yƭ{tg{go?|ٺۼ޿> '>I"Z"_:X1ӝj>+2ue;m D+O}g08~d`?z|eťK͕5@f}CIoh:0>حĚ\@k|W~pF80~t~z}bcaj#{NgzDN`YO0{ϥ07ћD6'fRibۭ̏z ] fopϡSS3<~nuVcGn?vmjGdgkV/~o{CzjY<|ޣzpܵYoj<"V~*{622kO IEՕ)Pn;O\zfZ7dK&7y8p+&ka7$ "BaRrY٧*;?r׆o?6)Nk8j_vE#wbvci'|HCn=en/(N^'7L)3JZ7xD^CX]/MvEĻ¡ Zs5l&+obq/yu~y?t뷥ٟ}湯=o>z_sK!E Fw8LXd$;#nٳW?x^,z3go֢x a) TI:Yź,&O+؀KS߼2q5lɩxޥ%MQ ٖ=+#|ۡ]N[sU^Ⅹs7 o,E,ܜ*;L|FPb8A!fs>X쪟NǩHYxP|Qgܔ3I谇L}2`_ŹPեג(sA;TTn*_zj/]BM~~ūril_ɋ`\Qk@/ S27.M"8R"E" ]FV5S*G.M;hB{~nuJCjϢ1X"b|~q|h+;B%n{!"$"k"4_z{ biO>{1z.kʰ١D'd쀩>y7$d9`[0u۽r{JdL|k=dh V%wۏ5k);6FFߘo|B$|&4&aO9RwT_W,˜j!kQ饘p]4ZW*{=W\3/Z1hՒRytz",y]@âNc?7+K72:>u3Ͻ /~ dP-mVíj vGhu ):,ȚP}JΗYbنV/<ބYդF@Umebu*JIDAT=ʫv~鹳F`pj!wRjm#Rr!jCŮۆ1!43W&./֝*M1u,(!)ȃ4>0vgÔf~wۿ=ð=EDa$[']^򗗾v=z.W++ӏCZCfQVEPZoV&{b5 9es0RIWg=nERB$ZO?'VV^ՉǾj6ܗO]# 6hAQ,]^75"Ar;:`+uYrs] YϤ 7>uß|2zHFe:7{[7ũF!u_T뒖CAc¹?Z1)"K@ JLcܥͮ7f4&g_Dq#Қ@G'M ZE sh=3AC D aK.oP0B޳zSizr(sgƫG?{}F 5vg909ߣ-ʭťV;2:*#痶}boqɜ><ukoL/3W-7)~QG7sjI꥛:pfxꎝi[񟼆"]_xxas慿ɧIbp (K/ ,L`&bLL3zZC^A">thdMo^J=v3֫)"%B%Y8⍛g?u֖ҦRKЉ"O}H Yl/dn\?=-|297|W x {ai蚕/x{4Z:!T#`5-Z'"k~+~c~+oRm_W_[`zT1#x%Kbe4X%gJ`Ls 4˯}yśTօ/^Ii֥1=8Tn˨) #Q4YN/UfɅk&O-olw t/4<p"[ }7{Md;!Pҝe/Xk?. ٓ_;@65C:/f_A%AR SOѢBژ< :;]Ǻ s2yz[R24c`Ir?[?:ڻv4|#6\܂e jTi(6L;. U#»23(Cn=L:Ґfݚ҉~&٧?o @d $&xѳ.|3YX|wS wpGd]^{?λP_u]ϝ:~ȬBQi I.1w+~ wl:;l|cR zhI=2ݚܩqpWƖz#f&E{צeE{f^h/ *J9̄ߤY {*N$qp h'R &LΏʖn~zF#\;s`EjSpC%!Y:˳7ͱn;BrD>HSw z&{.wHNOSC{};RIK/>wi3tEAX%`@rf:=']r 3O=N?6nh&e)2Dh(_wXD92_!O2`voZ3W}쉧WB9~&^ /ܰZ,1g{:~bODD'9;xy a9>fwZZmG[-b93fq.O]##ploƑF=18婿xi2Ԝ'$>d grⅅV/|w֑T4d@SʕjG?6uG7g``[Pcqrkyˋ7\<O#FݣbwFЈ3Y5m-Okď=ՙ|ẹ\٪}^9pᣈ}nPXZ>oJ5k_s?Z>8~[5A`}yj9 $.Фh  iQդ"07/]8|LJ;}V0|ک7>jN^j"w\\Ԟfưs>l6xC;Fb^X_ZYv.t ԓ_6;{l޷~Hmc}i;MWVO]x~rg03hXr hOΜ>ę'gyHh?|Կ}ٗf2.˧FcS4ɷK2J0g pkuqqA5%¸בљzJ~w]\'| +Z+LBG,:m *CGv UG1I0"@nZ+Rc\{ *3%ˋ/Y DE{Fjvx/$Sބ'Gr|(g9CQ"DikV3M}TvVoM8n9j(Q,XQzKrM>/h6sUH(Dž4%f]`8cH;ðL ozc0+קn|?2+{3HV:9kQ~޸-ɳFFJ 'Ҿڛ1X$j SjR\o]ts~28i<!y\Α B(# ,9̢ղr?Wr 'x|sa1Bi F H`..UR<<Cnv3;jׯWg7|L󾐱-^cQq ߤhL־<ٗgE?`#.u < ɭ(662IszJF1g*Lrq€"F2(/!X 0ma6e2Գ@0PР@ WVZMD/NLd6g EB|(G2 S7=D0\r)$w1z=t%` rGtSx3w'{J,=j^]i^=?Q:.g<,RU--+ѣCٴ2iu:8p^d)R|(Ve- ;L}Xyމe8 ])aR:d3!#;dRhULqhZJn1ZAFqS>"PRsҲSASRS,Vp[ Oɜ0Y$O.]I4Oh=S"Ŝx2?Ɯ8($x8’QZUH='k~ue Gxm8|PBfl"+ բÒ Dw(1<ψ2SZeHQc btQ46Va d[+Ks˙],0/%1 :-@$#PUȌQq-rɊ#A\C\!A".bUC!`uKA <u ρiq1:VZhU!6F9C-nގ}Q }NTnB֨KG?fv rO+Ʈ>UOb #xJ19ql*X5,Q S<(M 'īyA|4Dڊ9 `CzOun?y̭|t[yjw]u뗖+iJ1Uc'g @`H }i%/VZg-9`M{2I6PTZg٧׆'-O?ZȰ H$fbs>H.B <Sf"mɗNC~!fqP]*ПL;1(lYd*;LMClǧ:$Nkt7SѽKQ 71׈5^]Zd43PDZG Nif2,c:O8ƔAcvL$#x0 &V :`DObFMkau.2A~!4WoH)yEIOt2Ō/͌v{ûs=?wg{KSWV'4:<ݷTa#;#FfhIbD3ME6 *?HR5}\4C7O -A(tY y=52rYRRØ]!GDNH JbD{fV:$ڈn#vjYZr/l{-$32XJ҆y&J0ҿ.jRM'+hˡhah'B$P`DDNN].l{흩 ]T[IP2Qs$`]1_{8Isw_%XF3Cv͇$ZEnxU@#OOdP^4i0 "[:v%wʹwo4MoL\YX51uuZ_!jocc?C,,/~^.J5 3L,k63i0pɱi*Pe#/Kє:ۡ쀡(P[Pn֌A+>$Fê w18PH;JNrP3<܁Y{֠eqo)M8ci`" t;XÊd\sg[zdLb>Ui.C3i,jPH9A IVH*GI@hŷvL 4XRk &!ZhvK 4r,$ jL5偝c,mmIRZ(l jJ .u+/]H33KWc  g>Fv·bJ$8vmo3Qe;M\zs,k~ȚNLQC9nT0FHI;wF- $#Σ?ŠD牧kޒ { P…*W!р?\k,? k ,'K VA+ؘ:͕ˬ! n9aћ4@QP Uqw .1 36?^vQHL1Ŏq92VDi,^^fƏi4ϥD ]R-%,H\Vg?Eu 9$ 5Zl!x =w͉ipFQ P縵$ީ0ǑP%[Q)R/6Q.1yv '$F~K9 'ǬSnMȋUd, {韌fL MqLgT]V!Zƌ@3"LHϗ0ӄu>;Y>Wx-=^1[T԰O*bXVKXgBPAtb&jRq]x^.擉gliJJ&xF|(PUFrq@}$o[dhA8,f* ${=cWGj  H#FrBK3^ O5::"?`hɄcfL4HF[Q 8 t@_,}+-}ܳ=^y[^vkeQlC z:=B AQx W EmԒZ-\*Jl38I(3@VtAYenGJ)8xk z[EAxGhjPև31+Uy&B9< '-:Kr}{UONz#qcb)i訊LT(QW΁%:Vhtw; B%#LhS\ 3?A W_«l#'/A’HܛDRB6LǪPsF)3DtB&@ է'PS6,"frɷ硟%gnquf^5h91{H)2#Q !8!?2bDty Բ)h/k!h9x&lJVI;0'~z~G 0P[?8Fݥ+F G)`uʈPL|&(8 ڛ=xmwnVN Bep *?wUe9ME8' `nᴦ]%P1tʍD ߱ xvEXϴpMjnp \,rȵO8`"o2+QIw Eu01e 0)&O!2NQ'p&vTDQ愌5=~W\qcvB-G$l t&Oll8 3 AEU~F.7\1ޘV*\iRs t*(- 1S$"Qf$=hQJENRA8I!(p bۭU G>Ev,f~&N$@Ce2(93}Bm+o~I4T!v2H$M4N1Ea6 D#@E-<]~O೽)2i$와xG2K ݒUpT +Ijf2^6ðRpOkk f_ }_Bg$O;Bz >ZI  =nD(?=u}mQ]o߅utfɂ:`5 UDA% &iu+(rSY͎)Vaԝ8ӵS)I4\K`H1')2ҏw' r{փY vb J.IXMvE5td3އ+aFz'K}Luݺ|'.ܹ?\f[[d`Ywjc JES{g^((#)"31!aJpiaiftR& [:( 3 3:aՠZ5ȪP%e4*njb%I8ԕ7EP%taؓE{/ \*%&ٜwƅA:|\%1 !%4H_{i^Ga9ch߱?g`_ _xKW)"%K=&/d*EPD.#hV kldr!g87[,A |MTvSBL:>a 0N۵M _0bG)r%S{Mܱ F@cld#,]-*\ ; XVaFja +T3` LRTeKh4 K#E|!dYڷ}JĒ֊`@#$I ,ZT.m(pD_3$6+T.AWS8 HdMK}$ʼn8l6wlxR+ ݔoĕ}',.+cky%M h4 )ɗY?AqY *>oE7n x(~ FtIb!{ Nm4f #- 7ح8YQoIL ݥ\K{k]?RzYG b{ WXdfW &j]%⣞O;ሒ%< QJl\1GvE'^4)H5Y  :h<%jS46\ E =S}2&K %/ǝR4(F ;[<vFz䭃i;;o!k:lC_mv:vC;:8?8@X&AyzHs/5|~r[MHźADe3NJMbJ6;%YhY^{{'~W]kz^h=qB0Hfsgcr*M rĜIvO@!f6KZ",_(5wha xQs/H> 0@.Bv_"APɧ,D<lv|ij̶$y[x4 |SҕG>(7֬DAzfx4Rh᱊P%%4KL  +bcKרlfoSʜ Ui ,+X);y -a; /!~+ܞuF:KwBđ~b .?2!0=+XȰaE)7΂HA66 HTVZArJW% $Uխ Q*bI$s ~H<,rӚDk1eD]Ӥf3_<f?Le Dd )õQ}ְϖ}@Tk`c7AE"zU kS:z"jk sY>M&#Nf1ED=M|SٲaJ_ ȸކUDuX ?*B"*?'@Z ,No pBfS /Sca1W3AbB, M\ë#N6,g{ꒃqGpN:dRf^xC4rcS\84+8 f{kHThGQ K@@E1l(`q *^iJI&60^BrBEvR;q`]PST \Ժ2"9f{s!dF)2΋&ཅ>CN.;(ɷmC%@&uvs)R됼͛b8"K ^Ieos"↘ԖCtlGq)hlVvFuO;Zn'Íx;jVwq $dhmZIH@JkTҥjל˸v.0#aĺ[Nf>p{#icե53;h/geޖ[%=La8ipPc ,!c49 Ǎ9IM}ݘR%.3t&G*<RrdƲw΄Gv' fH60CŶ` x}7,&dۥ+̲$4"RXLSTL]*GN|t%9RfoBKZ D+Xf *QF=}[G':_5 7徣]rv2]!X#V+2a"3zP.%ԬPR=7Ը+'QlM^ceEgqfux)ը|(ζ[ YƖKeu(XiP8vd\t/^}c`0"2Ck~.GpϡVvddos EÄSCml4>djF"H`S _0LQыA9G+YPa-ܑBҰLdxۀP.ԑxZ)k@`08Bsv\3\ׂz} +FbK*ȞXLEaZz y@drT,:*up8Q)  w͌<\[?vem&AeAM5~J繢]R%]j\kMX}=5R?ךo^OPO{`"LC"y9/Y#" e2u*˴Ϛ}cB>(j04h Pt6 4Uۙeo!#k*Lsi?8MHut(0njAa \=(Ę0 ])LW*8] qI^*(.e- #, q8eygdF`QU#REIQK?56O ۻ@ʡ3 "I\d_IZF=IC({J`QDA$q.%'bbAۊ|sX6(e[BptPvuHlv,S"n%ΙO ?ܨ^Jq C霖TҬ6+4}p|_{flڷj9;@C,e\W(I<Ӿn,MT%@ކO#BB!/& 2B)ca,Mn<ɬta3*/ ŬO+AOl`>-ŭco߲pAM 1ejq,*d1RZdd5 4IFD0pBL-5taw2_tj䲌wG 9bܕ6;oWΐ ouHH]V膂 IֹG-ႾruP'rcdp jUI nw:Rvv2\B]# ~DyE5V2Z;~ *r5]]}nqu#kthgl`B=ps(CY4%)JWn8Ks'C$FhjM*BIſ10@| =#* hc:HƈđMt icنx ϤvT 9&f(-GuU(H,q4G Eܵ8,$6%}$ qT2YF՛&vWBɶYLL:Y4d\茦Y?9Mewˆ9ӤHܑ5{SNCN@h01ՋVG~ߥ"+]YJA񎳮URO VP }(ר{Q51 Nzxe/b׋v245'IWo =8ظwÍcOW^"O#0WEtQwO篩ID4f=tmww6 46h ŰIP8l3&WuN߃35Fy^ ‹NU!@ٕXDS52\T4`N|IȅIk*Xnut"ghTp(LTь E`xuu0d29F%8p!>ߵ6*{uOiVƷ řnP5\qS3|y5=CLN U~q/wh)dD@TUJԼsllOdIx B{˝v-d 3'P3ݡuB޹09 >A>=%hz uL9};;Ȩ-PJ1gyn|'$!/f'3>܀qqk=Ϳ` WbQ&{AH:k`vJ3ʶ.҄yn$|.Z=bf`rd)溌/O%r"W:\E4;3vjzK\X-afpսK_Kw.W5]FmQ߼q`3#vJ{.W"DH7DE"yG9"_Vc11jzlZ#^ּU%l/{o  JXl[Y qԚ_|$?9x8e퍬N%$w@y$Nш3d xIFbFYjv9dyS$3H'L\|*_c%j&4lA3]@'(ipWFRD~XXѴX`SC<#>0@,Zg < 6mZ*OG5;nVt61Y;w|vmHƅg~bq~2t%Xʦ`/NfWPHhye% zZcNH=&)8X 7+?_[nUvnjߑ aY_?ryB+t%XS~  ; Yt\a?|,ۊ )g N'uxI aj|,S<:3B@4ƭ&TmUAiАHGOrg`B#CВ6#;8}(=A8aXT͵6 ?TDS|`+6M8d.h_"oyOkh_nH! i&d. ΢Tc  ^?Nh=Bd8Z'qeǩY{REe)*0C{3a;T=Bq (fg ;y2Z/nRdal$2)q{3C-R_<OcnY}Mr]R +\h`E!q>s)J`\XI6>Ĭ,E  HE"erhm`)\؁mV~}Û.Ł;WjGGg+ri:MN ; "f-(R 1lYat"@ KP˪br`dHGABW5TN*+;~\V5h'L& *LՔ.&Z:67x!G؉ueޗTQ6 %"n̏9(9ZH27n__mQA6$-a QfJxudor6 RL6B;UxzٴS9@Tᆨ@mxADfȥVUVz84@biMjZ <,3DԶ=  AE/Q.Y9hhhuyWi WL#U[i/iw>1rsvr.D@,WfRtHO!f-!$t n WOGWF`nF2P750`l'4#1 ÎEa%, ~x;~& a+ >PIMiڍfW'ahk =PcMh 2a$؎3#I=,pI扩-ӵnZ+d.[TV>hT=ZזU/C1id ~u ;NU?{%Sp>6$W?M#"ܜ`ԒZJZl 93~YCCLq8{hˮD/p=i^~n!L d؞`b-. 3蟵!GB>"R0*$͗[A{5r׬ŅPX]  c[, է1W,dbxq>1]GlY[̷X1 [o}bM4"c#N4RQF81v%40M'βQጘ"5&.4Sl'P11ùS/G ) P+Epoi)c$zKHQtX5[" Lp.Hd,T"puI7f6hSOH`Bl LE!DLX) 1fٛgJmY!WL#ETMfCIx$yk}WPvϦ>o]X9kތ@<LL &vbH\[ \GHݐ#jq9Ʈg xja-,1Nf @q|iƠt$%51&8ntYt?x`Ç?Tb6Say%Ա)LIP"֬ϸ%0ae\BO5KT &˴b, L$ĭ+G98׉`Ё@ !Cϊ_ "*%S'&#s:i itM(7TA <0oRW 4cHr<&SfXeP#"4yQr"ogF'wg!I'[v \XP l$J^2bn7\1yI!2|d&oÆG"Agq#,.l+d}*ZRKW5Ȳ.x UgcGSlJFfX3JffŠkAM\Ȁ\?|}=tY0cl,`5E|"Zp;KbciI cimah?=tgn9X/Rdl. 25)o@=/s_mu( ;kʆ5 ێ ?" Qe֫%o-)41fx2~[eIޤgdfLpC0B& 3M0)@˺8y}y423l}?,:siPOd&@Mmd+`L`@QL"Z38bIE,zdV}`v$25H :bi 8m` 5Xw݋ ~oŊDա& 0f?*%7PS]LTJ&s%L͘gs}:$$a57%0OE#ȌƄJ*K IP59YpNmF dTo4`H}ݤ/hժɸ%*ԕ@|7*miM{aE; PX+*]+{)Y{`F$,b6J R ҇3`"kfڛYT 1wu^nB\wߍS#j:?@LOǽ^"vˊ9ći*Y,yJI+p f]e[o;5ǖن?PPHRm雠5I (L VPQVe"3KpI5CLa &r9vDJ.y08p1llCcE0Ab1붗暨gI]$[CeIbJ9n@ C{zݣkJ@';W| ) "grUsƁJIfjYnCٓDK@3FLQO`Ͽb+gk #-1tyQ<1**}7q|qj]ζh(",/F+яС #ioy~~k9t'&e6B@LF:ߡ,0q~^2$9H''7v[W:枾~~}܍ ~H`SoCn茭KZrH[9Ġ1;gZihw4soI\>Q)L a!~G<~]m=G#ĀcB%H1֘uϵbmeh7,wFgSz2,W cݗQt]0B~6G)ʜJ2cT0Ӱ¢U'4s.|no܀lDBSbC`Dl+eKdю bZ,6G;ʂe#TÐ=>57JP> -ca`09Tu,%hz59#LYsݸЃG[A[;)aZ$T:~(£9 [N0ͅFeo=8θbb %궟5>|ba.N`^p/ bF Hg)DbrD0FZzQ`&{̼af243Ȁj,{(ݰ٠>g#cC Pآ9.܉g9cuc2`{[PbthKJR )aUS_3'؇9̿><>2 I]((`xQFHE0`biCP# &UuM&*zj(q1b:!C CiAYYkפUK(A)T ggvGCOI^ܒ {Ĥ.M{H8(0ƂIh._pHK_Ja T\Xp9` `LNLXS*ڰĈk㷯>+5G-o~6-~9AbͅbnaХN(FkP;PGbq_-KVtP< c~݌e!=6LuZjq[ӃcWP` CX^i&CcLDžR=eV3?"v_XYm<ʕiR1gAke=s K , Z(u4, -Z95m.x?ғ6RPn^ :L*}J:0lr9zxPL1K~&7kB(7#FBu`@@,88i~D*eT%%%Q CGM7M(bh ::h\_{ {d}c+S*ύwp6{NCESE'.c":S"K+T| _gFx߅GܷYx1)M^;T2LRPqM{jCc;v׺3ϯw.)KCE Yya(}o㌼^hBMySpa[<ʌ0=B &^r4K(`1u2~e> [6], Ja,ul/7gg[aˉ[iqch7mqq9J!C[i?THA1 `D!z%vHiz9*|=y[OGn-!W3[`c Zb ʵ0QI2eAټ&5TV9z?zJLMrNuMGB۶÷\0R;@ͤ4\`+.w6æ"1ء)Q8$힔PL%ER? {o#2k)8M̛_xҳ;/Z9{ز1neyX:G 84ݣ%1h`#@*lSBag51; m9nA$aP \&#F"[5T %)sʏ֟m0?+;8$b=[2WH_<\>ro f(kc GeM*'PIE ~,Ss:GFr$4B1LBq6whpgtVȰgQ_>iځ?=e~4MJa@:IGFdEҖfwBd `5=bi5 Sf`.-<3:4F I#3ŀQ`8XvQMWBr# LrE1Fm&;uU8B 9hAp*d&;l͖$pTڐtmִيJÆ[ D憠tPa8 !4$YdkClA>CĂEg[ә^=|9g&сj YX63E%F`KtC'|F_@uίTڰڋͅa` "NOִXb3@"| "4رȹ3@ J4"ޜl_9iP.:R`S68VBDBxtzPf(fizMc"i4ruq1&Vőq|FI/)J+.Ĭ[/<,y4`7dZA Qp`.DaV&_MS!S`@tzn/|cK3lk`S-W`$_Fs>BqhGvm H 6|c`f*Y0ZR](dmxҮRGWST\Pit(-9<3l_jL`F`Q%c5Åu& k@GȒr2%yQδ]y1⼕RB>6ꚶCC4%YiY_bB)k ^Pk".,d}V3VƂJ[7- !v%X2K˜AnQpUmAߦ5UV=71TEh#[vܥ-<ނwy0km-#: `_z+5POkd)4OHڛL7h~b^LwN #H5F)TQA<$-W%1f$%#bݟ%nR?ñ:8OrDK0(vN?A!t5" Mnwhf 4 BS9:%ĒIhŒy쾢树b*EvcL`qb(ͷ~ N_Ÿ. cP], pڄNߦ`l'ܘ>t?Wگ,ljs0^2  g"gu,5jD7iҡ ,4U#t)݈GXm'-k'$d{Ζ(%`hk!k*ƹ`z5lڧ4T*K@қYyMFp#22jD?[hO@Ԑ"y|\IpN:X:^:lE\>'ehA,d+CU@Yqs(vIk dZ8ƶMø?c e E)P P9]~T7D( N@|$C>Sbg@J{a[ݿz+nKcA/T6/YȐ Hzp4%ٗьES)mgpv3'E\P6g{u\.9PP'Y U4%(*([n6vXw/m;-ZFQ@A t8ܥ/oiVup Ѹ{]{^syaY9@򡏒PJ vrҀD5l%9(D,PisEݢ1j)扥[~ӈqsFEVg$*QNE(y,T@Pvg-#[ ",ڨ1S8i;/)e> f-35% nQ&[Ό-u!,Nmz >:{eAnܡmbNhM`@*ҟ́YAȟWV ڼygOQWFM ݓt.,d^HGJ(=%8Ђ;ݾx} `ZQCQnD@㻬  ¼ d$e5!A@PZOܔ#=~YFk| ϾoH@M[s 7'c|GZ#?ҙbB1\KrǗ|rŶybb%Q^e7=.팞Óm37o'@ESDj@f|OF@hZbW3d, B}Vq054xzfadc/ƂƂ"@D*tl1 K`p749"<%]KHN1W|ߵb T_|hC&Lңc7_hbaR퇎ώyW|FiXZW/ƈɻpYh`SQit`lKZ PJ\\aX)]NyYD_Ȁ cኽ݁M%y,];Ii |eF; >cg Eef>8ZޕSαVY[Xm;M(MLg2n0P~I=_[34 ! ݙ'dGͭ5^n\Xc]M>(KoR<O{Vc#( Y>{ kfM jo<(W/ SS9l6!VC@ HW7 #Ƌ}+ɱ etGK$hQVw.G$yLOa "28g xo\ Zj"e6‹gȵ֏+YJ/Y(HV!|蔧 ]luܓ|%S˯YN9N#@h^"Štf`wO+o@C8`č#vo<@VuXjާ@0˴X4PWY"=r@^fO.uhGD@0 &Yh6BԌ{RBqp]>ڼRH \fl߳Ԣ]q]t[]ҚM#X9mk3!4婳R£p% [Bm)3Y uˑ̏~M(KJ*E(]dDi J\$ V0;K平S,,M/GFac}NۯmKKgfm|6vqEL<2%N!i:~EҤnSuI]mpoĸey-5с )5fzhY[/NEN1vsgN4Zrpp*ł|V8jz|,m1@+$-xKH6uTdmE XۨC!J/;wQ@szngYKK͘:q8V <>9yOBMye̿#e7"aslѼ~ye%xr˺_s;Q|l(ߞgaۑZ+R+b ףT/b?YDl{ L 5L,d82,dAQӋH43H!/PW[4Y߁ #@Zp;+bh& 0-Zx8[8A|i9M5|nKJň댪J %.>w͔ͅX0iuF7?GΈ!Y8Y`ێ&̟ޑNDn w$߬IDATC dp SY@6“ޗrN?usIex,Ǿ&.PvAH`WM؀`ik[9N*S{lx>1A5m!t,ZCI/Cxk*H 7Y>drw|zڣެ @ֱptts@.& ,XlkX+iݪ174O'͇;@㰴: iGqn] 0*D$͂t,&߼H/xk)8KJ0j8'f˲|?S<#_H~:sfee%|RDqeZGqn2NzOHx $5/m3n/nAذ2l\I8?{ȽS-<|9lڃLJwjE6-e byDw.6/mw6z뽷ݱ'@* :23~2Lw f^XbR@'K̸`"13pktvT2僸/"(2-8TO)k/5`k4g* !3sR@uKR;~1B/ttDLsOV& Ho:)YݧS#xVfL өp(o0Y<>LF`:_p8Hl7W;9Sŗ6#rUg~gqS}88RE7HTq g̰S>g} -]A>`xessF12qy?'͟?+Zrt#zB[tdNQ8OWSXJC3{Gi6-o.Jf* )rPaK[h4/tu.8O:Rʵ333O)~'~=zTJI@x;~߸ʍ/>kh> <{_CWݵܓ//8H,l9~΂L$N5Vw4+Gv¦{~Ԓ C?G:?wb28PbLU9_f R(rĢ˳gUs,w(!؎l5[.t`dˆT) waӘqͩ^?)rZXb&(R.':PY_zr1\Kb,#Ii[]<)1HSFpacLn&$ҔiAQF0淗FƗ{|J%' iR N>qLR$ivFcrkIdjGav"l W{mgfDX`[x_<9;񿦲m|L,N o5~Y2.>;k :h-}BHh`*bmN6ɐ'yD7gn]>CrD" (@׸/"0T#"vgl+B@MJG-."8(2B [&vQJ>#рT бw]'Ny߸~?yd7_B\c;89hM"\|.=:__Z8#Q+[}ZAojm>s>\֋``|5,1/-`!쟱9;_1G]&=JpK Za VvTf{2}kOg嶋D`+JjÔSIɑΈs˛zQ#i$8VC *B].IFh-ah͘5P-]A7_LY1· IZrAGRL8d#ɉ 0ʕ Q u5%2"`s6 v5SB'97_xx@fB1.U#abCi9tǤ< ְ=K+daqp`,9ky#;3^B/i'RgM ~߷;>G=ihpd*d2>K`R& # Ҫ`JaKÝ1*Ds,D020 8 JoujVJѦ [׃˪1-AR[ -vUw@(H<;$ަş:`CP\bZ/ ]cRLK d˯&ٚz7~я eP9M`g( ^o0[È2R'eC@tHk[i^e-sgh*А0W.s5c.<_u/QHEwʆ> OZP0!kT U8}_u{Dtȑc܏Mo:x'>YVeƎK֏Gg0Hق{Nԃ_A\6,kw#̅$j<\hXxw\kr>iCnE0_)πL2*0? *9[1w1~vu+kXs^Ƹ@)NNjιQ,߉2ilz(Kq2B=q{?-g}wA2nrG#JK0ƞZ9E@ 6͵ȫ\0nٽ߼xms]QH:&Z+J33jIVHԟxbSiss.5g~gw.Rp@2M=rGW0`^a(yrzZQɚ?6g*9vכO~./W瘟+O`BE>6 /"C G0+qYЂS[4+Ư]qiP#)3˭ٕ10UMwʌ)J8@(o5)o21jom^ڍ+&FpIdZ L2E(ǘknd>ژ=Qqz`ҟX{>ntx>PG:RE)OYv2)ߔލL7gfY6?ڜw޿h70Bo'{qn.r~ƅq!JxC 0,KՉ@dRE$6g aKf&$I@M:WU3o6O$94#W>xJD? Zk+C+O ډIRʍ "ଆ!]~#;e۶o޼|}}|0yx YP7\'j *$6,qlgqt:رQh{yʗ5V]O^Sߗ7heY2k#v_zko;*0rwR{́ XBioT]XW+'}-K8KL3숴`p`rXu[[<Ü1PR9n9uD %A6[,V‹{+Qvu*(T|3~yNB()kf'6 }۩owМy!e[lލ(&;:]x2o,’nv<ZOm0vrk9k&mq•wTRCN-83zfSkV.'l(HWUE5i"= GL%A[LeƌTp`,Q$nF&0u÷^cm_}p%sGˏ|‘w3#Gw~[c7u34X/VfRVS?R/x^}q׃EN?8pAڧǽg;XSY>sy򯉙9?nyo:@VB⋙lgfI#槰~)]A/QL S L o8zeY3R9]i spnaܒJvXQmEk 噟z_mm@e.IeMdEKUKU"ξ7[K2'R\=rp9逊%Fh !` wٚwsF/|% PZFJ8kFG#{jG(\x rGA 霊s8 -M[]Tx*:RzU޽kTf5W_3wpz￸y/?:~çj ]u?x=tCWx/=,8o¸Pb`Zϖϸ`vCĪ\fb);wLѾ >P@eWL\EG`]ѯOj61QUдx/}C[$vRrW~W?OZ5 bgoO2&"xlMocx!_s}ծ7p?Oonnw}>O>?~m~9s& ÈJ ?{G/ ~i-{vXo#bXpb)Iϊ[ó,TY+`mtMPTmw$9\ 6~Λ˷+0_?[O|!uR TG~0B G>uСc;ݮ=bjG@Eԗ&cK[Mtx1d 8_586лʷZK}_=lb`2 y#^'V$UzgO;nz&6UT={{_wٳgb(y<)pw4 cϣnQ.?Fr~ss" J)l>ǟLM6@ڶuiegM8ԘѸvKqӨxzÜ{%RiH|Q Bk#dҵ4H2S,VJ[3ڙH EUL)Pr"5բ) g֠kXW4KeE!TXBTw hsN?[7 #X5ļK/~s |^2(Y~~ENm[_ ڦ*zN\~.\PoN:9} ʳZת˼JnQV{Fk?Տ=~7" 8 .WZ?JV{\Jyƍnڵka..Y]u]wyDTkAR`jxO>)P4 "BqvԵ .<#1~ !?copĵ7[[nq&)u ?>>4eAxϿbh KKׅ=TD?);q/J,O`⣓4rg"?cI{zlߌwF) leWfF1soۻJ%`XI 6oya GRbbv)}JK+)e!`JJ>Tú޴xɱO/<`t|"w-MS.şVVYhM}rka(%wBa-aҜKJ3y-ς^FR"_$ kꟋZ9l2'j˝b֣Cܸ>фԺݯ8;_0t)":B5Zs(Pјszw*Dzy1 6j_yo Tq3 0?;f_# 20(;vaH`zy721etR ؑ$O>-J kwyI^*2)nMős` -Q8!Er0N,($U +dΒ?ԜTZ"]A)dn_4Њ? SeE+H[8+q6udܜ[v7&\V:%FD.$߯蝗&$Vyr€ӼX@[(o z4SjOYӏ?s:^*zRc#aJ hԚa2#ٲoW^AOz:{iK;<=-j%u0B8*u .l[;S,{ ݉r17F*(H aR΍ @F2ۢVPEA!|#Yrtx"J+k{RJ&ͽBR *D4bu dEZRQȒY^')z%FQg*֌i͌|2^y= QQ2?G(zmK%T L(E1?@ JѴ76^/=E{Yldo]5Z~byD3v_A$c rqpmOX\Gf\p/03|% G ҋA_@Ok͋B%-Hf}bNN˻rΧS;Ҿ} c͜ 6쯯^$k=zDTup@M 6UL/?3'cV"#'qHΐ!Zq;nG% IDQcI1뱘f,_s34e]oYl&6(n'eЏ,*ʮQ=b 10v͆#8toU*-)] ;U= j]sxpttY%1mez-eiX&ފ><0{$ le d݌kM b,ȇ;]j^M%((rXvApavnFʆFBf Ę$4:؉X9Ih' wJ#\SxYܾ׹|o°U&@idڧ^DK^7rMF瑼SMBXDORdmt;`̔ޝ $_)]In=VN/.[h'X+?'@HF%ԍGDqg[ZУ#s0.} 1׆"z:k#?3Tv g/A@{wyW'QѲ^[:zE?tI{;TZ{fPl*3kJ 3Vr$&[Q9An+l&\WdBl_يG{kPco?X {g&pq{hx*ר k%  w޻M6ጱ3BFeXg4s-Iً?oѣ3rG%XC`|>^}?x"OOP y9-oy+%y@ޅV7?/7P-=PPՆj_ UjYLni Pd7K$muG[TY46e)e) 6"Ycqa%{z.STY}GSI>u,#reeTYAAsc~ėAv'Q@.2#kTBH#;"UK=ƛr`?w|kBj 2EԘ}|}Y7K-No>R}ͷ1w wzyt|ATsY?;iPg@ܙ;[yDx!!z'>c>Lēa}ɓ Ϝ9 / էҙ#o=2 p(0|S~F4Dg\8E,f՞Wxajz% UʴB]Af;`U `a*|\BXn# ,Jv+j8o=rUNҟ[Tުyz5ts y4Jnjb<++2ѺsqC f5$2U'T@/FC5&hF_pfoZ=t,p8 =è0/ gt"GQijLEԌEg;.N;'iER`  W/O<{mZ^m8Ɂݯ@ì}>[Aѕ I)ozuv̑#GՊ(QI#ϼ|ח)=xffy|?1k@ӹR%vv=!b  }*9F $|\&5Tg9J;+S8hm._9s?O9Ϲ jIt^Вw-ؖ[oDFKi0{iz]R:ùѳjm:tI!=?D[2DEw, ,xuj0z7N{mnmzޜШZ]y|plqG9m S1Z/:ZՇ{ؑiF#{ꔔR4J8 AX1aoy/lFPKo(*S'abEwaRڭ9I:EavPYj &B"2VV˱=LF )izAS=ڍ!!lK)M&:na ~L_9WK3PBYT{?Nw|Q9~Ie {O> һ}sp:Ȋ̒O)pIWMm=y@1M[Fdi@ # "A*=JXȻK#cSv~s~/}hq ;:ݬ5f9v'tj?|O>q~06V狠SԼvbl7FmDp2К i̗-%͡>>s>i݈Au?ALXӽ׵u%R ;a:{{cPKO٥_G .7v[gSډj0e ]+]cϮ+]6qnCwYcek4!&t-gxa՝K3cA 2u@ Qa`a:$㴐 eP;B *JQ-S\:[`18rO(%wP~]VݏDp&E74]'r_1H=t#H@pʭB8`tͦ0©1ѿ89R>хqT vHUJL֠lJt{V│!Ty@^+ŵgצ{+ F]lٗ'/?/37!t />ho2Tg|CEST}CFFQ@) w(-!yӬNBvl@Ea2D.'+Aǖ}Hʧc),pV"J]=1ӄGcKT]|.XI9RA9#sHNwګWܷ>r&Qe&W*,&u0l@*-..~f#%e2@}7^ʸJLlz%PJ]䠡bu~TWDvr&L#UK_QЂ) )wFRNWןHfHBӮؼNg([l뗶ˑ]ҖLݐp%ME`Z@A"Dѣ7w{x5eoKGGHq@FʭB,zvA?-'͖0zcL4K$x/y `fl$a&0{."R|ΌAe㾹[MN)2 ZY[NQTʹ6ꮌ:Q{?_y>Fe(K>L3ټb8PK0)m²#3YAk[FfF+IM:qwUcN&lEm~}эF=po7C[O"У?7:Z*BlT8zcgן5:c}jHDbclI]*$szy'[Dx{hRʂ$gpAU5ʧ9!GHRwY=2Ok 6"',LJ 8J21n*YHd^$'09~\& L,%I D:JWi*n%ykݽ9?L6/ْ?''aBbT:;9 w o9V)S;9f䯏'hd](_ȪKp~ҮR(\YrrE3*k1jB{;T(o܃ƾ A97>.$>$| g +mVBn?ߴb|?UP[;DX.\]KweKҤxOՅY$7enOjw^>6UmVQ[ <5+ÿ7<:toѰ19xqۙU$Q .LFKhB(fO jΏmo1Jj**Kw,*SQ徨6tK=p)5; a/GJTr/Uxȯi(KSr?լht\w< CbdŮQ>^\xd$E gSӾ~u8no?zzz/ [$WL506?$!;TC~-C  $$ GU(f⣬TbHq噑ٱ'<|'[Pf#Vq)l}ƫ[͐F ^j )}o`I?G̦O֧9k_j,bNFsךF?3M%3T4vDTW_rM.'Hs O9fjDtz>.~' N]o?: -y9*I~pA(VP&r?ޜP/>lե:P3} ЦOOL6wۼB`&7dtR$թ/l.?ƙ1(ԶzR7!u: xII)75nrCf`DJH=~7ӷ|y/eyYY@MCJ;'L}$2 VBIw醆E&q)||1ɰ=GEg1ݡWb dOlH*cj &ɾ/prx _l{y&3:qB-+=L' BC%U/j2\3ѓv8z I`6uMhG:\]},eF1Z8C?{BGW[j/9SqiMOQͰU#߅5xjQ{xAO5xY5fNOM#%ҡ2c#d~I! %Q]L$Ddx=mL*}ssP_q槶q\Q){2҃&(Kya4ʨp&$<"P΍42T![l]LU#.1<"P"Rm*ȷureH207μH^T{,Mq k=$<2ĉZ3hN2\7Ћ=K$='?(K2*E$)pm{;4+]gs]g>2=AJyqza)III"O162n`qGGg4S?q`ޥ{&6 o[j6>(d S,dck2j5c֙SX\R|r&Pxύkc݉޾nE5 y06ʶ$NNAT_@PWl">\m?޸9mrxM DŽbs$H1N)+5uG0n8c0u-F3q* 5_ꐂ I( Ϗ̏ծvvӸIcĵϼWwzw/;"M64(fuYcRN( c Uͬ&JQ;+ٽD]$}$zz3]yyi:7@̿ 18YwĀY b_ H !SIBG +Ѫ>(d?9E![RabK5Mc\dv$ИS7$Zt+G'z@)jD% !#D$t(OҨxp#9X0m_\>8_ƒfjWO+p0TZ$j*0}a"fb;.1Su0j3~Rfxv<]&y+Bd$QI]/|DHك'Cm! BۀaFjms \h97ް~oy;M WݍZ|{]TH3PbNVt+@@/@ka/Mo?q _V}|NMkׯkrip"3SPaIw q\leznި g= LS\ڵy*\3Y,o~wcyN(zr$U*B| 1A@Cc#^ņ'4PI B?$rú5s,EhVIwv-}QL2|Ũ>֞%TyFL0&bN`{ǂBB")=SImifg,i=OM'HD$.GCRJ앞_kOpk;O=A ⒌`aH_H #~#uQF ȈD\ xxCpmڨE4T'^߻?x@eO{lQ^QbgK&H-G*A0CsC]͗s-Xy$O>@ %6"LX;Xrz&9T #(&);og8;D(,).l@hN u%sfqc+^ꆳZwޡ?Pf H^(*T(gۘk`t9:_k/˵k6i ٱGszpǑ> i*X!%RZ<2B5&SH%~Mwjqނ{BR>fEBTQk )*I?jG%TBMMA 2BрxIba˪VYIR7'AIʒ(I ΀!wC㪤bLÆK԰7Pc%֔ 3ҟ@lp<T ֩-7-?=3kjZnvaj93ѠqAQ@h3 }I s|Q.TT:"VlI`18rڨ_|kMʛsS[Ϯ:ď`5KBl>refѥa) O"SéS-tqG Pd4Ys o,yxm"&{Xni3%`&]{wPX&P tQUvJ  yRsm_-_eTy_ ~bѸ*;7,4v8/n6.l-z\VntsI]n>{iZTuw bJOvmVZ&h&].HMzLҥ~%%V{EDOBF(:HTiz ],Dh(%/oIh&[8:Sh߇e2C0+C:aԟI=suL0 ?¹!*bM@bU\miIzA}Y@k&:%VtBƪFo|J?j?Ҹė[ #^*zx*+Q<>Yg' BQAZ^G##*^7<Ċ-0贖`d_k/|~[fON% \{;WzuB`);H6l1r%F4P @t`ȚHn=+sYUs=4*L@SB5^]5ݒϥ[=2R۽3_fNkwڜ}yڰ|k&QSEB] BPTf_ xz۝ʎhyn޿i>'HsΩ/kd$P'IqIEy@sցϼ\iC86_x}tO/o^^7c{tACe=F{ZպĤ$aGnL2ڃX9u2 >Bk㍗DBld<A kڌ;wtJ2n8tCeCj*t171~E8P)*B\,F͔H:)ҞeS^CӐ#PB.lN`2@4Fh񭪯G<vՀ_>k%oB.yNB$T:y.TܪIͣ2!%%Y&MYpӾ-.i] 9YR6.?xM ݵgojP'{vCFrBpi {s[_.yErM XbOOf%nuቬZ2mj4t{*?5%"9k_܍$]D9}Q 1삮ԼZ°9ܰ[IbnqnLoJ?0}\~u}Wi2gQk?޽Ksm1f(limH-z煵mW:0h14"S$Z !H *s!z[jwj$ukk_z˷Om:煊τR35s<7ݷ BJڻO|ԝMߘ9 Dym՟~xtx֙ȏp\ S.&)06*LoOi5ki}Ǻ+q&'@|BENT~(H5{Y|iK_%[F(JA)E"ح%(#DJlezg"%U5&#lH*{uj;Q> khMٹiHՅSId%R!຦Od擰@0Q؄ )4Xؑ !j =eev%=…J: TP5Z,ݘ$EU2'bk 8$y*ôu2~ %Knk$j.UXL075Yؒ_uijCj@5sZ7G0B+d-VqU#q2!pEGi );|ZR05sop'EEϹw&o(pސ3Ed᥁a `d\+oz7!Yca"daD Yks%d'ѵGƾ4`\=5928gChO_, kͲg}\  lJ] 9/2Tf}2wpbdz%)&@d%ߨ!N6B;ܱګ})d,P!7|,UФS{5N58jV92MI:BtJfH3n:?wrx|ǁrM?5cC.b]y_>u+PkL$B1%CA}Dޔ6pKJG뇤 w8F :p_fCBBUV$^qνC"2,ؒ  PJX DMnG㉎+u!v]yuY0{͘#zSSQ<Ҡg [/XUӫ8/%,3 4JUaԕ@jqCU)K[t׫z_.m;fr/ƅɥ5Pxo",6pBZn: w6 HUϭP>8<:B2Cs$` +`$o f5+mLƤm7ƫXƶ=R8XڐUBxW=J$IFMl^Dž̒8ߠ"%GC8=׳LEhT 319Ⰾ\D"6߹ҵ2 D@ɤu)5(PnSKrprz)$L 'Q|qڠ#u]ܕ.cNE4\ooLm0c &Y_h%,,~O2ɩgb "@,lMWjLϫqexgw[\]W+ܞYHw[!B!dͳ7g˒:k=vCf0N{)ÐPn' D"UL]A@pR $yd kPam4XP)PPZR hW]ŭOB[F d{ @Vci1904B`#cNGT U`&^u*6Ñ9<ꄐd$<`:JaV5aJPA;|#,2M"#b@ݠ FƑx߮!$r#F*BCJV&t%TP|Sņ$uڐ?~{Z2w̛6,o `|)̣) 9w!3ʖ\ E (B O!8Ry5[-1s~sLYJpD``n΋b3wF͕ytѣ^}e w.7έ$vz 8uzBXfkt,plZ.`&N4&L5C`l]NEG!M eFm"6p0 * AYM9eC-UWMvML}rzd]d J$3& " 쾻xU=LܝذQTEQ-JٹX#A@P`jn K"x-%PlfDN:DR&9bSl0DI0T ,R^JW'e.m2Hq)%*,P,0TXi:b ' L3d(b[X brMHs2mm.TJHS0KYU[˕}On>4v$,(|],[sNIR`Ǿv] X.EkF VCVRc!!e{:Վ6tj7:z2ٜr1 yU G-Ȥd#!,,JᏟо!5*uF(!۬ajzt0uwFT??V+l2eTDل m0rHuP&E1NPI#? 'bXE,?FbWj!ڀ*B< b`5$PNTA1; 5 diW:]R P.!Q`gnspΠiXŠ"(6BBF,=G<:ۓ筃492A|MP׈u1,K+A8v"(e@p b^VV]1JCDn2a-W s װPX \PiIx:b9l ud#ݐF$ޡ"pJ:̲bC[[IMS;:re}U;c+7tK\FɸO&}y'wž;'%=^T8 dFhU^=#tO0]Vmaݺ%k?X$(Q".$搜:!I."7DR{Nw8$*Zzm3/֯Hu<ؿw?Q 5lge"}\sg k:ZϪ#< ޕA1|(L#sAnD#M@k\V(w_PW2J`Gh# _mJK:jkTxݰ)splѝfitrM ' Rg|w(T?fT* SP۾g]Mg?7yOR$D(*)r ڵJ>[;e:K a^**:,PTt"#" 1}~Ih  zjCP˫lmG3:.ͨ`i|SD`Hv@,e\F!O&4Uh6T q`%DH:TPTaZH&7gÆN;&xZ: }J=_U! VmV&(^266‚pز[#"2> > 4ԤWB^*<zxu,HS X/S͵,kZAyMch2>Ui C!%fIKy%lP=2 и WhQ _Ǝ3f/|˃}01ǂ9{!bXEaz2$d/Pmэw>@̼|BJgRS]0۫wkl'}6V2Q\EհxGc^,5,5yUU &*F(D3z' @D>U߮,r E*:5#mԮ폹g[J"p2\ʘLl_%1ջ$G C$dBR~!S ٍT6q_33ig͙ y$jmUyTd|Vi]y6ӟ1 #[ ԡRtu\pZ KL) H\#ށDJY *|O O] 3W2"JB]ۆfDS|ODV-G%`'+ySDxH+ŊcXb͆/4]^PMUQJAÍje4w&8n[0,?eFd⎧PW\c414Դ4I!./JE,dFf5^׷u*#W\ͥ ] ) ̗HPJ;$LUBlHpVj )`CPGj}j F|}ߋt$By;bA俓ia s&- S/ܳW}u J>U] w~׍9Y^#UtnJ!cY"ɖ,4n2Sm_޳H=K o" ' uePYiD&f4pqHӝ#% ?IB C=J~BAH<nӕ-ѡBN!`G}Z6}2޹#oز[׺G> ("3?ƅ.'࠵u% N4Q44)! J9='5:Ri<{)nN(*?:*0A*0ą4R2]eVCr D*YH!d~^Cl @hĐ7 xaiCS⥜C^(C!P+EhOD4t(SPB 3\ PA.O4G׆LBiJ0eE UlOƴrLN@E!Q +b#QKWk^~x|¼f&8@ (Hmpz(FQИz]j_~ WjH-tqv[&B5_LS4srX&~5Is"3vUuB!)3i``<#ɐel~A</ XYm2E.9܆nڷo͌cdF9'"{;#ܳͳ{ï&_?0Y/7VhvcVϨ `x456< c Ř- ɨq:ͳӗvͼzd /teރ1:G@A BH\UdQa M4DhMhi 4U,a'Ӆq/9M[GiUڦjD-Fj k3!­j}xkRQ Qb'$-=Dh"K!UB%;|rc(wΧ%  +&0kv'j[4N1L!T ա2fasliA}Ez@#%4Y\e9܂xq΢4o p9*PKdKMc] t䬭 |ZZȆchvpћS?C}J%E:5?47|ٕU@OU)8. :.r5l4 U ~ln ee;t_OQF7f١zنnxp=E 0PγYIjk/ӪK&)K&/yqh۽Iϸ\\oNo7Xv_hr8Y= c2cPv|ms[jxXCMby#$dd_dDIK(N7QU_[έnS뗩1+!B=U2\2$#dM$v e) z$I. Y"2FUcShbB2<_Lps3VE. et!X~4Yo26(@f/(/ o`w6/'WJ3UeX(R[l8XRh}[ë;rк+C V6.'EH ~ΒZa-k3Y$ cNR9(RёRMr>rOiB2I40DRS(L1N7O-Ŀe&0Q9y9b ֿy/n>{/jѥpw~j|V#I@y(QVyI;LYw&W?gi$@;cr&D]iqarAGǃǗѭ ?n=|efk ŭq(7?M0e}zrnT-*&6;2(eBZ8(> K";=+ۣ]1׬)UT/i*叼-qVm5,Ž8UU9 6|AǕɰw·9KI۶lZG!lGi:wBh;>F4E1@VD⌣*6KΔ-/3M|Ŀ2f8R4 y wURMM_ߛeNɜFxђ"|ią0AwE1<e Z $Qd{8z/.z7m?m_("zpZ3bt0r eyJ@ >_}[w4j˨8nPCU{RSł9Q??! ޤq<4{#K; lN:.a{C; rf,[i3Biprl|d'zxJTM\[=V>d O b5|7nɾ[Qn~ݷ!~SW'#LT#Tc5ZnEqt0ĝ2񤭱[i&Ez!rդ !BQ$\d'ƌ^8i{j$6aհjj51~eS\[<Оv@ɜ=!s"5)=6dt|AT8xN%SR,N)Xy DcG=4ibNzpP<ƞ1qO"R:wZh7#tn 2jfx`tQ2P$,Ýlݭ~ZJ eE^|_}]|#ǯDٽG7oj ix u[M4EB?y?v+@F{*mUȟb(dR<"d$nr CKj[+hؼux&GX tHZ\-?O*TKQ'AgG¹k]wG*GV1;*AhU報uPء l4Ks̠͍?Ė!Qr.醝%6,;e'ZKLe[ΎWu7. S #+^ߙI(2S`Y`I)1O緀sva޺( f~sdE[ٰycjӺXE Q5+-ݿ;xt|׮2)3+2S1v]u^zԴ͍^"lzԜ/.6Rc2 kAAnos# q(rpt_|/Hϴ7|?++|WwwXb ߵڏ/Y=hI۰ZN)~~ܑDuƃS\-%T @`wi`Ҹ9=C1;ۢ\gl:PdOLe+/eB {T ,G1Z`QOAENCʏ4blYD )N+=Z_PPyD ZV u8n@(i(@SYAHhu’zg/D+ P Prt KſE$0|,#Bx Y->C=L%5=qVFH/{w06MrsJ-0xYMFltVW*Ik~?7s?|o<װp};> YM4,# W*[yEõqH×&\Hy&.rQFG+JN <@ybEЖTҒ{tSd $?&!Al!Ub#$t…2WR^Ûz $EN 0f` /jW B|cG`yMz gS)@ @[M@5d&1_4 DBoL)1zJ ="LQ:K$2" + ]4"gbn.tlg¦t}kcfpwd={ t)VY|Ǐa<_slA/[fﰺxyv;\o~yPSJxTqkp1hL$*"Z71ZC/IS~J8]MxNX05WCOfj\Yf㈅Djb &TK4c0$$θ PN##J N}X%lշ4oje9ő83){:tb4L^'Ye).7E9>Ect@,ݸX!naHQ%͍G)inٺ)tn@0<(/2@,QiϢV$ĞQ`UXq@|IH -=FzTT&49!H[%! rLb+Qz,QUE 3 U( Z҅ ;{X7ߗLx]3_N b#bx z;>_HPpUϼQ5qpBEFۛٗ^5mk?ׯK_w+oE}D$+ٜ~s{6&>oÿU {y!(3''pY&CLĎT jkMz@UI2I\ȧTVR)0I(&%w>WswU(r< I8W@-gdqם9f -h"[IË0$^HUd=5)^DcRȽ׵ o9mZzdf_,0Ŵ)}[R |]ء^>3ـ8yEEf  vn.|#}2;cˠ0)uգlW'Փ8\;ʵխKd0iX_kb+*v@ B|AH,E5_Ȉ7S-͙= E0L$qcw3XzeC3 #lK4xR¢K Z(bD z\佴5|$+<ĵ5pJʑ52i6iTA=(dU#Ԏj*_ҩLF&WO@hLjW|Ѯ9 eA@,P_#aFa+SWQPγ93!ZѓFx"ÍY%L+KW;=<ﭱ".߄ هpq+l'i}kw'{bgTgk5l>w8/ҖTmGާ//ޖ߬T i&1]4ɴ*x#\'<98iD~m MաAi23K [pNkHJ Q5 uÈa%PYD*1'b4Pc@P"6<(Ȅ4O$0=۠m&F/C! n< W6vrx-iQHJ ohIMK3P[SC hl/~V(3rE(=Chde3gGχgBz/gP\Ѥ\ނބׯ¬hcxAKyolN˲y݃?NOJ:!-ր .]["de8(mE8xUv$hLGb8-2$#ʎ3\ _5,|FA6"a[ʎVI alS(1{ҪB_ x%s*Q%y4Bdi}R ot ;TߝO4e|10JFh ^7v;6No^_~ ;pwN&.|щ}|N8oM?ld ?Ų]'5'¿2!MQav!'(rA"v7Tt?pfPyaYt\чZh]TTX yFAYW* 3@ #+?gÊ5jOHm詐$p⠲ 9)P1=&Fv?a %GM2\oJ2&(L';n%ͺH2p{pI9$xGCWÓ=jH"?EݠckA7IJID*-/S O9z B`ZMX@HѴw0qM|Aâףzi& {ռ%867]UE[7rA&l۬YbH$BFd˿&AKVOF $%zhrnNZ;3E4eQ= + {xk۱N;%^ Q9(Ɔ* jᄻń!K +N{̲R~ce7^(J >b4JKq t0*2(_Cf&תI!|>D&Qkω-Cryb6i ggJd-\m %(]u{(xVFzW0bf?ɥzyRH%6x>O]. |> S(ҤĸBqjqbxO'/wO_^H&_7>i,Tg=Xj`-D)4HPzjIZ:{9 >KO! +cr3XqKW PbfiÚè’i3Oh+/ٻ[9L2e(dyfEY䙁A DKpmxz[T;[Ngc(mߩA.[Qv᧷K/Fh/F'H'o<ݨi:Y{ mW_D<P_lHF[&ZE^#~*AϻUD'P"2ԙP#} $5ȗPShD30H^ߑJIM9G-P A[IQjև6)˟wnN0E|JuV܈ :0ʚ$  Ć +0ѧW+#`_bONF˒yMȮx:\Շ:CɌApDP /xii!}'h!g>G3@ºkZE,GAo;n; D0w' lӀ^aT1"=*a~POg aPV .lHeʶ0+u^zI~Wubl8S[YA_A;[)CdSY@N,ʚZ/I*jmPYHá $$g U[@I% wiA0GrUH9p{JPQD=Ī{J7z)qm"Z%Y`\Cj8 P]:ѳPOWlli FmF#3!N[L)l)[XqO.ՅBFKPz[42>dCo\YY}PXo#,23`2|u"LvNSVv)pC4 )=\Iguu~p^4`?rg'\5&ЗЧpFMd8h&QUSgTO@ bt3)vG!DRdM 4NmrC(&ԋas /2#c|+IV0Z13Hg;(ĿCprT TfBpݰ HΪLŻtk$jDZeN-;F[tEZ-!-˺ $xffkN/[^W Na C,K*[ߡ0Xc]+K(=4Q%ohFa47 K;Ryn~!0EOyZyd'2 >)h_|s0( 1zAԅ 8C{ $ 3M@TG4e<pyFpk?) 6-inlisBR E_7 LD,{ a %^z5xr u9 p% X>j[z'Wz&Kzdٻq]{ w,!+AoWnt:`-̫q[|z΃*I5[w޼Vn;ڟֈc;O)֤]JTcLPPhFD5!uG7')N:\ A|%HX'+Ĥ\OWpP$j9)Fԕ%B47wRETG ݵU Fڕ&ZAH%FP *5.Tjզ(u%꒨h>uxP *X7=^@Bɀ9-Ctv\G!E.U&c(XE/ǺAեuNRߊVN~ lb&  nZql\*҈ dZ*`p7Зdhy:B0RxUGBoh){Jڄw,"x8k^%$n\Һ"7/"h~U" B,Ag4#?# R^HRwHq jxp2q]@&̺HlUiCR:]PmnFeC%T UeUlu&Hy\R߷"/8D_G%{ۿuKr`/بuvتW¥bF?5@\!!"(r̳2w Wk\wXs>\dmGAiQzՠX%ڪq 4x&)N$6BbKHNg Z?^`6![,ߞZjI lM_:!%"rSX:9T.-kD}M|n%D) "] cX#p )VFkUtE>v/:5_\M 4/|ʥr3nMZ]A.oiU(ϒw'+>-F+N{"KkrHU^ƹDDԶ$CpBbD^AG$KKCvMEUA9sS4a(S5!`4@\U/w/g!9 Q Րõ):H `ibygKC%U[}qi#K>QRe+E|1dC|_KYSߊ WpjO'K>UOVvӧB2t\O]K{1+b'jcO=:jhe),8b7$at *X_dBfQBQ*)׆yb-ֲ@74/:jHlGVs``uƋW9R,8"-%8iGI^@! IsĨ ?ItaTFqh^LC$-ѺL A{9BrV6T?* dWg:Ϫ^8ֵ,`H"7Ԛtݞ[Ѷ m/|q>6c[,[eagU6Y/ϯހ|*6 g {X+(!YLl >„5__|KBc{9?-_YFP$ Ak*1{Ru"9Pn-`䞼 c Gʥ<ۭ¨-Wmbm}HiG#|{ic^( Ϥ㖏, uH>xhkIu̥s;(`LRIQDTHg͘Au2~GKPTJo&2whh[v:ץO~ }Hi_GE/V6a2MA) }%{)!42 D #h&İk*2O.;d"ѥLhoCѲ.X`Ż5F,aܒ Ft˖ e~ .C&M=EH)o*(nJ]UuAzAS:d[!}tc.٭P,Dj -El&Ee_4}xB05xO? Ο` vWNG/“5g ¢tqY &o%T*dOZJ .9yJW\ эM%' GgF_ffq$Y; =7MPYH.2s=E#$-V[QǦg^[;ȒkWY-)v/S,{8K94-[n[9f2.\l^&YwN"8?9& S`QcxKJWyVX4bVsgkfeq8g [NRi4ŷ%Dv DZpUmxqn6Ѐݎ=6HO++HXR`&?#HƹP-Z'BkPJr6G-=$!V FQ5w`uo)Zק% (M#A|Sn6g~J;dz8kpm˟gwo btnm8Lb zЃ#xfe7/p޾ Ytctb 2K7/ntL--*\Kpq6ratk7npavM` ?5s)Sߪ>auONw֐QTEf( SCr]7)eEɅ[ l?):ѫgPkYS P`K#F؃=0adV t4&'a)dAiX(6mBM l(R*ı'*TWXlR*MR0;],'=Pݸ*c0hn8Q³D3[ s>t 3lu5=/TYTeIw-``xejb'޸ޭ}><:^ K5#puo}ȳ՜$72W6s2l63?•ݛ`3OljNBb@zn⍔J. 1I4r'T{B+Q'%AWb2(K7 ~# 0#< T6UC2 q;P"arn%[S(+AuA|| sI牏S0z3o' ^(ZP'1,Xdh `IARB ^Reܗ qDE5@LH+lM2\'bS#Ov&+?)( uE`%耹+jSQ_Sԫޖ Ua.RԌe 3*.;YV{E9RĠ2z. 4TM) AC^@ ޜWu%YzC&?(mm,H:N֩!ZMƋXFQXiP.!~0W3;fiFEZKz7DF }$=9B`F-$uEݮ6!YEb։:4X9e}JƉK'"bFЭ{,G؞%SujG~Q?ɼJ, "Xf{04iLdh;^R,O VG,5 XT.:*4q*+sLP-R*bF5K(fĘ)ydSޝ,VW#>T2JvF̺ s!Id9^+'<XKtre/G/W5e IШ}.qX&LfV^HC#(c8XOa&)TQ=a%Ҋ?eY5 Q$eJKY3MHDfg>l*4&u2ftj V:c96YA#뙘 bWe,/֋Qʧ'S2H7YD o؝B$X@wf6XɛUӄI4Z1-1.^>zv9ݖ>mA)ʪ:NK Ƀ@FcS@B>kԚEJ$]FV ! ${vq-F^{a)he(*u%(u O `_d }@+Bd]$&H) m%Cx'224㝱qX y^3͂i{\("S#E)xBDSy+B+BE[JBC`h{rq*㔅޸ʓ$`Jt6(aY˒V"k`kK3AǕ%܀:$<+By4_D-$b Cc:a%g(M{>wPTk b5V (UPA [ɡwc&BA^ԘM6Q/LD^qz-xd 1*y:wLDHrAnBeh_ɧ ̹ hGcצX$+&eTP&PkDdgSOy9q;UU+ĜV"` 3(Tԁ0W+}t()O Xk8LsVg0/ #50tF0(? &n9_WNjVzI) )>""q"o9$c(CQQtɋ<ڣJ~H]TWj%) q2_*W'H,U>UB1؀@^4B% E |6'$Jb r^=B.r$lFi>aySStX|U壔Xʛ( 5ZM-,/YZ<R(И>I%ŢVnY6~'JCռbt^#(c(+=eEUJTHw#hXS}V$( ,%Qq 5亄,%amß@87Z -j`ƖeL"!h(e Ч(y_z"KϢbMDѰ,,l0r%21@K\.j83>Wg7B Jj!;zXWp CH +g!-,S~Iue (SP*GRLh1eHx's"@"S ."jObnΈb ,К`syZI 6I3 Sre ɼ|(Ĕ}+S1NH WL뀭ΞNQ&0|} 0NSǩJxa^Fp oG@MI֖}m;#3Ѷ/qɊId(BRZq>hbPdO%!tζXLXPs9U{h+1Z R=>IT=pU<0N22+̥a dlP!Ӕ+PFCkt0`JfTmX;&H FǐLbҚ'NhW(F J}Sy9je-հ v?Y&>y`,@6Mff%jE-OXg^%&!dfZJMv hؖMS ҂M-õktXZUIah=Vnn'':*a[-M  麙?|"vOVX2NSg\XExF}&@*i#zHP'e-/(CY(H)2wq``@!AN (O´1&(b,Ŏ $9+>ҎM~"UK1DH(LRI{WM0 D(hπ,~;~]IVWce=2&h_`F걊IxVɢ5(C2 oQ3ԃRUM 1Z8\B_j0̩% 3LxH_M ؤ2.G'Uꑪ<].a˩aVH)CpfR'ݼz2ɟlaDUMf^WsR4 2+l Tn^`C.LWB2kAF`_oʒV5$+ψ\E͔婐ݲUKT쮉;RT) I&)FpV(9~͸9>0F?X=O{T*b/V썔,R޵}Ns K9*YUvNzZQFjZ^Y:VzZ*몌QQ{Udo"Ը {0G3kΒR.2p"O0ePԐ36OI!S?T;)Aąt֒2$\}!uf* ":鎧+hɩ,xSi]5ݝO⣡y0%fE sr+/[&tyb- \. Ga9&Y%bQ$JsS@^UZюr) ***miOȸ)z%\{=X_O^.(,6UTeÐ'$jf ܹXd y& d"R F&+z*H]N9O֌ L]51zTآ Ck5rŊئ;Zʗ%e  BǨMB'ff%JKIv7$ .RJAB_Cqs}i^/ivU`)ҧX< M JU @w ]}ӏ+\!O>;H]Qu% Ah^R~<4<XSbeMPXL{B::UV݈ T]w`ÿT6tӴB2T׶I5^jI/Bᩚ(jQ';5k*J2+ʲ3FYN-, eYAZ}jUI`lX+B ?htȫ= ]q+qcم<|kw|`,1i ժ=vyE8ZYJ)4ԠX$/йG"[q{NwT,ԪJI Zt#㱗V)Y9k R+][xji&]:(DIv SZ^ `9 a(5ˊ{qtQvyO@ a4e`S)[s*WDcQ ,@;=ӥr}T9 =:ItK P)Ly5V '{^wekW W G^M ߽Udu&pKԃf,ZX'3lOZ\#K ;dIz`Lv00gj3eo{ KW9JdEv5[f[s 2kv2agd"J>`:ŢwʗcXkY'g~еI3儳E;`P$0r1BtRMJǠjT)liD.gzmܴ~KAM9o jR.叜5H;ʧO3\|l_yyc< (.$*UIDl Z+7\i]:NvJx:t qabDD\k=Ea*oZ=Ij죾Pk!;H2J:trDI_jt%uƗdub[Y0 $5ODoimedC4U]862W9`)ɐ[VgG@z2#S#<``@`[!z|~wHI IE;KHdgI(X:dI9>pU-2&'m-= lc;2CsRÈIo)$WG]9|X24޸35fSM㺺V,'uLF ;yTnťBC*hYRf=Zk1F؊^S Je@] 4mZ[VpD !IWS pՃh .Ƿ4:.!څm%Z$F|tǸgpj{<XB7Wm9TA+J/ɜ<ʋA09ĘVB§feMt(\݉bhPzKqh Kb"n DQ7BL}R);jJZ\f>xeK%@eiugᓀȘfŽ)Y:i2C* }5qLމ0^@צ6RADŽY'޶Tf38 mcaE_xB,ng#Ǯ3S|U=ċ@s_>Ef>=ȩBh$ f#\>Ew<2!H$c A M?H~/ `u C q=F mM´Γg?1L%=1`I7Զzn{!PI8Pz#=ǂEzrj+$m`a-b$z I*Uz~3ZhUF3ӹH Z,K Gn*nR231o4WץU”DUV3&->g3,ue2I1(S"H윲$̯S $ZD(#4O&(ֽ\VDZ%-0}J'l/Xx0wz=! \2pdR1 %}"WEJV 1ry*0CVCyBud =AL:YoCx?VMY(<`TRC ^$H^LU6y4@`ehbX$ȶUy܅D+y㱔Uӣ;b ϭ$H Mx#Ml}F꜈'oHFD=/٣ bT U5VFBF${{;²G+->U6āx='~jԚ+Q{B}|22Sc\[:Ss5dx`Gh^wd 9`'pal'Ou =o:5S!IFrtXX2ُ,y#(: d{QyI'CAQїUj3IYjӧ$R>{mz%-v?v*bxtg չRCV%g0\(nԹ%Z'%ĮoVc'[u'eAt|7]+sK-bc[G~_Y9(v.O&LR-lY\{a q獈#02DZ4Ysy"#\bZm.Bea~a"rd˺ Dq(#Ɣ(dw5 ^@Fg[Q  tZ"煸 J)x9` k+_+gbSsC}GS %Xj;^ʋ>cBS"9K g+O6 5(8Ē>T{Xֺr+OTv({l+FĦV36z!E1V Vvx8E&tӕ!.# ,,J8Sƣ F xA0A: z YR6ԫ 8k!,J #C -J͓n]2KT:63.׵t%E'-aŁT:0H=HlM?7]/6#_eϗnWt(RC_d$BZGh*%k+~Y/b#1VL֡}j$ZÒp_3HPSD`=盇>į#}9>B^Hd9#R[jQA~-{KuEh4qw^T7%sĮieTO20{=#&c|S^c9BXb94+|X.5G1+Z []8,.NW,X%H?bSVjS/ABc1VACZ˫g$*pO9"}F/hrf!7輾e ARڤC`L*"T*$mpBZ1$XXWP8u6,~v-{|?:&CG>}.{=х#~gUWqê87<羽o^AH1ZrKW/t[n5OEHc</tn86GT-joWJ0j=6jv|. ϑz`&N~'Qjyǯj0UFQ ߡc󝹉{'w޻wubȲ[_m7L5B?pѹ)|>MSG!xYWٲzeV!.,=qt;ܽg8Y4 ) h L?3$/%L/0llBDc-ۏ*y_zHs<0NnX嗝5eA* w>{~`ab(Iao߰nS4$A?2N"VNm^ij;S7uv.yڡOOݨ^3s 9 ~_prT[e^P9}1+ǪFO#ޚqv W3g_} ,i:dBʘQ`zgPuVo=/ɖkuwˎ[ *Ѯƈ ~W_M[7Z]ާ`=>2rʕ /ؾwoᾇ3YsjWa s13$E/6oE;&_8F-+퟿vӫZ{%+]h e7p5>y{vͫ[G7f-}KCbOmKj7~vA+qN ;A4O\4(3_?% 0x;2pik0:}7}_:ȇ*U1'4#Q`]o!>;͆8;lyZ@ch`RZ[:?R*›W~BdNPRQ\yUת矹rYS5*>82 Ͽl5pgl?OqYJ7L],Y'.3e 3AeFZ[[n|z} qB _qO40!R*y+QFC]5i# :\*۔rM-55Xt :L/:8GGEdX( %_~kIq)wV3wuzRӛzɵ?9Z1:8|vAg AF,% >Xm(E^>OC,~~Zsch'rO;}ĩB~n5,&ÖO|QbKvu@{Q[EرP"&dVIhe,;Eފ,&BW-l-p/:U~s~"ϑ Pbzu3ph,ģ4d*2h$2[3৲Dpg^sڋz7'0[]`(ZCc[KXv764^nOKjϳ4tu SγVOrJ6{ ST`F +uT^ycp+L9c(;x4Rz:i5FT2oIðuo06\?#6%GΑYYZui3貿RIj*m*C=k[1C LM5^×+3ns0 |/j2_T/ a=' q4:+~䢕=J`gAbsqL =Fcŗ=R$!F~T @) SbkoT "IRļlCkәXXm1AR(F@R!+J3r˖~zcvO%YM,5+~⹗^;%KwKdU&4&!yʥvq]ׯ< xcµ#% +j á\W?GNGGǛ^oC _YD&IeKy.~%&37sTc3zdsmwχYʿѿg}`Fō 4)#Bg*bP#҄lAbV#oZ6CZX=F,Gjwab˹&*2nN!%ޢ(~X(FF(͓X<ѼU}uq"CRtC\kz1YN}6q3n g/S?el ޖBX=|'f' ZxieJco=jjUӯ8x|Tk@ӟu_;wp>3FS%OL S||b:v-.[_IΎ޲vѾ/vLL>4\bH:>)eD<\"@ު[ׯ1U$HIk\(op**chqx@JyV芵MvfFFl[<$hE;ŦgUq& *!kT=u(BI*Dպv>i*Kޑ|9G!@,;yB'tBC>+m#!b( oz݃T.uIq݊3XW/%o@k_xK&SÛAy9nc]'w<:]>ȍW\v;ڧU`ET*Ir1tĥslCPJfǕo/Ȯ~_P sj7\cWIs UGo6eD7u .#C`a=]^D#ɞg!ԡ/=j83;xJ˸=at dVAQ*V^Q mF%\a-#rgHٿ?wxH{mq恜{>sAx >oyOO_=6LsNJHXy1B@~See߉AZv |yW0NNQ租`bKspuҩ{׆$7PBiФhL8)t <۱DkL}+Ȅߟ`PKsgCj*Ԏ _(bUQz=;}pFPrߎ;y :rſ_<qi1 U^On<4uUfa3w֮;:-^FeKiὒ LcyO#C㓼؂!@x8pxo9 n?р2|шte8\H,}%8iT^?LkmA Bk_R5zG'sہqtǞuW.kgteIOuBU+77gDJ>9uJfCV%xZ>953bH&FmrTx.qT&,IQ+bMs~ltFy]= <9=ox+^1urtv1D`Fs  \yS~Wa of2KgS: Z>O2 e5m#HNt(iE/۲YMb;+NTĹzO_|Zx7:hF+Lz:ٙAOZ=lT 48kV֨Ã&fKo 4Z}i+ 9t]JH&$pt6M.Ԯyښk 2OGla\B"LP񅻏<6Zf5UUD,|R䒤^U<ƮX9Z?:V#'^0UdX#Ȅ|p(EK!H?&lm7F ϻ77+_zUz %?}9Ooki2a:z5Km :gs=}1eA,nX1\_b#SnǛvw|^HͅiNKC?cEgo=m}93qxU(}IkW$e ߜyͲO[ aTv)璪-fPY 09|~@uj0AN_^EWƊSN {-"Fom@tl[F2~؁NQ?gEgoXwv_Ÿhvn9Л`Ovg rVכL'ʄ 0v^﮹BޯZ>gK &t" mT:J=+cׁz V_Yuw6ࣛ6{Ǘ|[{yg]4m/"w˟۷?图0_~]Yc-t:w=Wy@dž[\tV.{ۏ]|}a}IXKfVZT#fу]Ϲ{g4=WDO+kwoӔa^%WlW]Ngg>!O;MV^=}G8Phbkltܑ Qr)a7^ҋ;b_CCc3aܖףճaMo  0 >Bg(fh˷<7;pw41aX!v^K5@hG: _}O> D֭~/> lgo~NC|.o8<աM@kxm}A_h.={û 7{OQwRKKdv|V(Q`6X,ׄ`~s>GNnNsgYz{}d7nc\yxkä˫7gY-sTlM}0]Oݖ8 (aw{g^򒓾8R;hTDE]GЃO;T~s ;~wl#V.{sOTZשreL݇v\QC _"3~KUFMB%#gHXAw8 䧦nZPSaW(Y8l8W߿cv.K5l/<_ط=M+Un`li}}5\uj0)n\\pSZϠ:}>Ej p& 6AH|\($9$NwGaKz)gvs@7OIĚ@CmǯУ+tW vu+ jX7~M /vBU@Yo]]Q]D+@ܳu㽻PhEg*u+N9%NuܴX:xN=qӝ?ŝdم{cBL,rQO^da׫'_1"%q%d:r c[Nh ^;9wG/|\ƞYcIFxl^ıy-QD4OO8x<߷Om8M';40 I*Q0;(d6$Bc𯜬s`xAX6D΃%냻MƮ}q]'k[M+<A@R;+ #::I Xg^D~ע_Ή1FE>f -~+_=):>ӿMFGv7B.|Ev{:4ůoN4s{_nzo2v=#Xge٬G}e_Sp)bcG]7},i|E/ꩡxcǬ#w'YB{W30ܨJ~fׁ$,nTt& {.UtQ\:XDrF kǾ :Djdgoԗi?&ͼE*꿸Ň D'^_+ufoHJqonS?"@XߺswwhӞmTQѳ98O7S<1>(|;Ra4|D̖Cf. L?aB׿voE#haa 7ݷ&׀2'27|}Cjw}wϛ_|P-B!}3'O!G~?oɦfJm YxgU.}Լ8|FQ5~ѾK8w~՞9w~lHj[j܊݉ JyI>Wl㺟Z1vA^c7ON|hSǿ[б ubF2z`fa=†Uoڴm4A01u#9x3#AP+ny?Se7nus p)frp=Z>zօg~tEy]޿ݲ}60S(6!p/i55Dtl\0Nb~}~? k8xdS_]F}lm}z7|]8gs ܷ7f\+4C-/䱚 űYΦIz?ovϽ׿tٹG<ֿ};F z.ZJsSujs#6~ՏZի^<<|Z]7;|ǿwtǿa*IQs"\V-{ik[>v`Dtg{Q ,mIw"h >;][}Y$6&-r1'+ׯxF]K.Opv#?zQp Ɔ>4bڻ؏~d`ٛ^14rXGco:3yotnRɼs}n1TwTvCiU֝UV{n~~}oM㦎?za\+G;쯅Q{5cc/~/{ظ~Gvß7޳cf8BB-ch2 :_hAY6ﯽ^N#}7)6(aVUWnըp}s~_vav)39Lꯎ-ĩ#'J] 'kJrd'L}QD+4@t Wn08 0b+y(f/,~92URSc0eFXh-zuε_t&M~CS<5cm7 [GFXUl [QNb}yadD]! i cp_N_ˋ8~ȁ#;r8ш(Ia#LTxb2yf1'PɆe6}obҤy_ؓv? FV ƤJ@ ZIǏ ^˗/iZ΁#S;w!5H =(I%&NE!Cu#ϻtƵ㝎_r*\3@2ً-svRNK ڴ~lʑPOy~841Y 6*hN-SIDKj^ؓE,fgeUdby:q(""A~!o鯅4(jm+QddXn$r1ejoSߛc>99|uHe뀦C.IjkxKy(U*B=u$o4_:L)Lebh@A$`i@(4%FEUH##^ޑUcUӧyq-=q9]QPkvZ^䐋0pzf{7фtaZFVNt7<*<$6b{d_ւǪ^VpkOɐAqhy?r5_K_g/oy[kX}D>Ey۞Eyٴ)UyR{^qE) oįp96p<"!X!ظ l S`lc)Sh9~9 쥍$2!pa1W]\o0GBP/XR0q5iR9=SvU,ˎ˘$ӛHF}fYƘ@'GXDJWYҜJ *9)ek˾aR~PCs t[>:%LfZԬ~P(E4Ơ袳Ȣf~ѶWiW+־7߽烻<47?nnYwٛYj]ٌ۳ q8LjFs_KG4 $j//Q ah4jVYRgO *GۡD  1)k ƨ̌ة%q"s(ՎggX=BZ6݀Ʋ'FJ[.l%MO,ŗ` lq> /37!OSO _"B ~%`L2茑%Wo黊bb RHnG>(䨷ưL$ N`i}?>YX ˁ̒o^NGR-%j&QTk~mx>sn36o)s|0q*(HDRK #q7Vhئ$*(h"X34B +,Mb:틘|@|PURT/Aό: # v[JJjtȇΘWgCkmXL_[PºJI˕9/S$C"W8B%QLtiYS[A$H4?OgX3fFilMUT5SvKҲ59~)S0%*Bnʩ y,O혝n 'ƞ"=g'\ֶ>u Va ~sg0]'^ sƨ&($DfrndE+@J_JS(dX+Lu*ݻ|QT4Ъ iG46)ͥ1Z:Hu!{pv[`{,1|BlvAÂN,NEQ[#rTTdܷ-V*:ka%qCvJ" _#.$oYt jO9krۓ' h9f+&zx(9+v@&=ݯy\I7+PZd t+V *Vdh Zet&[$x([jՓ_5QRZ]ّq-rHfțެơ#%\FJtX5L/kJRփcҷUĒ(&gb `gQ04J+7c@#I ZbG~ދ/uC'V,&ur\BiOQrEf`Nq&hHI{GH&'?dXT4VFQlޟJi;wr;)xV;|)"E6ϵN2OG@+m)ݍ5G釙hDҊT{3@\iQQhtѪB絲ja.z6a*)~\w*^HAT`E+k%E*{3A'#YaF dp;\ : EhP9E0ȆPxtk/m.7΅`ZK.!̅e9\N3Ƹ[вSatʫ n]^oS+|N1'pO&M*^ -ʼnM/ɬ";q IԺZjzVf3E]ϵ wVK gp xo>0%ïmFi Ӧ.U? 46C4[D֚d6n8eg :Gze§f yLKlZ7iaEN S|Hp&j#/&:!?#rم2b4E8 /tČXp"4jicJ?Ij"W=QkKĩ b^ESQ|xՅ/;c-\3n5#C6轟8x;w;2},EO0Tr,, Cv!PUCJ0,b8cFHr.rByosJ{|[q6Z=P!Wij/?ugJ/>_R cC{7lq 1/$=Ӕ4h&.〻.^ac;.D7Ry=C[t- Db拧`r:S5\ n}ye[Ơlea ^lmE<GV/[rٚVk 43;;;?tjѣ XPb1J VUgZdJ@`D), bxvǰ\.WK3 ;qhidRbAȌUK⛦S :"6y@z JjGޛ[vUcιӟS}TT:b$MBcA@ ^TQ WxǓN$  $R}_u9߷lZ:{VgW?9?PuFU맳:t:J UŲeqe:m*?E2Q;Mg=rRc* LMfm^z$"1M+ $csA.hxh+兩 r9zҷցvlD32)lxt/*wY )ϱr!e(J @Rjj0&j.m4xd _ z뮂W=VFA {( ~2c( _F$ 'S6&.ݤȨTO*-k{bL5XFiBd1= DA|f i%m@V;7CZ!֕LǠkSD }}Bƫ2)`V6jl LI%TfWes1<=RI=äYϛ;r%OUmsMЊT@HNSFvNRMcXDURԽVM`jO+Se0syoghUf& ADOUD6 J#]_)eUBF"T YA_CLXfʴ]TێŦKn3Oc,Ƅ&a5PBTqZ+ ^)Pܞ*[lXl\yĿ(lhq-(GH! cl? -K^ƺ i**!`(&7#3B+qZŒpzqJ/Hje&JWH9E3;s9R6d&˘ҢF5\Fq3yS3n2l;*"@,j aA%fbUo^TY .1ؤ(K44 ,K )ck)OJ ɵ,䨬 !DV7ҩ *">S{ld:%JÇB;eGϺ6&XA8ho=+:퍔 Kvɟ(8"a ,KJb%^)%NŹ(td?Ɨ#(ѨcUii[&3n! $` fɐ08%wPWV!AҖYI@PhRƹ}ʌq3ate!SE d ե0-jh 4y$)+ݨhY##/V`Y}`[`ǿBjT>.HtHas,ǔY%S2fzRӐwekqsgۨjI^/MO\؂gu˵c=ZtW8N)Ү"DH 1e)e[`t@o=e5= ,HR&P ndeט5yD.F+$y &.s#)E[:HڥUe5P{YJSN7jJ5M$Jj, D?$հ+=d{T g Br,X `adbsqmy2KpK\3%'~l,V sPA΁IÙv4pP@ýs`3 ~x lܜemuF=uPt~nWpVYi̥ƪ:no:v^\Eg^Ւ-G%M֬[c]-ұͮT|vcueCdB$-dх]3󋮼sv fIq]uE4hF1s(Jjat''[L inyA'!YVbZ^Sߵ4U)[i2\]tMI䪘'dya@T`>$U hA$pqʎME>$8VH(՞< fEŹӐI]ˀ4I`IIXyMK lS+®+*} u3T::#Ҥ;OoYQmN~nϭNbUml.n[b1|in$6*ev063pYT^)` @Llf;)"Lϙ (_cH~(b4HucALV0XKL*dԆ7P5iUhQ (If#, \(LX8}Ƙ'VjLDOb-[)r9(<8O$OD$TNRyw$(krD"IO%Z&I<7q,p!RSeQS+ZX7ꙵH OA*kOY)}y6_hJ-t7u߬Կ=ZG$MM`Dc%B)lR2<XTW̐H c ڰ0Vd\%wLx|@ۘ% e%92t'Zjh#EJJM{(Tlei(%k 3m[)Tdcj3&e{ ۷$*F(u8WURi,\P)ZbRD9e1\hj[Lr*IR֮M5ҹ{H$UsL kl-pRىpUWHN|1&_@ĸ%NqiRVÑqՑ 8S4'rB!vd;\y> ɬrSk.TaXi=\-f9'?= r-پ 7lpYYl[Ii s_9n km ?(3U^ORl%JY4Mg.blNԓSA+Ý2ݡiMKleaaH%`l.s@^I|@2G\Vl 3DJ{YM<9Yu % (?EHꯁ歔&n*zGzI{,CoŚ'Z$ <~9,ziu2U}|j5JsO:Sd[.yt^@^ /D4„Ht7(*Jr}RU"oe*3dr'#&t'rb!(eT%.qBzpwdczu&kq$J"Ƹ)P9\\x- .g0}{t_t365a:ln#9'XXzA׆2Qv1MڲlL-PjSXw M5 _XOT!?cjEPecqea *Fcxh@,A'Yu?635{0XdSٞZjT%ڑ`67u:]L@Y^p+7_0 CƘ=) ~e%OdҾ_M}5=!e X/*iS:&WJ: 7OBqYSA<<X.ZP$KdyգEvDʙxd{-ݫ:H0jh,LP9(XtdB K`HTJe^]yr.KDSBjoݎFf9 i %$pxKpP>VR\ =A*Ɍ cJns'aDZw-0R= E &;&BJqY ((EH&)T"+.;uՓOU.]8"&Ϙ0aezy~rq a9{\fr V2>u`# J-SVJ-_eI19 u0Q8 XDӎ*sC1\YBToQ.u7͢Z(@("}'S$(b]  vfhp=r FH6hW\dh!$TScm) ˟Bc ȉ9ƌ`8놾*/zl:1p(VJ@(r}?(J m%-*[8ps:`~ C' !1n!amsH/)2]L-ضAEuqڲys?PeY.*bpʁ$vj;:dgS%0Yv ´eA>8A [|"*Hȃ]q-6ELw[]t L؉cQOt@ӄ}{}rHy#C5HJ)YE+Pi Zlj6!Xvma)J,8NI( œQ[N칁ECֆogC|19K)U^TX1]Q60 7RPš6Z.NqhvN؉@e$VNopujץNDAQWV{>"d"̈R\H ^{xS)bϋfhb$؁t=2P-NI/$A[f_\bwxa9alYOH57TXQ8p?HYN^w.HC(zκ хWۏA"1?[7Uw_` vХ6 HXq"X'A2XH< "PںAPqMG76S"33KIJfCdPD cDV&Œ%Kuvn{a+ıEn>.x-=G-1IЉ\omNq8F>rQ ~ɇqnxR;Ks$ݼ;jɁq13j(\B^YYrdb URŃuY/il^BkתzW|?*bB`k%^+*?X0Bޣ $e8qݞlR +3M|TKxY#kWx5p&"Z녣c/tw^ݡzqglgҺߛ^&3k5|Wmr,HY1DF}@I YҤ,{W߄R]pQXjSRU eѹ|R b.g.+oj]W>P]8Z*KrM-a1;@ ENp=hQ BW"/]J,dA{ؠ'E lq;C"ljbS,0fJ2=ox>\y916!0Ja+m/l%D Fa.\ƭ6  ,xnͷԎPU^y^8ȋpP8JU h=s&`}ju<7l)n‚꜊ {YȬ`U6۸7i*~rȾKd)qR0V]灂?JvY鸡wJr-Ć Pv蓕d[tGvϡQ FF6zEWEtD KGNq야 i)_s;¦Fֻ3aDEѡbN&2e4OQ l zf+1?]oWvЬպZP H q}{GD1L[^A^8]"NcFNv:R.5{VXw}87m[i%eóY?+J&Q8wյ_Ƹ\yJi9$ [lXr`:hS]gΐ4 *"gmIi=Ks8(*A\pyښ{NvITcd˶4QI #+=^-:H]|}ٙFx@B!QR#bljHb^L ⶚UEK'BILØ\@۪VTha5OR‘ " {=`3Űrz඀޷1aM,> 랑EKn/hxUi+AXBD;U;`6CX^Ø8N`%1!1Ʊ놮˝leQ=RJE)kJSkQ,_n@|SJQDVdl#9?M&Gm{+' R{xSCU%PW 6) fz+/ˑN=ca:./Tae;]|>eQ! $0 =Y,_v9Y; oub-'fNEzrwz`-Isu|ew9Y}1nSc!bRkEE7,MRXRT(PWŌ- 컫47gP68L2R )Ya?HN$D*qRSl B 玬U]#;Γ!J١cQ^_t/\J]V= q9,\hi:A"qy(!. tf󪁾LSvtK^9(ǔ&Q ;V|DlQQ$2PI\nidR`d&q0e(0B}#kK3/W;ja+2bS6 w{/,F:ŅFzPx}[xqE3^D-r7ƆjZ |?vE|:$ƹCF\GW[31={ccbS-d;(tbqqZ y׾8,% [(U{~6p1v\2N@KONu_G" <ƭ3NR6 ͝|/Npz'B"#ZPMLnw]ݺ8U?1`Κyh\k&k%ky*"ݥ6JƊu,7FpK8%(?10޳0~HP䗖sr?^ p[m~2ߨϴ'ONZcBFVJii #˜aT{믣r-V}ӧϔJ.dڵ!dd/Gu;c<'vұC/nU$7N(|_|3Q:yt7ppxf]'y._[q0(fĤB<w%$ ҟXfh0XzZML [ݕu]*U 9x lAׁF! BLpCڋA`G֏&'v뵃pp[ܲ,k:+bqd-`}KT/k &?x#G'-/C~~N/^jTBE Wh phi|P_^;k8ډѳ\dP,zܷkoV>*nR?rm=OXDQkA][gǪ'+f}=TˁOby(ܦUYe9d*[{ѮmNUe:1]I[). 7ʅ_okԟ[>u B{҅}+{/=ă''&^?y7PGu]-;ėyDR,8q~( zz7߻|0w |4m9٬5?0p>zQr^gf'jIVr~#w?2?ۊF/>>ݾBlno![0ܼ1Y W;2#hhALN'{lu ( 8k a#E5ԛ%.^st3ɸmq5S^KOLu{C^18v)#8P(X2YNLIT0@N,f9r|LpK݀we]\)r! bQ. 游׻][\X2km^2LY&e)v7EMfO[ L jTSt(J>OT(=O%V$ù dxxS5k`<-VC%;É2YNVU*^6m}?!D'JJ'Cy Ia7}`mVFf?t}۝R-+jϭVrVJ  +:a|˶2=^w6bM]a+AA8d}j<+WKbV!(F}0L(A,w2 `#oHw?Jm@L?СCZw~o<+_jј=xMR& }cᦧk%?e{6xl֓~tXĂn@\vk 1QcC{֐]璒f*%ͺ)g()1s~î+(W#QϜ;=Cs+Βm9jMexNilt4cHV#\q)!ӕ;m7..k`eB$aO!M%4诧gаUUI-;]?96(~<͓=3{յ&Kfb4\^12O5?x p7M"IΪ*Q3tұ a&ɯ}Z[c.8Zy@SֶZϹRxHRKoԌ\G1ѺkUJ=ǯסdNr͚)hBB0'JSCIQTPZ* Bon)IE\RQ+aT<(_[=Y?dOzwhYztdS P-K/҂ '5y ]ѓcSk~ٝK7{+r?糺G83v1[&VcRx\?nݵ}^dHO#eZe)',[fdp۩*,6BXzxc!}ԋg_']p#G[@yŷl޸aÆWh%iwWbdbxS8XVW8p=/zets~!L|ȸDawX8Y3Jy!!RMSFzJ̠7hRC7Ԕ=I+`#mAvٌ2{3;\sR=.d2r6|&!ttK~qކ/:#o`WWrmk~E"Gb}? /G3`r*!7 9oؕ<8hm3Kwgn>ӋO#el4*76߬x}iәpYB<.l\*zxgyyo_[W(~ӛވPL_.gTB/?t[ny _f|u[gA\Bc7jx2uoxͷ֫**{06lY"N~{ Jx23qɫzKVϑd,Gt?_9bʜg).\?"eO }8<D3G'#ei޿y&/#~6s]1e`Q|ӳ|pdܚmjI:tו? #')#ln1_ғݷо-W# ϹLY=}9#q_M8|za Rzх;>pǎ(np8{yv~JŹcsv˥<[;&'>Ͻ/[2J w~7m49o.zy΃T!͓~  a6LVJޘT2rjnr =?2.'#]IEEtjLTS(6 PZ;m(֖k_rJIn~ԍi|: u{YzGSn{^ W^f؅;.x7}U 0b~,#-^)~o9nHV9ӧ>ya }* qteLnzRV4ݞжԫ썪?42ޠ==!egjz쿑fG?nR3敧[]rvrA-sipH=bh,39#`/>A?AP}#']:hRx&1^_=-OOwF F׵oDHCa53aJF=|񿖏F :{=?ug \}jݚ[~|4!$ 8P)6$ʜZgJGy{JcǮWG+._?ߜȜ<v>McčFTfPdW 8@H4< Br2W@].*-HN S0礙l_Rj|1* X6XX|@alɓ&'&0ds9b_02H"Z*q+53DgK%, ڦl-;=XR|L 8؂Nhbv:tLQַ+DZ|90#{m iL?b.kVvs34%*;3t٧dIp{N9^=Ӱh}Yr1xd}7ԇ!m@4U,{ÿ ?P(C0"~qg:<9GVw/R3w,>|=D{##{`m;J+L%SFpvswAiozWY\Wl E]s&2 /O+ZTE`+,ﱠmgBshx$K7A?/ȅ#ZHɩp3|8rYWaҶ Cj6: G:]["F]auڦ\A0a[JEfeဌs!Sa|^X_yU +<Ξ-h?ޒQWnټf_E4`ja0f{Pȁ` ( @ F9J'y>{ 7^mc7ҿ~sd1vEmݲ>Ypc}xBt=.T1̐;Bޚ٭Bl9/WS.x E rec7o2xь'&Cd+-m˲;/dr{=r:e!h\M4q ̢L!+ =)1ïO庚N:Dm[.b6sv))$5#r֪h)l pҞ])7Saz _˚-!c-4n`cϐ)qXI[q { N(ʓyRo%-!}%=5?̽Q}t{'>#8aqE'/[pC[ w!a_nGJba[k֘lU!o@߿F+ۍW>f%JŃO2f>Arrj#" iK67))^}:#ܫ4|(RGdmjdvGmBv+>7h% T{·G+"Z\>`|-GS'mi\М(F#P-NIB }\P͊KE]=j]{zh'Jgp'm#O-I\ƧSkɖK-L"1ᮍ/ρQ7Di}/~7{\O@Lwy衇;vǷnrS>iZޗoГ3I@0G?Pސ!%U+ﱯO+鰝Nt\:Hm!{| KN\<!L ^v2{"(=6FdJpEiZEDiΒL9$-Db%zdA"\ΆJ #De/"eWUk:9S4ku%s޹1`s Q\{@8ntp{2d !?+4R`˥D~( =)f<_ 8[*vn=ct>,FߗKrF(';!K+=6M#+h-#nezYTX֒ܫV@Oz@xODs7Oщ2:ɽy^Jj [?oЮ.[c\x{0r6q/_uG1#ztH{&I@) GLUrX%m\6 KAαl1sej# 7ycm\_s0 CpX02fR`ˢɻ1=Td߽w. GUCJϻ\^?W;o3ъeXٟ#5L&-BF 2>8YX˧?A+? .O~v)u8tz~Ow=NJ]#y0;w}dRTޞxф U4eI]@ak3EyJd1"DR*~ S , {un!td"lVH ̹bEktImo݌jaxƵs0-QՏ@)^)kIDմc` `pу0؋ 0~$ϸtS{SV!7r="2P\abT<(I ~3p}kmAC4OXYXgjg!+ c}a՘S6%E8XUi [,4A.dxwΙgS[2 [A*JLB k] ܇f8=t9 0stoV ͬS)<9J>ywgØ:y &m9 {$"LԡMƟ|Ŷ~huw5vt6^3?zp&jL.ox( FμuouE+3̹dna!a0 Jrݑ+!ϕ~"X D? z@Y$*d=q۔6%€&M֖VV*Η1?~Q֢=YmJ<+nnr߾\j.Wo\7>D1Okً~ |Qmzh瑯ыlW+q<гfrWgGw p͛7N l܆* iG>?w1ڰUx{>Ӽb(T*+QH˕׾w|lSobYo tf@c [7XG1Y OoXh 5C#3q4p.{.@/$W'aN+4X y)f4.XXO6m]6t81 72_"3mKNiomp;/a~:X뽒|x_ę^b#;hv$6 D;A6NE (hf)zNn՘e:A.)L>PȮG{jݵS#xڥ;wl" l@I;.E;.o9K'KKI'rW'mH(Yro.YO|F#BBC45w4QU`3Y"6A)bs.$ ,'xnD*99.\= (fYpP,Wrxdžl@}ס5ϩF,b,!+ fٲ(~[LqiW{Q›VKWunի#THZdHsX`)f}u>bwq#?^h]"ʕRf;l?L 45@92WT/x<'s,g'@m0 gu _Q(q1FqSFC8{ĴV}H ItN qǎWG^%.Y;5Z\q`y4s\4Dk{Sd9~,T|dyj+=,;Po[\ŏxhwEr4 O8̺ :J0BfK3h6'=m, -9j]-RCs2E=ez[+wHǤӉl r0`dFƔ8b;w$iS[vŌ|89&P%1q(pOgV2G<鎸(Gd+GGP*+"BGbJb"1KQ@3j_w6gxAz"M***؟Ga.81UѪelZ ~?xsI/̹?x\$nKg+`ITN, ƣ`s1i~꾥?hT7po[[8/sYNXM?~L(ؐ%YzE+ ' ΄~8cDS ROyΑdۣ( F{As7߸w|]Y[~G9?ws&oODƊ#aR&8M:u 聸;NqJy/F=;2Uܧ?8h~!}GEd[.Ff(X(vkt$I($$UØD(2z]?5ϖ{Akv|^x6z۝/[ J耡m'П9A=u=~O_5Xཀྵ֭,ךg9N\PTkv  Pj`{c1S/r:^cyA(`K"zsHd_󪦜6U(|T㻐$PRsl֨7hU@UI]=s,憷W'(c09A2BĶYyyr9R*tF) VpJr枟[#${Br<}T" (J))N S쩼'h,L{y޸i\Zz& (51e0a|ڈE~19R B3u髃OŔdɧGnnqq/|\s&pW>$jU`1F✪N4#.ϟz'l,S'{o(w7bsvJ![&<5zq ?aK"'Q*TAQ+7y8?7 R`7 x>ugOIsԦ92|vocO;0!$ H<{/g-Ż8v9'yꝱ83Y/\o}O{;ĩ߿_5_{fAUy^|E|2J3Jz֣=M<z$)FI>_C~`55*fbv'̙{N܉#ySŽx' 20p'ݝr(g!aC'q*m%C)SOyi;c2T2fYx~ltP7xc;>]jG0 >d&7WX% )Yq0;ް7Yr{CO+c!2"8)ZG7(hw[}dߙ~W^b$Q{ oY(wlNTIO*³n=V: LExgTUB`ԃO*O:mr=!C  "t#x致|Sϋ=sYgb%*=$ ݽ3 vF;q"$d50i{q\'*.2"OaU G^}. qM(g~{ӂp! R~c+G{mõ?ч>ꖗC2,!%, d@Ga( x;Z^y1?*@paRyH8$'C ;u+o LonW6.d']ǣT\FY0μA b㉻> Zyjŭf3$|!=KsU;*`; >T (YEA+;w;HJpӫc$M$OٟiF+(bUWYsB,wxK+O|+u'G~{&Hi(V|ΛBA._ww%ⓧ+B7 Xz;cvKw"3eȜLxS\9iKoÓt51#CA&$15c2YjB׵Eӥ0=nGrI$[ weHE/ %HEcHg_񸞤ay1`J 5,x[]P;jw "^;FK/?;“$G 9BVYH\O-ҍ)K|:lg="<)[#Q޴m(FȞsrMw `ɰPsHntv|f9WrtcS F8ZZ5I*"l%ri[L0 KпMS'd^s흟Q$2,b5o%`Ow o}q;{dP}붖Ru]7߽KIBhpb sOr҉ XjVh K!/Ety=&u\LɑquHP&bLKgL^?u.,^]ڐHIdB0CXI{xlI񺕍ZBwiEfajdY2[k""L#/{?|N#f{'&b"%«Sw/ڜĵ8,T)6|=^>4"Ҍhvd99晆*)S U0m5FQ}CJHEC-;V{$qةpr<#g a=X[>,5S0e|ovwc1h5Ƀ ^gJB'}Ow˅Vo5' q( R^㍅D=?iiVR攦vjmr_«,0ck ;e mg e*tY93J{ t֨S9/p*)Oۚڌnq:8'ph`kEI=|Q_?$p:h(@ nt i8p\$^yk?׉Rk*,zg>{н?/29O `$yI;KxW67mo8 iJL+@~ BPPp 3SEQq XH㷭=R.qR.=&'A[Z"=Kd԰ s sI$*qtS:Bȟ X/WLh9{O&;w&IsY& m@t4z VzdZKiH)p@ Ul䡠 bZ^3$ s-"DAW`k;` WCW(Jnȏ[Q8+*6tz@Y Һ}QY o-/R'l;RuE hzqMZQ n o[ֆ? &NV`̎iϧۙ׎F̵Tq}tJ>UăQP1VaokG'l#I& ta}}D5V-!Y)¼F:fu/N_\4aX:-HtͨW^ɚ!CrBt K_]^(M, r(a=_އwx\\ƀyV"9!R˗z_Y7 B jTV1ҀduIy*/.կ׃Q=l5f35d~! F8ja7lfK?́$ Eƚ7Gk/!o~L&y<?&kZ-QT*WA(Xo>X8!TRr{%Wjǥ%(jЙf &Ll0D"VJtUKPS#6=hc8#z^>E/鄐H[CKǗ;G=OAuJ޹ӻ8E6}C`5L|`ޗTLHY0XBK;V> wBP0͏ /qeYa[P-@Q _Dz0Zٌ0zAE&QXkPU3g9!KyH0KgJj'xߝ-7] H&<+)k t0.;z?~;S]DI&)ZXRkGŧzyȨ$Dw:Pk6t(IC%3f\*ZZG3'Yδ QIem~  &ˍA5 py,-Bk"nI>QVey+Y0 "afCdÑJ0Xp\ֺ h錕cscD&r2\ƀ]zqM;_!V°`fѫ6 ch|^ys9o_|}z; 5: Gz \Y<, n!2gKپ> TC(P =Q4. qO.\YC TTtAGG.8wޥrV ʀPڑ jH+NLQ;E5Y=捅4 IjOcIS/ Vz2 WAu;6{0Ddz`FpI}Yz@`E^=YEݛ^B.$4T%O3kC)U9)9KS.E*W?Y.ġK'6I7'=4 sI]3F2Ǔz?i&/y{M!Q\fh&İ?;>9}.4"B)g~SIT5:`A]_uăwfn_@ںHUIW*bǕ-@s2'Q(owF:I"J)C6h7# )TLDp ܇FX w腇8"*0*0C05[mH(+Px|˲$ͪɍؐ;I;W_m60 3G9%v;^?dc4IQ"VJgl~xܱԹwT+N(!YzcJ o:!(,5;sĪ}/gbJU 5,7cU| J7JM gkus` Q/y2ZhI{w^|ÜV8 L3Urj׃d}_6.IB آ-ȶXT&A_#\ˏ'LкCyfTlW]`B0P[I OTe.E8\F:_+ˏֿӋ=ϤWKg٘GYO.|/Dn!ɼm͙gaDXqM^ְC^0:ePƹSA$7׶83?2,cHy @\m%B{\eV@>tvNn8 ckC FClNbu++C)j=PY x%WR)K+YWC`xo=J̒^sE0dOb)0¹mePWnDw[cu+%qt 7uP%xy=, PZڀQ8铙ڧHVt?`WSS欪¥ jߏ٠OS*9}[/9KTk6 ql63hu+u/NV+/tw!wf:6kHH@3“Wy_WZ?HE8jG!]mFPVũ,B;BCةfۧpHF[6a0d0 &߫m.=P?&4DH&W1Jc*!i=JAw۲QT)fN~qg4~Zu|rWCV>$Ȗ!0Ҕx>D5Ցf(VGǡdhceJb'T1uii5L〄YnAH8f'M,/Jr%vt4,ppQ54Jδf*1l,څ"7“ jT\nZG꫘:)kYK|;jr`u;GǫI3LV]]:-R _^q&ңy]x?G9 *zIl.0]OVO Uf[@#1D" ݑBe4BCAR %ف Ae.Q@5~C(Fe e4R,9hbmGa+g=ŮP ewgWvJzT,߻,YՈ o Ĉ(bE & 岐W@9"0pJ:u9Ͷ@qY.JbמxEQ,0 p3 x~$nJT1&"mZ!Kʠjqf۩&B8o j0Z_l՞x<8cS*1@>d*8hU׾%(Y_} V!iEi)]BP?$ {HPl͙n.JbG!жӛW~!OSu,'gRuoph Ű b$S{` 6'mQ`)*vPW% ]+CcEFThȋ$ɔ:AT4R +70-jp}(/V>dNEfaIMδ#"Itڴ;tw@(ʽGGt׻r[Kw5#fO i}` ?`!6r/hO >AIA; 0;}wp1r׶k >WuH^Ho!l-1;~^޻پWu^ KM6Z2DLmfz](CM[bC%T^溉:AtZơИG]ՄA$2!䠄'ԃ8U27uفYPE0yQ<5X6-bЂ&5Z_p4J@T/|<5O/S g| _bٴ?w$g԰ZJe5'p9&hPƇeIzaPYLUi̞7Be臆^9a-go!G02eW= IzPί(ga]N+s[e$F ͊Jnn^ct+00EXaIp 3PNlPݡR8U,"6EX1Y@]PW4jP0%U'0n^X4Hsʚa4tԯpd~waq_= /eS凾ťg<}~B}gT0 (P*)H/`(%9 n,FS14YJ.4ZLNq[%H%&$|9UM$.fRedi+ZI)ڐkPB$~-Y鑪6&m(K-ajA484Grʣϝ?G7[oŽ'a V&PVk ӐT8]`ڗR3tNqg͆J"残M g:S9D!Ī%@,=hu`akG'yQ89w^P3%> nA 'OW >2 |UFͷ_?Fv 2.a9 E0ܭfOZ,ybUaP3)_!N25SC0=jLK#郚Ml.'/-`L&Fu84jhJZR~`0ݤ C JߢxJh:ko5 q̅!D U (Gt`r)NFm15ՍCw eeVJ}ށ5B)RYrdj?n\nT,Fsŀ[Q͞Ǫ}h:hHN :ԍgs wlۃ }\,{EǯoP ?;SYQFs t h_nBt$fKax`r$e"/1$WՠA̟տhFBjH Vrk\)CI5 P)cI2!h3ik^B xr%bD5NKwP> tWTlmy5>^J, :BS`3T`!Pt;Mg0̧-JKrqjKOS't=I5bj|)܏7>R0Էv\ c߅Vu?2J3!~qAH6Bʚ4˗KQ v!͜.} ]g9XV'a% +V/%-: ^py46;+=B=*g@Čz>!!b\@mawVo݀Va\8+y(-bkۂd٭\%O&WHSۃv0@1ê-T`(T6PXl TӃ~9'Q\E;IIt Iynޅ9A 2$nl%e`HH˕` rk5 Fh7 3ʶz)5m)Uc[ar:@*(n>zw6 hN 3;#TwfRUU|QKܬ u9ZQ51(u vէ=/a>\5R} S̋aV_˟ĵk@H`u땫0! ˟cs_wU{h av$8^ye{WC(vS MAnl9ECl-'ɧv-$PC#D+aJ|f//E& $dL&9C`jL' } ',(߬D(_`^ݳoКE991p%:+ (%6Y`sEgpmJp;az}e+]z֥DPBW! 2EloՂrI U"D0F'̃mr.0a/rZ 4, fMqZ3 Θ-;]bNB{呕P*LQ''pTe҄4+"`YJ7TKX!J])eMypta6UXe`=M@T'`u]cU0Fr߸zgg!$L ގ/"䕜IbeԘCSO6)5Y=6n\8^0%Y%!;&AD:X$LY9AA攞 &Je-*5T ELɝ)VNS"6MEUGu#ju˧Т:EV6 4eF8@W& chTQu:AOQJf%ik68-"}Yg;)o9Te` !a0Z|ƛ^;O?S& sq*5ȠV1  ZeوO?D`5Xf0 TL.lW&XMM)'JWE)`VFU^h+A ڈ܍6l[B5;iUT) "? \U[eePpo:(UJE;S[l0裹˫+hj]e@74 #繰űU֗ݛs~85Uo+#[s2 Xt9EyE|?]3xUyBs Y.T`x _}H'?i'"+}`ew=~PtFB勉W$/wJ1AJTRNO`@X8\ᣩ6QSRB_{B/%%kwF8Pk /1NE=aw*MͥKN6: fӑh궿 'jԽʢ[Ch-fpϯq^u^oDYZdѭVfX#P9 +Gߛvrd/29w{|Y @0$4ԂV022&]81S)Oe< ց,k;$fpzkje&SWΎ)cD{L2Xv##$2*yD7A53!¹K [ I QC}t<c 7`Tb$ ܚ;`Gns l ty@{<%\ڸ֮[)8o&Co4w iVCy4!yސsʚ[3߾wQYsd<%Bp!]X;7 ͧy0Rb|ܨTa|fv'εTh`wV?8V,\Mpكu\t0Jiiݜ]yk|<.yZ `k]Wك7!_xT$J> 0MZ:3gy?,e}C{þuy4`q?.Y= IA0C'\sXV< 918"=ĭ,~7_}iNZ6)` !mԧfW:0d6 dk 7:Zqt󑊳XC1[2%lrӉAa t,T~L06،V 3#?,=xٌ q^YJS W 7hC9! h}{~]UlϙŰƷo;7sm7I>JIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_6575f3a3c39a30cba9d76a6045c36de6.png000066400000000000000000001700711420147000300343450ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx eUu'ֹSGb(A 8M6tN!&ݦmNMImcJ4FAd ȠLULEA{ݻgZwϭ0qsg~kӏwr@@5'0=1HT{m}eȟ ؟SBX{aCa L;ӓ`R{Kh$`5=szܸO2%o1Z3VT=^Ivp0_4=3Y'CѼ ~ Piʷ>ӗ[%+Kw_buӥj]04tqdpkܵz1 nj@pBCX{5to! е#  *@u #7Fw &@C~Lҡ2.'{ <2U9/[J h%;YN o~JN"A x 1P(kL '|Rh1 #x'̂wdžuHU>g!评k_0iǒؑ( 0R HR2)b$I,Ȩ!.j41LgvgpIEX+ B>94} aC q6|ĉ JN\^v ;PʷanGk1^$fRc$Y[atR5=n!Sp74wgF}髊l$mUmrЙPE9AmtXja"2mJ̒YN@NLT'P0 0"0:H F*^Q%#P]E<IwGbʁ-}+ƇQ%gTtL`8d>1*!)/~N_tw"? 4J iG9Ksr89#'1H<" ? [Kz$ mAwͥi!ŏetzB:B dd!hm< X T$rB 4'UuԀWPE{^'E}Tu1`+<<ļT5( U;4PeItATUQFKZ!vEL tX;G){[?nC; !b{izUe)x ^62 F F'.\RVdO^Z-$~!m!hv7 (Fv+@',{X[$B WRD~$NfZVia fGcPÌWb)حf2`a M`1rHA"n9|, L,F~E,bBB0@|s(RN/yUPcȑJVy-2 ).T" p`9KdX!Rq M>"7Ɣ&CwBY9㕀6Ҋe(G!5Mna~O(o(D/!i-g)G{آ!VDRFadHN 8E@ʐsX.K>NT5oQ,l%I/@CQ$D&,WLX $WfX"x"J*h#Q "a,JKSX{11k%4r`U8#'T^" WO*K^$iޠk4 CE=$aGC2YU&qG@`dt/H2 A`^PE\U:3G :O3W_ : 7 pRzSt_!|+ %ze*`&gc2v5(RF<> |2Š6z;rL&Cs 3u*q!YWWa]@-d1$0!EJ Xՠ|e &&{N!yuڄ h :2VL;r]aX|~I/DX4/yeӀ*,a$z+td`_5G[&Rf?:*2trE$8E$}sRkSٖMI(@=K\^h$E$&!K[Ņ~EyWӀ,;[rZj(TqŞƏsXuS!\2,)6 E"dn ҷ@R̷9QEl (z!S]VWyT,}šʖ֫abc*GBH$f$ˆ$jX7_Jl.7IoA "&Igca_DĸR! %Z#ex :.DL@9?,PÙālygXcje?(,XcQEv5;b-ÄX;po:}l)] wl#"Y%p)څACK+cj  DD)ʤ٘F w!F>J ~ی&E~.+X'/^e Z6Hj"]fn!!E9%038g'lQlr8M4)JySV?U!OŽ!%WD*)b-/!`^z] 3 |pQY;$?n_Xd)lJ#+R)V!?`t9zpdM]eg 4T³du(cŬGl3C|%j&F.+ r4,CTN#*ύ%10ɒ!iQ9|^!䪇S/'J.#0PI)e)ْɸe@L@d1PB02@sbN^Q9B %W"\f+پ =jJ#`Pz.yd=J^CQZ?G֖j9p޴z/7 C8 a灎 ^ʇ_ހv.)-y,06ݡ;< Z":ɼxPRS+K+SKCa9&Shn##CB@LƈsWGٴ]-o@O&/"`2 swCʿ-#fe *gˡ% 'n!K [q)uBdp; >_Cqυ:yrXڂ-%n* [R6lb6n/fNd2짾=˗ogFϖ}`ř-w;ᙏ-,,|K1z)0k."I3E4\H9aK:@:ZL1$1H{RWHOiXXj52ZV懌9)F:a8C^h( W/pTqB .Lb_=Ca H?iMBXK@L PrjkE7OUKپgJGZu ] ~o<>37YSbwe.%e /"6zb[/ʤI;x<ǫh)zA1:~>K>T43aOM 0.u+0 ŸA<8 4ݓ͢c)C + Y)"ªTD5 ʚM*wBTĎB[M_[ȹnTjK~l G 8U{jGVސ|K'1X蜳nZ~\fr ɵ+D^9ek +JG˱k*8cժ{wۻ:;1+:o=354b ոnȀ1@ ~k?UmIOf fP''ީ~q(yQY_C[IFe%CUjɸku1XG`8ϱ3\ʹ*R$T!A12 b=]0PJgLՀ`D (LRHR4aQs6}2)|$ZY¥7]xfȞ)% N?q'_h=:w]Nw}ࢧڌ[[ۼfû/Y~'K{.Z6s}/hryJC֓Eҕ}wMC݋kf;g FmYOav4P.M~ɘNF~ /*Ia1!:qI:Z=oU'$WZ /o[[_[ #n>̄u&5)OT݉l|ؚ;%@e:r:|^&V"gm"a@LTAl:^FJ2Cy!dR$\R!@Qm%1aT %@HlBƘuk4EC b(/hEgLh{Moo׬v"$^ w/`a܅=_#SSXDЍ{|=3]kwtˋy O.o7Oͱ;=_WXԲ.ZN2Q t: i>}B̷`"2Cr:۔2!k Njj|(!kcA\tS`T?yljvX3ciwyֵK?)[.YS`;eujvO,/JՙRu/?aSjICcWZ +-K?ֹ)NR[cuc5,e?Nc?&>@!4"B ;IyVӼk#zkȶ3{o_~Sߨ_cwOS9#"F0.C{rximL?r0-ݷ,d1,/`D"P<2sQJ]8dhwq߬!A\= ̟D|~`Ie g0pRdz2, 3n'jaiP8k:`tTkbŚSu1`UK7-$m^yі]6ta ]ޓ@my_SJ~fN倀T҂qCFWBoAoD(pS4*0$un1X$A.ǻ]L  158&Muu%̊~*t),[Xˁw\899>~;q ~{[.g;L-;s7tc'_Z̻]c_M;7 w(y dnъ;!j@Fl#2T`e߬~I5Z$Xn A@aWAHV<"&WT(hX+w]9K$! El"I4@r5r?1v!!\P{@W(~ƬjŶ%*@#몪)s)':8)cX3GzwUT<}p=۫)Z2>3k\rjGmSRTƞ lFgB$geGf#a44kyQRgƟ녬a xtQPr+PP`c[XT5YI o0=L?H .' L`(nSmqet8ϧbLRT%yh9M #3-9iQdoOߨ1)Ka> 2\b:!:e5ue-χ_>|֣ ޵KsVN*̓?:eU3CÏ{N,[a b[` ˰{j*{0SBUYYśbyKJG菟:ʄZ?`f@\)&b W@BV8}br JsI*ˋRՖ#XmQX@y@!98CVp^;X^C1B?VRƁyws3ww~Ko8MO8rضݏ0,MY{, ;0UUFZDTxʩm252%?\7} ]_~;|Y$i O̓ Qu|O8IJAʻ J$rG~<Ð[j0] o᚛ n kHf !e~yҨhIa1GH`C\)D{{l AM闿d_`r6ޡ_}Ƈ:0n|wSqT۶]Iuv{[8IʢF?&ڃk.Yy4iuKʝ5I|,bDTꌩC-G*#hQleHb{0"@ôאNy"\Il)6wܹO V^N ²߽rs؃Ϟ'1oy푒&QM e.] w/ikIZGLs]N ,_^\:=}/NźI0fW-XֽdÊsV[jҞr`R5թٙɃGу}SCrrkE U*=aH!$׭^´{ 0kUC tA\ 拓?lt]cUWrRBLVGgwO04?;4\+r gv΃omk̑?~۱_zmD+]=ai>dL)Ɂ^e5w`O=V߶ߝ|*Lx*'7EΖe76/z{kUIsԶi&X#ߝ>䤥SAVdI`u(SƬuޒ¹NRyM쐢u+]MsCAɫ$i!:5o_Z[ӖKm-]YG{p-IRz~g3J1"?U-Zp+/XnEk$j]uvsSz~xfֱ$5 SZ&' )rҙ iAPsի|=ožkC y VcWK2-Ph)'mM+_npŎѿ}-;>74%hs-¬/'af<&=}P,Yv_}+|l(+<}P1c{jruض?ETk [Y r`X/a $=n^5{Cykp`myk?c㻾4S'f"e l˯ΓMocM[8Ʀ5;)Wދ[z\z^zU8tARnpy' #&l[?4z4IU\=x%Įɔ^+_ο KKSgl\~Ƈ^ ?>vhI11X%N֥]M,'Vd*LE[د.]#Ve9wɼ%̓SHdj8}OM[lD8wQ?_N>.hY$sO;XD_rv(Z'~tz=OS-xx7 ''Ǟh/D¶1Bw8 ᥎Kz6|#Qf_zſ8Z7.MKGKEz=bRj+ %C%3n\oq\_o7םcU:weXOEP>S_֌v_zsޡ̊cܳy?ڱo^5[ʷɁg؊E.t.RcDAlP bȊEжK'ֲox!~^0V(88'$h *T+DaI] Zq̆hz%]z9*)Z!1(xkTvߺ_[v\^}L "f'>S'%lCfYcXo \W7՛6ܴdW޴il58/1&K@c>2 _xg #[W1X,o9goO<]㷳A~>+P޵hd ( Eu;ǘlr%]}$ʖWv_fU"I\s+yjA=qn%IGa#pix)!Ɓ.܉{7_[@֜ߘsG-tyW$ZT*}w0@Ɉ0 C}8%z7 ;ZF \>߹v_| rt]Cidrc,q܊%OoΊh'-+7|.iOUKPՈ2nn!B /z.>9r;"u+nxM޲*mw~yʸM0I^U $EfaFqx5ޭ5~o۷siKS;--O_sWyw?"U=ur@ v@W-?uwK؎tR SتuHVc}XήRN۱-<WV{LD`R¤T Jq<X uvlaRjd NÖ޳κorΫ5ʨuH>H(NXe~GU۽ۭ:Ni^ɩ1(r[3Rwk=yrAGwSwpʖ֦igz|NHyƲ؂ҭ0O.|lGk={moS8Z/d&8?Ap2j*bK^uJMiEy/Za4OӯB'ܫuJā[{-7/W!zFZl >zѰLa9_8N:fXv#ѪW'u3x!xRq5KN=u?ۻoFFP/xM=UZ(@2Jw Bಥ=ן7.}ŚܲlV [QQŴBLK\?,Tʤ{o׊K%.>yNzEyDM7u6Y:SRs8s2>XYzy  ),a_2/ȯ\su-l(ȑRgq{[yS7}K:چC493=[moik*m\|M9K\ @ˡ!Q^YxC,LT&gfۚښ[3zB́#a sb=OHs8k ^)* &:'g,^IO߱7~}wѽߡh ^ϵ. QiYZBx t籢_u,7USlB:AqўՋwk1Ky;uȥ==,]Hk{Oq%TxD2+*~m8F7`dk*q͢s?gd tx^|kEþC?[NJI4z,NdX`D65p|1жX:{̨=;^}jr>WmywOHbeo{Y͇M9B^5 a6eEun\R/LVˏgOKc?k[/Z֓79D@2͓4ı {n3:Ns6 =L>IffXr#mŋaCOΎMM%mۻT )⦋zu33F>]%pCx )%@yzF Bd- =wA粞|}zu=[Ww#e#!@J+~1>?@CuX5fyFJGc&AL*9CEP*~DM^^4Ej$c@ua#E>26 *Y,{>>n*%?^.-[.ھ.hk-u^TYβr%4R| D?8-I s'>Cc}E`di[S&qRQ: \QiAf(v;MYò^j_QxG}lm u3-p\v1]Bd01 ;PKN)&Gd⫧ 7zC 齻(awkߦ#Ta!o$w`4*C7&*~o/qt$Ǫ"X-iR(3a6G)C}Ž`"^›ĤS?o\q~+KuW23Bބ0;ISVT|Sk-!lH{~bl_ lš g_gf?Ͳ{.2> ]Õjep| @x~Cㅗn)IGNw`ZI d` bzS&{r-R:4>3!(F2ϓ>0HW `Pu"x&w[eNIS6uA X'nZPMǔLreNdæ:3X|9 252=r1]ڊW#q~ pQhj.})1l#;w$EVy*#TG KG1MA6#pYYiRT4Y4#ƅC$%=l1(){ߟ":Tj(eA-`:JMUq;gb=u I\@Ix2lI8!8vtO, 38ʼ u}=_ :73M5AfR {V[k^xG1s(cH;Mkwun%_gŽ.髿uA ƶ kB,@tӅVmʩfFcs82JF\Ddj0b4T[jG#{oJ s:Q4~|6?5LxG~V2 hUHu=#koC8πowqac|Rr/KRր&)8b,_, BWV\ Y{z$9 n_ƉHx,JOo*F4=x;I: ?607FQ0s"T.2רL8)`4Sq@Y i?5Z4-fXԼYɟ Bz}oQ[u:6[pukXjힿ: ~-MkJI2?+%YEW/ hZTn9xy$KP2=!^ӊ)\6ڶYj`aՄkE:ϑ9 ^x9^ fGV&mԩyYum,xM({CuzPnm#+䱰3HxAPF9 R+O1~"'Įm٬faR)~ - ڮ?粞||zNBTnm'c rqAWsstzaII j*DrF1bXVB CwJҔ +U0k|-a4:S B$3c -X6:lWE*NٖsbPkN!{DYUIc"Ә;(dbc {hjm Ck$uXmBj<`bjb^g8r4Ȱ6tDk*und~絖Ϟ?js#n֖K FvW{,-岮ũD'۱Yc$6 b= e>B\Qg=־(޵oukR6]# sOо-\q9_[jYܾ D3c!jXqvVЏ`UAc_J,9s/k'r[Bhqޥřີ5vqOx|g}Kgٺwg+eކ#cU}|zQBK[> ~681;΃CAhr[HG`АslsVO4srob/~zt6`\e)ZԱ:_㙦7S))~)Ό f <%x9gw:c.zɆhj^IYrk, A).e U+ׯZ__wur#fNd@;XxMg+b6J)#.-_ mIw]mֿ|Uڍ}$|m y+UY.fW_/}es6i~Q1{K"`,5xo#\\X|-_ffݝ󪝦U-=.*v@YL m19_yG>uƛV\ +?D\ٌÏW:Ci4{zil`TblRIs{rdZ x|!fW߻dI9]oȣ[FsϾ374x|-Iw(~eoݵ'Vk R.-o{E9f+g&f"ĎW~-u)]c#nAԠՂ$g={tdba]u,ot<ZJ.]~i7bl2\%!s~(CN nْ^L6w͵GM LbR*7Z:Z6IDA6|>`g}OWg˭ݽg56ٿU݋\45ZB k!YRNVg'MdԮUc []Y=׿>`knxo} : )ݷS?aCKS6 #&ϿrM{>J^\)Gݰn%d$ }t%GBcQPqg#.`5KyƳvㆋh-^pVS(RdzUbZO{3ڷ[:Ĺk;6:1K245#@! SƦFVǛ2o’:y~? Cȴ+Qk|t˟?V/n7*LMϿef#}vˆ"fF%XKR*.yKej)Ω 9ep^<͐J2LPm ^p;p*-P{q~[OF''? flhzfO_C|nW(3}jpxo94/H{#wm"0QiqIb;2iĐLZb@[rp;)9"IP0 ώxz5}2IeU~RTRDk  YywAREÌp쫓y}# ŧ*N6t{N^ÿ& !WXMcKͦ2UVR|C/| < o^1ӳӣZ IfFmB,qgT[ƭEIg+Dy㳣;s߿57 iJ=w>}CUxޒ43;xIo\T&(Zt˿EE)0v:qC/~ZF??%+_SIKa(R$wG$cvzq߸{-e/>{zHk.(ز;k(*9MyoO?z/|y w?2G'yf1q2_%#Ɋԭ}o]('bj~[ ~6TdRPad L:V!م<3Lb/}kodMWVLTn~lWu`Pd]N2'usg<4flP؎#b0,vh%6{/~cYolYVfo?Ȟ&CSA3ؕ"G-PslsM5TvlUwȫ!DqXu5Ko7ۿZ>"nuC^%hqHkR`@ytKn0Ժ缵%N"<*Ε6\Đ &k#0Hah ;;^T*O ٽщQ=~F'F?Sʡ/:!}ھ$ottq7]x̕Vtx|ݻc7Y%^\21ɧxt~Ђ֖yG^\ tKHڙ iә}փ|*e'OH)^/j+|g,lm_0>5m_ySg.-%-a(,+D "Y8!L4&Mjlu:;5;10;?5$U쌅$$ Ȱ%#3oJ-iZܱIR2UOEJB|!m5RZ6܏WbXQ̜Qv ;]~AA4.ymGʦ֮j:168`3o娄3(udcK9H6}h@wEVDvD =._{["s~?SRCphU9j xke+wtuJ%chR?0y`Jғ'rHKvW*fϘdyY:?>ߊR2#/n6 MH[ѻb^ǂ4lԡMZG+}R UO03Zqn*- X1Xevbv\U7%X2r{CEr g,eˊ5 ( fzmufCwx=(N..Trǜ+uX#Q6%ɝiSz`& x_o #chtT j#+˸LN ^x+r&/` M]x%6*/^5Wб"C "|jɩXwl4>[yt'3YLJ]WJYAt2YI^&@ cY9?~ ,Bs푸[^Go, ~ cD$EKam퟾Y.M4BF6 V2Pڅ`V蘀@zTܪtv!8(Dž_Lܙ\w 6:=+IIH>)R)-D<8B-r?vrq^KsUs9O&ƃzbl)cO]t[`'4IP! a 6?b߂{m"R;&(VH Rۓ C,Z 2FWPI̜$VtJ9&jڃ9D$xHwp%F Cý); 9Z/8(\'VI0lĂ*BST~[!XO !/d1q݀\ӦmSX( HFI, EgIlFjw x$NgraVbnFD\x-w'H#H/{kXl )@4S#C!|?cZe5D+g#3AB 2عGGt v})ɍ3tsv nDجh=赒;n92ZLKE(1t\RkLf#glS#'\ (ύ/GUwn=ߣʕ0Mn$ y>>*U2%dr YW[qǀtz#8sFIɋ^&~ȍn=CWGM&BYkw57>C#ǦgeV^vA:}ږщ<;'h m_  {+|jM\ILh8ԜpC FUߞ~:Ό.1Śi-?  Q0)0^J[nH%Im$,#LK5H;)yym 3^x uN+LqAޚ1#SB4 nYOg)1L@;*@ʔ^@^2H`+ݱN XPLIF@|eE4<5"+#EH"kbW 'ΎvcHb]k:mt L1Isσf"86 Pm^9Z"g ЫE6A^ 1B0ِ4Re&˱ xDȯ )%OYv&ҍok*7THy~=vp3bh!},121$?I6Y^e Տ^`b@ ak Rl$J$#PHPkֲ.Щ49ܗP:=)}҃!B7;nB9ٸ!ᵴ Q;@ gv#dp% k"QVƅϪth$G "߈;9 /J2Y0wB#I ֶxe a9u}~yE32$Ӯ\46FH6e6 VɭK]|cP5T"Qrզ\='cΛSD-+Iҵ2J캙H9~U6p`&ܚAr%=o 4s-~ @/<ʸ(ك;_vMH>CB P߆wmZ#̒cVTm", "wJǿ,X(h1n؛dd=NuS=ո@.V?|ax~/I YR5@ 1P'OZ*U!B]{r4qؾ{yw~J)]s^>)_B8B+wXQW8 tW'a 8foZ!ۧ }?)'uY=?@h^R:awA녛N̚9kgz@Éq Է @6_ fN%<$.=LI| Ȥ<ˠR UmTn\ݹTjNLMNL  JE|,˭Xh9Baߵũĸf v֜SLȦ sl= m&!/"Qxz-Ss$Ջ8Y*yVtֳN?&8F0ƀ_'(CDuei-(#|[!zMܽ'("`AS'("zw8q`.dSC OWd v髫%/ ymk1! C'R+|U:蔋" *["\$ڙob*Z] C`cеB}A"kNz`vyg D PH[&[VNݣΣ%d;Z d1R}/-_fΉ%] ɞxՏA.ch&L tHGk:WL-.1S(`:TEp|D]Jc8byP>%^Q务 - SwD ' <RT_,d6E8G\ʥ'^R8<<Od:֕&%#DI+ѫXJ$ MMQJ擢(2C6hJi%PgD']R<^犑\\A.$n' 7(^\3iIHD%'2 ԇQ naEDxFHG2w)I/ OK()MR"\ҩ & ʭʈ-n*C{D'AVK̯Ži8v9Ffsԗ\RK5!ZE vCbCRPV[LccsqjEHB|c`tjفW8@jތm]lP, 1h h=unE58P>ђ8궡w{9ה}gi#P~i=ښQ͎AX$ņ«Kky5׌a;>1W ueJPgS`["hŃ@QEI܋|͠]pFIP0 ZCQ>҂N.Y|Z 瘧CeܯȲ=(vXr1rd D?fR~ɑX{nOq8DN4go /&W4^Fxt=]:I:>MX7ٰ(U{ dy+pRTQ<~ ~I:%{\SOD_@,9Q(,lM@[\9)+vq Nj *F[ Zp>qȱ4E)Q%H/2]@2$ գD +^aj<2ƻ[=IgQtɒ+2z.Jlr#2Ƅ<~2mQ|xpf s/CLѶ7ho53)I'oR. #,ɏєdN$-j^0"Ԣm"h* +Ո^:!W 峠JV6h(}T[C}eWb%H"#T[6$tmWޭ'LA ]zv 3Z\?v>ʌفxI_V?_NPdÿaFҥ!Wpi"&udRyqq"GHWfHyaT[XqNĒ V:SUŚv}*Y9žkz $% >+p l11PLթkvZSiyR[$:viJPPƽIt,N7=;1D}z==#b"KdɍNf(>w0՞ IoJ)BM#t=-2jcb=$ :iڟ>c}+R.mgn=>7R[븟fqR嚱76~mIfʅ\>>A  n :S'2 @Qb]u2г A G"1%C_9H2DSRzQBJ)rQ A'W$>IAPv@dAlc$)T  ZR$zsBg ~njG1"sa!msQQ\+ IY!J͞6-yQ }ɤЊgO:~ٍ,V۴ٝ2y'G#Us5D DM(E2Y<]S=a$@ ,Yi*s^ah( dMI2;!"8s#2iI&K8PT1yNED@Π*E#]De#?0xT"D9atWtzqҸ%St2T@QS'*B9inJ[&Bh[)bLb$MYCTVHJWϓXuȗ_o#o\.?s[wF+#_*uXDbi품wrwCL2 0'A{SٚØluYx@(@+\UP$d+yW1a19IRTP.2%dgueSafH`S8ٙm- ["`¸yCѥ1 K6`K<йWJт4AJPE 4o =?R4$ŗtd M[bT1m Mљ~RO "79:AXtVUX2Dh_U)UbQZһoT ^ g >fّxӳ~یPh6 4E78 F%2b cf]"`0w x̠h-!jV&Fg"nN&@&iN$oM0Ģ"ܱMtt,pm(bЙ*m90DXZ1j!CAIO'2$PDe 'XEp0"EYobäZ@ ),C*]Aj 6+.!N dPHt Q:d%B`hp9H d\D 񈉞.{HP )su!\!|գ_1DYw|Kh*^.\cp=EÆ+3!,o-^rҒP+INC-= 3"L#( th.ٸDbu! 籋_=ոw@ہ E@9Z >+eU}l{b㒆@T Ί_ɶ=W [tWx*5HE("n5]]) % w39VŒ͗bRb8KrX:DDZ>-hR$P1%4ȍ^$r- (A› F]4DgΚV[Y Y3Ӧ> +TРve[6]Pp ͠[*<?sy3|;RCķD^Nkw=e Ӕ?7lvU;٬F2T_J|I P~/|i_g e犁 -%ם}"M*^튮,Z;ߟQ+цC[ڴkooea Pp TZӝ|S:6`ڔO%&'#`rW Ȧ۲<w|eOdiuPvUgvK_0 ;F1|Eß.=}ɹb)B`*یٴɿ)pc n{p}S7?@iϥNP΄[31k%\N`(/=Ӫ5P.27@̡ ¨p\jEUT21`L@'cCǦ>%S2$z䱢Zs9TMQ4a+$@5y悆C$Cݩ+vxCv@L"H$T3ķQ{eĘ{ʬD!/D .3ǂ $Y*U)'\H!sQ]&tqa@j9Kh?VA)} `a>r}[FzCNE|Ad qvzWVhlg<:saeKZƔ 1Eo@fe5^o\ J6+`d7Pr6Ѥ2i^[̾8UׯI'6|JKd,=\hXN,2.FkK50)(bMjlԘqfz"tmvgrIeaԠ1ݖu} !2Ŗi{$,"%PXH, Co aqMqw,/hĊA4CA 81b04|blwU1 vDu,*QR|F[pᎱZĦ8V]*[`4v]a!@СOmV}(Hr M#Nx B &DM_2X6`VtK[n5 1cwL 1Ap:vnY)( uNbӧI3BO`A*cI$($#ڨWPKtOdVwa%P~m ~5Fly6 lP~}̭Cnkˤw XHrV;LIHIŠ` 59&{Vҡ!,J^8wOW֐ӳ?{oIDAT3~ sڎ3qLvQ:ˁH]fu VVʑ/qH=+wDY,r|[7\]4˟ʙfbNp㎴gE*Dg5ACpQ0Pȸʾh݊VzxI;d< \ zUՉr0]n'~'X>Yk.wch V *^056tMS(Td u',rj1o)ob%XO,&cm#OhՙOHOwPlD I||&>Xa+a}ZyI+!]kRƍUIi,_6%iskx.vQA ,["^PO̧df , O<{ՓvkiVn-M}rt^k2hmA4;A=M}'Y<[fC-{{}Ө0*!YIef7sZK!=U/ r输+A_,AoqZ/o M%9VYӡQVEɑbZ?b/tfvxd(X)CvєS5,8PKQ,Cπ'LoYUwĞe[pNY.],h3brbia&E[cZA3R{Q™(@B4%e@<..THT|2Ujr]3VA R xɬܒtɕXpEmzHDb@{@eQUm(܋M]Z *B ,ްY(NL6=]qQ-~bApb-Y# VS7gQX+N>P=fkOY >UuFݠy?g?KfLFBkJ:pE{J;-^}Q]ьV)Bnp<s|…=͓#ʠa۵d,¿Gh\)eSRKxm٦q0T Xf*: /Id?mҡ8Ujܰg>:FFTN NgrH)IoZ) &V95XK Ͻ}~O30,[E*:@J`EI`폿㺠\i=#](7վXOʬxI`GSfz a*~E+Lo!? i#h6H`!1 NN E`FOE~7X:Yϵz xf30%߫}ݹg= JI V{{hOw%OF:eb!Qi+ODRm1*rG<is$Ma6 ƸpnЕY)p#Kl=9$γl$P1OyaBz]V ` !_)z]B! ig;jw'Kcz]ٔYFۋ^2iڕ'HǭV`g/׼?̼hٗV4s+,Y"1@ZpĢxǶ5wt(2k7P̯>XnJN,? ]*fío? kQ0ʮi&ɂZ\9XFN)g+.VM-@8(,ᜡ\.}өwksB#-f3=U;ս琤bív4X+.\,=Te26{:Wk̇J!/ zb+Y! ( ,,◍ ]%&09  {B[&񍞜b44ah]@uO֒_'5vX.xBBV-U'yPY]zvUL*6BQn}:L^еۂͶU>eB^(=UX*+^Lg;zI@,4|W+ XXB$xyVicH9z _np:Ua lD#ZW[=@W>5\TZm[1.걞_ 1H* zj2XC-b 8lAzHyhDqekF!oQ&>A"w09 &hY$zMR66W+#%2mƄ[NP&1%2vCN x'WU8e~m{aPY@B\ꖃejq:ȏwvm, e@j`"7z y$?> 4 0(>  5Hh%2ⲱMocMђ[u̅24x zt \whѐ4qQ<22hf<ntPmlAҿ"\ydD 6SBX\Vnrbm;uE4'& dU4j7-`8_s]`٠v %y}vSl9Mx8_;{E-(Hc&j*e;Ooe *ԴLfo͸;?2>'[9H 8_ cY@ +/;>XTg~Y;#DʰO* rY# ++'>ȿ?MV`*JȎ2|b}/)vtC@\k$vigR'>ocKn:Y. 0B|:ayZYі}[t:j],04z Tg k<^ـ[ƎGBǮHVFo>0x- )BR8Snhkd=e0>R(6by)zKL3#z;Yѻp| ĠMmZl;@y4vh$h.(!z3[ʋÅ.c=^̓>mp-p6]g<0Vh`A=9i"L)8/]2[#<ٓW* x:"BUYbhm/--:|xn\T<S}7\_/]gǀMSRFOqDH)0_3w®&n+AXN pn`3_;{vp/2ۤ~Rtébra#$Xv_bzkeiAL ?)02x (6 鐎CxPvFw *NNBrAz^y mVgﶼIhᇆVUq'"4H,u' +J*M}~$I qvz|͗ݸ} ~v]6IC8a|@̓5 lwA.V@()M7O(A\T{Ϋ=<]w~G赪~ktp\Hnz<"98ov,Ntmڻ6[1לwQ<4/^qp[Xw^Dg :S;V.բl)#1fbrU q0D+k|B`@6A m۷~rw׼/%(w\Uyoh~AvI :xۋZ{4),GT063L ~h6j\g{ۧe%}ehi[{ƽRHs0kzw W̓HȄ`=ꩬ)Z.*Ύ& бBMpS!h]RDl'Y`~S)fXtE VMSBzQijII;`HLR.$dh^)]r Ǔzwyp 0bAZ7D-/!4UaMYe4=!W%L;C_x~[cml.lyfH5Tϟ|pnڭ) FӘ7G%k(l{Y/m#&M(Dx]9Z:N( N9|(v7$3D)M^Ce4Q9syٹsaXE_׿uVǎ뺽Tҫ [LHa{sG>@Q0: uotn~z/1mch\pP7 Ϡԝz5L8q`y)3AD;JHFĶQN F KB`R1bb 7lBt!;cNF^2|]'+A1ǃ@$bnXq52U\(n#a+½dXi7*۞ZHo ;l#p_6ܲS=}BDz/)%Sט:OX>Ao¢;%{r-w"l4_y^|2O/ʗl=\K%x> cĪG2R|V9#?_jqhM8s\==`)V_kFqQ|26 XG@T U["M[c0ki\]g"{u8t-.[C[K'joP02WgV}"`z77wȑjF-a̜bL(玽TM*mZ׻닭*4DYqrΫK ;܂AQU*zU#pݳr3'+y\BΠT{)ܴ=&ցfI,s f\fTdZ h2|wڑo񓝺9˪|[hF^>0K_Rk.E!CR4oEi܀P +s+QR9\iA=m`!9p4]S~!uuAЇ2jµ-H d0a>-tZ~WAIU$zAfE+'_=rŸgӒ"&):H@$ֳy,\j%vѓV;Q52d:~5X,EfGk:о/)s+_L7[DRZaTI(@-2!Zxg\燒KԓO"( +*t(rvܰK <{j$f97~e+ycsGghk̻x̫6mWVܼ̄ߧ)#i;{$:gAaelYD俹fY֙ Vq6]__Ȅ ڳ"/!Q"mf'9BGyaQV+{̜mk[ZaůЧ_SiS;\^YK/y=kۤceY 8Qk>N\UlUh|wWZ>iFYGUm⩁#Ann90B<%f{Kҋc ZXvO3B-|MTB|Ǽ]rJɬSE ^bE^BzZK\tM@ }Y'U<\7Ćy˂N(#JbA8Am Cf=km46p={bk}G+3qۓj_D]c\׼5[cto;Cnu\o}[(̓6?pn==|=a җ|^~|֛nh|+_77m{Fa70&+շ?so9EVx~|ﱷ_M;O~rOPTՙ;1I5$ h.UڣOS֡E2&r~H/yw a KͧN2щNh)m`6TOF ɳ ۥԅ?v׽g[v) *xݏ+v[cͻ-?&^ ^#\dGpwq;үxr/zf ^l]*7rE|޶AXf͙/| eؿ}؉ ?{QS'_O`!1 [mw2>>}կ~73V(q77^PbOlm 7ɞ0:xhu~ѡ׍/~^qZ9κïQ |\n@SR Jsr75?X/ݺ.Z+z -DyM #C_Zj$R"uڢ&/ەߝF\.~|w}hk K3YQ~KNJifg=`Rw=I`xIwS_^75&[_KH5k+l XԽk;Ne=koxWLNN߷7k}th b;],>8^3A|;NݎYÈNG);" K%vrܻhje +% #LY}Br%NڞH27z-e;o0JSBb_BFC`BRֺuĜBRQ(^ v3`ԅ`3gz_\ hsY}Ǯ!ŻY4Iv:%Nr;9GA}/$4n+m{txCgxRjE:WM t|rlja,'jJVc?/wbCcFbRJyǞxT,:ug?}ɓ'/;c~s7n/;.`OI#$pjiW$v$Չ)Y,JʚV!^n@RhHME {"Bf `n_?<:>v[PP_"燛3ԓ] s|oO\:{57eA'.9#1w;]K{?V,rVyoy}|<{Txw;WopuT 4%d?|G W4Sv}/x*IggώQ~KZ=k VN S:B_B>@ֈ]FjJ";]l6.i.ZI՚(]$%#$GoY!?_K%ļOt'( Dd\[K٫v18;QYbD0Ol GܻWb5+fV?iJ;$捝rEVv(mԏdu+e%3{=/ 3(c7CEc1@KtHNl2^uy<59o}wS/ѷ]*Dp(a f;ܽd0ۀ0|/Oqm:A}D5Rb.fVs+z"ZH[}h->p o.$#,-4to7ܐ EwQj랎"zuXrXH^ [%?TgC@Q;BREXfQdT__iy08-}<1|9-({_m|7soxEb@qŔ@3Ao9BӠ纷+\C0##7dHPq8cv@7^Hqʭr(o:_@ZD=StI юδg>AdGq:B%FGS NjVz _j:oϹ dK!y]r (l[رNwd ѠExf3\S6  )^ (r^:un 3U^{A9=w]w\9z}0Q꩛.a,'37_M?zy<<`D%ȇ?'~'' o|}(ʭjL2 uQOO' !6XڛO䆮= JU9by}ПfR:yWLjv%JSWMBܴvU,NAس>wq$T”*zeZHőV~XY%T ?+G~ )Ou@X h{zM?NNUaqO>=yG~7u:zij#I owhRZUHǞڝe8P< PKR{p<ynӊRRWHt"H|g!R VZH1D@9,ZZsID&fк?8m_Ci{hU3=qJƧ*ɖ}/_zڙ]|ϖj& c197)( _Pjg>33VX{C]NxB6Wx}fcs|p`}gox|SNu:;?몫aAOU_~OI9Iy[dM5˭'{=&Ok HDI,(2j$zңLhO]S1O.S9'd"B5:5RG'XSZ7aa.&)|W:t؉=v&WQ$u9ƼmORo!Hmxf%EJ;9/vϚae}x}ugݿT/ An@jlnQoUUgFcȏXV'7ow/B7ߣnH2cQԩns.0m۶mΝoesF88_u8޽ӄcƋ&M.`Z)Cq%)}P5F r[pLPDl')5ΜT).DKq;~MэP!ZU4!:L0c}7u>^8Z^_Bo5xIH ڄE~={-8$U$VGZʞ3*2]9K 'Y9LtG*'" SZR%\0SpRn)7O-{/>utXNa%xͻ>r|[aZo=fn.sbCp ɺh{q0#s/ r}s^wQn)wZMY%DOz -HXăNR<y-YNJF4H(Wa9!=Z"%)@/OJju?;%S@5jAP|bW|}DyYbnG~ePpk-x-LC% Cګ!Ú3F%<':5k('OIޏΫj2 ~SEJ 5ܚ`:ϥ!w|?=yUw1L&6XG ~Ģ$t> Q>fޞvڱVAj^uW 瀐b"<%@:hMIڲ&,q.}.Ecؒn}V@.²:Al:9@)&uv;Zjn_V9vhX;B/MH}86J-n%2+%3hJ`=h =-XyDXw‚dugdo5O"!IjQ 2auⅥ^!gɌxzq~1闺:@oa/[>dY֚U$䭥fWm?GDcs+v3^'v#wmvuds߽p̱]#*;T>_<{L)!w]MfZrugQ)~0JTbCѦj橥znJq97S-ՃexH!Toΰ慣|&OE lŏ 'pbޏWNg/K#J`B4/mFY O IrcZˑb_ìy"=RVM)籎?YVzaӜKrkA֍y"Y6W*8oyk7n-BZ;ܶW.~=/ῼ^cg~t԰'X9k3e@699󵔐"ra*O1)mTx*wrDt?O 1sty$ SRd`A90XSiΙYo!2g) .dX~}OϓB拮:n2O<We8usn\f;B~ڿ 6/f=zRfu(ݟ:k$L #7ü{8_3Ѥl0kӇh ]3zfoD(I;S #w"PBeh Ekz(cZ\< v/q:8^PW{jpq_.kÚO"1  k]ЌL/q"Fljk"h=9  mx! SKP-WzB-ӱGi#+zz"Ô[G~8׺u[tʉwS& rFҤ>?$'H*>HՍh PF8/r؟go}ucv] kPyЖ]a#3s;epn Ta# chY71K{;mt&/:go YΐYcV$vs3hfmk|p7[瞒q}7X=7!Md&EJE{+H eCV'wRw~lO( Id!o,Dƨ0PAP}I{1s#2Bw=O\\дѣw~#Id6Sh8~"Saf7m# m2d(VtO0o9~z+{E}|ĐU>=trk֝&@"I'ֆX8p}mKWm7ỏW[L L.\v`(50e,vY@S(Tv;œGO'dەniU?˭rHkf jUB!A "u*z|ayC7@<`.l:8j@&VR=J{j'lQ 8\t;USd&g /VWxg ]{>ookuwU:onMO2%Q%Eϒc#_0q_ I#6ax c;' HQIQ$n|޾әOM{U{:uz *4/9sv o}kq rx2 K*W|dw?Ϳ2pEʖ G_ e,h0FݛFZ K|B\qd~7uS%?_ݻ3/鯜ؿY{;=oφk:H)4L{H3X'~\I)\|s0Jt1Q+YNMZ98}Od+<{oc$dKVCp"G`Q`4IenPeXuHX5Oӵo_Y͵֟{kxn|2.]oNzgwd7w|=~O֘f/sJ!i6Gbs":97 Vf E>|j%qrõGzaQBE'v},'zWf ;Ƈ( a6&AUP@ 8  r )M" b]|~ㅭ'j«oC]WjV3٢Z0x/mirUf#`!0VވLҬWU#/ُ}nܲ3 g_8FAf eۓt Vo3FJ๝s?rLҩ2gYzdrD_Wg>|l">^x+"ՈlXtģ̛a'xSg;{l5Cȕv۟~b]:GZ~7gOu W?a+'_ =&=mco~UI1tVvz>ZZ"J!I01E>O&SK$+RB .@bJpkDHS拴Ft֍g ] KB <)ge80/™_|/~\Œ,_ktaCrS9Cbq  e6lRVҔ遟mGc0~<_߽/t\potVr;3q0M ^kMۓTVEHwv|䱀g!Od4XXtfHed×~7VB ]~oᖍoL/aUW)낉Hx,{g5];',Ua_c|v.t&$7olo?gΓ0)}b%ZEQ)\T$:qxص~k/D3*Z`屼fK=ү ˤI*(eWAf PUp/0#WҢܸw >v;ld" 8?z{9̿xTgV;~L!wI?/oAN{W$X /F:%^|㓓[wd0G2/܆soN EoF)5SS͌S;һI}߾5('8J- /:~~Qu'6H}d^NMsro48ҚAwzy?vVyw֒iK[Iߘ*wiFۓlkb a0o֢ sQĝ_~_-_ :~/"5C%/ 6?<-?uù(Kbt+2GpMfbG7L-ߞ.}~,, /|dS@.yWK7Vsuן+8L-֏o&1k"džeOt<MS/$ïWs{G刈L5`ɉjh$1 I~M6m`C0cav^mC) \{Tlb;oLJS$ J, ƭtp"yb}\OX Bțig"Z5bhe asU*vtpzɕ񥠩ko^ÍwuզӬ UC`6[ 0YG]"iFs8Õ&5xm/2F.0G4:́*'>١U.5?uO/yuWXHg1+}JFCM3 6Fiw{[e NI7+Cˀeg,J^7ֿy?DOOUrsz"p們͉i=YA5ulk]INу0 X:!,R)3 ^TQ%G=U/ELdr,Ǭ2_ZQB64 yorx˪XEs0! \d K4ӸΖh=TIF,Pȥ~5ak+ѱgԌ)H Ȉ>r, _j<} $`]T+R-'E$BJ!l4R&7X䔚!DMҸpo.*MHo6y۫wc-,D@?LdڈV$aM2mMp#?F8X KM#v<8ΎN1W'o_7ы&i0IqKGnC/Z>%mzڮ}x79Y7? G {>utV\IL ӌ>Io4 8',N,Lf |Yk&+fFJ#x~]"r(5L䡤~U`sqW?%p1A fחpa#OL9K=̐!m7[EfJ*`9PVA7{WxVX%4 Y7?\#o" uwYH|"pJx-ƌā-au9^7?{`,)8 *+XUZKE Y%j*&Q=/Tbd[7y㉎2tP" $2! e~{t\ujV[5ǟ]m6A/iGM,XF?}HG87rtL1yͭc1I~ǭ;h鏮~Ń o+TOw RqK?xSb~,z r1gQꏢΠy}mu0=(bqҬPɨ.XQ9 gM?^nEɥɉfɇ\3or^+XXS$gm0.Һ?ZX $ŬZ3 Qy bO9ۊƙ;1ǖ-u-W| z}/ST"󳴙%auҸ2 (,@Ѐ,Qm>,#SE[<4bb̝y*`PP G)V,w!=$TPj8Qa%Ev:MH [:; -~$ Ю 9NX(sX8A'PC7**=$L3'^ZiQןviȓ+4hcvt Kdqs^8J'29HwfǾeO`аJ0sޓ^=|#&+/8]M]gxO;Co5ik 1|B5Ai0^n&0Yne ǚ1 n/3' f?ip fAfy@0^mEao/C65ʄ¨'RQZd[BB0t&d9fE~[ k/zݐ|ڏH N _$a6Ө;O Nf^, H)VRƲPUpFfVzvr ЈD}*52l9A,-W1fI=ߠ!Q < ,5,&t'āxY"-RVj=?gݙfc G*Lx%&A}d'6^}fJ0^k 9laƓxxDhx$&?h.@ U^UIsf;|c55H1zxe$g~Sx5zlLéߟ(,ogM?mz'gChNR@UnWfpZ{+U),TYc? Ǎq06vG?#6v.`1Pw-%*Mq7]EqDt_W} +YyXFOou~',xa1C^H;hzj[DivI# g9TYJVjpe(@@NxIpfw7O`zrj;^V)xY[L [yEP*` O4P?hĸ R(*`QLLRZ&mO">K٬$^*-*Njn/yeyDeIJ2'!j&pk˰4fkG^+Zۅ?xQǟ5Xfdt2[WTµp4A~mpkwƝ'fjaU* ˡ:C,9r}ʓ%6Mn8mFޙR XzC9HTgf| >*mZUIP &$]Qܥ.LWjj&ypiz>2ȊR!|ibrb1FzjixͲYkÛLH,v{LbbBw£ѭt!*ObB 15 T 901J {Rrd d/,Rj2EЬʅ-yT]]}`yL,eo*<1;Dj5F7:n,&r4,/k4'yV>\XlX =3W6s moOͺ,Y~Zr!K?˼Q~UW&ǿ|C_uNցTU~VD+ ܝ^؄yIvr$L3m#V}G/cXpU<&R02{T܇*?n  y(B.j7yQ (x %׼y# !|cs! 9k5XhOgiF5DJV:[O7:{PӘn g#])J7((+7$$dB!7p3&'CDnpP6Z. ]pHkb/%V@248<E6<4 %a[AO:48ztyIяiӋΤsRM췣,6U$0Vj7HpgYa /hl`L Cc󬀭P"'‹2o6i nvXzOz5X= 3>Mzol^ݾ̩}EJC k0:ge[YӎܠNZcw2+SBgȄ.YaېjHOܜAx}ag>L9K8 13jaђ4ii36ss+2\I9K2Gbv,2C{bd(C L{'JfDi ~~f\ JtWa!ˡ 6.A'Y&r+ɠt0 Z͵E@H)SڙjS V#Y;xL^xc{XUZZdYUfp_JaU6X&tBzc߿3_9߽,% ["y1oEԏ7I²poM^:py\%V5UXS6x{HM(5up݋;Kmy7?dnl$)v7Juy9 zPQsXR9>Ev, kF緒ըuiZO2G>͈EXſXe~"mP+C8Ls[ W1%rISJ¤3Pot7ݼ-`$R":ؚXROƀ|INXA <)y7+X|&Pj,EoPzJRQb&-(eilJ`ZH*/ ظM3?hh,et\%^;5]6A$?Ӧ<ͩkXT0i ֝{}z̋gqPJ¼#]6hq; I0lm~7//B\R9a~?ZFF=?{^̟|)U2;ً ۅ}lP i#fM3@FzׯhH]8Xxq'>,Xr ./04tۣQ>f@;"GIgQYNЍ+[؍yxHA26Ze>=v̿Z0Y©pm)RFyCml\,Qti01Z,ZT)ܬrk,aFM4"IZ>XRSx/6_Ñms3;jxS;*b% hjC)uw wk"Uu1y2JK%[{ʢBgyl_\vIabx~8<5dmǩ`wfߨfZݚt^zXp)%4̓l0R_R^ÇY͍KЊP1*^Kdd NQNj9-h&^d{¤ tJTQ{e߯OVWdΪzϐ_zfՐ~ΌsǿãL pF^[.vj2ۻ7ZW{Ns7xkwbqU>&;s,,?޹|/&biƧ:66.5-SDXJ Y]WNۧ*PGJ`Tˋ%L$3Oޞ64 1]Q;N72ի[,FT|F@+Y$gOezndx 5V58c&K<M\%VfU]7SHx* T'nPhE)E)Mˊ4Ʋ1K{gO'6.kgߜw=G7>I~QttG.i@ә5,WZud=ˋyj0Ի*GH9qwdŮ+*9 Tq"HG*CCdx$e\HFD1Äɐq7" kl~7.򧣍!{ȢoH=*K]f[Wg;)(ՊDI(Q,Gd2{RMpdZmV蜂 i-cZb(yDkDb2EhJͅ^AeXrPɐ)ŧ$f)Mc&3XKCHRVGھ6įY}7ڼ2߿z%)uTI20Ta5Vw,,Κ[}nϝ}O$DO_1H̒n7J/>;9dvן?s݄-8glj3;ʅЍȢV]7&[ji"0 4"%ʙ&9 ()zWODOA#0Rb>6l"X( Z$i;S+?с'r~ktQ 1K3J5Bfkc+Θ jGJ]ܑLR4c~m qB!ЮLU\0\4?{ B7lCBA> vZ.G =F a D)n.V]z_DzC>Kxc7\)&,,ݘNYɺP0mq_jZIԃd$N2ǮCIġJ4ݟJ>`RR S MaV,8`LU4ZD|BlX9ߊ^<#ӊ ^EU?u/&pnITRGЫJ{]+I]`~/`(i`j#X镫{0a-"_J 6\݅/ԡS;[\\7O|= F-؆Rw2)'JHvP S]!Zأ)eHnkhrfRQ\.D?T.+J*XK4r-0④OKm%?*xGE A&U ph0.Դ(jJXcଶ1TJsrȂê  aLWw,rh[6ut}[5a ɹn]oK#]hԢxh|ǚ: ҝzIG` zM8xf'K՟HNrxH|cFdNOA@sZEj =}\d:0BhڢLJRHY<@:63uxL y.BSz6bTfF(,Z)$M+Ge7*!'HjANvn: 'lcBe.)}#I M[T5n,D=4l)8+*V^rf`dE*֗ Ry*rjڄ%$rճ`޷5Ku4 l{˓ټī払\1pK*uhT+Ab:u.>{q+-bXлp b.)7h{& 87` q©A^߁֍sۿY6ob:(mد=Jnۮ_W?y̓[v ڋN߱4m,/e"[ ~@unb%$2[zmLe sE+12SQ`Uzռ%bz$D8POZ!-WEڎth\|o+&Gs,2*Rb|nE_m amA >э;CyXIvew>xQLvqc;Go>GȡMc2LҴU<@\K{Ew8㮷"][Ua7ѡWi0Q/дәq4Z|#S3HY&^Zv/$ҚQ1Aُ^JꡲYUDhZNXbO0PH-̶EnN e3z?:elF.Wը:YK+STi!w*5hνUF(}]qgD_K}Jg0B3T5{l#Aj`!YBj.7f7nCdJv4K;QoL j qz\jID)h|@֬8ˬtY/A&L k,"'t]ekg;fRjri} ЫetJPK9[`Ҡ}վJnXC`Vq-ZۖxUqEK, KsTU*lPكy3sMH']T':]s &܋!N-Z Oa^P5!D%"#Ǻ[HU=`bN;^0meocp}GpuF;(! h jf i6=\t~G`9٭Zru~_(tkg;XLO}vRgq9ig8KPC!CWs߯: ֘k~\*ަ,S7|QbA3tRIbYh…h#;M] jEi7\ YLi[8^ScR T/=Ҝ8C'^k:-бn2[`y|7c#cXg֫!᩵Mbnwn@M"qMN`m܂hPr #x^I_"m8ӵ;@I2wCвҴ\9ZglN/C*ZFgL,LJS阑J %C3fZ5iwnwM. m&025s,aƐ!y *1n[x6T CecIV\v;vALRPJnw:h)Z,Q9ѥ{sFInNvQ{ \XzJK2 er E[5ďS^E*3(״J^v?@֧`f8 ٩ ~JɖKImꇤ{еLȥA{tDiuu }QiIzr41 h:ZMaYNQ9p673 +*5{:{Oy򶠪6ZĹlϩ]rd>Z?;C"h6X!I) l>aƝؙ?ҹ{Fy!!iE`f% ؐogS~zp5虜E` Xل !2PMudM68RutF+BA)]AU*,QTMA[ӤGL mK+ m,%dbaЬȁr2AWSPf{]UByZD͇2u@#P%nsD(Ktu6Y4Np0]o%2ؽl+;pff},iz*)^ (z?Q׷sуlbʮ#QM Ihn  'ihI ձ:ѓ@$);IA ͼJHzmS[:I7TSݶqN!`8IFr'C iR{dKuHc>|P*}8UPͧ΋k~@#ЪX/!,GGp_+#'K/na0i,2A`o_[$Xzr.zJ; Jt#Ar` "'!LpAv0zgz%۶%I)-ɾ,r5H׸Use (p^V* Q7 NVx-@j$Yo9F\\̔7%^YDN A'GVK\CÌ0/7gGzT^~'N V UJR+Iu(*VWȂj繉Rq99^|ѐ[l1g {t"fISIs,:[Uf3SE/$ҍm9@Wp W''sBklxw.nCװ`o7mt!J.^޼e<}TXnfٮ5cjhʛ?uة B55ݛ3KssLoSQ rA~/ݖqqf;hxls&.3D7Mv)iOֲAj \cO/q1*3D՝z|q1J,ޑ.5paA{}B<|3qIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_8166ccaf22bdabb94c9bb90bffe64133.png000066400000000000000000001770531420147000300346450ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx eQZAVԚey61 C'b0yqBs# 䅰$ !yS0'6;U_}Uգ/Oqq䁀 {$9үj^P=fMBP"6o 0ƪ0Ryy[CC$+\J?zxbCB?:Pq-KVݬ=$Slͷx 5^TEӇWf!D"}@!$D i+ Xs$l6l%@tj M`s(bsub:55/F.|.4/z xw^u_RGQ`HnA&>Gr_'@Ö @H^S3_^@ĺX C#˔(Q~#im0g%bZjAK C~~QC>Iou4a)ʰqHl@M@/i+!ydرyņDbӁ]bmQ 1G͂ UΙwDf1Hz ʨ|G 1̫tQiy MY}aE8t^SLf}Ka*WY:9WbfbdGi)bQJ+%2EC"ԘrkKz* uUb njBT%/'DȆ1e5V BTJqyE5hV'7 mtuf3,~L#:Y {3.7.aU/9BФ9ay%  V@5Ll#2a3i `5bh@H!yY% Dp^јuPKJp H^f$ү굯ݠZ!{m窨4 iuq`f똳@9/\BA@W!f`R( R@-dFSe@ d8R'A9Gy|"MZP!qUwl+45]Yp}ET@}MT܋[T5+fFsA!P@lI[!R_q^Ȃƾemymf1Fk3Ah~oLhQ?ffrj"YE]uL)%I}nGr'"csBr+fQ(gH<%"RA.rqh չ&rߋ. tr( l]x!tj(W (+tCx5fvt0k>MXb)0ER^˹Q;S[keJ'㼔Ďi~0D"#(IƄ)o~_բ)cyjUdૢC19'ni\AΥaW-Jx?Hb[?0q8J,)r #J[Z*Y5VHhsf&2:~1{@eK]WK)!9$Tg6駂8r%b@Dh{EsoBJ23 n#"3Jy)}f\ۿpQ" Zbz>9D\"9oT_Gɉ$)K~č2Jercr>)MeuG5#/f:l:\5CӋ3H,LIUP_ʅבRGy!6W!gT4\?75RcL&E1UCl?J0*̅} o'(8U&=ԷW+n~b&e y '8J|,{vUǹ`1LI5?JAB@P Ņfc-8(CR 2)W&*y,g">`ӳ˼RC`ivhu^ZpBi>n,,R{ȠW"bQ:AMV$DbQLrzz`Zmrg^dlqOv|?~b)_(,ԄA-*޼bQ*D+geyT9~9"Kq^~#y>8JA7 Euzaš4P盩4rU=T+E@Y3C#z'9Wam;U1iG+mb7>wB>^I =V*B6*N%Xɹ9w @>D*o`\P"QZr8ݝKUΧAWBruIu`N‰yem%s IA.DUc墣TƊ,+ b*Oba)DZ}8<9oƇ]"TVB[(rqH;D)8!3{ـ/nlLAK^8EzQE~ GU itC` rA_ 5!4)8؞@d4',)w$5>hfݺتJDYW|C  ?*Ģ25Ѩp3iS1p2gAc6 LKK7.F _nCo"2l Y qJz `Q}KϞ~SkvsCZAO^JF95'})5 "80?$G!srU+Y! `TQE+KQ(R+Ez F0,Vr qP~$F PPRK#Vx{*ygypibZxs`ytVDӴV0#2[[ IZ ! cyD{U+ܞ-۔IGáO02...70+5o{{r^zFkj%VIa]46|vT̫淦eG;:kK8dFD JjA4E!PrbQ*"Aij:GG;I1($~,ך b刡M"^ i4IR1\4(AXJ\h%3w^Sq'g#Ti FH{f2K4herМȐ5* f֍ ޒFxC&}\qJJQÕa%>tKtF- %hVLB' z L֮YJ:7pwyqu+XKA@)y,7m*G5f0jHɩ[,+s7^R1o S%/]UsTQLq1\2޽u?2RA*HvM)E"d3(:^r)Cf]Tau`6΂)Z>4b\MMs%Iy(#Sk'+=ܡl$똯8; ƋXCg-wl 8l/2r]pP>a8e@\,Z52:uVSr"-'O ыE Jɒr161(m}g[Q#RBMދ+Sc:aς|浙AvXɒœ~E̐DhJwJu"(qum^bbeGm)* +/"` 6в_Am l-[*SE<$wawÒ*J7n>!tZrEN7 yM_lk;Ǻ*N Zik]LRn+oT.=*͜s@.FVCR3OE*e('*Lm a4 uQEE%٧kY@!H#Ei_-j[iOk|biL5zˆ%,_ t;J&-!Xi_8rC2_28`jDO'X֞;%pPWR)B# Eж1"`{Ŷ[P[2&T u=Xф18R r"1.31i*R T RAeh6BeHV=K b1ó!JSZS,:B-ȯ"V*gll|T% ˢ,2G YˡUq̭=z 7~O#a2]Eܨ\;Dj}J2?,K7mrDPL~pm ŽR̀Hy%+֖ѰIX:. jR*r-'3F1ذƚBy(f݁& :CCܹ%,x!k]Z Z҈fQ.n2D.Eüuݿ Zr$8Bw"&A +NnHcu{997Ȉzk@;z)GPڊ)GRŖUrZAaKE ]8 :Rg nGWD5 \&-I~ei/']STHWSI TQ[BR׽ ɜ˛}UhxkԵPhݜD%Yhg39X`87gёV|2+T&>8,}u ê+9}D/ v7(AJN0j>+JX1fWBZsHQZ1.$5*9&XL*Gj=F&p b+ՙ吖'UgՖH3 L$;9hB.`l"zkp궬 S(u%Gm'P^Di .so%1k ZQ I+j5nIʹK|j^N|yry$WA hRJN(M;/ֺB;k ,uB*rVlVM &7K 36^n\V3ļ14Q,2LUI7/GANU|gn,Ȣ@5Z:$Ps#^v[V_jj;Կ>;wA>q3͍[+lWxk9}nż?Dt :pѹx!dcV^$LSaj%^=Zy.H8jSXrN(I)-KWX KuU˳48ھF+Z۞Q0ѩSGNʱju ǔ;3)gP`@W4JORUlٳ[(uJ$])Ga1%őLq s|TB8N:Hw]+]A{߃S_ؽb \ b2U44uG XЪ=oŪ"SlR6Of*-=ALC\ΛZζCeQ2 hn_̄Rm)ؓx JOb$ɺ mML1+׃U3M&Tg3DK:$/B2{5k>(9M1^5DKD 2א78a.jTbY_,BMufa}bЕz̐(tcT-;~-{_qŧn{?zSID;}(hVrP%W/ 橠)~ Yٶ"Y4y휳B\Q{[r-h<$AX/  [E>8p|95Cf8:LfѠ1qT(ƹ2fY-'AVf`Vᑇcc0 FZ@۷Aiɤ Z~"Q,􄗋VNMwaۉ?CLUa432s%߸79xTAPIB& rfa*QJ 1%P,~2ih:45vPӫn,SPE5j.KwJ-J3ZVlub+R.,s sj,ZJܐ=$J(4M+fܘ7nX7~ (p׮+nG1.\2'¶`IV.7~f_|>^±ON?ms Y}vMTD4: 7yKYV.DP1V*ݢ1JwS2'EA6ĭfhչb\2 c2XbJR49 0! cvZ%MfpJj[~Z# .c'V5e5;3*ߟv12 #s^;Gſѵy+푃~@-aQWreu ~B֠38̶&fآ$\^=Iu_yg~ll+ì!v.ږgo>z])v>Q;V݇|snvxF1&6}h'92ܹo?|3LW/G9h2jX`K}A2Չ=AL^cߦ4 P_YRgm.;ATLKlLk)7u' 3ծʢJj RvPTgZpP #A/(S,;ẻ2(F >ՈٍdY`\!2(u\LYZZ)rS ҈S=?ƫG\~{s1X_h =iLoVjS,F'zFlAmD̜N"G{bR #&׽y۰qȡOCwA f8i?՜lRvj/u/ҥkj[5uoԥf?{j>s~I~˷'o"K"B"B0h^:E)&L7̺ rn[EŬ5+a[; 8GOk\ͺ~p tkO,k_7f5^/?unOm516'et\X|Z rn0k S1cEbS2UoZn]1uzrF ;vg~C_8xxzb%^iSRc\<ɂ ,FPhR<9r*849CwƏìn;LJ!oa2+;(-gNgzz6־}b.{UrjeVL}`CX1[LL* V6Yq>}KEbp,2+]r Q7`Y/3=k_f!*.Y|Ù; 5mvn5~{v3cQH2ccPNNq.s;&ֶ S7K߾؃7B姖8~&mGLT kI--+77PaX3r۪ >r?':֏DA5bHm. J:<'S]I('x:Mwɻnlk>gT Vz/o&vd8=^vڱ_7 ugv=m tkaֹ|9ߔ av`+7v6K^Xѽ@Oy'A)E)Ŋy'$ o+ Vu=#8\~ĩ">6Daq߻ 9}: 96j9xZ+?8}]Be5qab#^Q;jo&6WQdժ" HW˫ %~vl?bl[Ny6eK_xq㜞ଝd[E8&}Mw|ou%XzWmU.GGDiC1%JIqAsR5h6ixe~[nX1*M+֭Xu Vk;LwiکHDyԯmV^/+ք=YFxl=-h!4s,f09s9L_?vt>* -'ψ(6#VGWӶ ̯c6L<|k!$D^wfҩǍ~XPD51WؠIOH6-T$vvjPϑbJݘ"Y:b@[oxgwcϿoܹ:ju1njV9)u%`r* y9pԗaY>o}~džht~7a>FZXY,ԩoJ\FSa1\8I'd<ʓS B߀;6\pˏ߰O#w;yJ e^u,rhDRR c< Y/Q$u@U'$ּqUr)KYE$AZ5XL+qugkSoZ{wE%=8گHBpD-.,&ߍ}1iaŞwn\|؍GR~IbOc_{p Y9 ,!ɭP8KOyM-rєu6VV<ֽ vRT,ӒTR[dlD;'Q1 6j,>̆dobgI$y[ v† Vi4NU:5v͞Xc7HѣΫ<ъDuZh|,QK;kg\:rsk&d9R`ͫnGo=/U'~wݼT`퉫y| n \3d-#@rB``E:[ eKc{{?!;l v1 "$A"ˬ Sώ\wuCY&=MQ9q=|d 9)ENA=ۯyӝ7Bmqڷ#p6YP1h .D<: s@Σ9;\i,[EbLw]2=<"7VM_~ͪ߾o=9%k%[~w(g_FR8#ӄM|c?qICkZ쬉jtψ5XX3 ~U27]U +gbY^"~ܦ˸ࡓqM|7Lu x~;ڬV6gy|m%TUՀ5ot͈O+{'wv,zos/TZS?5^56}쥿y_ |S4J)PssM2b4ۇ:ncڡQYM~CX>:FTDf6)X'қ޸o;>uD.^I0k 4aD3j`DFʚUܗo^s< U~K!Ic#_X*(8S{7VuQ l1/Ёx|AmڎǦ;{AEa^,;iN`xk Vj̯]jDiPJ-ɦí/& KcdJ[]#'arݪKgN0Nc[NX kFۯ}S]ZX/ݶaVw$Q%uUj*Y{xW5f )NY0ϊΑ1fm]۳٥ފ3|N'CCO}?LOQe ĥزϯ VdoX?=9׼ʛqꇵo-r}Jmu|^a\D;Iǯ'qlwx!*|si uĕ+^f'?ǟQ0^ugc##/bWpx"\11+:l=O{#ơ7;_^U^aNʹCB,M53)j\E0gsJ&'woHǓG͛j[^Ll^9u}$^VR AVS褜mPUB;x~VK( (`7_c?WY]#?>~3ט# }¿5|;r!Y*W1UG/kh`|Ubkn+WR9s~yaiicw⧿jש{E7n&!a#.F>O>2vWBݜaS\0o]ve0 ћ$ 44o̮qmlk6|>3cSfc}eir`pTH]r?q*n߰` c??Ou %|OQ\ͫ .aI3([d9N? %W$:U:Tsaf^oK}rc:'?_xvRZ1]>Q1'=0.)B#Y\'Ytf{$Kͷ_RMaP!rwڹNn_=cB~vWWZn)|tX:e`ؿ*U}[eb{s@S/uj5cClt=GDϰUp$б]ZyI )(/.oq]z㥨_/ɑ1b|uzD瓓2{x>s_b &N`]{oqk1_lgox=}7ONfN^-ؗ^D?]7 w)>Fz\3 ḁpFMpht!†V s)a$tU\slR'k#H.lJG7s5X rɎ;~mGk7܋Im6/%t(di%QYp$ܩٹ7`]NAAi"lZlqa'uM nxT< q))R~P cpbDg{</my=utnIiNl ih_rCmRFE>dճpj!ڹ̊WE);َs_7!oKZXC-@;je3G-Uf thC|W2lr/\s9+2/?B:H1(%&cgnz`sXĸgjM|i/Ω٫ǎ=P˘_!޷g?ĬA|f~NDKN~|rK󊗥OT[zFsA6?<~a2R:kǃ=c625LC^Gg|IQInVwjgƃ~?RQKC/4Y;B _VKPR;F1pyvq@3YWE(zfcn4lZ*-J0jg}EYS: 6edrt\3KΏѧ{UIt2F^25-@ijom<`ao}`p!b>cN u2^`A8`}wi/:?{oÈ ^ #LsqAdJDZYSE)˵R yzj|7vJV ڡX\y ki!S;ĕ]ŕV[G0lV9S#zلD ] %Ҟ}e]9Mc |ve@e _껱cH. @d+fwm26=g#~\*1񕯛xGZ CW1D֟;8#M[HKGf7V7w8V\BA"5dv0$?K ۘRqCqj-} l\72V*]`>ߐDjl4S`;%1) Q=u Ҳ,x(2%]:f,vdܡLsCFoYjR+$0hޱfևI,o-Ǯ|~L4M0YuZXz_^xl8y$b 9ab8R;EʖK1 U̩vjmİuxQIuo\bicʥz"Xg $3 EDR9A-".!7ɂ̟{T*6 /9&̭+ǚd?B t"rP7P[6/ %⒨jωߐ~h=#AE}]UEЁZ59:ѕ~"BO]+L$ ɒb?fUgw٧bX{yzU >BŇ8>2M+^يzšW]Vl`=ZݑyvB$Ɇm}KHs(m \XS+nL'bg]fp[A'M cޫ+$Κ4GqBw'X  %d\6|˺;ז 7Ye9e`sҪ..yU#s1ZTf/w 2ۤCf>KK`Q\s3Tcs㉑67n[7&~vO|MCU‡+ +rudoq7i8+2ǮEj͙ujmkƹTuP[Ern z Zilkb* vLe)K{qt\j=Μ}.1sfۖ^z MoezոM^o2#Ʈ5W^fH!zSgXXʿG @㯻}Eo[v3XG-||.%=°Ji>9º}JXj8<^Yz׶ :{51 =[M+?wr:WmiG$8ǟ kGD So5wu7^cw>34}sHP4qRCaa' ^X,7bTooOD.[-]?9$SGO-ҶAj՚:6 ]X9N' }rpms naW5f-\tq$:ĻR\w ]M/v4weg*4y쩣ycB(+s8/?{/6iA/'S<,1Γ>eLD~j8xf9,RW:[9 & VkZ%e(1:a-4 .Ci 」1.־O~m[7>;\DoX?ҿ.- # $SK\8>9P Ζ$b N?>u=>~#z@$*Bu~lGv<Czz41+G貶?ۯZQ0vlUӽ=H~b'?q1O~t[)w39!K\;QSΓZ<~瑿3 jyt0;Yª*tk!MPƺ_:g>p虑3"aA;y%R>x=C3JO}W~_>scIfs!6'`\`CXƿ؇>Og}}L *+T?1S/?I݂IN8vѻ^?١G06qH~Xv[_@~êD聸n[Au;T|<:x} *kewk/Q/?=FFšOC$L)/`YtrVrXZKUQ'쉧~{쿬􍣎Mi*F=PsU0];rӵㆫ߱vf,+O'zF{Si% ]rJWɈ/>w/óRz;^q^gz}''.5$$U68FCR9x`}ryZEQ xp\5x)ź@Vw4l0{Y5&V`OŸ4GsܳG<>AgǿeaTWn++@o**Kp9t+'/6jaF Kh1V(9v ߭ Ð56YJ}buRQMz̑S;{>ِ&yO1ʷW1'L*E+nȇPG)N_58@XqQrA f% WJj)L$lv8ЁBUZHI_WNLݼ +׬^YUUPϝ:ɇLd+$Wp4J C&e߱uekW.-CN}ð/v$J@1coD/ V-(m+Lm~}3'߽ϖ\-b!l)V/jh`.>? ><[wzqsx 'Z**OK2 4$jUw;|A9,yqa2=:6 I˹wN y #CzR'5b?{cg$pahPt٭ ٰ$kQ}fa1u7zv{ \!nu} 4)$TTש!u2EvN#uD*v(+!_5챢1Vi):vԇ;)#˯ysndNe2 3haeܤe`Rw@0OP aC2|z֍Âئ x*\E}QTiVǛ#9`;^K1:Qfo2]2863i i0S>{9bIqZD(iâq@:nO*i"L8Bqe)4$9o, RT]L>=4 &f_{{w~_v0RrO8/u1M:G!)9OiLwP='t$d*J&[yJF^[ )3KMr+T|J QhH^A`*qXuVK!2dh#>f"~QC#伱ePZY;j}NQ VZeW Jp%w((|Qː:- XH,SAN8߳&}s+T#uXζ6^jl/1XIz!1Sd! p8myT)7}xoC{iqw~7ᾧXUitqF4:Q3 1(ub0}(YJW!J^GUʚȂz H91~6US26b;fATn'hت=~_6h&\8=o H I=@^ᐯ>ie;C2h*;=A I}bNF*o!43(hD°I A=V]eB-%)v= fCFl فdg5Y^r44f'7"l.߃t#-ܯbM_ƿysy/K7\yk7=9wCOTXY1% SDaL 2=Kc1 6%J篁?R]CaB&ܿ"V^֏Ω' hk5e WQrV{h][Vq~HB`4)D NPLk$ژ zr'MLZaQJCnݦYGpQ~ݐwT+1$+C /:,!a{QrސV9Mt3#p5{` dnf; -g̵dPwr3 .͹Pb?¯bIKY ̳ߤU 䁍N3֜G !N̴ +u'xA͌Eޅ n&p ; gVlx[E;v{Ӈ# *ݤo`I3P Lǽy 11Td: L XjR*C,x8\m2:_8-nAY!I@掊4` kv<3*daxuVP˲7&"/ga r?O'nR]Ӡރiլ۝lwrlJ*J/(}}VIN$Q>ӑ{IQZ6{~붿i}ncsӿij@-$rSS%M.ĵ UC}.!HfOl\ &[J+W'ҰϠ%x{%Ž2oBXnY3S4}C$:`d Z8 };l?(@j j^Px%+=qWջogTis>rX8n;պ*/e 3iC&GQ hb"Z:D`]1TB421Dn{?~,R%TH_cXI,!Z]c?ulX:R:Rb^{y>'&JzW5Q XUU =N! RNj&pr诪zzo-, ƀ!cpC 9 B8B &\洹cز-Kni=ڙٝ麺gG^Q]f8AE!8LI)H4Rdg $\ m2΢Zsju 2yUS Rz/_Fd(\M6LRŽdLZh"amd(^,hQ2`˺S,Z䲁!a&İPŗ 6͂MW8jV*$ ZvaXE\cd|f”GLA8 {\h(.-[bmNhNÆe۶n+L~-a52_6} neV9Δ}J&`8FyMIԒ5 ’K6b´) Us=q*=2JIdPX)A,*B#?鐎pWi0+B\PZ^l=hSFhET+G8A#<%r *^z^9}(7 |D1&%J1WI+M@(Z.wQNbXUŘA3ZS-2Ix!91` 7B,-UKlllWH d-s&= c bo9KCcARݐXiO̎j{f 昛 :V!jPLk 2qp-[ǔ)u8XGԾL(q()%- zt_BGԉWB*""F (\h& eq5= Q/?9?Ψ4V<0}"QVcv#")0K|Y!T[ !3 C(i+Ag{R+'rqD6-!#S빵-L!,+ H, DK-Q17 h9xtc.@, Bg T(Q 1eRtS弸(KAe KvىSjsd$ub$('YDV~$IaƯ7Mn2=;.=osi%.qm8su;PN1ʂ<B U5۬aAW75ey#+8ɪ»,q<ű5-`܀TAF~A6qWj4Bvi)adr (~ w11oS+Lj8NHR(F]"b&S #i鈎%B Xg%RQ"TW Rp{_pT2Q,!83!,s&u*_̌7^"s bft hw3~3&S֬[jB'م0ΙaeL03']c&w~=7VC>.Pȉ3C2pX-*zdyfghYwj$<J4l1LN MRPGT%kfGMlRR3ۮ -|C%iS.|˔OAr٬ LoB<LfTeF/.2;(!Lʉp6V(HT:K!M$h,r0 [LZd&S\buYSp 4.1Ö54(! yuJI`6:GrX+Ź . [tps)-fAXzS!k PxC4;G7? XˇNU!f8~!!Db1FJHnspqX?(&\c%=DYE  o0 zޅJ%S9j*yɪ86"\@0 )QY>C TID4Uȼ"ǣp29\b( L3^|Dc* U^ʤASGqw]HSok=BR8C6Z8X;Xs~'4  V:& ΋wwMD<DByP(úrqݑ̰{/itYԜ֩P[ %&gtм6bLk#Är R-]5$G;NLf(VljlzMǣAIXYʶNev+P,2X(VN9P(kT8%T3@!g lB<9Waddj$y: fG&c q/;W]I$@!:,LCƟ w؅d"+ ~Ūfaj{e b~U Z +9MIJ̞ V=4bk#S|vT ̙,r(s#sp_>]U#9YZ T9Aht [O?u[-,IhCiI{9iF#>0$#c\¨K~X:F|лQ) 3ΊЊ%. JogY2T*맘 |n ̦oYN7?*P͑4lSx|ϛn?|w6n,$n˔ӵi,3TK ڠׂ?F$ y wtY2 15*M4ֈKF  F, pcmܙ8RG @jpnjIJř5QcPyYR#- !)^2qcv%B|NbDff K"Hfp9`Z LL%l ed t,c:ej,cզbA6 R@bf$.M=2q*113VRf/h:р0 u7Fvh /j~ uk%o. FdoC]c/óA!@*81=XF }ETW|p|ϋ@PKQ W ,0ȑxjeس*(+J0@nsN!2c ו8q׌xX8e\b;1H\u'j곘=:Ăzu̿Y~Yj*Dd0 3X3VPJƷ0 M|u>h]/pF߰Vy8?뉊 2hAVy"RaC }#[-z@eRJt,iq y[nPT99)=QJW0a:R,?\cR( y])؇q@ 8əi(0iCo,B10~4LKxW [*r1^)јP%T"`0b`˃ a]p|o+^t⌵7Se/xˎ'+eCierZRӾN _Yμ?>ޡSUZ/He`DImJ+MĐ!+aC2V\W,=Hw|GвG.JCFBџ[aB9e|5-*˿S_تHyN)UYG G#L HQ@YK tBBjjD }W ƥEfx]iJGNØ7q *`8xa )- R,yHH[t檫jq^CJ·J'k ?H{2t9&|;&{! L.m2Ct~ aӤZ,Nt,5՚I$TkaKKZ u_DAyQ%T Y\̩U n0HҊ; *%CGU*=YXn)@V0V.p MG|,"UaT題ΘY[n;>7'u %ٖhx3ղh5<_RW*e "bxlJ'Egͥ?X~u!Vplk:X3GoڙJDJ!-> c}3,\iaɪ(_*Fr}|ʜy\vk $! 9dž|0˥?m 1DEOr6ViJwB' EPɺ!S՞Ejh^!=BH/אfN/PEF!UAcƂt7ft0 Rfqд`ؓbg t[xWQ 0n/l-\{0lTF6dHYxYY76=x}ݺ%%sǬDiȆ0pG2K R m+g/Ty1XA\;0k%(ÕYu֚+g|CX"8-!"8<Ȥ]hܹ>HgNn.BOm^HpreVļ"J h`1dk)+%Fhg*  ]B[7Qz pR0T)X X:4ҥLP[}IDATw3D) /YW̴\7ƈQGmibn <R0,*pѩЬDRT. _\$_sMO"3=3f0@\(}u q1d̺EX 6vǟ;vReUBW/&l%(ҹP-mEAJV0s[>PbȠCQڕ/A0z 3Qp0ȁs5v5_{/. HZ%z Bi% ]LÀ*/scS{-PP%sʹ172Zi"12Cכa!A(B X\.| ,HEQ~4fAUϪQX-N @%t4` aԲ3R鯥eXS:{ӜϓSMx倀B. 쯌}PT%0xerk7Í "u7,hF? cs9[ Ia8BG{SNV^ʀHڠ!rLf;Pi礋kDBB,VWp4Ɗ"(n C` Xd"DPz9J{%<")}hVUH 9̓bڢu>eH6^.X(BË_U$H_h3}Dm"c#y-ׯypC̐[5!ǡJPp|H}XnoS[]<2e7ҁ\.o~,NDsV[s 5<68д1җP^%{0%)2Chg 3N >N TnLLW[8zC# :j͞Zm]uL9H%RtHmm~:iYB<. ' L5~ <ҳCɅceħVMlpݖ r]&={ zVef&-8(#g2 Ι^y.A,jVVG6`!cUGP-:"00c2eF̛~r0 6òa3W>{fЭ= ~Xg #7iCɀxUZBBhhѻ<ψz'lȉ< [B2YXZzӨQ 9~!N178yeox#Z=YD7uS/}Ian[ ZgYRA6IC1U+MLVX@M+s}bu :# :1X"`3\8 Ja4i8j:y=3W^;.rN ̪g;`9LC$+ ؒfA!n6·}鹌w!xCSs5K""9h>9i#aQ'`*EE*4Pc8Z)KLJݤo#'0dCDr08}Pٺ`V`6ˠW O +}[mӣrW|p3P 1,*A #WĶr0 'k}lSoK ljYv~ `O2r)\靸h=m]ePt7 JteOQ3yVyB9fu R\PƮH\c?[;5@BLJ퀔O` fy`dcPWSä53|-^0ëG*s.ʬD,MVfhfH:XaN,ʻ\ :=_;U_8hH\9 M1Sɲ^jznbb.Ή"a9~cPG._Xe|3-{t Yi*&JI9 <^om&wwHe pi6tv$/L.vi.u su'Ww':N`*y7)"24 Rq$ io=sOkǙ50'Vꭏ^:zMkQ*$F̈1e:!>ݕH)Ym$eXABv}NU#b)EĪI0ļb:\h{ޏ&8ܜ`&?K5>eTzΛ B/p8`508Nk-"{MciU= d]ƲֶY`ZlMuhzXr%"WP1 Ep9VaE=-hA!K*@nc.8) [,b#4NB7VV]0SՕ3BE =`U Bb <ޚŰ3bU>QN<@VKdb)L%bzysOq1H dkHkH=ݟe>V:AK n"#8,"~5pp>B.Z(ĭja9pm A 75/|WwW9O5(=%żs+AhiHws墣}}Aˀd  YKaZ/zWt٢3]ڿ?ΰLJ:T lDLJC2Z޻~}vr_w6yp+48&iVZ2xx S; )Ok6Ź]N5sӑH%TZ<ר_!zm7E#lyω36Z,V[d`1>nwJh\\f &*IԗƂ\%/=[ !R|Kc U53ͥ [_|쌅YI\$&:Ȉ%q kkU7nBNY]!D%&P]CXrңc6yFq1ut+8< Z'7=u٧M\yJ|*Z-µsAbCGPr 9 W]aJ0/ #ؒf;&1 KbZEN!SIGyDgDx̊^(՝xU<-rdoi_bKd0ӄɚ/Ȇj9`6EW=[ˮC[{__ۡj窗i&"|1[xEh쭌~c|׭_ &JY ۑC V{^U^A]p`< W|EKPɧ݂ e.JpZXAOtSX J<#j0ƎPBGkOo;1-IYCwVǿ\t]yhr/l꤅-%T#!.;w0+iCitz[6%bL!TFr"juN$2C uw3"7=Ҁ6R?l)xw0E:S/' 6pѨ5M_M} Ŋ/Jp6F>̑OX\^_^1 7HQ!)!K[BLh !aK Cm0b\oHn|@I/NcNum}jaNHP}lXdB-U?yca9eT4|y r,A^8o?sQDn!NP: _.9&X|(_O/A;s$Z4tN$υy\on=!zicda[*LLՂˠmV=~Rt+Wr8\x;w[#^n5 9oaww\Mt8{ow[_-ӽLqRzOZxN -)4zi!lBcDߛh"Ͻq|49@JyV+;BrGSu%F-<+rw<U{`545OFiլQ 鿳cs0ЙjQ2U}PnV^I!/pJTh1؜N*{K|*hk|+Vڛ0:nǥPH%ƒ٢3pf]TaȒ\Ovt<1F)ys+h/}mwMU dw~?ۙk^Vm#\Ąh@?v`rPZ8:u+VO^6v$+{Bu*晣@ͥӹ"r2ǂY܈QNkS/Fsq+/VE2`|%vbE,{M x䢾݋` !Xx=Z]{  vpʺ)00G`h; 2nb[;:3H|wւ{ʂ-QP'9Rr@Tc m*UY){йeܖy`_&z<6x&{ƳF-_45rjOi`~s$J$ BX`svz.K>߆c֊O(3瓎q<QnVwku]ÏRYw\|bmDF=m+`O:& !\$_uUz+k'?cG/jB6_95̝NhК?ǺGw;A1#1Q:G_7:_7{ݖf`pWIʰvUX*9'Cݚ$4̢TqT!O`ZBs^3EKG13l,MsoED[;+(8fi< ,;Nc Vׅ \fc%M12 PÂZE@LЇtYPa ]=w$z^W{ ;*A!KpP0^O"8o{| $;Xc%R2&bP\:6j=\s Am5)C.Cڗ]PBgA2kDuiއ潧$ ^7%)lM_旽l-7"162]/&dZe9Ze :xu08v+q @ۄiWМK7tٕ5ʧqag0ɤC.2FXN-R ^8K&VЙ'Py 0\Al&/ SBE^Rc`L."$kI6v^7{-m.-J^ۘxwC] G*".++Ud֌]4ZUw_kgɟ%%(xiQ@f'W&BŹ UO>A^Uгp`[5Kkcm\J(bO&'rB}Q.#cȵ`dKPHT]cJv Aԥoˮois[߭ kJRzMy,)UӮaB>h RcF#DVC!^G|j&X\ߑVA N*\~ʏAN-Sm勣GԩLpDs8a*vqTKLFKKo#X4::l*~-cB;!DP΃KcI`T{ tϡKy((vk4€dI.t=^qs:3SB6/=ZcC#TqbKc' `XV~] 6W0 [v2* ;*`y-Q甠S)E(eb W'XkJ-iZ*4**"/E;"rS(:nwNDhGb%. =x^.tttත[^x /tsLֻ~Z.A4))>e5z.!ҁc<55я}\ōX|bV TB0_2ɟ O ̚dR7<J0ʝ+I212!Dbv75H,m%"u5׽+?ZggxFĒ?O֟Xw]haVXYcl|:][QR8L jG{v@'g@&%&&Fl{ڽуVW@ xrV-ͅѱ70BV+3/|M"9# & cgc{T(?+o'NvmT1|֯u)бUsN'L wt(.H Bu͌r3,Q0nXjLX$5VUJ2S3r/ jSU̞ƞ8H׭hs0IDj g3XrS}vhha:МJ>cO"@KxJKgJ*R&T98's=k`3b:~fxcejӍsXƬ;&?<yWٽ /Ɵ7A[MU-2^y7uhts > h6ij~oAF2ĩDuO7ShE*_ g`IK,%jŒyB#'?e87 s 0AgʿbC m蟼',A2+!Aډ)aݕ5x>,2D7Gx7ӧƢ )b-"MR,!$L'b(mH3^*;Ey4VCqm4Iճ(czr8jo\XK@nc=GucE:\`}yɄȬ4s kgZq[mS?jze}I*F&s)c f@CaZ2/"scF @f0޶IA:fɶZgCzU}8F MmG}qiZF5 hPWT sjFP'+Wκ[cʟWxk[/tfh50+}= ?{Ӌ}W0u$nBʐ> @ Cw>@38cu."\QzǾw~X(fyG>>z3 &Cjfvb\>KL@fgU@ʛ8GbY${23Q"H "(<(Nղp[jX,ŭ鴷WZ&%e'HvSaSȒw}~3 Ζm{jb$5n129o|6 I|f!:'.BVVӴecw疠?_q< azw{)!mww37yя4|^cs3-Z<{JxQ r桸̺ɭ#ǷFchhhÆu"χ"Q@+}HÏO{D.pߟx W<-wWpg47,1"[,6TLS6+Y3c ` Q{XmkL?.sG覌W o%SC3k,r^]TC q2 mܐ"8f̐.{ *jC"U$PSS@z`K/$VvoDl+S,ipdLu0E%[q!v1Q:+Mi~e6]"[+o۠u-ieX ='76ơuR $bƍ@Y!+6A V ݇N>zSZnn`ﵗmpj/@'\׆ZW]W^ڽ]rSuqݱcܴ(0`ݦ]JZm^7̂a᜚96$i( ȇ*QPM$<7%;4*u>B5zL%u^@}2[$}yꬍn,Q_NK "<αdX !b9K:;ü/`G+{ChZ;١+/v7ʞ@OHC2iɲ̚1eDҕrw*I,8^$+Ag~φ_Y͹-󤱉+*[Q39Zn/_ o -?};6p*1&j@)UkW䷝[n<>T ߻}^NپS ߩCxpj>o(iڏzQ5t $gpLhܹPgD")2F!l5S(,ʩ30ˠo<GIe;Fq% 0b@I4]0Bđ= 'ҋV.];R*nO_nFMma\QlBćB%I.?Mh"9xK\?*ͤ QARHwS0uEb !BҙCG>SOm0XHIv^FoKeI3 3?6 wAOG] ]BZၬMoO5λ~g>5z?t)#\rh;9|qU8ywGs"Ge*f;Qb\+2r:S[F> G !** /7䔩)0k;#cMBTB%*2Z渀1)#pielóL"ĽQsxi,'c۬-/6szA5ZNJoyW+7CṔRBPx11à e> :eબk,XZ/ qnSzVav73@zz%Q\UC #Q z`0r'm tne$@1L5pS.>%,%$:W?ohՐý+z\`9cǮ>8vwm8yJLYZjЬQ]q)i[Q5B7ľ^}E@HB$ɖFHP,YxFg${cY>{d9(thJiҔDR\bFwoWfF{#"#ǔ/{wM:nv;V 7rE"2K'6N@0"_ЃSɏMp{xzQ%wc[K@'aTJp$NgQ=0z4y l*N˙hޠD}9)Õ@/)rr:͍P;??yL䫯N>w*RDZ2H4VAY;Zxц"pKT`Q{W7rQv9ngy6:?yηRc~DRȯX^{rfqsWA=j'1'^ktKeW80y! ,~$Z(-u' s+Ȱ T,lj8굇-rίWǿur'>؉Cyx];0QJZ/! 8gcyC]k]j~ɂ5 `ܪc2{Ps4Ȓ/- xҏlįW:ҠJEW[sg ʊH(pj6+0,K$qomLvRP #חbk^rY<!9ʈ%ûn>G_8ԛyU Wej47qU&TZ>՝eRo6N~%7M5GL_" }̳$YwBX ToEON T;0^4/nuD0SBIWq?rr54512L}8}B -|zh\Z€%!Qsǖ[5bX h r7CL JϜ1׮}Ɲu<ѧgF U**YIZ0UZ"!$:V3)!7$=@Ȟh@Kll+vϴ^- ygi:\3=3XwP_M -/pj8X"R怮Lo5ۄZSks[\̔P-euX*?luCi*OX:p+ $=+%LK^԰Ǟ[;+pfka^́%t5B[?ef d kOSɷb>Tve+B'UOS!Gq8QB+{>w+%Hᡕ%.P[oDَ}_?{/v59ܳéEgP sA*Aj}?~b0W׻I_;k,%NݝzF|[ Ӆx6+ԮL&~|v:}4n9`դĄ^B}B [!~ߙ/ߺJHe9Ph6R~XHTK>=G9<=x8G86/'1莸CB=lZ"0 ĵ6ɑT!,7jbH" $jBA!Z7; am@W~_ހo/|M N0AhaK'(v;ؓhiQcbCeX (oRS[3m++@'ɳxssP ىC8fνG޻4aI(t9]uS;s[:E&t+ɔt'B8՘M>`Y*]v52"|uْmirDJRps1$c}b F @%:ofNgzD 8JZe4[zWؼS4pX4E-sO %ױﲸDtwwPMVWKJ %Mbvmzcqq:m#R XURRF5hY=>}k&7ݙcB?}jVX)s 2{%mE&-`v&$H kTM|~o|Y:T#*Np՜w}YKųDV:hO;`td XguSBDbex5x[FjF%H/TYivgX }akBJ8?$15AUSRr>,.㧤Bnn4?]EiMZαP51Zh=#+h UˡU̼v!ztp6Z7ý޽o*uˆh9 h6=G!MF9ZEbgR{H'UMZٱ|_lM())Հ KQ:?8HA;,5=  96u:3~|v%dc*b9kѶOٖ4 Be]Wc+SPP!ؒr?Ʀvᶪőt"ʀgЏ[S݋.=.i*(ҖZRnB "8KAJ VHDx|rjo"Ŭ0[8#)T"p Ǫ T`kZYie1,9?&"KwE mD&(ca`#[IOb+MB6 DZ!Zwsx r;/'mRR–juw 2o&|Q!zQ+K?:6??HZ))F^:r[(*7}#&?ڮ/;؊,RA7?5u`jsw}}6Woύdݚjց5"ARj*rsb=ҝ]lO]ܘ5~yD7oik,"uAz r ՕM4Ę"s_>;_[*oEI="FQFx{iǫ *ݽ4 NtǭNz `ڀQgם]yí} bޤb_!{E.VA(wlC`c7_D87 ǮEcWUi !dJ{cG}n_fh1 3#;ӫ7x+ KJ[&f*Nou ᯜ?\p'$Ed!ZR3M֫'IS=5 BA@gUƫk_#ǖq딺(BԁvHCIT{ ٸńYR%Ȕ Z&lja1rTd&IY>]jG*ھeCrRdŖQ~‚OYSW4 LK3H =hf6j`ȭ"\10MP]FN!jѭ\/+uak|a")Jz@Ob^qnYnYc s&Vd< 8 f}nh}ɑ8HU,n}ʃ:+XmAe#UEjnMMLBxqe'y腟9 Ll&&6>{){8.^JKK@ė;+`,*n!Yd&sTB[-=5xe^""cLkb&!UR{[ۋo[_xjڥZ1RJ. )[0亢2/JoIEdL ?.ǫv}4 SAht IR!+;V!&VXN 'u9SٜDX18%I] K@,fKa,<ΜfiԧQDxYmG鏿)QLIBeɰ7maAFO?_=y瞗5V'VHf %mF0bq8/峫#`UJx_j$[~Ehy=O]=η#{5x??1FocH2u>=^eU>($\^m=6 *l,txP|}_~'5 3mwkwiD{ m[$^e%Qii߸:ii2 i!^(R2NtZ$ZZj%RGL®|nwYltRzŠTa4SΥ_{]Ƨ!-9?6!Fbd hG#^`:΁IDx$S:߷KÈaO҄J7vT1BZi(1P iKXhc ~!Ƕ3J![+53իx?_ypq$Ϳ}E =-.~S{ΘJh/X!z.3 {`k˿UB@rʉt:R"I 6DI JF[*OM֮փA$TJJ?zdF]E*ZO.8}0,Mo0+DvvuC%; RX ]ݞ4Q^DP{ʋSr)IR0$ "NPmjБh4N%G\YV9tzߩN]+1eU*GtE~ ^*^C8=[^:Ҝ8kHſ+7>wrܫWƥ~o^ #aKfFŞk[0V7X;2,!PBџze鞿|}O^lV4 \;]2J$]ZBg;k(z/6vfU咾Zol 1aHUД6Ha֍DmK>OL?\ŀ1  b='^m[>SP[%5+?wqIi`ٴA{e>f^ImeY64uT|%LxcWrQ)C|t)<%In|BY"þ*ej-dP |ip8AL,3J2'oE释rb Jʰ6#zH(,&I29↡e[)ՋyˢtI6JϘ!;\7 #q@&nRN m6s% sPdo?;;GF=5V7b n#gX%ο|ē@5h 11SǛXka26ƃozR]@i'_uh ~e< \ fB=lFd^eR$k-jUz)a' }tER pT!hK!ktXS@1U>ҥ#q9f͕u`u\4vV1Yhu YN Y|P H,bR!SƷ%THi\wJ%y1q9M :)XkO=S_m=bwiFO>lָuv;֡N%L[oQv DB/J1kaE h<\4_>k#-T{a.7d~/IkrApPz];5!'hZ +ɭɃlhDu $س~acHIYDڢv%-HIS,Xc@ʌ t)`Sc24Km@?;  +[.u A+6LP[I!ȷE RRX`` خ <nQFWVX(hNe|61ކ?2c]ݜAv3.uk1X@ض,0u~uQkd1)]ǩAc(Ѩ?cԤIZ=jB;JsI[+_]yP bd`4oVX䡕]} cPTe] lLҔN Rܾ25D;)) *!xM*`" 0M$ Vv NpCDt-;n!"0 4b) McΓc.y>3\ N &Dhu?[,Ca(|=6/ܕBj"BnΊo;_<_IaQz`n {Fy枹 ů79LaӋ/>O .bOwOw~G£~b7I,w#\` o9:r,gAv-9,hr4q5wJWE L1D!!(]R$2{%eO vSN83WB=+ͭYn:hCͤNnVgb: L0 ٍGRuJʂa ̢:ׁEtx抝Њ;ɏSi[mc Zz: )2$("ywʴh6B!S'i,4<Heb\KzsYǫ A˳A@g4n>oo'\eG/na b"*di#2}}=n6\$ %i`D~K2Q80;z$P( h^]C9j^K72O'KqFnn_E]PCĴ ۮH6iWX7QJ," #T k= @JIB -񂋝SGX37۟P)i.-2?rA`\QRN\$5/0S ثyS{U2HB,;ґ1vJzWzG,T/&ujP9WCm+WN1QO糷{C5X^6B[8WTfaY}%ߔ=CS浳 KH>0=:s+12JR3ί8jIՖ,GvM;/~.3t^ѐM`oqp|'G=}{N a5e9(& Mǩ2HAw w+{+^;($Y4Y# ?~ LU,[JvurjŽNi|0H7 FXА>FH!M#!U@. _/Py'ؠQ1^۰ֈ_ƺطU`.vhzg\Ċߢܽ 䃃HF{۹ $yuVjO0F:yyQG+E:IFl {&{&o;lw/>AKHnԙnbP8]3|!T##+lܵ־('DF%dZ0Ye8dBqCgU9ifkώ%'t%hB{03&G(7"%d).iVg.`Mg!H]WFFFdm=+9Y.8cV d¼{|$gN+]DaB{l-*4mj9t< 7Sa:@>Y.PG|UCF~Sz(:q-B?@QXTLIW?؎fzg7٥ff*|Dn^/<7]R6DT[cĕ-18MaEʩ[xNIjUlGC? ^]B/Bes5j@83^, _.oB;^ek:o< hm~ oNʘ~ I4a0TA0Ѯl@ b% ܱa{fQǗ^Ax…RcڊtKXUk "KyF.juz Hֲ+F]VelCǫ52$x]ư a$hRx.`bĦs{URzG~!bV(5&F#J7q?y m}53380Zȗ07ip+Je~Ώ\~οya)/Ur}B9*Ȍ5\c.S9Y̘pZ-U(`cPy#9*ad3RXSU4\HE@Qš1I2v] 2o.+V`&@Y40$39k %zTqڋr /l8AvC(혋WܪSvx5Taa+t1Ը‘"mJ}uHsQJ۴ƥ5+DϹ^4Nm_kh]Մ-!qڀ-O[}ǟS]M K9/R)ɏb2퓂xTxrֳs7ש0&apVN'Sb!>VqN"4-H$ M!C/630jAeH63ԵTtrZVN* 0a.F덀1閣u잧i5f}#h䖡WzاUUroe}=h- 2U|A`7 U#ߢôH7l솻RXB`Z _ƽ<.iH qܠ1ۣ-[Ck7)?&hUP)%-`e 4;e bK Yj픣M)qŴ&)t4FPPi=VVEҠ!wH ΄0Eq$iOf] ܄Cvu1uDA$tۨ mPd[*%an0mP9z@촢@Ҝw=DPx>#<: BM"n753oDa 8L4eCwԎ#j`rY@dj i;Z9ډ4?{&g|SqS-"ULֻf՟Ur+0˸\BOH՜E]Ѐɋ [Jh" 9g:o+yN] ,Ps<eD*У Ri"d FX1oNrE3%gV(5k 2eLm?R re-AU.z*'22pVUVūڱvi{^'A#>vB}C#4'oV;5Tb8s,6}R3g.Zo:0utj l0* j8#TxMeIsςkxi"]NeKSXJM<ڒ0xAc(T=6=M5dRV=ots ׅ_;CW 7 6`n6~+(JrduU`MUH<'{9\Eovi[9Sd)P).y!SzȏWo_A&6hw}#[Fj>;lm?r(hvGXScؕk=saHsЕuxmz[\ L'\S "* b\(  u&V``e$dG\(oHZ(:lM,G9YqX4QV &#PޥI$bVJAMq0LHM%I[SVs4RX-HQBeVYa=r.g/udU<XNG2㌿Q a_7Q"; 7>f7 h IENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9165e5559db8ba31a401327b5617c098.png000066400000000000000000002474071420147000300340550ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx]E?9[nMI 4]E(ʫ _TbDbMپ˙N3svl q {δ3><#xX:̄DWL N܃Q>c 'A?(`>!y Xϊޠ5. AJF#jYd5gtA{Wbd"_{HY_l"҉ R7o9+E{y\}A&w}u3_%X:eW!i7V> G8|` ֪N'D+#zԿSWi9W) ,0z0͜#NBV6A̢ cQk *i/l/:"_zVk cFbf ;;SH, #TO"Y)_3<! ÒЦ6Qfn幈o#VXe֪ԞK h9$SDm=y1Q@ֱDu=:gčH `%g0&'eaS27&ab,gX3fZt:ba5 Ŋl`x5p%0eG &YF0)D>xL%<,+A8C 7CzEòH  A`3Vs(1GeLa:aq_X0#1Z3X|Gi{l0% ğx #WWX2$*gc2xM}bLƪ!2+h3Oa@8XeTDEeLQ`Z6s0z.}.C4KbfA d1!Y pb9x LF&3^ J'~bZB:Xǒ8 C{nFd 5v,Aː5=IL0JBOmsoReͭ78*f;Y9#*QNɍ06W^Ngr"'0tb30˅*BWQ #/sd`K8`N'0LSF }(A6F8EJ@DW Oysrs^d,h LJ,X\49q%Ƃ.`G&Q*SbHKcu, $e G )Fq:J(d2cB`'Mb1X\z5!zHHxh3ywnD<=bj|?X|-xz48# dI-Tcu,yI, d9&Q6)n³WYou,8pR i@rp ۟6;PNcJdbkev/ʊ]@,JRѶU=[1޸.!kD"X^!^%x&&N, >Mj).>}MBB[C+t >&%xqr`^a暖,&X^yn3 ښf{&s, ${ I}f< ;NL?@LƊ:GWnM ;cf#.hTθ+?zO%r%R=dsq!ŐXME@J` Q:&Ӫsx.GXND^D*Rb#tĹ dV4GXD\P##*d?zIHTx4e`D!~Gr@΃J ĢhC[ "< +cg+f7l65ίr"cc0BZDw-2!gFd;2U f:f$&583DZ@-ơs`vZF5G34 ܄j|<<]!XC~,%| 3c$AV'OXz3Iwk!'_M`ydz8 [!/@9w}T@R$_G_%CY${+Ibk. K DLrBRzI,Dg8IDGb)4f>Oerb !rJ{Il6гX}D7cvL Ez O=6HeR1,^ .S: pbkn>"G&%_N{"ѳ(ڟPS|/Hk,m sN9k`ϦWTT[j9䅾ScXgx7:XP>.P|kOʩNXiE+OvsOha?]f_ogt[PTiޕÑ!fסq#[dU.14%?t'Aފܾu8Y(xy7X|VL/"$N0䚩6aXM[Rf˵#B2۬w-K)HŹKE[+Ƚ`smbՃx䷹oiŒo"f49Ja!E\ǤzR| I `烐VEs^hU=4S:+ g@R@,BVuwo}SR*g;K^jamU}OtT[L= EU|=6\.Eq,uٴٲof]|]"ъZH} F'r!m70Vڵ~eca-u3j]pNfw}Z1})]RV9c .rymմ<7_UHjKYj'1 x Rj# ;H>tTGWlKi]b&L~*\Db9bї-^ ȉ~FR-p żeï̴ mw$ǞVW3'qש~[h !& i8s L>fG0UI͝m%DgItk{1$}EzȤ XNeӻ?S&rU6.uHoc4Sga}*L{6iږLȦwYZ6ʾR!(r{M 5\//Z-,C t7)',΢bq'g1=2tՂqj4£8YE`r ?+".9gczI)"^!$G-H*DΙ$բ_/1_%#MQ<&~t?JzE>_Bz!i{ {w$p&KnӒM@ǝO7y+;P6\MzQ #GBUc#Oo[`Zsn1Y38y$ Ʊ7Q_^r:Ϡ( Y06ywl-]%F4LfCoy}Z MO]bCϩh!a]6ϑux],זqKbcb4~ťO?, Ga_>8EMa 4]b2#JGS.*Bb]bxWrMg8Rd<3ȳ٫KCo$id˿k\2]mo0u-!]<HbPz1X1"P[aq[QU-ȊvEy< -ll~|E{oZ'(q=Dؼ۷Y+jWXjr9O+Ļy2=x+ʯsά-/jP!Th2wi>+wa7z|7`Qq.<׻ lVŌkpk T"`qL630"2Mq?=«A :>;尪؎CRPilj9i9wQAnvC܅lŊ 81!C S{X~SυA~hҫ'UTر ڛ^R(ydzAU!r.rPyS8܍3ֲdb猃zRol H0Go Y +^'ì&Kpjc7={=)Eŗ[cg~=>&yY KyaDҩEeghzl_3,֖;WR[ Hxpn\ J3aؠ u:ǩ~̛ x\5rB\$Dt*%Us?__t]5 9gOQB$zq)H[>U1pFM1ɶ+w\nZp5*:)i8LƔ6zӔSumwDT%ԧ2龑_nddHp NewQ!b%ש(X>`I>8 Ax5eDte ~ G{#H ܁+{Qli1 t꺅K ,JPJWpV4 k b&ZM7hL"+Qޢt>BeHjdDv>Iʍiv.{DzgBjpLL'; Ǒ{4bgʻA'ZU]aA,`oQ_-Γr]*m'ũm4}A8D͟VXDY-<"wN?u(c۲񭂭4*S2#$q[Ѧ͝\VaAtE2l\TQ^>ѩb&.\\(;?= ?$溸z$ 퉦c\,d_jΛA@lK+g3BTm&+W-s$vA0 >?VM@~`xw0!$rv,1G%˿ 8I**H z"נsb $;ǟc Ey'J?!GXEۄdR"Go?~*V/Dޓ{G#TB*j&!6[9A y d* #Vܙ뼖R$IOl?;@WGn/\#ĉx<`V*] fzݮG{|2x/r2PcܳSod]YM AB5s =dFΪ/ȑ)LC $l>Bx\XQzxupɎs7MZĚ7+9y7ww?7iIdy`Ӯ#QyK}U3g'suks8' X"nO4o[x\YVx lroqmn(3_t寫%Ynlf{?=kwgeL~ju2'w sI:z~O:1X9LJ0VN8-};l7}yMٔgD9f{35W۳)X>ʹiW%u>DZWFv¦&H_XGjT$s6=pޜ K5D*ys&;O߰EUs"ovzO>qFh(U;-*_T|ݲy8|vuUUzβ}woE\`nr2tA>Mघ[aJoJr˶#[ S$IaV8ż"8dQNHz~ evwLM {"a1 9ꑘGê!W 1+W/ {5 @Lݏs&HEI 9@&-G#[ ~ Y èwIuqD[r B~&3 bRDNz@Qגu*2A~DNJ'WϒrXF$&f)̃(8 el# S~%glyV>+&x;J&ep ֮D[I^k< [4'tgD u{@"LID~F#@}j :4vVkx\WJ+*A).1M{1e#CxPe'acЄ2j$p%կfjJԂ|ʳ]aC̲(xEfP Ig5%GMA 3qaTɧCw$hB)re$t7QsyH:oV36E%j~1u>82QCgO> cpL,})`5Az1fgH,#Ёw}@Q#r!NM'&L>U*YoI sC WsXQ*9.Z sLX +T lvיԓ &DTFOU/n0K:'!UPe"bmb.!?W p[b t0:4O *!g<'B[\M8,NsE#v1g X_ qB`"=401&IiF#\e56L֡ +-,]ORt[aAp7|c]KVj~*Mf$R1xNé^N;HIEWd_B@&&0~d|s Vt`=2-ʦ uܑ͌0RexC1 evj DzĊ?gxw < 7G+pcD+f+HR%5]$,~2&)dKE0X5QT ĊVmB/F'ӑH@jFG<Ų;GuBx+ӑD X'k&J#xqP8a-ޡЊhE}f?.$Gt?-E+jWc";& ;{C`قsX|=oɍ=eH.9m&ۊ.}ktʍ;Sm 3ӃʱΪmdk: jU_ʉTd)ȥ 3^;R \[U8:{D*/!5ÿƁ E_F`ydzo-^Co#3~"rKSzn dl׊S N3!Ó 6{բw#A ߣPv]*߲b0)/ɻ^|Cr\|k~"G5C669s @^mnl[e)]&9k\/~)2Vv^\Xq BBbu`x E?,\rVH'zgYj,m床3yі-I}H?& [ꍅiv=ҁpI3/s`CY9ݶJ/ /fI8N$"k~e<&|CA努վLjHmNd [NϥsNFԼmvqڪiP϶atIk*OD/uP1wޱov;!:.{qQ[Y48w@藻 F EKg)K r/):gj 79»wZ-~c ОaX\蹪pSCN舦httK*](pG_3Qm9gU&X, Đ9]`@j8'ȱ]b|gt1!|Ms쥗qw[ygMgEț02/D@PgT"^&lC@pT*A*4[ryrˑz5גث'qeS7*eId,!tȣ`ؕ6R$95D'H%_$ș賬,%B@pzfU[S[D(S s&-$N9Vpt=ɶo`x @,UC r. 8_\m>_NWhb9K̷7ȩ6cWZc NSpn6՚lEǴ &ًzۿ'ƍ`Xzʈn1D3aApMvgͭ*=%mY{ &X@R;ß7t\& 3{&|xF=ol"/^Tth LpH ==(6hIamѡ\Q=w hc񟚳:+ uǕԮj1쎓kgLo<~m$RSpks v=Ǘ/ujKY)Ξ^s^K\U:i,9K˂B9?X^_0h;[c"mam܂7zMtˑ6ݱbM.z߻Ɛߴl޿{}gqS~@ eCxr#G2A_EWl#}6Xݔ+J.Ͼ1fcꢣP+{n . > gԀ6Q7dm~Kw?X<%&1,OpJ޹wZ2)= ? =J '1 L }N@TEC%$~  $GcLOHJ\{ ye*rȅ_W$8䳗~Fr c+8HZtV5:`n D$ ؾorkh{Yy^e;+`+8y3ْjo䙟o3V*lgx%TŠx!O΍k9.!)9#`  $rkxYCon&Ƣm6w=AHxO.U8*W_>{Y Pe'TچX<;pr;c0 rU6Azc=QcM6Xz|[ɘf?w_>슌imŧ! 'd;liŴ)ú;)uUy74YmwZUU粹6cq moKH2H<+ί/b~bጏlRϼiG#BΙJՌ'$݁ 1J/˩> T ɍK?eTZ[hGKm ,'{{~ c]ȍ<;urF$pRi<y16!yI怬 ĤU/rZ_Lzr؊ֈo訡JXm8r[p^|C-SfL ;"^FtĶi2]ZͳL|3rK?F7f!`:5Gs#~d$[n( i_ݲJv $k"fy >ܾeճӲ匬 uBD6;GyZ]Q)*\צa $bl2JfMc9f'`BbQx/7E%4VHELTl"@,z<;.ɩb12TWT 'Byv'D)L[9Hi _g WU= |6@< ?xk϶QFVyL Ho4Uu_APc` 9KB6v)Lvk#HG!~vqQp;N' '{e衕{=VQ;JFSaTJTu2/ۮKX$-4B"=K&Uc6Q}19DETAZTKpT\HHtTbW;f1TDCvFs &vdtd/Wb0±b}]/WGqQD{{ISx5v6? g(ڷ&*F%`aqs -`o 52{\"y|eQ]ݱ HD=޼O43CʊA+J!ʗtnJiB#+ؕM[0Y\`}% Eru+5£QO1 1H;pѕt4dOUۓ8Vp.WH7[yFdĉmr|*{TQGlJ3C*%_=.8N@67 ѥ:IXIy :%C&ڙ{ӱ=VpAV )ͻgcYѧLE(41f;bL\* 2zmT2"$:cN~UjNG:.8]d^ү}ʸjjgVcL9#&'$3qh;PtBͲEڒJ1mS^PQjJnX7m0JĚ0Pq! UEP$3MTŧۻek1IgSy.I<r^)a4 &y2RM{+nY\a7;#fC(fJ(fKYKLw~)\(8[ő"Ktu]L k!KD1v)7BnL-}@t~KVqY Z 19WqZ*9U[]{Vq#U9iJS[`\%N(Xi90[E+̻Wtf: V6ltͷ 8W?jo5Bl6ݘ"2|ǣӷ{Slę,=_E#lD;}D,,)0<9m5xU)o~_ __Uvj&q: 7w?#R m(OXʭY{~/^_.<=? {Α;C V-]w{hXQwbCQî]R3{YPx)<+onivk66,UTe|cO7xVqW3#,@iΘLGgkd< WT;P,-[zպox0,8O(/~jo-=3>W=W/{}p=}u_= DST{]뫃_}+Ke{஑pr/yxΘw{W痙fEB!Ǝ9& $sX)sXZVU%RϊS-"9!'RK'1AXhK}qvUGJZ.#^_g:NM>_}{b4#GS78W|F=Uܨ&Gxa$JsāWθe"ʔOK~]ULc{~.ZW)w陪94f@VwҰSš<]~'|vE6Ʊ7oNG-t:}msf}ӣ׷|\| {;N;o2I-P=ѿ锅WΫY=fV4w?:qIMsINj߰ᄳ木9 )?kNĪڙ'dxC;:>@4ZX+ Pb:q@'Fzg93vZBPu!V5֟{jO\;"lrt'#Qi,֥͌CbbNỌ(6Ywgr}FS4Rc}d:S$XwFR¨8ULH_4PF) ny$4'b4DGOB-Dƙz) lH1M#P*FbۢifeYyG2 d3NVLɽO6dF16W]c N ЧId$Nf5* Ą!,20 M1C0Epj62vb!@ 35:{ B0!bc @YxT2GlJEϯ\_u_Dûo#rLs#FVkEH%rķMx~ɡ^SB,U,5#JSq##U3 `z! 0pn?Kg)YE/! 3 &;1`4ΞP=C_5HUү#^ D6Z뛄XZY1;ME4OuB JGSm /&*@`R-#itEW4F֝҅XP\' ;SR,l)hDuP҄"L91N@8 Wj!ؾ{_D@rK*:WwQӂ_0Ut@u/@gc8َC+"9 mw7[p H"N\pQ[n-M&46f s؄U;)Z jht=ўWg,@Mț8?) /}nF$bX5D)ù\ ]hspQQi LG$Ll% F;O`e+sEz!lb7}y UHtYj]剮''F0'M#LL Or7$,C:g:SV7Ͼ8evQb| :o ǚ|3椥"qa(L_3vc]:Ú$]`mC{^ gA G8C6GV^hAygC[3Z3tRI7r8 G᠆ t;6JT/WVN]?kf?|a.]Vn6u/V_ex&L1Q!ԧ 骯ɺ?-,x*fhPUpngN2jf6:J1#3 o?1v'Хq9 Yq_X˝u?r_)Ax߼ϸ`/>Ɯh`e-Jq8>ponlkgoGV\^;"KDYrq*$ugISԨn~5LBîx蝆eE,(]*]se4T"Jnߌig.[G$Aɇ?Ѣ9_9Yъ>uY篛:Zmwrl{_Z#"\> ɠW 1-YBը5S kf>pܩx'~~NK 4p[|= `MJN#9*8+8 *↫LN8r|$0Zb9VUv`yt]mkg5 Wm?MRl!@4:Y4O#[!n1@Cj`RL 35[$:J˸iWM |xX!F0W4>mL ldgt͹xQD%@.5Drx(S)(k(+%ȄwF޻YN>qFlm~범0V$(Xm)'&ADFl6՜w`&GBr Di,b8l265xjM4V5;=b,$yɴvcP5^?lbׯ):avq]k׾w+S&MOfߪ# & 2|)3 ._i^Uwo:鍠cc&S Ul-=Mʲѩ찪G&>~:-YkIj8{(-8#{ѽH?M' oӝ-{ S}~d &fb#;TWsޡ՝=fADtOᩳ݇G,k% *hN h/SƠ阥SX+gpq8Z%!'jP{@yNQ "AV *yL)14`ô:ni-r؎CeUO{Qϙf7WRHB  (RU^QDJG%@R I6m3nD',wg9s Μ(æ-u5EηmYոLEQbJZ&B-@JVWTl1#_ ~5ХK ,@h+'Nά(>ݶq-l\\j[Ӡogޮt^;ϏX~ {Pj|Sh7Ne~'hEBDMXa?92nH[G1L)Zʰ qk*~8L7TJSdh+nba`Oo*Km,u>0hm 1ODê(*fbj4J38bCCV30V^-J{ OM7mvC[`!mz6>IT EK~c8㓋Y.A (9wa6&Ƽkl MFjF] ufÆjhAverH@WTTU~ʪ1|L!/@TTsmZE=v겢.i]Y{[=CgٮQ= j.O,(/(8[0-,*PҊUk<t-ם,s-o|n[VCθWRBN)cҭ_iqW;RٵPʊUt34Lt@fY6? S>my\4IEX %燆yND_&#V (=gg#9l6˯HM o-c󋜚 sk/ϩ0){w<<~ձ*yk{l>On~Z?.*j. .ע^FCЁ%wM9Pog&+3]'X9]ഒ+q8uXTO Y|{sv ŗ|45ˊ^nzpagPY1)F ix7*~Ӆ+3I7Hb]Vnbv+0{4,-yp osEꪼl*KcqFdv1h6T!gĘH^\DmR ظ3TeN6eQW?@_ ~!Z YPGl+!+9iC4ט_9̥4;.8+8Tep" i}6E-\TyiL?k`_sR^'-}; M˟#+c;k $g`c#2`-(=h7d~W%Q/ݬ O0-ןbgn.udIPK{_ 1hg2.* |ce%yT}t HS3+zp.+''&<\CpӱPHnGSui,'>wVrǸWR7SX X!K_a#J9.\0Z%fˠB+MX,ew+x!ESW/ɝN`^cWf+XEXIu<Φb˧|o͚V$lDϭ]C V)pdr5bkrZ]|Ӭ <8LJ?sk kӶc<ؚ&0So' !W oLpl ]+#DD +"9'e")w?i .ЉĄzeY&jlS&hym->bc5%'O4gEC_2AO""ͩxH[ V]|q59SIg4/6*4VKdZMfhO3dyID2Xh`1J"fVgץLd CL0$frbkZy{;)~wr9*z*%#QV8hu{ \ t@ro+HK AO"'2O XK 89 #5٥r{dB>_C&k]""8PHf\Px+[Ĉ%$btSe0 PRcԀ¢ P:q5i$sRQT^(N*5(qq&6ܪ-I~r{tʺ,k|c1lѩg*')#+ !}08uI/-~&&g<++ 8}Amu9;B5WJOzkat%C$ڴ* #n 4PNxC$\w Ҕ%;`|)ŸM( SéJdN8$}uډIG@O7,͘sr~x7㹔KvLQZ|#' ^ȯOGe+YUT5)kl+xoygSPURގOD,Ub1 69Zmfx<ʟz)̜7"P V*V$ $NS% 3MzmFs'jU*E!^NԫTX_<w-CsVB "1k%(nY> ߅1wL5*̋k$0䭏qM^*'mL u%o M*:^R_qz\]p@:HSxit}mѥ)* '2+P[8y&iSP!0W#DI*h>}Jj84Z)&S:NѮt^4u81/z0*[t^ V֝`J( M7*6SeMLOG'NZDh\ +Q*ă{n-ZOE=3˷k'{"T7֊*]V~氻#'Տ_ G=kwwaKxw㼲 c6t1%rR䑡c=={kjVdDHx lkE u5XqszϪЛ"N5k7{M{^9dGn!b~rF{e\_'6ɝ^PH řI1B"x\<`-9W?ًW/_Pa^$dM6s*1HF>^L-c$0ޘ`K"KnNN`pcCm}&> &2;0 %'<#H|"*V'F>Ml<1 nӴMM7z{?=kvsQ~fUbeo;ZKC݊Y_ M^&zR2/FFmX ߃ΞbAVʸ h񞏌8ګ,4w4[ 2;;֝m˫hT\(!̃~B7*,ry&Mץ֝Ki,hoG3œq&Qe^㗶m-+('!SzgK:-)׽t-9.wcp(ov*l:3FH[B (ޏ`tulH=G|j,e(v_Ĵ{U6ֆY 2x:HLκ`l WY`X1JR@.hfRu6+~bDQ߀Pt#k4>RJtVe3{Qx]ʴƞL|i6 ;0{'Scb,b=]o/as1 8T4ȫc}pYr2EdcWhq5I܇:^M s {s4~p'Q' u *Zhl5X E)2H.@Rh8P<9詟F L~! ,O,փh,[j'^jɬ`9CPGI.M銥j_@3QkX>i2}k"HUVΈ%[bD P,[s5/DaݤUO e,/OdTJVX`8vj,@Hoo Xm~S +9>D42xtpL\`y eyRUzKcXZ#Ә`!E/:S-PEAi`Ĵ470eX:'y,֮$[oO   LSyh:dy7ɕfdD0و@#$2kөrmfaaju87!#!pjhr$<g<R"D$y١^7rj7|vyM. K=NE՘4SG|}_ܕC~%Vd&27bT ؟RCZvX}Y8ª3-2kcQB/`'gT*],!E\ᆆڬ@D0BN$hgV֌=$Ng-.xa_@\H8?X8E3I:- VMA!"2hƳLb۩s3Xb }GHFyӓ~:0JI46x96s1e$8F(#nH3W UIf*]E UghSfP0 λ9uX,ו^d&H dڸ rQ(殺`Lls Dd+ʦ/f6,۰l.-DOYY '30nGsiznuf ix5)ًϺ~>Ǡgܻ|mCelx~NvțYU[_z̞ƽ*UzJU9cI:Y}P$* sEVQ/5aglvr5Cp H„0EL$Q5<ֽ>g٥+~#é7C,},IGx MWDx|%B#r"Ɓ9(&qjJS\,t)CrmG_X87lCBTka kg:iPfs/=ӽȡ8xJuΝ7YDXLYȨ~E'uQMKgt:}/4Y27I@{Pޔ_l{ᥥk^{JLC7iJ(lf S>\2;"JU脣gjνT/-ހ*.72Ͳ,5΢Ukn|咆!87wŌug~mt2tOUB莕kpEL qƐOyZƼ,yͬ{SXfmxQ*`lG tE3v|i#tHbeԍ:Y+I9? !ލl|'#~&h 8k8?톕)5}Wh2Mw m 9dGS 4 SjR*R*$O\WqRie[v'3Ej^U\[6,-%bٝB B|?|.]bt|X8̀$5u󣣯;rfu?#41+I,֗]D>{G1묵{whl4~SrKWo7z!1.'j;|M"<1nF9]& nEt Z(J&ym!Qv4@Zwr+)_zƏl 'ibp #1g F7n|WGHTSZ~޶6\>q>u@[B,[!, 3JjYRP`6#g@TtcV BҼ+T/(vݷ)^dT  nȾs<tP]IJOGKe-.і\ܣg}Rw8v~niLSs4U鋌%g' >3񆨯'JIg 5ۧ_84z!On/|Ӊ0MZ,ѧmhmr0y[帳~Y jsI<8BJRE n/Y tM՚EOL[y`q,4Z>'֘g(:or֊" ξѱv/7?XEiպH<]u:þ#An[l7鮡634vorg,7O$t*uk[']/^-.+f$Q>(" +rL[g ؗW@ٮT rhHvluԱk2ƾ!20hs[\{. O :=hj}nNcPlHvyz6y>5orwƛv4]ucmG\ǐ;G'1L(v),)sي=VG }$ed}.n"IɬZw2>I4w,O}fg6Wg߸'($nRꜳ2rz޶=|M98Źo|OWX|[^BЕϟ^^["7f*1E/=xڕj4OhkKgM>V+ wpxˬ'/^~{^?gժ;ܼ^lJ&M5o` M սG6(d H6*Jѓelt}p3 ;I%C sCR=uY-&> lB 51n7) do䂞QH|SiMcO^/Lh※l:ɭ8[p xv}J]w/ufLE%OVM[c+ѵG.QZ-n/?CkB?x!IF=p,O?{_k$S7_(|r#]#As[LLciAQ}o$iʢ"UNG g:{=l"un8 ==daɮ~H3뗄h5'S&p!ߟM'ZS)G WuţB`iH~PT5y߷Lؒ%fL}{+t1 cE+o:&B!z!@.Jn]VE/6P Hi*~CzB_ŀs2Ra&rδKaRIyg*,K3̹z8]5N?DHk*ME|dQjZ|Xxgܱ"8)&xG;up=K& ţvcG?/o: 30/:gOip篿; [p 5]>UMMZ p5 O (%-sr"5` L J+\4vkU/ޒ+T[$x`r Pi&7;'J.i#6XI~UNNKPj HP9?p)wlgn%rv"ZgCp"W-ag[C{ ~?|=Ix$x># _uc20ŢC_}7@r],\m#0N ɩx;) ~#l >y0ftsU%>[h Psc{LKeg]ǜ=KSSof # )+( @;;ž( ~R늦-s5&ΗO&Xp5Eb{M}Ɖ/FF%%0KToi,l42u}oIQׇ>ih2shZW^Nq: b$3s!g0)w Y!OIveݬgYPQPx`poGǚ _$2pi055O]yADŽnc1]2{"}ɬYHNK?t_=sZe+;!c`yKmz'#\q-4n]^ 佦p<#h {Xzy:H؀o6㬨]"AMj2"eSh^*!% LTڜ`J'dC ֚K^ XJpWLJ |+|܊(jݔط7#:RU'cۉ? e:$$OqP2&xp 9 5r14EL<ăc(yiVi3]g&6w7D&:Zk2W]"W%lə5Wr?Deg1h#XTCf^9# C]oyrEƏs -ejaPvt-?޼9zG1 G Qe͙M/ppDaJ <f-]60=̠ ;f wrqt`-[boؤ=o%WZ9#L$9 BWCO[XQH+M06PjBLu-g4Dء6W 9LMӪOjmӁؙC!y do,$KMq/est;W, t.ϷllP`lW"2a*Xlm yEk ꓋. _X\+U1sωHHU"`aK,W+[_C#a("&À\AZ(W i^05u:՛Ritfsq[ׁh,T_3?VpcFl8pK~ϣ='0^$A 'bۚѵIDAT{.|7HE08'dňt锗bhz`€*rI1q-I3kk4L/y`}t{ߚWb̰XF"!Y:9)E.Uqշ:d? o %$q>J *A2 ę| {ES5*LYBIΧV[g@Pi,=wkca⁓?=b*[S4Vs܆H?7l*YrJoV{&W[6_r/5Ҝi:=7g `B\ yI)'mNc+BWBzeg55W ]8[|tJP0@<:}ſW<GXj/Zs5a9ÂauUλ'RYs*oKJ痕/vyAaE{}}c͹s1 (hw} 츭lsn eٚ۰E N[n9/ooK8nQw?̿h/=? oϛ3]"Bd$7Ȟ*7S ~q 9<]NѲi̽2SƊ) 3O̾ޯw?[`:ohQߙmZ9mªi³G#M$'|RV8ࣤ @ 3 {KmEeEٸ*?_M+*{ׇ]jK ]GB  ""VuO 3RjTaE}-,7R1ѺDK-*CE"∅BR]Ҙ:Y!7"%y\:=oDf&cшe9M]^8#Ho*F}XsR{ZkX]x"Ŋ썫`d3$Xr2 BHuۍY-+,:\c#}hDWVs3lp vhN[ Yv*wͮ\XʟO=h@`9y pM2wS,t:I*Ytjudl!/$ %طc`Oҋ)E&49W+iG6C$#@(6șӠ CPݤETEi74OAcD;qxX%XcXg2Ov3$IlJpyE}DLAJx\J$Wī Dwʺ6S'tNb ⳻['hHQ,U2o*p VxE (GKDcp8GCI]9WO1SOk;o}1PN!(r#+ܛp,,qhGX΂"9JzvV|Js‹^_|_R:tJG)a$7Z3RI*XJ(UEu4i+}`M3jEUZ<ʕI0OjDHK,c_ 5&K';"o KAw 93I a7tk2#$DaIh+%B!5)_J@%bP2VށOT,ɩM ?%eP$ljy ޓwLL,n+f5B-lK%,4H` wy7]ɀߦDOK~E%N:Wl>SV}?>  kg{a$d> y7brD".a9OX8Ӂ7Tɬ2xT"O&G:L,@MN J&dS s R*-"` HqA$k/RBXmʇˑoGmD1"3!X !a,D}V& P+a–$2@Tq%{)AT8"n0xF@+1W\/,b03GM)5eISm xvx80!Quuфp  ăH^02NB+㸸sDZo5ɽP =_6)bJJ?` GZ@y\\H/#i"[H+VHlJ]$@.hLJ!"\'mO$CT@w(!E,J HG+PNASJBI#)#6?h.pGz #w@(E_ [^lD˚( %x_O^ϔCS$()-qQP)lX1E/߆mipA20Z¾2g0"$~ayJ\ iH4$IJhP˺CLTc/\u O|%A"Of R1*$Lv@2&[4Bfo^ҷkKA,(pn6D!6/_[')4 ăF`4O7]G-5:XУXNJ8pxD.'*P" /r`ZK1dw; "%m2ZPS"¶&VoDJ ؉b&?`Ar6N KPUw, _) R$P̤;Q鐄OBDBiթ Eh_--)AZҼE<2)X(uXywAKQ䊊8MRYMFLZ(QQq()V\)X#b#s ;( q%#^XQT)5 :L79c*ʺ>H8 )0$čdTEK>U (NW"erP_ȑ H4g6F)a3`bޱAϝq.wP 0Qxx0fhx#I[0n1X,V[*i)p}WILPTX.DbɓMUי ⍴6;=ME`ImBbCnH?P׽*\m*R&5mCoj4gjxcS]em  0_+@&> CEUB^P-_TVi8m~=>"_qݙgXL:Z5ҵwHrƚN[άv:5ά,6vf_{f$=c!w kg3Tވ'Ř;vv@Iw߲߭թoޞk[xAbKUJ?H[7ĢB(MښLKY%T[8c}rCZ}gWv&7eP|+0h[Ԧ2sy/oØJp}3>ITg(\>qDx a_F\ls_z5d.U(RJ;hjSTTaH2 ͶOc6w}h컺M$|[-FOMl0C[CxG[t%R9emuQSLUmg`D!h}0Tjtk1 u$(\Z;/' z[ix"hI 7 fD8,(-2_mEniqMDZAEL"袚n0#vOʬ>o4cW`57*6cӀ4U^XjE{s~af $`q ֔ٚ`YwVUp0^$/\3E'ka&®O7?F쵛/4V&%ʫEz|vo s*c)@s mvvj71guޮWI0Q+z@ ޼}Pw'=y2E(/GkُqsZ62 1=I#*8pOc/,m-(MKFi MM[jeg4^o?;@|ຠ0yw~uV~FWsK6>_s}}b*vU]<@iH"MF56޺竛•Klw]syIҶ-DA WGc?mSQ4ז/sZI2>}_wæۖZuw5vFP\916ȪKU{ʼj{GvU5?Zu!t n6]}Ӓ5?x%,B8|a@˯J%Ma D{_;eZlڭ=\/h(^{ {fYv\N+3f *zɿ $$B@j=А_Sf}/+R ֝*%Hn]OJDOY3<:CGrRXQKn|aFI(TB$Xa$VT:Ң xX}cÃ+9?cBj&? w~'lCjJDvkb]Y\'{77UR$ST[sH$w(bu,&vV5.]3Øάk7ws;8~m/\:~䕣0`.+dYl" phdl9&30&cJӇ;lP/mg4;XԤSMEze[8owMeNqVtHxPʋ@bhiYEBNEF-z-8Y 2E JkJ%$4)qfTBJW 4F"% #Ki1m䆛k1"3 $gGJ#ʐMe얖U).I"SuTgp*?&?]9T86}Au |9b[(&,WG<|xŒ[5A|]siMJS@s9[h&W-l,Hr 40nu1l!L$q*y K,%ֿc/$aE.5!Ui=Gx0MpG[q ^[h gP1)?^,i> `n^r 8mߞDF}|Sw=̠!ۥ;ײ())8je94T1>5㭥m* j]ˌ)M(`r6MD]w'ia8ƌ\^K,JZ_ҿHi 1-.SD8e_b7PXD2.m乃E_ܒ+4J ƣ$ZA>)Fƒ|b,'r L| z)%S(#dg]S)Y@SV @@Ș5૎\Z;yt7Yʆ3*R^\@*’%%b `TkѼ j z_4oĹID ar+XvڢK >>@LŮs,+3u gXX^};&~yp0 HB?RUX)V pJ *}?B54tQ~FB4JmP1 #EHAJPe`PS*3mz5ܬ8J< :-cCu}{iqÊvX$E N։8%`(=1t„cF{I} HL2toV|JIBER2zQے, *>i-8H㱘 Ztvx_lŊ"xkR\IV!_J䤏RϤE~a5&U#,;]?̎qhF Q`MZpNklcv]'p^pmIP&癓C}f$wy=C>}~kϘ#ַ-c*S[?ˌf`l4A>K)+o.`a"PVc[2@"-Ghp`;ewq" e'OXUjhGB\f, vK 6AWo̢ˈCIzyXGv:^Y߽eU 40)"0bKT%@{~J*ZËY`Wsfa9󁵚[ vS1HHM(MPqǃ[kK%x9w\{KX6^f. X-`nM[Jl(cz5,,_ O@x(f@|6L,-r.XG qp@t—-Zyݑ_9Bl9 ȉj d&K;˩S["c 3 ˪*TVlz=FV_9<8py:jA6s(*D ~4h4zvtUU=)^|F3a1˨l[jmj=Rޕ2z"(DL;{=im=ꊎ(8Wjzi>dg.['uV}G[A1XC fj#0&$8:A7ߤ*w#XHjއ.52..q \=WIm+|١58N0qe־@#q猧Y3|e X B !Bc 'J~xDlU)tH/e=p>v wer nq3]?9,t~OSqd0ѷ{e9j oԈO6ʒՅ^(ET x!fwS6ǡکgF>vcsF)cppc{BIs{SCLT5Mx/Y'ӳf^EО-O]cu#+L*)c8ݲƌnl& PI)'1dJ}i{d) , DA*Jx4')̍ +G&K2vݸ{ZH0O]0:Wx2CAcxL !S9/J{ܓ.)cyltM/ p>pH&zRU3Sѱ^ޟ[jۜ|H[BކL%P3!,Nڙڅ@=Wn*>&w%CLt]gJvOYcf(JNNY5XQ4ИoK /kZ\j7ؑZX.jtYE.\vDb+G7'γАlM.kmزS?E3 K=AN:ÆE4s4UVZG4t{U+Ω WL3{FYyY-wq=/sϡdTսvȎqLlZϫ=2AhnReU5OjܦڷFsTf:+H>MkWm$C?z5U/]p4]=r5ւ9-MQֵ rӂWM&L+piolz|^RF6TeJ'& cn&6D3\<,8} _La}+uq[16آ级J.XP*v/th9 Zɢy[Sr`O(نdϾFyAbĵ:9;O?eĠ#Vwo)+}曆<3׏h,s|ro,J fgz;\N_cپP^͵l,V3mXo fTGi9C\5`H,"CϽ+- q\r(~f0>NZsT%.sS͔}nHLt&b X{8ur mi@`_Z);oӊTȞms #R0+MKVSX2Kw̪S ѝAt6"9ˑ7zW,YIg:4-;L0}@D0 '3I!AY&,>9霌|Mo6U04KSHyAV״]H}bp)$bVՔdUtdp2f5DȨhڭtnҕ2 D/75Zv+m3G'(*yIQ`;`Xm/@"^UVso4r.ÂSY"H6oBl錊#+8O R ەkputR!C۞b[D6L95Y:MDY=]K#^_{VaRb8fcS H0]o2FSz!R#Kᘣu̎FS, ,@<5 Rea5wYm5OFm䲭V sVPm<НSae Ҡ]j* [^Dʄ9b("i~FVbd+MF:~2D(OG8ԆdI*<,4+) )}Wo zT^CaA$[ykCfC+HfˣCkwS;^IŹl˅|)R7P8'R\ʛ5@7C6kfwTn0hEf.zM_OAhHZCiLoe}U˪htDT4`seB{-S/BnvVAPy 4nQSh  &L 00}˴s1P 0WL m:Yn`Tt᩟Xv5eg~nH:#J'cZIAPARAe_.X<Lmʵkj6@lUʝr]tG:E}| n]bqu֣2" 4& da!<ǣ9/wE?AQFWm28, Ge׶W3|^`U eG4jd/߶$a1.K>Z`)Y#2B5 s;вlecG.\z'U4%&M5Hcq:*i,c݈㴗;.3VU `[3 l$&n!XN@q5K NG!6l~7(=s0s(EX(SP,+A$z*=0Er=͞/RyAk 9ㆴ kڳM~ ͤ4DB`5JВV,[/U@{$̈U躞YE&L2yU|:F@QLk :Кy Z ;1 RXx ^%YQ4B=Y5DB)z"6K}!֘d\g bk۫dYI`v3*{.}3f|6LEI4HC`6WNQ.M%5[WE؆B6,hy?\/,pb<č4E U ]e0)続{i{/-t$% y@eWTrZVXì@gIb&H&Cٯ@40*fTP0k[N}49Gy 3=Uhwp(" ,(/nx#?~z(@g "2<=/sDΰ[Oeo e>W%n5 :,ՎJ @28$bVBtdGVP eȀ$aOQ 6GTe~ѡeܤnf|6V]hEa"F6Жw*ETH"v%Ca^pBH}bX QX ?cP 8JR AVź/7VeL1LW4TʨC7d_7UPso?q8)R%{9eL`ŰXaa7l+LК'!d͏oO3U5~xY  _:$ḂY`A'"7#LA;Jܡ f?rpڬO`mssIfJ|gUP^O0֢0vա?x`EP@lOE<m L4$@ij#ijS7;-DNlt%!3rquhp48M'fah6* œI/b Dx0XCiS +P+P(E( 0BJ\ǩR:$-MFSfSpRMd j A&TAc E!IQ!VҬ"$ 9I2_qT[#>VkiՋ&N?0e=nIKpS|:lO ^Z xeޠAGl#дvL3# J>}Ň]A`Em3Q$ƿ0ҵ\A:ު.z޼ЧOɮOL"CIqwcB*4G9eŏG #pà5rTQYQ1,-Q~IP`Ο֝ԇݣVLΝ,JxkM.rAt \Z 2.H8QG@Wnzxa7+S/` A{\%K|l1PHHәL*VbG.CD||r7SݞPיDG^:bcwoV]:R@H/Cbqp߅mJ}3:0hvc)cƕN0!4M9񻏈Bs|@% x0-% +"*ZGb)ꡋO{ EWkc᥮g8uy1ˍJ]N(ڲ#xO|+R4c_Bl=¨כ7_qQR<~k1uyi ~cN1A77ψV2TaS"fĖSIv17Uʺ؍+] n^CMښ@>5_XzQ򦠄AZy('Ȅ„'#kN 2; :`ytTiě/&pB͗ԭ \}"&zs3]\0N8mӈ3ѷ>/ |lu'!)⤷*_S;n*nUuoUA. [ YBjc":(廄HBuWOTGlWy9u!{bd4y Mw_pEgǃ jim?O5/J ! 1RbIjf!q|fR,t&姗Oԭ ܰoՕiҙWhHJxͥs{guA2(wſ\w}7_ۻFbR.iK Fs =쒆ɼ̡AuWo8gh2 ݜvoƓ ( %?S( еt&DӡtdQ,@j:ܑyJlp_TX<&>QEZlXϧ.Xt bH5\d!O EQ[pG'ox1IQ5\rmoZuy T各)UƦUWY<{_xsGޙf7vpM7_HY3֬,o9oz`řH~zZ'̋%-]O9W@?!ׯ;nXTc C"몎xp~/c\ϔL$V3WRcON} z)s9LTi#ұ )*lV 0a0 :ڬ”Qe=dVcq9u#%] @}#m^ oKՃsٺGɢJSO[ $+XoJ` 雟Uzӟ=9ꬻ'][).<!sL?*$x+R*0Wt|x`i K@kax0s1}4mb+5М":~6glzտ+ _@I e¡\v)(QGBȻ#]Qǯ{2B"%N>>♦gǼq&C7I1㓝[?EQk FCI)"d¨Rk1 QysP}AP^\WOZޓ )?B4|^?4<@4[Xd]q"I-ͯ(/ RS^2T O{(eQkpdqofT]tQ~uϦXe ^YK(%>yȾCP'wI\AA"t3K]OCWy:y5 o,t8y?])&HUEUKC/{DQrT8@>CDeS0&S^m*,.e 9\dWdF@Y ZS̫P١q̪ÔJ.,neLakUZUo~`_m\e|rljG S)$(C,#u<<,)XԵ^o_e% 0tyek5pT_TZU5h.J ht|@{tt010&2R,?]bB}xt'Y{Lɀ>m驕V$66(G O9ϙ:D,^ed͐7˪5Ia CG3  |@>RJi ? KAS1T+԰HB𘐏0z\b6Z-/ z0@/4V K̙l; YӮ+/rQBPP}PY0H O.V7 IL;K{X}O+ٝh TiE+PfpںVD\@p")ŊɲEga _BLA1{!:U^6@.zƭ>lrF#*KSy2TXlRF_?oXOk 0q~~ ZF("G0]喌 }Ð͊/wD9 b%^@:b#D)2F6TکW0 MCh : D2cKCP`DXdCœ:LAA7]*u4ה,0k`3A8J~P7xz^PyU ]`aǒ*C*龎3?:f)#XCӅou8/^72&5e)4EXV/+HVU$ޱ ABAĠ%) A,B9#C8US%kqUB4åcS֕8Q&Bjdi0sÒ ϖPѪ(Hz&*w IFByLZ;/( kQ V"ۏC#1'xr.{J1=s%6K9k[Ѿ 9vKwї/ݞOxt߳f_KjOHx@i5ߕI^^= +L_}ۜ>ds+[FĠfFZbbHN))8xRA.2lC51a՞ۙ.R ěC-_}$#DEq/ kY7aj/)D  R户p_%i<@I2`:> CW{Յ(V<,yn77,|,6~}+inkyTjPhLPW빡.ASPkC.)e%gQDHtɢܟP3|o-g\"gGmC5PZ tx+uґEXLcɐ'PžKeb Ci2tF] 4)L{, +(+kou C]x F=*A&+Ч5&x8wE=n^/7 }5Oe( ?SCn)Jx" *'Rx;59QTAV؅W9KO%o\ 6]櫻0{~ <]2W,7 \6yFӽ 5mx^bL[j|@$ZW"OߴBDW@{@7BCCG%: ZO1FcQTB-1R}#f6rhaYUr(w8%LE sj7rǴa`7]T28X7V yfj/bU R[]jLGAK5uVE#/i)Q܉?j_p_S aa$+j'(g#s)]8.ˬڿ;GwXSrX#k8,"K,RxJbQ:[&Wi1ذdY$[a]t7o&ςXY'+Osrizk#6GYC'>H=it['ͧS\4Tu^PZ)Oz?Dz$YN HZ/mQVג5I=I'"qE![gsP1 y@$"@h$o;%ĠiǦ=# ⼊[URk7Jل,/ 箙~9AK8QG݃~iazɯ=tVOwq%П:GR[;b0g+BඁU/l;NV#g[p,ۗ,Y~S'Xhߊ;:Nrמ^BKّ:#x5v#bEP`Yݫo /Hs>VgL o8z^EH/7/=NJ@C!4WsD XBfW=?ڶm K.k{m}mX<x*" %V.E65iaɦx7hZ86/?usDƳmOܨ%в ܵ VH>pA[{aX1 v4 !^zΜoOR]S߹gR s/zF┇sr/7wQ2p>r){rUw'{3 |lΟt?٘ۥWe`tF{YAf\jzKG)uf'sRcP]/)YQݮ;n;۷l w)0ʇ9GGD U_ToMl[zekc43h]!i4墌W?o7]6uX Ȇt~sϕW}i__|`_z_ڝ0>5ְoP\hXV?ߕ޹oq]"].KI[_eE<.EkV c.<tv`(0H[V z󝿑KiFc ɞ5#GtmMu&GeV"Llΰ n12D:[n -$YY/dz3,.Nsxsu]Ԃp?YMd8q]SC k,o4\RynzW~| 3Y3T+ޜZfοAIUh<-L"$'I xֹT[[s 7oo+EQveu yN7҂a&jJ^;>+ .;qJSyYI"AILsٖ hhLH3k#E}d F*SK.Gi=. &HRϘBS҃Aq.h(Q@AzTu!  ɋJפ 2ؑ `╳Kͤ$ ǀYmNH@((f"tP"L v1W -{sZRqϊS?B7UCUhPtђLv dʇ . %JszT@eP6;:׎Ә.7?Pq's2ƝYU!C5lGKCZ(E2,N .9 fA&0_ 7/lsNH fo>b<%yhvUxoֲp#ҝ Ow#]]GCSi~bwkuv2(sfuq$jIQ&E 9 UCPQ d|<PI^<#i#L.n#;* 2 $M?8U wFBơ_0i h5 Ԃ&c:5[>1N.g 4RYdkt2r3(v&e1ߙVYZVДYVaS&x^_Br"X57ֵ'F,MHH N7",g:!E;9ܜ|5*f itP@.E0f8yk?ƥq)ONӝXUK@d EITII)hJ*CY(,,ѦĴ ؛G3Kؼe%ØB d$&k8*zA&[8T5Ȍ$g*wСZ3|LݥX沙"yVT(?c0 0in=l6|<d~&Mg9 8+`um>Jn?boi꺅kb h. rɧn 0$ΦAPJ|}0DkUU{cV"rAyC!'b9": UCb@81 }"6u2&!.QeNn+tik[[zR?>8B(i!cvUuO,: !V )Sh<$*)dIIK)ytxJȪ8˜(; bE)X^,Vc9q"z"j1صr;:8<88,(@W]{fb2i+=g<a6|b^? YyZi|3ɓ.83gYeۀq 3[zK ï2#8~vZGf>sJa{4$jX`f>܀`n M^qmmW,kދ476חkz. J]kzFI.! Sm۶M'S,-] _Nfik!roÅ2S7L$vb_H4Ve_")8,zU'3An֠FBg@+~OZCl) -g$=+y7,a`eMj +bv=VN<r̂YcSfT.V\G`o 7\ُٙvJdN{<%ѕg Ѝ ?1!\ʈXuLAX#.ZB8s+Gw9f8hd4}[pU{@5X?a+W!G6? cNoq4c'$x<Z‘hE=]|ɱe]fۿyDPHIo˥5@.Ί+kזCm=^q貖j:-YOVa^B\Y[*NNqÏmzs9Դρ]Y]P8l]f;[€ u⾒5NR*k-h j!nk'4a7ٶ Z0-"9=ce7 ~烝ḕ%T'9y쇇^׿.ep󸐷G7:*ڏi8qxq=]4fTv]Z9AijG~BjnLd]b=z(_@r;Eo*32?h /d RHQ?oo$IQL$BdYǿom|Y.D)(l/zDEc=y?ʪz뮻>(mo%JAG^ [ /\6˷&zB*!#>}vJfa-@-L%38G%-rZh y]ζ*!C$9>7(?~͎*t=zy$,,ִf^ls8LZ6V`,!taM*iH;Ə}.NhB.|h~?uo&Tٿ8i vq5_FfvܥS3$w( -Jfr{̨p<@ʉ1.y~/ZT>1A  ~wV,+׭kڽgب,ɱXunUW]qic\6vBmZu ɔKBHX, @@S,ё?Q]k+J8+LRPh9iws뵛.a \eUlJ, c;ZyrZmI*e"'1Ҥf^nKg9u2 5}}R~lI٦Ҍ%s|32.vß{YpH/$ɂ+k.A^l8 6zVe3T}|}mITLSA;}08YZ&Njs vÆ#jEE¿w@hv[`ݨ9# 6hh雫O cO,Pɜ-[dg 5Epk/MN䣱*&!h,PsatSu*j/[#tĘA|R99 0rd$1'^f壣|3ozӛ//_,NLL}obb5dLvHdx |Ee8 Hdy5F+.mA"%%ē#BkӻC͜O?XԺfNnrG,M;ԉb<#ɕ+b+E(cNEºD^;K^s)t؇Fo@N?"j=._x4),{g'w=ͪvn=6u.ļjO޷.YzaVg&ZiВ޹r 8u^jG{dyBU̎FY7n[#g_ 9t87xEin/K:D֍UnlhOzC`έ7)>]<EPhR+Oz0Bvoؔ蔢C3>vխ/N>R&wC[W^'qWnAỮ_&sѥHjƑ 0[^;W Ze9=R?8ԥW>Y`[mjKt^K5=?LZHt{oM7_΃IѦWR2UwE_ʭ[O ,@[?&yi z䵫_uc}q5EImj_dttC4K.ڹsg4+Sԓ;w&I .$|, ՇFT4}&}"Vxm{MG7ik 斝F)Ժ9?L͞lh k~-D{gh-3S7'`֭_NYث-mיC_"DJ8F-sb?GxٷX霢<1K&%"\T7ރb h_*}>U|A!ah *k[}+?sU¥5˶7OϏVv^qžY;VI M=z2Ť2.h k/X>\7GF~tty2kGƓŤFW.-{f߰鎃sH0PtiKlpd|2pq=v;yэiQ>.]n\~`uYP7Ov] 1XۧDϋ􇒿;䰔/kVFRGsJ~kw5u}䮂b>U׶.Z{Cѱ|!0#ӎ5+J[6`A۾Ό<) l{O;k<6UJUlّC )>[wnp"OK|ÐT AcZ9 &'r͛|3~z @wz?9DA_t5f~Hx͎yQmv%x׻Hԧvuv/YcSFLق?V*O=n4׶mְ3;,Ė>|saNN/yԦO4ɖ͟__%<6uANECWχS=-/^}s)>PGmJe}<ҍ  eg/6WB}IM[_ywp:hLaku[ &V _ٰe|K#3ß~bڼ9W$%|kvBB贷aۗqiC#moboY*Y([Jywt޳l󯺶7ɮ:!tZd[^ ձm}WpaKsz!dkږGRryJQJ@u8ӱ7L Q%W4')'smZccJƎ׶.ߝxg 23n`7 .pםx3.JM.O_Ps>z}¾ ~"M03G,PY0sj\ 2fFwپPH#\Si;p&gΓ/Щ\-%i+0?7qx;iG>ƪ[n&Sd8_-m٭6WVyf$ &XQg({Cv7/t]㼳p3r5x8oS pۆX6GF|O)<PO'_$#C+ m_9nx#wAoF @#pgYׇhF}Hϕmc0#3ܯɩOAh O[ݽC/0MS̃*?xwhAlC=ŭ!kRy~x׸wG?|b̙b*eVbiǦl{ekp]Uh'D i~ɯl?n_ M/ʨjBJAFm7on 8U%GQͯ  10'|#ړ xfY]}wAj"zaHk}z:Įw_t3̍Yv]ҿ`[aIv`8<@d%dܛfљN8͸*96CʮVl|2e`av$B0l 4{3lvq!Ђh5YO&G`V4șYԡˤ=Yb -Vן:q 4u \O`P:Y&kt;Yg\a=2;xm_]p=}9;N*KRdDi') 86E @5B7yaV|D5'7/}@๳:ߧ>vGOM-h":Ƒ (2d"ί"g-Sb%hkdG49Jة\C (B㑷goJ%|NEQt)j;{2xHYVi%m-hP+b/D͠HKM,?\s>m'&l9S‘ ǟp%4is"]4%0+@h-%0,Ȣ_л y5 g{`eНQ*2 n^#u4ٹt?ڹEB-()r =]Kx*f: Rވ5nB#Ho}k;מϕdN j̇3F\h,۵bb䣕CR-HDgtgvVr3)$NIDATqho̯hͯlZskͳT ٲb 0mҖӷ^`AUkL8I =!wDovM涕i~p*_#:crpILYAkKn{?80zCls҆`޲cKuH+x!dki2cG%Ȟ?TUr]@n2ġx3G*~V{z}ѥxWB*B4HHK7P]#'NM]]~O '7&|f<5H︠ʝ.{Nb"W:Ck3/:|}j uĨ$ܠ:2_eZF9qI(qTkχکn]e/M]yvYVк VratݿP'e|O62uT}VFG6p4oa|1uĉNVgu6Bv"k-Y >rgd6N5C …pqe~G>oJ _B4۾dݶDfE~ڋ$Mcy5O_f PLSh녙/=L>PqD6vZ`ےq) <|b%8r ov)Ho𻸘¨?75Mcn/ UF]qydc+FKV 6e~vi#wEa,&CS?b}wSxreѲ%C:̔Cr*' ڧ3/ih_IJYO9QnM;oq濵ha ZU / ?ƃ02LfP o7N>rOB$l:)JC?Pu,)^4#nz q7R?p2^E%7]z\qΰ\p XkjKͫpQ7Sa}yoJjX_=kS wG'rk豷vd״g&E8fOL{oXWKuBK o>ǹ! o>gN12MiEXFWᗵ.wWlwU -Z4-vo{_SَrŘ:)I%_qG|8Mo±GAqM|V aq`i 8K-[x3,r%'=MҜ}%t;3\vbֽOvoxS|E?q[+j=vy]yq0-r6pjwxu'G~ =rG-;ur@P. [>_-l+484)r|F`RVv+|䑃Y4_ݹ0OM8 ڹ-;*O+/[MSۛ~1z˽'6~ǒez&ƿVTf ]9Co!彝5SIq3K^geOnI=ռI4ܐUX[x؜*%'ŋz"HV0X|~37흳u=mͲ׾iӦo_?oo~zߞr=] j [cA#|K$mnfo+c mvuxsWx/ 2Ԛ[Skn#?igwenɟo[K_i*S{> hr;s?=+ձcٱKtRQ_qg.\~|dz^5?Wɯ\z2wLa ڐ62P}.\.a3Հ cS>gi{qT1x`M 3hrmoû*ɕݴ4O[' S/p7?öEo+?qÍ7mv6,4g_Z0ϭ5/?ӌ2c5x]c^- J 5M6>xI炛xyJ-, 'k3v)oޠP/C, wW__84}ŋA*O$rUU`-^µPtgSIWkm?TbE 6ZjZ;fعx&@#SnߊbfzaGСCNwoX_KL+F\>1OHLCh}h8@qߛe+޽}l]?/jMA'hqӮi^=C-=pTećC &W@Mu(O8;sS;8itNb}~%@>12Ih<ܶ2ƒ1 FHxrC5dT>z{8 1DeS)kkP,SjVlBf`Jqm)RzrIaHBz{{x竖܈aC;-%saȂjPu+6WZC\g?QUل/-kH08LIe:lO$ӑ\xRzݧ" i`xPb@c5Y(PT^,V!hGTϠ1]ꚦMU /h7<9||v+#tu^).59(enĵkC M{[=9B`\(]m=D($4ceW!㬲d736̓/=Յ~W+nk&sU9&7B n& 2d]=/ͫv 42]h"9 2F\p֬Wg±`<{IեbNﷀvj6לmE~06K g53`20@9 Lhe];ulN(p",J5z/ty!`ھ&SȞwm('`>swOjBSL 8罴Cꕉy0Ԥr~o8/2`+\G+pwxKǾe lu2aŪFj+\^[6Z<,ܤa3HKNQLVU^3dtpvQ 5o|~rf fJgb;9 X3syr%& 7^fLr!w4QTi`_aA^N c佌I@?wzi[a#ݒǜ1C1@RCܼ*Oo`jb+g&!^|]@oNwЪlhsPFXMt|?ToʘW^ӺΜ,z0Bo([z7'ɸsl |_5k`\w/}f'.Omǿ?h2sG}9c\bu״"s+80) }؂GNyq/3؝_ޚ]ߥ'BAX 2mZكe$구!b#TMXII9^/b@fC9HfF۵K-k5OZ|#Znh : c@kVW?nkAL!,P«JoQ[A33E9&U ADAg@M@[*kRJ Ɯʩok+khf(Wm!+ B@Uл7a班y%k|kcR;{7%:jYv0UbJo";zFq]Oǜ'|7(` gh' Me k2FZ71_&j {+UW{2Ɍ#*"Hlb˹r5Y[? rJB Cjvk8ԴgFTJM7n\ګ5GAΑsAFg6εmHMkڛjkZ, L ұv\yx5]Tl<+>>,ༀUu>& p]?ݷr,dDH!0eB>2cT_eBk.gRNZ*nOaK?2JC!F1c[dY A̩cF7WH%c_ytBZC<=Uf+_ٟxʦzc٨8Yҫԣ%renKz*I?̚4 cT%s*SS;Ok2SfX?ʹ9?|h# (o  Ki}znNѓGZ8zz024 St+6ڂ7ݺ۔֨C( xqfVǚ ٶ -R<Аqj&H`A(gu`MxLOYOmQA&+2/8_7;5_p ̎M"F9F8f "2 9Vr"HuMc4&}i}ᆭq)`W`l!-b e6@@ʹoBؔF[E*NeXv. O=5ڶoL*lIӷgB8ՆrZ Ȕ9뉶T<-/ԥ{эDxC(2dRNcJ jE)C8H },jxdѩ?kґȭnhinuaRBd$HB%Jqn @!DPi7_xc!\jCz`_o:֠[08ОBX*&%d4Yt5j2@I&vI 2gj‘zT%gSATT$b9s2K!1$R.)4$P@u  :HU*^;gΥq;LCbPPҠ&&LB\֊ dR׃ΔL1^gԱF>w.O>>&Po;ʜ}E aKOºPmhVK]ݑLPʦ!!b6 'WsZ/4Fuczg7~i?IF) 9oe{V2u-PHވCd!=)ϟo~tGROnl)'`8(W3's'bkGB"AYsp0o0oP%2\}@=_s YD h2Ti<2tcv(YV }{tX]32j3bD& niPң &8]i$Y:d~n2-sv60ܾt'Ve D5E`Ɗή2)&aXHȫ,DeȸIA_oʖe \F槿xrsO!t,hE+o b5Y.y*'(qSHMAV3ʽU'AE~7ӽQ= D~"*R5W6ł)Мܟ.v.&5ڥe#/[9yjdر;MKc<ʝ1~0UrJa]#!'b_s x;R PrU1 Kcf@Oge,"JK \ΕY%ms<JM{_Wްm /tt.;YdQOM¦՘1)Kc@ju*?6k)Ep@OGt tIxۜҳ+W{_[dGF<6wX1`An:ݚ`f`9*e *èlvC`l`fx"~[Oyy{ߖWtr{~0O<'(@fz¶ !%\6<0@&62gȤ jk@f&¾OcI^fe~oFJceo!zJRD5ʩD(UJg7 ΋V*ZZXM `2lvF9)Z]glYi/l|*a\h F8*cQA3tfZ"ĚoAͧhs `9]?I$Tcqig$ 4~ MaNFe)"8dp"Hb&  )W`b~ > ʹR)P U@LhaSNmfEi=c\X܏Vmc֬ k=/͚2 iLԁh2Ŷv]/^_y<ן*=NنmrFH3'Z[,(!G L )FRdW+9\!lgJbPG_6,4n0Sl eSVNj=ܲ?קS袕ϧzp  jeR_DyrEuli)`K&cGC|yn5=9 l}nj'C͇(B&:eS,BЬw_7a0)AOU X!rZgʝq+ʝ d@X4Cz4/jL^ˆGCYi*/dJ\QC:A& gĀ pNZ(Ɛ1#c"z"bJW\L* =&QY@fyWiC_sʼnf`r9 %#hlw, Z!KbX/'&C,h-Nk턂$Ѧz7)||HɓY>&s\^KXѱjlhF%=!1H,XX#p$,01G $ϫX1T. 2_,S-ad%)Xnɟ̰,OwXǭ|+dVP`9l:H]pU<قGe$X6l!HQ8!"TyA>ȕ6?SafԐ)ZPS|rm@U6[q9҄9ef̈DSm1c"_ [8@U\`YACz /@(Tyg RS&Y fQ.lq%$b֚3_%lV!%GY" J] lÍj݇mKHt<)BWc["` l:B/Wʉ !cjA :l-`7žji 1yd*gRoSEpg! d4ӈajЖ %LQ܂ ,E\z=i[/F8-«"2lb@3]Ҿa)#PPL`HEC"=|$]+TZ'`Uf^ko@'*BgOH1̨V\R5؞ /UOrE..eTw ^I̯IXAWU⼶ lXSכNЃ3 u6ģO-KX" # $1wD9/H.;^ RD)Ǩ`E$ =d̩HޟF\J@漭ʹg4 2;.]0* &LaˣZ2Yv "@ѡfI6q @hH'  1c!XUQ H]زDG8D$)cfa=#qZr σjN#U,r9R#ZϪ<eb!$o͇[B)̩la2H՘|hDJtʫ+Rl:]xhjC˼ j~ֈVpfzW,QceÌXyI [4J/FMϟ^/LjBef?䥂qȵ4,13=E@@ljyj .6 Vs!'wv$Xᡎ-O cn 2ωT+jڬa;dA4HaL5efז&l5 y} 483? ]M2Dǰ ̷p=g-7 Y~ԡ3Qx!B8;ӛ=- I6TAbGW2Ō@MƼt+BnjES4(`y,[b-!ˑM-Sx'PM Jssۼ]GN:00LV+ V hb 󬊰[[xCL PC4$0_)PF)L1zxF/sTa#jVHE. 0Š;1;:>=gH3 U1VB3@2;g:0k1j.n<5yR/p20ZWH}xASgGgG&9;9oj)M_:%\YI!KWY>WUA{VXd${t븕s RrM"F:,"aTL;,?XUz(kdr>09EpPgvug@f:vʃj.خƌi<ʜ2%t&"FM@LۇQ-w=beb`r#Z )O)gw٢}NE I`;ȉtb\ev-Vd^4>oq_̦{JAgf*VG4*`[I-_^̠Iɗ=6壼"6-jad0kzhV*߼7ӗӅZTPZk6ǝA_LBFy ([?zj0~hRXlp&Q/|&-t4Qvvj˅OݔgVY塂UЭEۚ|Tg#JᆪWwO'r.im#tyL<))"F[xSͅ'gŤڐO4h!=qYgA yGCzC&ؑر AZ1^mLLݴV* E]튗Gnr+xs|$<<5Ӳ dKF[=Y0' q?:g.^^d?WKM"Qԁ V;Z: o ~ ]3+e d5mѶldV ,A gj!g%n 3B[ s]8Ś"7zT/@\mGs36; ˅? 1I)*o[<.wBK7m!6v-A[i=УQb\\:@]z|Rc^Jcw}䙷rnÞLJQb7LcV-ʚCZ>U`%tܜ*|ݜ5X׬xp|,rWDdpBkpάRŒj{[O&xUPhu B֌BtXČ4&x c$窷yBPTļ%+V޸jФ+P!oM ߀i/}}j.r"UܡW/MO3^{%UC(rP{n!A=O"&rxJ9vx/J R/o"L̊n|w5z s_G7hΚSs2 .B@ ;POnX*o/> *N@9AՈ1!Hei~aod**eTA5*l{U9ޛ?[5 ƑVgj9?%LNmn KX-flVє>pSzPbGab B!&=#ѓ3SBq(#2 PDB U=  9^[פZ$X1\ \NeM$aKH]q+brr[Qm&f# Z~T'/,DP`4T k妲/ Gw2W6BUC7G9=,ppw0Wwc=wNfn"*^'@F5k&J$Vr&Xb@M+R+XCLUoA6$5{@no% ϛFrytDO*Ï,?[hsq.O\0R3jhS#ݨmnՐy몲Ag]CZ B#?y.)S#bAF!1SFBg?2J#MK:%t{e{u,4tH{@W X%CoGz铽Yns# AvsQz-fAhI)^NG*"RZ3YDҵQ!sC/#O2ڃ] my-򠌡"#ȸJly{U_`+5Bm歛UDCWrd+̷}S^&큒'P sX ^s: 3>5,p @-3 f  g U7PZ;F$0*x79I@Mn X(j}FDW(x_22y1eZ:W"]dY!APC WMX`Y)H}%;G*j PB#i5!q;k_x>/2X#,n|l!"!Eÿ+tەȐyRo*dʯS%fқqU=ˑhA![ʿŕVNHj@3@Nʬ>S0R$ JuҝacXG3KWgz,pTz%{!D_L T¬Ku Y41{G7ӷ?qyK_Pq9з\>W;ί/7ݘˢ΁VYgҺύ@Jjy8<\ smr:3( }bn{We'A< ԇ7ڇlo( ?V"DZ`'$s*VX u.beYt{*|d+0*ڑ+{U";%~p1"'= s-PURr$A}> r-V0h ֠ՋhIS9a$dvVDD_Hէ@ePTfB[8$zd |7ГyV 1 O.\&Yja5G~ Z|lu݁Nk;9ƒ3 zNFu0×@%*Ua>ZU} D? 6 j Z%+8A_EZX~@ڮ7$+tU.gDL/@B6H#`{VG X`jKV , LWu7z(l7Ff:!μyoܛ_|/Ǭ/MĆU3BV̡T9xAU\ LޭJ 1!%!ߚsu~Ğ!ҫEPWnpt_F?X?l|{ϟyZY;~M[0j-xˎq]9n.J+UZ5jkpۓ|wn#8:px`8AnAG `ؕɔ&&;7jodVջ8ȾZ?]QWOҿ g Lcu`a|CXYW14R׏B0)K >UhZ<4_e^op!4xSb(E4eÍ+sObɷ%ߎњ&?&%}d6k|i5Fq.T|fe$/س%u :j`'mcSbXM{o~lS6sOc(-Q:L/nc3i2I(g"e2"/ gnH.pdl7ctg-vI2g(J͐2*/{M1v-+fd\jgqz {#U #X_ :e'|psg'p6,k콵|Ffb_>W|I^y" J=rB@PdnPdd؏d)Y(E㞖{wP)wTn0$K lQ?eN5cR:S@_L$ޢ`R!U=ncB2\#o8 0R!ȭ &>(7;ZI[^ hҚSK {hU`}iʳ~p?po݁`{sf70Cq] kƛ GC5nh}ZkA:"Xj^i34FQIB~3uS5&VaZNt"h*+N=D2qEEα-+0Lxݜ$Ԍ?Kȗc Y@ȮD A3.hDwt?몢 HPr͟hN6!4!e*MEPxz;Ş,ug79CY0pl»p{k[q'6:%*ƫH}8_u?uZޡ '5w@4dhar\YxU'!)6MjUEbx tJ'?oX j.ae08٢㪓`|!UdLHJ5,Gȸa`$JSň؈oۊA 1/iշ=$h+XR__TŖVzOz%V5#iD6'uҟ_)V0ozD(Oh8"OO|_v~흋;aX3FBb=] &;AMF*3$`H?xV5I"2\>" bTd$q4$GFuB1S# S$^\o1 ʦW)nnf{ 9zKdPgDic0;9 i"NL/ҥf塪O@MZDyYBz~P[axE"Ɏ>~q#ӣ [4PV'YFVWiw^'FrO^//߸^|v}Xk5xTM+j`uShK$eeGιʂ.ڲno9`U'[a8iy}!*<nlm/axs0@t~ogy}6v`"F_?E;5,wM3`glz': gSZ'ZpX C&;gHch.GdHVi~RY3DT |iĥb8wĉ挿,!m/ Q7ޝ'IENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9a8d95423df65a9c230a4cc88056c13a.png000066400000000000000000001625361420147000300342740ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx콋۶-<Ri8m,4q{N -Q kί_6 ܐHQ+_Co)oZ}4݇O.c˿Nzc/ҽCbg*}K@SGlSv$)lf2aex(>ۯlu.-O>>Ft h=P>T\NGB˛7/ri2Xޤaqg=~֯8Ov/RL~&!A+ڦչ꠰7Dl?9(@~ UKZ| 9/?;|`zxT{n>^ Vɪ72`n1aL?D; 5 Hـf0 ;r C{`\)<n^vtjJBe`znn@g:y򫴢'! -B-'PQ5o튊ܞXǍ'OoETJxt{2jt/l쪐7je^Yߤy`HV^4 br]ng<~qOꀫRUr+^i5m65蘭7=',VUB+o?u4Z9{b.c0um}\o/>ѫP#")wE(ݳnj }HnETƪ M†Y  CXnPxѶ -|ZPoT.mے/D Fo+Z?\|Cެ&h+>$6 ୸Z?gbWv+YN$j) }2Q  W}z no+@Y{~Aۛ3;bAkw2e,;H*bdن oL7:WD+^ϢIX]](rwR`Q7'}/|ţ?{ЫӇIIJuzcNjLPFOEYAM{ bY72"ЎP-NҫeTLz WEqnRsf e( xd*?i 1mOBV݈V;څy [iz6e(jI*@ҫ,!?^Uz`Wl ]췖&UjǯAȘY̞{%Mol0Ѫ?؀kC~㟐nqW{h'ӫ_n SWDr87VFV# S(6|@W`nr7Z#*c֫WL]K(P\MD ?W_WGR1u}?ЫRD!'8 L?;<sqfH*~ón->n#E[ TG=~cOT^zműzWs*pgݪTXз4jV`]ۉ70I,HқqiaU%jmA,=;`VЫrqʢi" oӫe~q–C_Y !> Dzrws~'Ko0y!v2+?AtBڢRg5'TZEn܁}lF+U9Vw^x[YF')^ Wn哟vpc65(e;)\֍tWUڮț'sL.{?l+~59rL a-j: hMGSx˧nm݋V݊*ћ\6hZ{58_H0,&L175ay@Oo}ʣһe8f>@wOJuQi*V7î)o2qw6߻O|q^ݚ{x9v~$ٵY͝eo-/;O]{XjXPd"Z8j?ӫ<wεd%;gʂ@1 mhP\?/AX˟]h/X=4I%~?ҫwgY?sқn\)N#Cx .WќrRPs:W0wUZ܈ߣsKCO *%|04EuHv~e_X;Cn9L-̟a{j}Ҷ:TmBVFl@-3Mb;zXIwn7DM4ݧ:m GZn,>%YRo[ l!?7Zo1жY_>P׭d'OJ@>/}r,1PvnU}UXUc*{-^ۂȟ2}Sz hޘCHW]j}h<h-6 @0[S|k/Qɏ nn|.taoc>/2reآj{t5osQ1ƂY3b #Z[B&n"0ӊ;/aϨcY`m'&;@NvRB6yHpwWFƗyȣ:r]ʿ?;b_)Y\7Y}c┰9`k /? د 4L]r|`G}Tf&µM LuW|KPB|Tx#Zp%4~'\Uh[@6BѰDBeV(ůxMv5hڃ6k;noJV&Y6`G UPAi ՟kKUALAeH##wuu)$#'g,x y6%J%fZR!mqZJL@%\(ÖBx]z[iW\6zE嫼Ђ)"6l1{Pa'Vt+u_oqp;[v;Mڶ7󴴟4 \4b$k̊\oO`趂r@ 6X7lDD4O[a%#}}Ѵ}ga֡ MZMODm0oJ\oBZR283ix0PV-0 EtVz Az3IúBޏ7cg?ޠ:oi9 n؛>!oS*E+A܆ЫH # jcܢ0ɩ5>ڱ EˈXbWs EXb+lm8.E2Z߬P isB|ŦB.7J' ߺ KXS:!Vlv,gX"8P}sft1? v2h73Yi)Bɳu>°w `؂IТ? RH9yvXGhv.S2,ߐ;f2DV9a$1gM ]'ƭ=ϪH঩Wģغհ?eDp=EbNnu4<Ol [ԫ ^9,V#\ XTsǟX;ohueO;fme \^)׉o^wPvL^@+?#Q-ߧp"*[qzЙi6d?y Ũ8fQ P6*᪶fj75{x&{+,v,VbeӵedۃOGh8ɰ%z=x#6R7 d}Qji(͋0,Z] ZU:'5 %TK&.p2w p]6*8&f=U%Bh`Nj8׷i$n:Ima׻ luDT0rEъ'@ƏdY=1kq(fw8B"ջBq|{kTgKW|xe35ɭz2jư&Z$K4曲%ށlLs&KMLƑhb坬OVx/ZGd`"6!"9#4ΘxWV>XL64>P1jX9{/0 :obn&ka6ßȶFҫ /oyw*0(Zܪ==8*9Z16A" h"yS-38 8HmX#+v\BVɈu*P{𫰭f#dLz5Մ<,KC0 .&V`b)x#xĐK{[ZkUFZSsq[AN(OZ$b7a"Eg .A,^ &!2Ú,*}(;0 9"1"pCC=4)H=oG0f 1(lPaKC Mܯ% i9DH7~Q9b/tlΞG-.v 0A3Z ̌Unf tˮ>~1ژO/F&#AѭHȹfTSL)Ob^-=):]6H1H\_vI(#P! 2[YNMv4ۃ01qUU6Eq6Nf22_}kT AT(WJ(h]_x eo?Xp*oz+A?9ѪWf ZWr&ep('WU,-54EcHW1 k2xdGCxF"F xј U0f+fIqVb}`%E"$(4{Ӷ ^zTtw(N Uw iV'Cd_c*vDpxr9%8.~¬,[? ja T?\fLZ;产>TӮb v,y O3#X'?#v|%5~Uёr!0넠H.|1&J aX|u KK*2Z=~89?j3ۖ‰!V,\yd#9F ̝ۜuNTTq>FϠƢX(c, DE,I2@HICoQ%UkyF8+Foa]c&POVuJ), 3nO(n a!8^dbhω#n);_a:AIY4:W E(].☕|s'W["3ΔR*Nh,)NΫ\FBƐ :6 Sh^E2gɞdb9K/>J_R],ga PΧG–LL$CyrC [98Z]VCza)@eìo n[`e[EȰG!%'D :Ѓg]%5X5O eXshRj/c#Ą,3Yvzjuci"L'AH]6o:ktm>bY5LY*sVx"Zc8eO4TTfT3p-;(5( Z %Gl(vX謅PFۍcR 1PcpsH9 g 4(Zfzؑe$Ѵ:Xh*<+r=zNLw ʛa9!˓OTy'v r$/KL 9fN-X+pUvC ͡J XEc `Qz2;zij`q[C@j`al瘅)f1Zd\Kb+[J^cN߅֝( jXPa^l)\0Ɯ\>SJV|JlAX+YqIjI8A]3sB+ ME-<9Rԃ \t/&am+p%[{(SBH0 G;+qaaHr*̱>9ƳQBl F,AT^-f3JM,BTQH,MC/ /ypP-,bXY p̳4LE%^0hkTL)z0V:N-,BlB=8NJ]TS1뇽rĄ\,pXҙPـ&,sF1Z1:sWD\$S)!&BeXYCc|M9#fB Nj3+UM8XJ%snlt Xpdj< Z,3X@47LSNYI[eD3"äjZ&`ZN̲Z(rp1"-rxd8,/VNjRN =GneQ6 Õ(V Ugh5_B,,'^c<}m,76c&GDKK=hp~e;r  7^hEA"-DџԟLg1U<^KSNr(^Kh(iMgYfIͤQVO">2Z, psi4܄ ΣEުHyQ6}NFVj4ffA13QI,%X B[Q s-MtCP"S \K{&"6MwpS@lQ0Ce. 5j&ŌV (pmfXAxDVCOm"aji9-QnliYuz R3&=E#^|#qNnLro}9gMH\Ơju}a"Nz -:VE+Ŭ=9OK$.͓ac)OlYr;J5 CzyKz2p|B{Sl WP{?N:og`|eņ!Ʀa;By>XyڤrTg$yVB&YokSnQq uN6f5k8&wl /1^lXwwnEI΋r ?F7a lC<XMB fᨫq>q<*i,@V̏ai/+E?+`sV3b݇M9޲&kZ1,r Ú"H; "ekq(i+HW>esЩY,g(rhm0D1p8$TfΓ-|~<XT¨4BYqeXɪ آF YP M{m )"jޘ n'4 dt8.eNCa˩eN1mk'G+pxm㙌}`(ywofd $ދpCX!eF-ُ#aV AD˒rܢ(H|`<56y`{jb; N*.B$/V#i5F2ҏ!f1hX=_<,)ɪĭR3H[ʷ,nO9 ?XeC Ovc gN-Ml."ZV,"G0`DWz&Yg "nyD]2#&`lNdcMKh?aPsOHXL W& Yy@, ZgfʫzPHØ+B3,ѹqUx?O UqχiɫB3MyWËY.P.@i~} mHʓ J =ǂG*+TFXpڲ14TОx1@ƈ:2ڋS VmX3Zj~X9˦D&y!HuҤhN h #ti2& z+YR] CزAI?"h &> qVM鬙t[o.gX-M_/./aF4X%HFmDTo* c֡V4C"$qH(5Qn5:5Ո GTv&gtmN_A5 a54$,,Ef=8/:6+A., :Tη9ӢN 8Py)~K'i_[F <صŢZNKQ`QΒ)p9Hfn.|A-9qQS{0KP̒h@$VYD84TeJBtcVoͲS(uQqj@v5W#`ϗDoB);DKW'DcH%Y(8y.e;uҋ[/(^:hlm놠?6C&`m"L"RqƳ&N=fKih7Gt5Ɖ4 X|DX^+ERM7sg6e:4n%R>?v|D8ÄLɒ]Qkrv5LPw)CBM˩aVmVwhX:@EJRSbym7Q )SԌW[ Y{Ts+Ru% <<5 V#c; ([ |O!,ZFO/™ͱDGVZP%H H`E@a#ru؄RI#CrhIxj(MMuc Ő#';$l-Enn;Z[GLiVh5|n%ݷ6jI W1IE225-PeXDaΎ־g1l~8?(b#*|QZ={zG'bCV""dY_wІQ-]wObY |1Bꇬ.XuJsǐZZ@i5睮 χ ^rY5RCaݠ"I: T㠦xڡ&J{c_0>:X֊8ItUO V Ed$5XZ:V(L18f KԟvXq4l](E̅W]9[FZp8#*8P^LKc>ܻФiu6-A~ZhԊWSO+;ن]Q/UlZ35=YWzQP*HX(4 VZI$Rȇ`e.u3#s:j` %t:JojO:$-5<9d?ƇEVdT XY]ϹxUVLJkp># iᡛ#RP%}nZ70fu*MWIN1ĕ.=ݯٶAEG#s<(WC{*S!TB-M'0M%q &a4EIej N4q+?(f,DIΦ8ټvYGV".As< ClHf%=FcbU F,s(YGZi$B3c[Kʁ6 >/q¯U egmE Ƽ2JK:ҭϭжf vq"VAhxY"h cAaY&Ma% Sr\׍@J,uR5(,nˢIK~AݬDT4H%bJ|hgpM2sJK!4ȵ%EJ0^W'X`H8ck 2]KO-,E=y*ZMz[VN{M`Q\o2z$LCf>] pwK)e!]垮-g"TXD;;eʵUXJD{7 wKU̇pVG" 錍>bɣI\˰F\!V2YU43jAmv9ՌݲRk{"@+-!ai!e!/%B )薪喅RTV<VäqHCca3"":7Ė19U:dFZqt 4"5D0}X;<┏~H2V.L4,UbTeF",7?53X̝jyNH ђ^̡tڞRT}iJW4/2sXhA X[7Rr$bP C23=tVt/RaUeX6pyyS&ydWgiXf_*GNrP9M4$XФ'T&k1lL &kLwS Q k&~z oS*? 1gZbl!K)cO6AfMsHJ6%>ײqBR1Oy𝣫|`|"g9Ff}=-sqxI 'Fٰ8UW]i:ɽ`5BdR[P3Uh%L _ib22\dk}z!I)ʩAD~EJ}qE!ÒKlg Q0CO4=V$4ekj^z%NꣀYYҷGwȾ^DݫUEP>̩* RhIs2<\姉H)eKCS=q2FqpnX:S_َL`~'%,MI yu;LwK6yMo4eګ緆Y6s U8h|"!p2X,"0,*C!tQ(]Ԕ{(ᘋv5'ph"'rx!X8ul >D/:prmscz!tAcH)rXC9ٜjYᙑ3AօhM #F@+`4W8|(dl(J 俌SQf`xv74_lwZzkqUgOJ>(5bƬLb IHjE R^("nh뼇kyWKx^^9Y72X9Z)8rXmh"Hzy kڰk (A>+UAcJuNIJ:*9G_(% `h@$}6eD b(gY};pʉ%(qނŒ/QV9Ta'@)Ի-P~M4 ('OH.h'V׺΂Yx{iwEX߉H"*Xn P P>H1 vhwEJ\*[U8_zB( 3h#VOm0uEsO])7/O,mިz;:Vay1*Q髢g{%Wa!aP }I~# ¨/TF{s4E[r:UHB$'+H^GofǛIU& -'P"pTɼ]8ʳwY:!ATk[¡73DKe洬EW%ul(qfUՕI N&j96]:'TB+,gt)qEcE]10]JVXnc1:_+`ae(‰ Sݬr;L8& ZVܮHL;fM*̑ƌWЦ&W-+KQt<袀[w?U)Itj*ljjM8Xy,Rc Gӓ;"'CH nMQDKm єm:[9 EP,,X̀D/ϓ" okbȘڦX}8oiԂ[l Z@QBHĵk 'NY .u54jn8ZC O(k $!P'NsѣǟKH[KZɿ"r>.f0x|G˶uRwSo9r,֖]fqe-_4Ia~8ָۍ)fCX9OZLCC /.ZM-.n16V̒ SאJtpYDZQ2wkep &i@ EF9Ak-B(1MvW6ThX46* UzcM @nXJJJ  1'Tos$,}s Zbw0xQꠘ冪Fl*,#G@z Xf/(!{C J/ѰH¯_ C*GFg$_l$*V`Th8Lbu{;Jƺ|G eI>ZD.Pk55`Ԫ*v-$5M> JkhXK4ZK%s0KfI XdXOEsޔ:b7t's2fff=XzaG($Sv \zLςyny)>\b+6meY4 3T>J)fu,-Ǭ0b!PJi7#mF~(9 HL&j!MSpm^5JmI巏AY7Q#qXEb^=3]mvmzl㤡D"GA٩cHT8U! :V8x P Nú>cN)O=H"FӢ~IDSn-":]ѸN6g+VKǻHK 7'(Cb-;ni)Ȕ+티.Vq/ 7|>>Fl>.B9Ȧ4ٰnT)JĈ۫hId/s][L8hU5Hˀ%l%2u%'V7otiZ]M-aj"zޞ×2,m8Q$%/5R*YXh ;ť32 R\A +}!5${bEo z=J1!<4\!\ V]kHcQ?AqyaVpqq;:<`pԥ=ȞA Π[rhYtcxM*зlBzg)4歮9W Ჱl+Ha@aqS`3?~m\jp%BZ0 )1Gg]Iۣ42YH*&8ک11a=8ՄtK70"+Z)A{28(KfL LDhEy[z% br3q^~) $g>G5(Ĕ]f6n=1mB7]Tq,)Yq `~vuR%DdEb`BZX RL?죵qs$\J1g<vХ~BSʞj4 Ms>Fd .zvDI- N iPxcs1ZTG/4ctso)o9"\2 tX5walAϽ-'`ž NLoY,"j33<ހ=%,*)ljD\!<S9_d̞\ 䃟"OeE^ӱ|nuC K @;32vƍC0a A=K!]xZ(5HQCjcd&Bxm*fVS2I!#MЀpώk?^9e>-Hsoի.s8jrff>eN&`SK󶥴&- 12҇U1A.%B5YrtDi.;߉C ؆s$“ t&Z=E|ܖ+0`MI ԩ^Ӳs!55 4fECh5UaJc(BTu2-°b`u/l'Oާ%t(-XIF eYN_̤ \r;9k|Wl!z3ߖx rn`i10bL9Edzz f7b y3G{z?9&qFFIO{ú?; NɳbּDH2Nt^H>he[o# \[ ^\E'LjiUi%Hz8#eH,jɞbZx9/*m瑀KGnܚj_W]̌7'$DC,pbBW$YI!|1yav.ײ']RsङVc/h>eALQ^;&H>)Lgҩ+qL]ŒgڂD(tсlbSod2DV׿GA9y֓A5}w9!nF)u4*Bڄ1`y,;{9k e<2⩔Yz8ӪqMA+:]2ERfXJ,cVW5heX2*d:~ %zS4L )@ : eG )G6rƬBcֿ'v\V哖 %Rea.t'DJeZgTf3UhV9ސN"#Iai3X u tel ~j&!좜EQ UTiTW{[x`̰~ z5{Ɇ Ge/-4i];6^'6đ('ҭP>g-+h-U, !/\erG k/Zb]CnfAP~pOd:Q՘j/{8Ż'5a)͡'lX1`DŽVB_=: gvbgX ^wF':\&w-,R-$\݅aBS!Hr</О*v{Vb N[?AcX:7]KD%cҠsޚ_]7q^Y7B?UxVXd>RJQR2rU8."veN|>$,eXRNaV6 ,OZ8Tl&>5dr4 50u=YyNR%, :U(7Uq&2eQrrQ}b8<],n=1X4 XYt{кgE! DvzF-K h4x 8,PR$$1KKb2\#Eyqң^uEW Wİ8jAvejV + dyZT  KJ3߱DKky a $\=uM"̆UN\EU6_j6 :׶dm.#p xJ|D0tR $E4Wrsz%2<] 2|V;1tݳƐLiK+y6t:U\; T<88qCVϗt2FeWg/=gKET᪸bh(vAZr  1\Ԙݨ] 8`~=xѭ[}fXM*e05 "c礃8]jbfp7 $4n@&)1XbXUmvQy-wuIMBR ) ?(!cy9\ʛ8oX|^ü !s.8" 3 irÁFO/6%MaU%9]3ؠHɼJjUEU2=$كD(ҢUS dUlR1 %F|0GmU1J͸[+ɒ+ Ɓalpf*aXbjo6;t[vȰc?UܧYĪX5+B]iWvfԭAJE${uG84!lO#C{<+m^E:Ai[m P~1R` f2ÈkHj\ǽM 56z^okN'%'[!8zc E xX|>@A!5 vt3h n b,}ԯkOuҜ2MEk!_4m;kq?тLpJevsPݪBLK[t7;QD#HuMAjl 50p!ÓnWMNP< IKGKm2V8V/YY)m>,^"FRCeqy_xJV{\8vՆ7mVEâmp+詰-\bɾhЗt ]Ar$.),&h7YHh|Vw<96X⚟LFgy1!xF+\ Yh61ffixRAᏴ%gͼA [mnH bš 4!P{ĘAH]tLφz;euḾ.w5^|]ʰ R41kt$HRACْX3V [ɻБl\H%/Rs )@EL@YjnpmB/Vg[D$ [u[=cj:oP*0.TDߌ} Y>^e5BD!jCIaM4 tcWAy+ p%Y܅Y*$ƋQ Xu&6)Ót?#i i>rA VSo_11+7pkkpc S01,iA1 ,) VJґ򼀎GP 'EOՓ^Pm%$%:U:$jpHQKq%?_Cٹx^u8z69W)-eOܥW L_V$ܵcnJTQ!lcyx:z򷺻X oGAѭʾP7s$hS6ڊAsim fa,k/%_ȥS 7 E,DM^U1xQ8  w ~h^Bloq rjP r,+TQ!Hd975 Z͹瓺D[dKuI9w  0M5A>Ċn* o A]Ճ d)%dezFY׵}cx1%ӫb:gRY8C~KXK^,|`M1QfJdKL<beh51V_o9W*XLZ`m,xrD+.sQgG օeސmSf):a{S 򒘗8  gfmU@NJ,\Y^5Pn(uOVP 0$J(S&̈cȍ Z2`edB/5 YWM#%)L r2sl'ewVuQY ~ٝ ڸ;!-7 2,i{ijHBL|#[eκaYf4I`jzh1'@@k^q1+"3Q#n(Z9 v.bG,+-Do)Z"UEd bO 8&nU/AqZUzwg nRQJb%{U}1YT@+ңv^Jc>mHVIDž-hӉ"1$9rťoTE\0JWa]i٬T"@]3y_0odn* eCG77M|6$Us,]ð̘-b KJ& PʮkSI53xCy^!Gp chZ˭Y)Ѳ%)!ing-NS%–^0 -IF*["7 cޭSUP+}f]cG'fZjqU&]bӒݝv&"WY'㲹WnBh(%#n&>u[*@i=hVΊ L~7>ï XaZq:\̂¶`HI@^*h8%@ސgVpdJᰵI1wwh]r;n=!\EgaӊS*к2g GH>tåHCtlSCF4%-ͷLxZeZ^-AOӾsQ˿ժ ^J4oCu*ZRhqU_SLX7:gu d)â̐pV)ԉ-K)cIͬ-=I5!smFk$6J(g=-/ ECA=3JD=X= U><h2mvx:u$[EMgjCm+C]#fA_֝W}KvnyY:yCA|H{"y۽|XlT+H!!?F@Pz%ZޠԂlCpe7!Gi5q@&g^G@ ~Ⱦ?]{ȥgwn7=TԆ_;BVvA6d=۶j?|ThY$PRZhy2:#DO烵+qRW *҇-j*Ks1\vNj桘u?t>F9Ȑj&+,u7EgO)shSi"7oȶ˖RimV/í]6$8d1~1_S4nQI{q񩄪ޕ~r5Ϊ`"}j/i~?Gw~a ,-iB`KN ITkq8Ƒm7} 8 IY¬-pőRe eG+L?fJX)HE:F1=#6`&ν 4%ZmJg7!^}K>}AB>|!lQdmfC B[<'s E孼~uŶZ#Rԩ qfĪf oZ5tY>F?m?ީopJn?/?Vٌ!X:JJp'72j[a{JUZ=ZfXI({LEr2S:f<5:;'4$D/P93/B #\u|ިƮ9?*- l ~,dn炟 [r+wnM)TZ T@|4͑ʠ=^jKf겥\F)Ri?0tC s";rme]7 3n]4x'97b}m9dGtUI} Um~y |Zw:w}ZTO|Ulk1In*.Lu=<7nYa@0٨< M6̸8uח7vEe۳g)&ԣgY{; rmjQk5?%YX9h0:)8NH0AﬣM{O=O!caLbUpᔾt=o5l v/'\9|EVODV(O䥈WCT*Z!Sy=+ ֠/HjS(I )pe$/AprT{q20,N&-$,noZ aMyś찅*t $1o{!݁-e;ؼ `w[jA.oPLPe4~B,C"qjiℰFLp%Ho IP&ؚKrISɹ }n'SpG+Oi^ynYX`)'xoBx9 DE(,@-ֽ5 'G:p& ?+ e[B7)$;&{z)0p zBGc JjRZ 03nj&ŲL頶YI^$O"CMt]д=ix-!)TG4Z+7 VőR?;ٱi]&~nOQ)Vyl rY>&'@ N[L6~V2/VI#.a UVS ;]YeFGylܪ v<`aV63P;d9q\ [#EWI-ڴo!߉@O_ǜb_e (JXֹEA"l!hJٷ+ל=!ϐ8Y,}W: `/byE"!r 9,69Z>. ,Wf BٻH-1dX('a#VTZ2G<VC UvHMDMDƏ+^o"PUΪ8(ۣ_kÖF'Yv 4[Z{Ly!`+d랷cGM,(U<}ː^"lz@

    ~q"BEx -sXୀh)3O2Z r*%>TIS* Voџ+W\;b7ȱthڮ4(rFpIZb3 UܲT ;嘵׉wF¬2jZ&뗍*"=ELOa¼f$ۡj c`?09壦iKZN<*:>H]+gk ^%T8Y8>7 [ ZK7E+ZDz|KiuI`X(66RRl20 ^ ERۼ97s=zV:m <rZ'cubʶ,j:W)y* O ySZ[:Eƞi$k{ERڴe\pt5e!I$C.PMqd_s>{2'SؔryܹUjy /W%/*$I^׃sa\u}UR$~Ozx#/\C`k*Bl ÷0ǭ~Vd}h D9QF,XPE,bF;ɕtʃ0;luSU~xOpskz1,z ;cp"@*xP)knY#E.m\VǬ@i Q+4UŪ8c@  gL^NDWԴ;zݸ*oh-4PY&QjAشʵbzK,H#^_ '֩4ZQ,D)Zr3@jxG?OƄaD7 J31g9fYLv]5*9H'T#j Z[.l-x2hv}`]>"Uahy}lG:" |DZyTPcf`S_ʰPt\PR7D{J,4:H E֟x-FåpcDŽd GhuOW-\ƀWlhh g G#,./U5q̚4Xj1(6m N-i_ L[ LA*PbG+؂qaU RIo-(0k=[XaW?02VZȍA~)2'&DHF/Z8Vb`HEF$vVhU¦cqa`Z,4 czۗ\hυ\kS0}_[73#:4ـ5oZ^8.9iǞ~Boנ<:ZV65EL#YG^@Ö ms=G(hhO@y,2B~+c-+#/̲5O{כaƇF蕉 U=츠zN=YMB|4U]Sjꉈ<瘺aOWˌc…V,2RPK -Tra`UdZ1a cX*kh) TK?cl |BJ԰w$N9SA"{@JOhkC3/,\Wnq*Nq?K (gҪxx-—sʓ1`>j5*uzXE`66'܊7=CJTRf M[YXruʐk[P6WIAXm5D##>w^'Ȗ#z7PTP.KA|$Jʠ|hP zhx=y-VM9bZ_̼)2k%c1MwQ ѵ^_ X)`=f"hݶ%rZ LCklBzHnSܖ !R:Gw)} *rjl42Y:M+]ejX4!VZ*3@s\*ʠj?CSAƳvxd6sVia@9E"1LkuihճE .V҅xf[Ie 4^,ZhEÑ+G)C$A;V#.U BԣUL-+`= Zyuz,׀2Ek)-uêl@hcɭLhu&Z=zj G~ڋ Ds4+XE TưdE&Q"$Zwpa)f! ^6)ft: N8^R<׉AudYcTu]hOM֔VOtʄ Q"HC[焫6X>eي7R!uOh1ZXb+`6źbZqu+Un+ R:NsO#VU_`Nl*v7&KZ7L)s(1CabrtfUd`kU2ȫr#qtq€9, cVi`7԰ck,21Bg@Jd=^U뎢THt("w+D+Z<Tzt?( X{U)p$^,;`ajSHU\13P'> conУ[" V MTXyqq )2BcNjݸQnݑg+ڠL )y,?F^uN4\J3BGԕIk,?h_CP# TAOlv,NWHFß2L]yr68g77ݗrc&LMk! 47LE4' Ж |JvJŰ XU]7}dX)Vz3eWgpjO4 l ^οE#S L?R:`2X|kOc["^ \r+0zYUU_>Q=6 )j*Ts]x XV@u1"F:pE~sIeǩ,:0kAzBk Ul2?F~,T ˱ v4kpzgGkbCRS:* *r!E+ _ŦxׅY9w+i(9kf(]^%/>@RVEտbX! CW@ՓAm;&6O51X< ŒVVsODc s$*fưnRR"hͽg.%3;%lB<@εqxg^T|6K0*?oM8M')'?A,TZJj1ŪkŰSAq"f -u7Tlr.Zxc4+AhDžIlj /*eX_FTik'o-*`\ Q4Ug7JPCn x)XՐ {;5T?ܪ,|kMcё0`ɾ2DWgg-F(Zv|+yRն*! =KtXNixp2\^n`pF8TP+!a@jj 3W2B,zR%m8WZ2Z>AD.;)vbRWγq)f]QhE{U6f2w$Z,EZtcN{/qc8{4ΡR̮9֍tqT=cm[4Z2+-pUʝrEvS|W<@4V$Tj޵q1,WbuxB$66K1 4oZWqTf'C~*=FnTǨ( LEm6r4qˢ%EhZ &6,Ijc,4$`a@R#K>X<'XUK(NF+jUi;rƤO#;w4Y::5,` +Zp&@]ZV@; ݪ{4{k//[Z2o>Ԥ1Yd5%U*ZM@},?dMEABHt^3@nd7DȟP~ 9USⷞZ=>Bjrkʍwl=}z,HK-0a?hIh?Vy'8YG= | @#kE;I5nUb˗)V>*)CO|0HŚ TFplIM 'Mjmj\V|ټTr^XXd -\WLZݕtz ,8Z ۨT>d ,TEZ<80ɕIFG1%P% e2\TBP"&{Gd ˵FUHȷieO]A[+"gXY_JV*љ6g]ds:鲝ܶjf$1uۓaw5[ۍf"VZ$xVJ ]}EMRCEY^Չ[ -K׀K"5uyxusAh{ XXP빁u}a{ ;3ES0GLuͶm? ۳%dQ{ϩ%U)Wg8rͨfnQvJMlD+Ym ̚Y.9=־Em2u g,x<@vyE"cf0Y1Xe:ǢZ*WSev,U0;Ŧ9#RP\/ysڗ2pQ#PSزN"ԉ?=[7B e kcLT}xOEHoC4< ^BVKOY~f[@5[5Ԛ~;T{H<ށki/^-`/\@@ o~n>U(.O2,w2vLPtHoBfLBP4Y ĨwOO$KLX{ݲk/19cLQFrsr`O(nY@wi>9ˬnls, jjB`zh +.r)h0XbrHfIXhi1M *Zi$2ldhHmMɈk)B̩ju8&t6g(#id>iӦ  sVy#䠆VȲ?3@:zVTl4 R(g) f)_zщ-#m*_(K5dY3?|C+X-=J^oP%=l󰃠 |Y'na{aR%n4s_w:mE5i70=*Vԣ fyװ(x/4 X:[;^dR]E@U#|"֕$}{XqQʤ",ܜg9CͲPG,1Kr]&J6bO;.6%P˚8m)ZRRGKRkqo%]wCB kɅԳi,(cs}~}*Yxz<!eh2ѪjB|CFu~\KǤ{TR\~:!19\*9uJ9xD8N GJàaVpoh@<z``⵶ {[j4t|5P$8E u:lAg;db-% x ZR&E 'lbg5h(O Ŝ݋w/Mp m#e$G!-D–h_+#+Wk[5@ATG~f 6Qg`똏,RS)(k`D=CVHˆMaCU!L!&D8-gbRE13+sS :^Q|6{נaihؖRBÒưlؐCL yzV /Tae,Z ){׷x5H q{*٠Jd"$A[qq;`K%,4̑^aVʦ R&d 'qQJ\hcM"*$S)ѴCچ)_ xZJc9Q5;ce'KcfEGizw!. %Dۗ|L VI\&R֧/,Ca:Y]xOLS (Ԡhr C.TXY2i~$x;E PZ}Ű 쥁!2Դ:i)E2=j;D50gL ZDeºm~{žl7Ij7sn-5V iGIMg.:=ʅɿpH˾#-,޿b%?/ E}K#Hn@b1䳥 4 QR"*ȧDVNǩ͓HեʊHVh] !aH7Z U7nm;@ףs ŮTS$A0<.#TW%bV2ؔuӦ`)gݟMtrbmkfVh%Hւ-E+ vZrXBڊCvC!CBLGl+U_.;P_ HYX=yMKaT۝EBtCh#v.Tϛ/+ݬ ̻T[&+8n -#VYٔs*ϹW=á[ͪ.;JHϮ2|oH쑠*儰;,۳^ߖ H$C<> Y^,PuN8t׽; di:81P9cyG% b؆aBS`9$¬ȸ[K1K.Q1}}0.B J:@41PhՓ=Bmc[m6-Z3ܐW[ϠBx;TAϵ'0*)γ}ZIp1Ɵo8txWA{0MMQ,r(ƒ?hg8;%`d3k-yE'Ñ0@ \=f˝_U[,XgջY(iVa2ώG0Dhy-'VTDxrP#)Pwd5%IlpASvj<2Kˑ#g.#S Swf;}[Tfz%/P`S׮^Ƃ(n0ك k/ g.Ȗ̔Sڳ 9)<3 a7NPL&SV ~67xilRN JrCT,A]`BZYpE:4+11?k݇Jsi'o֕G56e,D*% Qr25{M-eF(ju(xPׇN>>e+ƒzs2iX`GU&b+{l eә-[֊J0v~cԨ1 ub+ʠ.Wc[c }"tVN;/lOkвXG?X1 h jޮpn4K^|7xYgdqGf>MCp@]cqǿz=%gx- WeFt:=Sڶk{K!Og N; Z4ڬs/0 ˅3N;ھVH U4kPj2jz9*R& +d2,Guyo(aǠӋl-*Mr5ÎVc6ٟZd[2wxm޸vZ)@* y_,~? A_n~#\pJ%ɰd# ^~+ڳs+ ]n㍔?:-[V+=xN䅨y/RjI{m2TK3 v4p}z~qLWg..<1{p.Щt%^bHkӪGIhBb&`!ࡖK15{t)yň[,Q$1Ԏí^`P.ٸu#S&tWJ;4 WQ}{21л]d;grw`N?w7 ,z5OȤk=6{o賿=7$ZOa RAtkJ7RKp4#Qf=׳hi2[ ŕvTMt3jKʲnLw Wݟ}띾 (T0:,59ة ow+RU6`. ҈1p)lVDr 1gfxin fh*.l;}~^IAl_t$ Z-E:Hwffm]D"Hg)jI7|$rm~] * 9SRZX;Y.y7"2ܸ~;q!{ckR/K)[sۄtPqr|ϐn#n'򐙪aإ m^T=_Y ӭ7[eTyɨE#1Zk<Ϡ];\ڻhplZ>lbx<':A$ikrS*pqw1Gr"=|RSbqD (EVPs pp4+ Gy%ْ?kh+s t%2r^ l{}!s՛K9pY qlG GPŢ ,.~Pow8-}VH6eiSA*ْHٛWw'Mb@5||޾/ F9jpVrM4C>qLQ~q(梸ڎu/_MR#}Y/Mǵc4mBa6mpdsw3wl'/#,=ɓzT-RwB 6%i(lj~\[Fa1d>%]Gs߹/ ɾjfPCYۣyǝ/>lO\(i*m9'af)7zi5 @st>V#Y#}/"FB7T嶺d6EGūQa8=TF,ڣoiܺro VS*v[>> Fs+X9;ɉl;vPZe(y#cl>C3$ڦ 5wF%J<+o|^|zfx@%3Ţ^m~*La:{tط$r{XA:mf%kNo"(*,ѽڧ)'H X-ar9 ţ;Њbv9$#Z͞*ǫpS_ٷKܣ[׷ڴ'l].7|jX-8Jpu EUtTac1xUo69C+_Xg !f !@D6`/cO,nWȢr*ީZv>r +:P'wGÖuFn&~% l^%dveU7ag:F:3ŀP\T/$X"\{A Z~1|L$/0dV51]@sXapaV{}u&lCU@eʅ m"$c/AKt"AuԹ^Ե Ͷ4y?OhF}W?];ĹebkVR1gM1_났FރGnscT1z6@6 q`k-/ nlVuK/isn?v{hd/"V:_/{4&Eu^ 򟑺LU= ̗wL_ *IȄYnAŒPUC%yHV0Cn:681YCa^S}6խ¥\z#00K7˘ MS3S*@/d7 a29tC:W3ez.DR[6),!)o}D5)TT>NL082UB?qQYQuR€Lj1+-5^Z[l6w\ĐuS@V}Q68e+DI0x Vx,&K,G- jj82HDQf!"[^p9 )'w(g]XگKŴ8`@v4I45|y1ٟn 7Kh~þIhV_)ߗ!;lǂ^2- QPl=*yc`syMlAK&MuF=m&<CIDkv,id][08цxV\l/smg|ig9WDh-Zu]VQf wi k\yeK.j,HS:VŔST`VsMySۓDH\M/ Pݦ4WG10RtS<;y!׺9{-~MPV)p a]^saxYh-d~N54g:\ڳJ&#bʧTzz Γ|`,r>(YGch3b=iyd(f) 9] KS~XVP-@Tc`i!D5펥y2LCٖ59`F5uqz}Aܖh ecr|`e=[68 !phg>uB4%frm;?[I٤>JhybS\ KW/RJyќG z0.ߟ  0TjRFlwݨ`VpSI)zr&D%۠R? 2b͔=}"e4u.5%%2ZJ>Y9EjG|Bʃp5x5#h%G„U$5zs2`[_1b/>\|X$ x>S#Z*S-ߦԝŌe`uЖ\nU.[)䭸 )`TpFB(;Tq{I y~ p;| iviF.$Z>Ժ8K@:u3rcEFZl!1Wsyuc֩)7!ʷV@t3ˇ~v1Aa](-44%'ڧf LMZshI GaGc:I E~ 3vA'@!AWlYD/JvG:4GhZ{'lX`GwF N8 dN627C'_T>E`8$06 93#qhTf޾AԗG6[bB>Dbf΅Stʳ֋aJeX8`K.|p\!*Z94U}i'Ud5u)bŬD+݄r܎rKYP|1,t _D7@w722nה+$8pӧMK'-^8%TJ4DOYq1h597di@)\BuT(+ׂ*ϤY|/~,#Ya]@d&Ȋdt-1B”\I+[t@Jhe l0U[aaA/{f;`5W%)C48ZDG+M,) J}c؋X!k^;WDĤ+?CAUTGFkHY ذZSiV_{/Ҹ#<麆1VVBp] K2:R3C۽_gH` *" t<=$iqaA:p_bnn@Z-ZE#`ɧxK[RBgXsʸIK$p"M3--]s)`C3o"վ'WuYV5׼(k<^7?"*4h噬7V9dd[)G U{( bL&(iaV[H~ VVx'Y!{m[pJzj6 AGuLԔxyT],ӸN:4NET[b\1oF/hj.>Rz)`9Z)Z5@Xj`^>kVZ`PZt-y54.b%h>5ΰ,xZ<zSPƃ ([4LrD_?2hxJ=ȧC>h>uų+HVɴ4QEiepZ\K2'M]u7NԊGTsXpMj얍 VPUk]r"V=QV V0ȎVF ,$< I¹]B(tb%(kvIR=(w_or 1Wcz2Kz{zdxiy9I>Rap˩$2 'S2L@6''XՅ,%rq2,^]8[`,hrk;ohuն`BX$%WC0#V,"sbkh9[Eryeo&RG!)rlOlV\7`QNWz7 M\3^D|y4SZY4 cikf0kXQgm[[`6N1Ղׂ* j5XG~5K V:ǃU(܊|ت^یqIb9x"O1D-|oèf4v'%:d^Sk] b*>/ܧNܠ 08$ˆC77c#iqjʇZ[5LC1k-|sak{faNG+Z'ʭ+5wgͷf֊]O}M`A٣ t9mk'%cU2 z UVZa1zCn]DŽW "V(!vueU-ҧSWRޑ Fq$D8S2].qĊ^EαNUE S jp2xAs+u)Z_ X)`/y<$Eъ'xkZq+2{_otk!`Kw2Ul2M_y&Pӽ r%OXM(hJiP~'J m᧡?y¾YNebJGOlkGXy 54Iӛ-ś)NeG< VcJ{)iPG6Zђm< /:`Eq/,U5ޅ]$1Lpaֈi8[ v5l)cPu.3u5Uj8q^j=218e.ھsÎZ54DxhI_|{c>+Ԟ=b+*)=x%4̰yr^z^EP A΅#V'ư"CT<\LQʐ0 Hyv:#>}dP R9-(=~~fl1)FS`|&iUcDB܅7w2D&) IE2FchhFڞz6o6VLȵ%âX0ͪ[A r:Xe}|mSQ#<K7pU<,R#Z5ʅ8l)VˢZøYlr S{MBGݏ!uJTR6#BO멈vb O"e-Y#V(  a`kXHCazU k4zTcƃfem%^)ӡ[\ˮhz1kRP`<8xW:~hϗӰ<`"ί;!n(#UZQcj]#}>'$dìz=b[sb };z>YaػbH=͌Ja<2Kџd8)T*?♵t_k S7:€PCڨ-?=Wr%煱&EOE]ѧFaP C8df}é*g2rO,lHXkϚζd||Ek"F[@*+Xշg ^rWU`ŃMǘLJeudJ8uG`0 ГYezi KuBbC-f3F90:0eObX< X<3-RVZr5LYFټ}Nt60Zyd۾Q!\Y;`5:UP5MU+/5GV%T-Р9.V?5T+ܼ[S򍭉ُ-w4mhj[OqTl,,&YA*$xNLx*`}B/4a`X X Lq菍U KWJ,i{쉔D<(- Is3Lj0Bay[.Ԅ VY(U72>0 ʼng܎Snp|<΁aפoZʔEAOmL`ZxzHDGH;?iJ[ ?j-L̊'Iu$ˁ$w(ԕjy2WUivÝbiC=NrAVb(VN R n 8KYrLT?T=F`=x-ǓX4N ygXYghT8_aà/h-IvRUq ԉq+/9Z;NU;/Rv1B3Ț/mkFmPKXdIobve u9z~B-$| ?fo v \B͑0ĉ`pNTNݒS H8`tMh1 k6I0+%>7᪛f{(ۄ[MX.Λ^).bMǴuRRYyKUl?ӏo r)'AwrR SQg/Kuy<4*$HtwUdSK1 0+fRG˶Ez~Bl&7.Β".2K6.--ָrw=-ȔUCqxü6g'l v(l2vܛ_G P`j=ewct ?G꣡ܘ;ç7+X@I4AF./ZPC vriLI ~ _+%X dt X Z9_$ 88)0JuwFrUaa ]ߏL z:^"!Ja1CXĈۖlAXh-k\&2߶L kOCc @: ޠ GȵFwy.+j0wH5 +S^+J̲֯5mY ճT -tBKOݸUSWБO%[XLc2kvˬwh@U5 5!;52hC0먆;gXYNCL@Mth@N_?iK]r㸮Znr2{r)K")x,r7b :d|Km Xi'A%W0L'Ryاahia Fxnr&|B^%J _^Ulj@1Z5WlY\DYW1E%sw̴"A`X,CU@$%򆹸Z+0dU230Q-Ǯ \Q5({cև}Ɇ2hu) Ԟ؏O%Z O+Xe\>?{} 幾2M. veV ^`ҭlF%9Y(2 vBs{ ">_׎]aVz%ÕT͐fJ/ 23R$ > `R&vߕ5YQ[{Mkѣv`l'+pV0֬ ΰگADurre\2#Է^ VW%TE?L{2[ Q6. 5۪_xd,lX4{Y UX#ڳ;ZZ[hehy4AdJ͞1sZa=ѫͰX$܎ #<&2xUbi)#N bc9dgAn}Q!3S^E3ב'L)\"N*Enf'Zy8U`⯅wTۨ, ̺$zt۽۶?Çcq~wDaϜ%<*aPHx@U`_[!+,3Kt@Uˣ` 0`tb2,PX6~}d[%rtiV녦X6] ^ nK쎠v*N{JHXKc?*;*YW#daWu[<8''y|mIBwCCokZEʇX*^i)H P{ddmV6/Htiy-z.a>{W/j*Ja C[ :^` tRKV[u@ CT)R f``VNAt}`ؒbRs2*ޘ7`! DqFiK-|L n{lk'yԭ [~J Jʃ;Q]GIpDBI*,7Q3z/z`&ڛcWDR[DsWתu-H}]_V/Š~mMG_rOPi4&] 9ˁau:IĘe>a *v^r{V5כM#]W9S6L1ۄd&vߋUؖ((VK~IJeVzh+ wWn\}HSϦn1X*>[u $A4(NIwh%o wN˲LB+O Zv.+(ԲΖ+]6u~m2 >i"#CFeB2l:00xnLRX`!Q+OB% Y0xK%:Jȑ=4*|sUKtbh9q u X%D!vXU[lTqк%՗.cMVC%A80lM~VSL Ub֐ACE kg7(vI*Tސ Dpwc☕'ٗ  ٖcx&.kx J{ S;m1p- $%[[h}ݔ?-?qp|Lr@ t?2I'bI7pf78hձ)bY:h S4eM1r9Is!SL̇|YֶEh` 3 xT=iC-Z=ȕ9[ *;W]'(*oTKOP\MUV}슢;yu{W hҀ),?$A%\#qy7lUحtFĊNvGΟSZ\;052^`d@ze~A?l,hsVO' {-IOe G/HV6է2r Ҽ?Mmn%>q3T;z91\OXUUţYvvl*V*G@IPGn5C\J8NɝLE`Ytkg5򚯝M}xqp<ˤdBË .h ;ej Z 0Ie,7[jISWUڦۃN7K_J(!1m!e=` kP tghU HV -tUA} aI6M"QBDV:q ŵs&nXZ hO"iƬ;jȲvYqB)N)ISI6>"9QL T"tƨ)q |#Y!Oy>aVѱh8(keYZK2/胺-b~ z >nwE,_011JɒH:3rOѪ`>WPnrNwOe"sGaBT*T2|7"$[[ mTLz Ǭe*x~?F4 muUuXtVuYpOPrKc˶W“HeJ)W\zn]ֹk ne#Xl/.52r%Ik7\$l_u˔ UU,R3+M%vrYea4,ϯa?k9]Bhwy )hg3I#NĪ ɗ%Y$Ns~sdE -1tasXGqUyӁg`aSUjx;D5|-^@F8FO ( ~N %vYڢRX`Z>(82y#X՛`etU&Q7cڍMDm':ֻs5O,EL^E`KR'"Y0P+vT(晚N2oByT/cB[[%ϊ` j,KJ`݁#\ (:NoY'VE2>C;5d4dI‹wYԘgγ,sb061˃4I~S?\F,%{of"E0( LF$1JJ9-T҃Wu 32>H"ƥ PHʐ`c^_d$U]>U1ݻ5S}ntd_ZgKZ(젼7e; hjo!%0EɆe/0%{K/@7-ϡj>a:[1 vϔbIjҦ"$J0ͅdF xἵpgV%;H% DEy?,=XKEL@jI>6pVR;$Y\p" >EDD}T6*^EBi蓇|Cg[?#JM#xև_>kff:lm9H^ڤ'ovo&j{R[?G _N1:zlwMgkڽbak$ht؂A9\t I$ A8!:lælEmV܋5kth(F,ƐF`sܽ ޯmf lXG7PVQv8z'g@βo=-"$ڢ,u~˷L1 Y)V~xx*law谰KW+ۋNU1D_+HO {P]> pbz?U/Vu5tؑ.9'oU>q٥"k3TH4X2!&2-h86i)f{0ixC޾CKKNhq=4##zk/.r$P <  /!}{&hFJ Wk;l^CiXtq+fpV- 2A~Ш/U/Id9nIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_a38a1924befb1721a09be7d432f5f70f.png000066400000000000000000001655531420147000300344260ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx du yǚyԒ%k$$F/??/~A,Ƌx=,K<=l,˒'ՒZCW]]5VFcG7ϭ[Xշ3O!N|;vt׎7͒H>(a~ua#>9p*oMcHRBUs%HAڞPZ  d&{bц[|vX's-zd3&s t3,/ ȅ6ꦆu"#)*iPWCv}X+55 DBqb*OEr^Ae1̄mI@A_F7HY$nh'* DUE^&`,Zz_Sɨ3PmߜLeTנa]hA_(T1ZR(4-S\)5yI)$33 2 Hom +ZP֦l Z% s07 I*Pzu&…r519G hh; )}BaRh+LPpc(eBQQS 6ZRlM2yN7w)fVb֜doMܠhe,$%8JzyO[}ѐ, KYF Ӷ}MYLIƍ#đUz!H9$ldL^y+9v#B:[he89baBy mA#eJA<"P2Ƈ(d%sR_gv7Oμ*6eW^%2&<#KWb5FTYS|q,eYԶт@CLM-DeL&oM<|w>0T)oڤ^sFǧ3U,x9$k3z˼bSWA7sJ1K@ X7cO[d\ `+(Ȉl%Nh{)S~C=,#q[{"Bs,V@8!#e6Z^_klj0t.*)vKZur- #(2[4`zj^s\s${e[%o1A-7f ccp9SHT C#[ZCsx(<]-ex8.z(cWXhU([@)i٩Ufo>6݈[K0. d#PUĬc}M/$`aTVuZ$ZYq|Y;bIzв08tvjh_0?!sہ0(iCHI9F` Ԑ()ܙf`-_eP[ޤ>IbWzҁYz+WO&z]ʿDJby*!70sAQdU2sQfzڂ,H< omLe!kW1Җ$Z>sE1Ry:A}baM\7SoWyd_lwF@AH 2U4ITiccӓ!8JtJY nʚ[HN)3TTaL00 k%Xh75Q3Jxa)}L%롦vc"YUS&Wf 0aFncP-)PirfAl@ s[)IP])WĚrұ5j Tlh Cw.26Jx3+,(P:::#ļ1RQEXV(_M= [ 34 i4ZJ02ř6TԠ3%Eiү827hE-%Tp3&'a76wPF-kskm-(<ašy`&vxjTɰ^lz".`+{MPj teM!dVVkRh:Yo7W`D,sKxK`+%({sSdEƧ"m<"6GT?#i-bEma8UmO`*7Dnt rEE<` K oR$uePV.TȃS$ȍB2D>Rdm];/jhJȾLPB.E#*ȭ02U<5)7BReB%U:+aK2qc,e%CyrÕ0DZ z)yB!(O[d!,5}S2_gQ"!%Y杴z^%V1r7xԫXn2sqyo{ XhU&ZqTfQI{eٌ]&8dF3HN1bLhg)'*WѪ5&ԓ>SJlJ`S&XE&BrYx"fɰ^υzxX{Dh0 µrJH*Vv غD1, |.Wp"@]J\kٯg Yj]A'ެ'3#2J)`S2h xMzQЅZ^iw_J+} WzKH3 ¯T) ֆF,\}j.@M|:a,BZQ*3YAkG ߛ}\lb#5dX7MW)*kL ld/%c1C̮!T.?48}+_DfDYX]/Ȱ*P|Y;6 @5-9%H?bU|:γA_k@!hI"lMzg` fƂ^S9:214 `A*cf ) d)\PBm cb(e(m$,,H.e-Khф%U HRĔtB_>S3Z+qSQKuk~OuF;*(р\͚zRm7higki4o [*)Xr! i J!8 V5>0)A|I!YGWNba~ _+dE$rvs"&0BB1;? *;ڝQ(Bi<EXV|TֈWQR*0YXZRޔ;('LےI&B-lB>5d1] #BiS_[{UO`bK62ȋ:s*Ar:p'~o^?6̲V7g<ЉJ=+hpEe D:`S1NyB&^ (\)Ł?G#*]o">;pj4hYʏ+(gI%M_?`,7 PEf0z\[~6͜)&G\kĬ.l܁ס0\i4}y"ϊB%/DكC3^ N4 XU}&R JVb/_ǰ#888Y}\ut`(Xf˛iױ ҄'$VB SLQH %ƪK4D y{u|HByTi@%rU^0]Ed e@s Y@ \~} mθ٣;]Ѱ6M;Bx"i ϫ d8;b%m 9Kf9,=3P~\Ӟ-Y9(]sh&V-] `+3HZ1H1Z"uu} -AI<\j2=@E `G6fq8q;v6cg]T_"T>Hp1KHc0zrFg-85tEr ~HO妨Iub׾`rb2d䤔6Q#EC5J$2S4Z+cYҥtr3(Pf(~Ff.rx+1͝UIjH](` _~]#zMyȉ0҆ԙW1VE$e`3V37Y@C@(E7Fuw}뜩童O0w̫?"vHթ2ya&Q_A@+8ڞVHsqsM4^rȴ$V"_H^r,ቲ县l%6\T~%d^4`pmӓaymW¥U\-ۺᡷ~F6he@K(m;n3yKgIsqO?x%Vb^0k} -Xv~*u(OI08 Ɗ{m1j$:LJݎIkJ;9*b;XM,EBZtɠlNr ։S /gћ@'ЕpFY6YI{?YߨD`)=tDrOt=}[g6lM4C R&A .%{zZ"j;Su`L!Jj^}UnVԠմku;^j3*)&VybOL^' v<8{|",yTl/θ j.h%:myC Fp nCI-&Hel"nI10HrLXM-B$N>ņM \Ky'IBONiǔgKAm[ʿ!:Y/u,4*t%OV?{>뇄Iꪐ*q !n2ѼW ~WS^ =Zlo_׷`wvֿP<_-GI̳ eMа2uLUv{]rrçPAV['n%s %F\)K'1HV䆄 ͆ \dmPx;Salh.)d2֘Tdy c+8Wl#qյdoKu5,]+!<= Bl] f*DT1u^wZ M>B.,6D2Veo!z7"/P'JoAD`"cy0}6Z1!z'p/f Hv3 PThω(P oYU DNӍH\@MbrgN!3&$qi4^ʡί ~ȱ?pPCzigb4y̒vҫ qdaLhFf#ajֵVCPL\7hEnC\cFjxhd,$ Ѳl7SNN !NZPjoa'Ji; fC ꐏE]W$L 8<\X^ğEJ2I|x(@NT$r djm2 jsѭd*eȢ;r8abRdzҰPPׄ11mClO};޽}ԣg:C!SV%]C՗B:&΅oZכa[|VfnmWUV<Օ_T }!̞9D؄<FC U5nxXA ;GK:؎kC<[=%a SPy3(I$\K$%*iܦE;r4|ODr$y2$~79Cf$XG{Nr pGʞ/ת@&~PT+'{f&{//ϟPv9´AOYsQ%ސa2ޮbr$cPўZn[z Y !p晌w:1Ywm?i}qibIlj@{eI~ a4jZEgg MyZ $;D![kj`R r ;I  z AZ$l1o~;+{b-N!I8ZЀ7fJ01fe[d2WYy.iYඵPV'V/svuzvom~wL-~xSun8,"]`dCe ѽKeIyȜ!cU=_/!M)Bp85mbb&Z[^_XpfS,/M~4FO_:@&Xp{Ċذ{v]voڱkىd9D_k../xW5pyS3hԆdPTöeG::mvl1Q++sac ^UAr\6sM2utodT~impzib?wa.n6EC%0jEEOJڛ3X…'¯>kB<sȯ}wտ;峟\d:Txm|8RU+oݭn~DQ+.v`b[gpo|nw ~} i9Ѫ-`2U<}I SooOu?X~婹#V9wH;H_Z|'h:9}[lNns-#>н8|o}D1uȤ+~= 5vnڛu:Ngzbrxç.=~㧎_^D"HƈYD7KjCRٌH^CҠo߷Qғ‰1y0Zb*Bz~-ܷޝ3-9;--8ue;_W.ڕ~n YMr&H/*;sس.\dC2_cp/]y`F$h\4 cdT֌A"nmKg`G7cr&w`VNoT+XV*AUMY3>.~VD)wXML11{Guz݉ۗxBӛf׹m2=aI0Vïc3"vᥕ]Y6b~Qh%d-w>|^u:w:cw=qL%@SA,fxCQRh sLg'ת-n=8{yFbA _S!C-{m%fDu=48׎^ MVd (@ʃκc׿Bb씽 5r,I n 5NাyOn2;f+SPgXTS%A0nڝG/-MtR3c+/YīʷB^/rE߶C_8;mLMFqɇI)00l#}qx7G+[&w|ˁ@:nL9l-`Cd9"]L C婊/l 3ad|;;#Lk+g1Sq94$`y.Z1eL!՗ޖgՅ* gX$BO?>SBG.!]cE$_ ӛM&ء&snvlNAC=G3,M]ﻖMzk~c^^Te5,VUvHU^1ѳEv#]0I÷\K  ;_;sd-L]W WGzCŀBz$6 XE&Pϐ87AqGT3D5z妾yF徙?AՄeX̭L3,*_z-#k GsރTm*3uTݵ:Dv}1l^oL<>b{-|5U,߶#iLVڼײY=^-[l+)cIV֓[n皢:cC;v~fZgXK^-[,IWoX3Z[K}dqʛιA67!%p&g=8}#iZMV/|qU $Ȅ{@3{qwÂ+ށdt]~%W481GD{(O|]Ox}w{caoّG1ƷѷeϞXx?UȤ6*ꠐ5uFFU4W?Yz߽e'^З^G/f)"* ðkn|~>Z[sKPIФ{.]?2k2[ E$fҕ:-;c3HiKZHiՉuOCIV + A8d3h̰&z;yC_M2.a=tw=¦ɩޫ ҟ(ɗ :4${*ЍV=4]]~`#Z2|]|'& Q$k^uU +$[r!dvтj S;? ?ߊ0+/󵹏(>TAhݩ[mǖlwkKۘxmt&ZXOcd {yƜ' ?OlX,lgvu<}TH2D!| {v߹g'wo3gE{p<$ 'aR`<"l.ܴ[GFj9~ȧg;}->JޣS{Sg~ëc}}p}+r̽;v~RN,A+fy*cX#yfz>4Z  dOx_=ws_{|ߜ<5Ŀ{y}qVw_4<5dW9QoBt_Uo&[4/~b?kgb-V.¥~Qd]id^P)e v.6C,`"a<yez\,~:v!ammW~8,;vGrWO\m_g~KŸ`O'oOn - uOy%vVUg_zCf?Z/し}/D$ ݶk| ;rqi1C ~+Ǐ=pLJEGthzH_z{kp l>3FʉQԗWĻ6O@yCRMt'MZKH*Hjn8*Ɨކb,v{e.]7O g# y|emܸ[pnL'pܲp6\m6gz5욌$wb=<_ ּnsN:%+X$رi3=u"R˸EʇSebBb V46/OoI66!=40}N/]\8zl?kET~IS,-Ȝb'L3qnsqd0ipb¶ J@v-gUWyjKqV FShaÓ4Y]A*;+cݙ&wbc֏+L`mocr=d| S JWlM<ڕ6Kh^ow2y*R9CrM[^Y,22"M:Yl<^27/'kgYcVM3C,!RHN'i­f"H Ok&aj(9ŦmPuh AJGLgbYИ9`7u<I6E:YRl xq *-QY_>2x|9pUqq0=WEݹ}LTtY5'eyyNi8Ҏ3aguT6LfzH(w U_v6WjV#*MNطM_:,epL sJc Wsi5@>dvn^.toӡ\2 t|W~Y[w T&n[pյkbj2_ 2N͛9  _\#Nl9M nẘ1أ{3K CicSv[ZV.㒰"YوSi { vUi! Z4<{U9:lyWg:|f]AvdQ;2=[6m<^Z⪗%!Y^iNgjmk~ӣܿw Dmܨ\YZرeuϾN?t(]<\XZqX裟^0G&=wlz|v|DG^y߲أmk@oܾiӣ?`e0 ҍ\2⭨~3/>-.'|Gʰx2Xɿ8O>yOgac`u>|T*Y#/ik1L{DplNR9?=95>O2S<lj:%Um?YrfqMo.]c<"t[VldS^Bkkvc>ؚѹgi(eg kRiItLHwnm|ov:g@Ľdʯ2^2u0šGIXκ wDžֻn{m^b$UK^?mzzjoGoG޽wpʽaiњϟ~1r=;u>Lv~;xǘUUp*cpsOmۚ:>>]avm*mc{fnq~yuzv;O?`x{:#[{?:!j;tMnCpԶRnWϭ-͎ID~q3~V*r;zOTêw!t^x7;F t~m31;xXf3/ `H3jlP薦8I[1n#%#Zpg>ԯ77;>fb0"s-k3uk-]X>ƈ31\#n*@xXqgsmx%Ak{n/NsQ~̹g|\TxpFV¥Μ~{\EOK4u J{J6X,h gb(qu/ŪyXhE,Ø*Uʱ cPTW;w]!CrYkqnv *>4v/[* Xf=q~ Ǿpc.-=&w W/>}f/TB:'m"%m< M ԥ'^|Py?z<`[5;7P\7e)|,b|`BLvV|_nyMMey‰rz/DfoY-k\@nl9ZzE] v57`t$ K"¾vזWnDBB+Vb쯍,s?\+pfpem|S, };=a{J %<%٣׭“'{rentS52Y`~{(gi(GEt,P-~ܗM6__WqpL-Uh..2\NxQvv}$3uW.~z髾.Wfr+ >p&,xe<7"6觞'r~'~G|s gyaQ.wZ<]_86QmG?w';3hD4b-v%ӰjSR,YX91*v叞yc]UI$f rc/?G֪i;FYQq's_>wʤΊzcpy7dE2+HV6A+1YR|KϞ~Y^c_|iacqbPϼxb꿿tVs% vZ|(D,D3 kǬ_?Y+0嵽ZY-XŊ;@Xo~pTk-̬/.zlo-6d[-+/ѕK,% •;tlOv&[pj |bKq=^SEl(UK4XuW9jcGQ'0F޺x{}zf}F(q o?KwzZDH< ^txHXfa]hnS}m~ewwme~y;O?|q @2= BC'\>|ߣ{4 +O? }<:q*UH04PTREF̽(ix/_'?ܹgEU,kSϟ3ݙ+Vh䪙W^´>.ݭLߐI6E5-gvm7f74XYX;rҙϮeo\M^5#^&|xq_gLT]9pⷖNj"6>]b jm <*Ey+3{;hCX[?%ϱyz✸m=ʼK O×O`8>3{ޖps :tB! ),C͡CN33{zjsg^XX^on_/>nyuG)Ї:\4;5c>r3SE'?r~^%N f dDOu~Ю?u߾Cl]]gO  Dr|P`^̅u#j<鯔ɱ[RIaz_!}ٝݛڊIN>\r?TdxL*s&Vkݙ9x?&{s`l55;2R+ɪP`9&B v2&, *ǯ>r ]Ñ |_ܼS3{˗.tWEF BñǸ@l\Xx085rѸD Hƒ._9x:/_c"߉rS 1oŵݷ63;;1:{TťW>GL V=zg~?9};n4SUt<{i98VsIJsA x ЇuR(282l$;>{󭛧L:?}e忟[8I(Gu- Вa=1ƨF`d2p$Q$..#^QYƌrPC(`B!.-*%ԊGFuЌ#.ӿ)#Q"83$(PœcCBb.9No9&WA1P MNrI?| BGL9(M٭GOsVgdA]y0 zF@2,8ܭ r]9U|sŽGޠ6~dUz'A !͊&iHD(p(q"ul4~aF_˰Fѫ+k7pE62?8j*cx"66Re/k`.tGxr֗ۙbB4i9n?@.4-ɊXiBΖiY8<8UGɺߨSOqBLZFn\e ZaK',]:p )?uЫ88ѝ}~ۭ{_z+IlJ̘Dg/v0]t$(DM`vH܉,F4!ٝ D޲y$7VSCÂҏha:Xl)Qd{4զya )xjV-0%}lKL*05MBA >)soF3.#;"K ʛE( e c"@Y*nNڄ< 7YUҐɧĤ1݋cB10pb-]px^G-%Ívⰰ~/ϘQpd/++J"Ks /:)C'`MdރlxP"1$p4prQl" zɧBp(LyK{[pf!Dܱm׎m,Uva `D` +(w;K^e;7Pl2˃a7elg'jxVԜ5wE}()ȍ1#c#l)?gdg-hϰ%iLʸJjdd5mm$`%]Qd+;]&Q%!{]a9⫸LwPڞaV''_!yF)2rg V4ˎ BdU.xI2eTR-.sC}-k/U6ɃNM Ec"8 9b'NB_p'>%-Bϟ @XT)'aVȰ-]PWʆN,:uΪI?/@sc4 2**#QysI2V$(E|_A.bf5}:ײ' \Epgfb_|IAGP4.X4a8㆖Fd֯gGt(9a$l!}MѸ5 azf6+/_yɋ9;: KJ|lİU8A_~E.dd5lLbGk(Wr! f. #zr@ba{?jy?wG*B54圮<zVPkU˵M9jX;D0l1p! AzOЁwő1ʢJ7{ |Fy#j8)@SW9͙#F-ZwgYbkˁiC2%!ST^ET,>!:w|c\^K:FS%K¨^~!z~l1D^LHk;gcR40b{~%_Y*])' œm9擨5*)C{:jgTN6 KZ_}U*\u`Hn< 1+P sm,dC麘Ql5_]Mؚ ֵ n.rP%ǃm&a\t,ϤKĨ[,Ɔd0Сx@4#&PtZ]bP@)™_ڿ.rvoNϟ3 B@r.J"0GYsHw敯aXH&K/s6~֫e.ȼI2DͲ_c[HH`+ӟٟ)=ڬI{fP%YGY,UK6/>"68JKkTS%ȳ" \ 2KD7Esq1}0+((i#.Q8zgR}Y}iHXbqUJhh4B_;o5Xq^`*EmC\@:!7e}ӡ Xt` @GS*pR=sxӟuθiB'Ϟ/sItPV%VToҵ*-IP'H0 SPJ洊r7HT'v11^/T b-Vcfڥa Xi+ºhն?\ #T#qk\8Z*˰ZCf1p;Z̡Y%Úƶc\ W4_w6WT)G8aP6-SāDN*}d$5DqZ5v"ے,9{⹇T!r7G\$!z<0 ajbz뎭{6l7#9 HHl!ZLU<*j 5^EhRb8 Hj_]ʧ4V>5| Uh7 ,eJ Y!rYK^7|eXwW8uU&1b&W?U'0M)ť$e@"ÃQC8K7 XgÎ#!1an_\Ky晝&zS bJuum…J8#j+ra l9dL޸_uЈ@ѐry#לA`!`d{A.[cR'äW>QȶTVtq-&mR\&ǿw7A>CF[ϴWl1@ JhPZf f)n458USu,41A.7 8`ay0Mqn̷-JF\ZnD+'ה[ڟB>H x,HxJӌBqYHnXE(a}NbxAholºTjuk4cU浊c˂fCx_k|Syj5v'5^usk\#QC~lvׄ;TҢWwg`i JTҥB*{CiupF-SBAK@S;1lpB>@4)QĹxn3 >(Qff^/p@Lk`'L0qÇNDh[" Z29ID5IΌ,)0g!-B j^Bv2\d%j{Dmu[R,$yKP` I"*Gadyn?B{5$($)j ]ma1 ׸5cp4tֿr)3gg='xB *UG kHV= _цi*#E;>dDF/pyMxQ-lP>D"\HY(V쏄"c݉`-tIn6"D0LJ9$/d́0AѤQ~Ҹ<1khƠ3![ϺP(%lHY@-9e"`2L~si4u>% ,=PPMo , 9m1` JeMT۾ 6Ѕ|hfuL5Yt-M̻L޽$9@TTՙV2y7+Skg6>3?:ਃ+nIHO Hfvi@,ٙ( >* ΰ$R>^,8NӴ|'q./?)Uuc5m@H`|A8#*dQ  -S3 U4U-ܑC, R<0LYrlJn|Jzf` mzETqT"I0pT9OJ>b%h<De*̸0#DzhIRl!ז!>|L0KE>A8;V@O*!KmK8j5%2/q˩(+H2̢D8zHlfbgc!ޅD+ {2D;%iM<L$(w+#+`Rd$X߸O#biC4#T^2 Tt/8VեL۰w+\~w.M1[le-6ɻL}~ӻzgfW߲GSkO!]Y6-X)Sڭ(1Od:AܝG³!d# ]r7 9=,I;/Lf>[ڛ=aaA ȃĮ,JZJӂ #CBpbIaLk3MyK̈HSՃq_˗&"2Ϥ-=8\YSP"FXE"  Tߧv#ϝ65TD IScʗ vzLQ>.}E\CSebe  !% .-h@P8EYU6%ڐAjaI>^ ?9[Z!dX .t-`T[.xaՍ~Q5:ĖF_S%Bhk? 'hJ| MRh_,c!n)p^$11p)Fe ߑ߇H܌;1rި ص&^53x*J?Äg)xHk;re)7!q[Gǵ]{&Iҫ "W>fH%R.\aLi.Qub%<Y`ai쮂2f%w#طYuX[ǎݬ[!N),3>F"9gsHLJU+bMA܅^}er_d&FPN znGGG[}A2.PFǦjhsUьǟ$D2J)MDO6ѱ_H F+ ՒqCIqb 11ZUAڤ2хvD9SUd$*J@drڲAwqM'@V>(34e|Q;KheV(uPXQG"IJ7^—ЦHN(4ZJ"Rh%b*|!=% } K $i!YӂUzk5~l dxARZ|l)@['Mʜ*(Tk;NJQ9MA[7v G ǣEp2$,5ƄqPVT$ )ZS6l0._Ho @bjL$=K *R5)Oڨ5dbH""IIp5ڄJ)u!JF֍~]Ȏ$:lҩ_R@Q'_RqW3~H %׶rr3'2 gnpUNT -e0 ՘vIPm~\KUz,_\:R@BQ:L"'jiPp2Gu^?BcӔM)L%`JJB7VòBqibTt-o?53&%B+ *SZJFd9n{y ڧo%zMVM,"Q L;"9K\boA 6xSUFYiK7үVʉo+oL])=Bdb椰ڊ)|FAe&e-qrf]S,.5E-w_&}ʿ) ,Ý,+p[cZ8yeeF$jc4 Oo ږ]NrlH ]:L؁.WQǁz4= %,zg6!։U!m&ADQQ: a26V+VxUz7; +# n wؙ%S¶$R:"d&u% :$6Y)e=$JQŘB$wG#aگ.X ug!D ŕUD$dEB%"Pv_ɺKEB ~==Y ,Fԅ)gg݂6߄2N)-HP(RΒ3mA'*DZ%(Q'AQw\މ بm> (PcA*D9-V lf\?Do*z7>t7RBIdtv`x>|o2͝XN@Yob0R= Z) A v-a4a+xХ>1Y*SMt&#ȏL˸˫.vNP[ww~?VaQ#8s@aMlxU*eoU8A6 T\k/O utdm2 j (-0] 74!Z≶QHYI_Kda ? VQj#G'!Z%K,`_f /g=|)^.z |o!Nhxr3QU`(xl& %(/|Pis+}A@|=@A!b{ی3Ib؋@ Zކ:\Vk#N]CxHhKmO*L X+6Yr <j/$T!M%Xb%vdP'q5J= 2\xTT~KyU,r+@2=;T;5lլv6ʤk}_('h 'PPθP% s)BA$z4XE:$ r]U?d*Y2E> ʋ70:`%2DPf؈xQ!\0E\Y`3aʱy,_a LKi_3qޱoOgk=iQ5^VPM#y򌴸Mw0]ØS)) lۍAe.@S)+BW,Y演u:; : %^Jh97k:9ě|FQ!Z)D|<eM$9˔ ۀAf.AB2M0zv9%US+An_%x5y%G[o 4\9${qS`#K?0Qgy^PpHm=m?\+" [yU{PaJU]Vm\Ox9_VDOL*mɵ <)tD Y, }t6h$w7)Kͽ1+|C~Ї7r:q6J7g '_8Xp?K UPǂz4L8ۜځ=`dXd.NQHƿ {=\eA[u4צ擘B3Y1Ta.e>u^ v"MEKe$Y[^FQP`z@8nȶf*x@# !mPU'hChd,<~G:\,<hfBrRiuX&6.xΣˣJj֬C6nIbAFQf!m@v_T 00jvPuŬlG1zDNP"AB@ZVfz-~2NT `p3ڢG dv`W0@<`(. *E&pfN-ApD@\n9=`[uڽ| 0Uwr^: 'a`x D!J=]A=H"W.K>Cm &1',#hJelљ2Z%ǨOPl@:6 UI hI|Wv X{^%٫{EYE,µM¡6_9yto:diLC#Aoݪ ƥ9V[R׹;g8k+X!Z>EKU| M5ەkO%H%G`JXpNjmNRD,x0hD~Ak}EsT9C'?.d놑2^?4KYd"/XFRPjԛ uݱ;XaPX3 o5R#x`%l\{,M5~4+Mܤwz57)E5S u.5X- <)elnSʟ| ZFtY+`ּ j*Jbu,|*B.= #ZՌG{{xmW4DUEH~ "wCC~`*j vx;nYX3n(.A!ɡRxWkI* ԋM7ΧO~1f!gE(mG B>q(}KNgkPVѨj&zZq" s# 5bkmRmugg'M7MKVCW)(,RXĿ3ߝ.b|ʂTE@uWNKxm7rm5[._^Y]-J ƣK@p}sRYFԂ6vnL}əW\YQ^4瞮~c0* !wAb9rN6yrQ!dɝun 6$͢N,碡c 2ic*5ʷl`D~y+!?--fwV)vįw 6JKE ՗L7.K}wWX[׹Hv]s6/E)B+xKYWIU5Q%ҤaS^랠1R5|=bdBAATwu./ Wލyn|:!?0 CAH.0/_jEQ6DdySzph&j'x3} _BA0=55=5WwA@*o #Ү;3C_T:6 S7,q%Q m$9UVV.P"lO4֝){ܽvdSw=%=k[vR~ L!+ԑT" {uo1 .AˉQhS5j:#To$bc; ܨs +jg 7Ngz"G'V@v[iH8]p;i 'hG -6qyiZ UGx=?x KeVG4`~`B[!`XS{BոUzġ7BWnSeҩ?Ԙ'漞FˤNЉ>Tl]I^8z|jYM7)bQ꯿1LIÇakсka7VwW=X}ĝ473PZ:aDŽq\Ua ]|.'G쒍V7Pi( ?8}eYr^җꕯ󱿹|OďVD{D'CYV?^hܺc+4wGRw@Z~7Gp A21S[@JtleR& (F|Dt2Q KA{P4-p- Ń7 `')>y_kM $4VJ}>\Ll?t-.*q4B} MոO (r[JQc'DTBW!B,hE6Q ^ch޺ЕOr- ډ}d~3)`>_g>eK^q gD[إc39)[cw"gkgi([_.5kJ<- Ƭ,Mzh$# 3k~e˲#z//l߾~g~f}ϻy:?<y|;E[_/՜$A.+[~dyǐ}淟17+&/1xxU5 "9,)0 Z]6 @A}b E 5k}cC=i -@kvCu>1YMO^V !{+ MZmXgͫ6nn| EcL 1A727 8V)g#ӱԭ~~m{*iۇvLn2?S{ f7ew08<G7D+s]7(^di7#l}GFCaVDA&{AŮ]w3 4}6gUt1Ky33~dҥKv;?!%@~BS* h2d2_!h؂! (O[.q'8/;+䰀MM;nFtDCIֱih/Dۂk©DփZU G%x'ԕ^аag9Z'"60S9j;2(6h C YMԦ^^l1qO" zvZEuLĎ6GwOwVNwV&gnsubA_Fs__$NA#RΎ+o΅_wFMjQ{ [-7 `᪋Ԓ-BQ$;Bvj?YG.sF ^fYgoii"A[?yayaz,ZlTe+>f;|W(6O_{'~/_ޱǵR}kc:__˨`OL YQadhg`ܔ1tih%=qRvTnaF叚(8TćxL'D{&LB[[+٘V~:$3:6ʃ $'B),PJmc,ӂsQo/ %+XwLb3pײ-ATr3Ds`N."7)ӎT bXpΗj/BK<.Ԛ2.(jsg0bJ@J&6l]B%O- r@J4M#R}"3 p>P ڱK B/+UB^JfyN} Kp׍#zK?0%K$5s)2/1xZBlu%թ|y_ 7WXikP0/3w2 piR(SomK/,"#\!cN"ƸZ;͜o~l|,ccW]ݍ(.Dڨt<ťR|-7?=r赣{!qxs`&݃ݙ#íϗG0@WQJ3Y`sH2[T,]i:&|;N޸QL4euPK)W/XE=IqV6ǦΘ~#wO@Ymcm64l/>qN74udВ }۩)e$Gzq<Xɀ_"r[wWޣspok)H덽SCHQ`$X F1Z i!ijk ܷ8RBIplMo>.wo؏^|?ӯ|+?w=kuJ8#s tXI'Uv;Ѕl_|gU$Jdȵd6(O2eYqTl]ݘqPKOĢ#jGeACvJMͫ6B^~`ƹW9b #B2xUYa q˩%xfؘ~zZLn@n%^zߛDX{cyBTw م3L+NDv?yCqwMOtmz=ߗp]55;[w~cY&?zv3yGmc,G_{{[~׻'? N'3"roA+~Muw^#ք"KA0㣥 ~G1!2bK^/: WJU*$QXכBI$ "n ROy aa>^l ')E̻?ݤ(ny?x#V/U/5>:~יܜCUQWǔLk f7ag5|${~W׉d?<=9 H5OS+]yOΐA?-uk4ȑSO<|ыoϞڠ!)'Alr B1| t\-`PzO9i7+%!wnH QKEGT?L's0= 9 o B$ LH!U-*@$M)%:0 R'>J)}7xg=JWK .n8Xf=>r m (||~3sFq`͵%Gnik<ݙ8)|O7Hm_ƌT0ZZ(x\KQbTШ}kQ* Ғ}[{FF^׼o9qk9{x|.v _'N ox^7;;O|^X+_CCƓn=0yG z.˗?u B<a&j38Y} B}^trGܒ>H>"),NSN3 *q'/>KQ$"{rAls1_tz(]hs~^5)u +|OrU BA|B&qSzeD+b̩@vU_|ӭ{{ewXli܂)SuB%> "nx{yӂk2ȳPz_};1Ʊ}\~eyuxp8# /Kn9 wNtwb_jDmndm'H$̿BMNl\kg%6誊 ^aT= 2l&J;Z\?"9 k}&]k6w" P ' Qf_&٘~;ú τ-ke x\ $ zU=;xW쫣19j<;'s"h]wKb㣣Лfm[ \I!{xt[x\ۑpmkZÑB{0 $SN UDѮI`DZDv_M_!*@ hCX ă*[’ 4!}&Bi"^gnb% lT6`((lENʟ#Kl,o?z3u12Yyyb*l^Q>FiP'Ow8 (p2Z @;!U%EW۷/f``/KPNApwONnZ@_@ZnV7[J$e]mX(&F[UT=驿zನb> Q M+ l9Gv*9,R oz'_j)\}gȯJ*Uܗ5x)YJ."C-2& 8˻l>[WI*'ܨQ{^~P, tq01Tj J0.n.>doqrxJnI*[r(z7UTw]CbXzڙ+lYVKw׵HCSA˟۫]C#!bc, Voف~#s?HoceDZ{ϾxӧΝ;Z˲bBLc;w?xJüW=ͲÆr&Wv&Ee>`,. -$fC EZ$hml<4es,D+RզW((w(z1[%Vj%HӘ% 0r̮#ə]WVW>"ThI%0}c5Ȭa o˥C w:sZm-Y~ ]q2/Sn`*7Zk;\5k?ʓܽ>4|nAԟ>, 1oOKa&Ul۶8`@pAP V?}dYAogkfQU=r0F(~%aɔ=HITL##22i[e9"< UgGƓtUCXډȖjb鳠Ńd)`0]"h埅(DcyA92K8ywxXHsKpgfW W(&8ȐwʽroyoK=Gm/y/t?R="2( z5e:yغsQCu Y1O/vمYк8*R`-<7/߹0{{yf"^J H_!`l2"sSUNU DaQuRLR-Md "_VdD{HBbĖѰ-j!k?dl'Rs>ELD*D=_iRGXxZ9M#P]DLY@3&Jl\6bɻD-RoY ?7A+XYG|}h|5gvϮ>:Ny!K=~}20QL{yOn}"U`&) 5k7 256ʽR]s(KlzC-AMHW ]wٜɓEQ'Sior/ɀ feRcgӰ-TTߌggX Pdn&(۞Q pH\Ea󏷗| LGBܨEmp2|P^i[QP̸ubH*L 7 ]ȭg< *ZX3؄ q,k 78eǻnv%]rJ 3o޽y\W,"*6d#O?ÜbiJ,4]0DCic &E±#W$^#82FJs '=aG%U0ɘD>Xrm;^(1i(#$cFDi_[,ЎXu-ʐggo^cݕrݙ˞@-yY SJו"Y Gu1_)ڄ*PA*⤮VY~[o:{q:u~urəޱ973` 0y_*XgҳZ'Gz9$ ȖU@~)`gO-߹ʔ%Z`$ؐLT4ĉ|<6y k!ťJ-YhCBiTj0Bf 0\3ND90\c>K[sXxs-?/9Jyg8$auWKg^2q0S2~ssjOK(`}ty0X:>"`g#ZOb>S.o/ǣzf3G<}ݹ iRp$;hs:`yyDw;^&_=RZqCX0S1#O=SN>sΕ, ^98ysz8c[|>JwKx5;Ywʬj1 X`y4>7XI NL6sL^ըbೕrgҩB2Fad-A+7&fpIA,T$] :th UH0-$,t6z7(j,ʙʆk%t%`a`?9}C;_MATizqgL9҃I5r=M=m;Ү k 8X0k<:f')v2k{p}Bw[>j NÁmHo ֭ݽ#~͉S+oDVME( .b#ύ: >cF::(s_ oRB,/;ԃ6.+9s0Zl̯Yc)}0LA"F-j[ <  Ѻ@]B#xuojŹH}ϭxR{ږ>BԇO!eoVUm ͗fP﯎5cm-{]31|}m|{V>3dc.ܬYe*ψOȎƤaGz[tv4_Dsu{+:yT5@*Sرo$0] q.(W)dѧFv~ \|u~ߢ̅@ _7vn`hnyGk(B TlM7B3ȪW_4"?C=)Ŕrm|" õ 큃 ]Έ4]Z׷#5}!J QgA(*Y8)||C ;U+iCy&Ӻ37.W"?zHe>UU/jTER%R.Ԡc[0aKiJ?>D:@VH'*!q9JA̝|@CMcg2Ȫ[#7oڲ+N5 q1s}QSLJD"Oԩ   [\ @:Ux૭ytѷPhz\>MD{8h\ -F\N}a%l.lj%s=$Abڿo]uA{Ob -D;p<˹cl/ncʚn*=rѿfp=U:pF p#mLG:Kػ_nί&LrOΟyXƃ}.!Tr\ RLuas[yTJPG+@Mo[pm'+!~ܽQ^{ ]}[3L>YT;AV,KG_b$RO2W{xj'9;s_0Ҹsghu LC,}s(6sg;Zh0su*ëFl-X![(qEw4l 2İuV@! 64ȸndJ]=8ϺZ VAeM^Tl`$+! >x6R#A8R^m^0L'n2}&EoKڃHԞU=CfPYcwXu=F{hDNغJ` F.VVoZc~Ջk9^bk ;Jsݰ] paB1j3rnW 27:\( +gn8#FbB{| :=8$e{~`F,PF{-w_~fʠZ !TDCl_6h1K댑$wqP1~{K<{c{[.Yk]5G ( ifA-ِ`Y6@߆ma6m,M(R6EYIq-vwu7̗o#^f-]M]ŋqc_|;S_ _΃`ӷ|eiRQ<Z F qG 81 +74,QV>*21x39S{%6+~:@?i+q[ʒz/DTm[4|Ւ\HlTKzLf?|p|5ow~"$e?e$~2ؘ?/*\1 ,$Tv :'ou@Y&9GʕAP%&u($VK$}zpa)8",+DZwmpaiB7AN%5-K{9绋˓򠄈DJȪ/NجbS[S;pM)=$('^К3ޭo?nx5Zf L%e y6 @4w5 07z2 (X [NńE 1a6.|pprws;:yk.ʛ\{= |*ՅA}xBj(2qC =s_s39XO;|E-jj食3ԈkƋ]x8ߕ-}*in&KnHH*+e6֧b0,_}U p=|BVT|DrMr՝?ѝy`gfO+tqsp0b;lo<R2i<tDט*&ڔaj#;|}"a1԰mKzvfPlVss,3;< m@J(n5ʾ/C]Wˋ{; ) 4l"lW]N:?|{Fq)Ϊ_?wg*&^H(D&TjnɊ8F9Vk -kzSjXBα \177vkK7yy;s?ry~=A'3Pk Id#7$u|]w.6irx@p$`w]7ӁY[:ώv0E)`GdOٍ6l$ƜcŬt/]E*m\l T'MJIvȨWeO3,4&u9^/'2P:xQA|QVM 浑\ E{1b/1mg2M؅RDTF+XE Xn#!dfkĖP!S`12ŽLLUJ^dQ.bp:f%l&<WI ݒ^+L);Y%l,l( Nknt* {ѤG %laAj>Qq|trq)t`*/LflVţKs҄,~*ӨȪn\ ,ԑ;gaM 3fIR&vYjUF.Yrx<ܘQ<$7r൅HU?em`Q%kUV/V1Tb( UǬ.MjU3鱄BE]Y5aP?;ؒȇ nE_ϭ\Q6ޚcs+Hx )$lYqNbP~J.)wL<}Nb*kJri>rsͻ?=6F!{kgw l'G2lq"pޛfwFٝIrgݟar {һ" :`Sd(er[ToT/?/ze/$BxK?߀,,2aA;4Y'`v)e8W&yWSxS?{E5Zp0Z?lg溢WFizrxPz(1*U&^aHr3KUI( [$uG_ZlFD3*bs`zc!X|WF-P+R,(G ^ym A[cj[AN.4cÎUũd XWNz&ax pFt%4PY!PqlxvѭnKs(QOh=uqb6OcT{'G&G\$ǷtL -Dw&3rÏ{פƠ`8xzK7z߼O g/>?hR$9$-~ٸd.q:Vki,DP4#L%T!,PhRƋhR"ѰQFZIwV<,4QZu>Zm*T2f6J7of36M8V,=t/v2`Z~ȋa1z}R eTU*NV/G/t)gO9{* T338}ک:9$SU `UkՀe='2YT`媤fURCU5VI+`&l˄ Yd+ Ja ¤ akᅄMXdn/7pCMJ.pz#OT$g_vWJ]/aJj؃6B2V1&!zXG Qm ;ӵ%2Vt( YO̾{%0fObTXMd,eD}!Uq\ / 0Zzc Lr-DSk,4! ֽ'NܨU:X ^uVfQ*^CH@*|Ŧl@׀$7.ۢ( պa[IZfVLa)Y)lUl5oXd TMӃᓷL7^ޕG =`QKME) Rͦ.)[TMT/N^<|a:hVh kg`:P EE;ް][oFy\fG"V7ᚷٌ[UztLro5dJ 1~/j=Ϯoǯ XPL,` X FJ-HѫDOe~iqlm,Cd3e  :0m-G.?@>UISK;S)Ź*b/kAF@ D Uՙ(C&nxX-X2 |8umMbKA`2312Ȳ4&Ō ʄ^AjVQ#hWqP`>fn0Qg^& 8<{mɍ ouJ($aXkzI$3f`X[`tj{QT\VmUqBHz $ ߸۽b!)cRL/dqѢdP#OחN5?PqqлleE$Jzwd,kOsC,21@v3=68f y#HŪ+AU{/cmO݇`KíTI%VjJ^N4A[[ɼeME+KQ$T~>tATDbQ+~aϹ=NYְ4Ю4ыϞ ZtE",xMmq)\g{XlCwnHA|\5{~AlaXRtʽVʐM̸:Ƣj*>{/_~qCgN!x K[aw 5HF vd īNjȨecZn&AcN(@hmkLzg/WgR"Lb /Hc>֔4[$K'uO.#+P&Q-4JCix]+צB- k[saJ#! `3ZeY>+JldtM|GcEZ$W]+Qrd"x X`m^:,Qh;UEAZ7raZCe ;<u9շTzNO7/tŴg[ՈVR\dZUﻓ??ڨM5*D+f` V8aIxYuN/v_ُO Jϰ3`iuX31gr^5Lȃ|fSGĩS 鯯og lo M9U[ ]%Ø.M'3sE*{&L-Qz)VA[^'hVfEPY*x`#X)¯ MN!BO/ Uޓ,%}'zCՆXH}&ɠ~^JiUFww @1yX%VPD͊Rk*+kR!TYUdjlԘNV,[yspjYZضB}ʶeL歏]HY)Qx.W|e[37$ 2TQU0C2:?`=aI΢O/t<^ًK0$zY1.;u!fϾy/~triIPH6mu`tV\U-(8nr׃5TҤXFX ùVMψJUnmQ*jHA>{l/:)PbME6Fُ̭wgȋ{zj%bo_76 Kg̨܎v|S6BC F$7 +tS|-,+cI PΠ44/|wI3yp:N+&J +,PRP[́+^B FNI#ZI ] 0_٫_fR*e \ێ{Q[뗞3Bؕ2r*i X1h=nɂ,U VOH"[_ޒXXgzr?Ww`OEqޓެ&{gzvZ4,+IqbWBm//$jphm2jj&͈91*}UCB8o(]ݘ`~kJEV3"PlgO6{gj1gAS zngW`R--TY*A7DA3f h}( z|8ioCUk\Rax x|{=XVazwB)tܻRiZ죀c?}T0`arD>}eYgG⽟{'.={-lz>L ُ*8ZD>A<3$f>Um-١i)]Cu:`Bu!鸌60 AiitdF88*sR]̫fY6:-`QC%sÀ1;MaUWr#EϠ6ʹe1Jެ>#{.B/f©TҦWe4[.Ö1+n{`[ձhKcMB vJGo' Q1drar&=ov<켱Ww<$E9L5KxAp l^5_ʀ7罄6黥[+f.\/mzMB<' ~cBp(TyHK+neѧ6$ؠ-r-UiǦ8݅~cr6U" & 6X\"6K0"(X/iR+)b\=m-&*y6z `{K2MRvn8eߙK`Yq4Wۀ!a0^O{+7?w}+n_<WB֟u;mq¦Y8h.N`BhQ8-0 .w nɎ9{SlM0ZXތ+H0 5=DR SC?N NkL(adx-.?g8ӏވ*Z2w`wPsYY,- 3ch>St?ZXhU$3Kcj*0͈/nFN1ȋbz3?[Fo"ѳZZLGfa p0k@+!sDz'5^D :AMJ'& A`B(Id/ޛ*`VaX[0\*!Ȏj{M΅H=^4` D;бL0$4m5`UxiDpi^+;WU 3k56Yg>*Ź_rn<86.",0Q^A@_A(l\9Q =5[@G{z"3dfσV;h^4p6IK63D€v5&͜4>`Wh2iM6]ځyߟޒuZX3Hy2ȤKtDdE ba,҇P§_Ʃe\_Z\(Cy޿ l@)zYUx,NpkV#  lҫR kSP%krxRk<}mt~#?}?L;ꙛ3=}?+q"]vy+۰Q qA7^SYffo @v<ôġHl׸\: wAjBJқ5dbp2dI-А?. $nvA 4{QAU %t\8%m_0^o*0LCgG+|sU#@ Ƒ;\}U2 TBwhj'e9<m<N6O  FK^h| 50h G yxB{=jMشW36Hym2 a-^>7^U1I ȧ%/4z|h[o|'.Ʈ2J +"{MVj{4B `%H⇮ q^s;]Ih\xK̖h N(Ȕ@Qg2OS.G2 YuIfYl8..7І7"3D!,Y 2OLM@vvG 5Oj3}&;SI͏WJ' 'Bd' d cИP9jP6/i~"# AN7 hPr"9%e:C%b23 HP?76 %moɄ#!P0miv4 uK iAr^hVϙ8Nzo=<}>5jBj<(OOtk,KDpo E!xJǞ_18\/**s\޻ 2Ayg+ONXzg @d+w5xNhNm/ !a;K=l5QGa )hM1@W{>DcO pJ2CW h1Bl}h(8j.GV a͍=k+LvIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_a487ef4bea3dba1e1a84be5358cfef39.png000066400000000000000000001654261420147000300347400ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx u[͎}EK"ŲXHuo8q/_tMjxI$^8.)E[)"E. Xg{~{@Qg~U߽u{)8_ΗX׿Fy!G:ۯ򩀜9fH.0s"x̅S-[$G'g.|!ȿ6235T?_|j?,ό`oV6IP5/T|-ϮVoU9kŝS/K.c? th?й/+ c@A`DR m o! xFwq 0p+ _8'\51KPO*2@|d`r_@JwpV|Iy71l1OI0(P8TG)`Zc4g>6I 4*PPOXk]C{|$cCl FmmC3,}YvOdA*54W9u½<%yA|8e;L ԋ)ˆ&\-Jn'Q>^f`p6Ø4ɡ$1{#Pz XpN!#tVX]] S1K d8\i"3!6PJwK1 }_Ȥ F  HIH _Xπqd2E)!f]kcN?ǹ(¥1ף)OQwa>MPxHmrQɒ>BQ3ʊFF@Լ{9 gߏFpGYLVB %Ue[Rbf/`<X5"tԊ| =ysa"HPdupnljò@:%WͭmΏ> +#Ṁ*_"'cF#ؒbEU(DM*QzU^}t4v0jֳ4֙M*@midQJB׌,("PtY%&H*1JJte 3;2d&tr Eʬ,5ڍ)߄ ™U&%5)^zƿY B!X Hi}:XK,hh,L_5>&`R}M"kG^0h7MHJUNѨ0*;W9D)E5 0 rp Q#8?HkDǕ@u,|۹W|Ÿ݊2@m @>Eb-(J$*5%|^MU0w3qBsi(yprUI m`m@ :3j('(M؊k-L?_yT(XfMTT|وYڢ?<`/Lp8g0E`> UIE1AAS04A$DH*:FɭHzL E BF[0*$!Ԝ1Jʃ|PĨĢ?qC<`/\lшG~QDe셼#9˜q(HfT_F^&XLVʽCЃIT? HVƒ' := 2mr)9JI\{Ҁ"͉B})32봨O0&PlEF&hjFa5vfQJ7TtUl^i`bQʤɽ~ZWEvhx`Ƞ&sT+X-CI!~6L -R g0FfW\B-QAQ6Hr RQz\ P+ Ƶ LnecYiBlC4cP縜Wx!S'Q(\tF 9Po2+]0zаRJ"O5 bj؛2,b$d-J F(jU)J T+at)2QiqA7)Ɣ'pBY%㕂6eG15MndU'7Csorar :"0>D/yO-4lE( @2,u`%DȈI %WL{wv\pb$!%-2I샲֗ =DZeT1^EFl3a8_ra2BK[+ݿOH`D-ı-M%ca ĤJQ<ȑUAPx,; T ah4&y*{GZu#CUEMl5X ^[0# ^u^r^8E5Yx싞T؍UR52h8$#%f,Pg KVxpcQ!*]pѯi,@ F)k]zhvԜ gdKx(OO8iT% Vk9 R׹,MWVI*L=G|Ae9n)yEJ!뺊k΅PL(rRmG5X9i)S(c^j5!#Z:U3@^iu =U oxc^^{<`K3h(vp$J&1Z+WQրzŏ J%Ɛ )N iߜLe@頭(0040zAϲ?7hAi26$Z_1r Zԧx9A8Xc h(iVJHHaHf”BV0`08cAr+T!Kukо|buG+SBs<WӢB.Iu[C8+e*_kX"R 2' k! #Ҩl,~1@b| ,rb2H qB(ED!JkXH/P\rh-9Rg'`BL̔k*JF/v~W0v l \.7j߽ԠLŲgADZ2}hi%C]ژ$!\_XY-%}0(ܗKR!KO5TJ*1Z/\gӯp~-"=1u_E:G^,{鑝bSoːlV_E;ݑ2m5gڴ(HǦG(lAj.&pq&=BgMJBYђJtw܁E.?8*\_ GxUڠ3G ,fNduª4TQwe->"",~): @sk"W;'l0v)($5s)b[e3R(B<|Sh8"j s)E:e8CYh(( WpV:!ire*G&YFW`'2F[@.PҽEp ' Ar&>{ö*I hN:'-xߡ9@ʉ\^Bרhftm<mȩQj'[,V-e%k<1FXWP:\dK#K:Zmc86Q!T*sB%GB&p8P,t0oY#h'w26ZF%9[6YAd4 uDJub{qQ6D( 5 x -S"~8t⇲v9Zi :0Mdq: 1B"w. [RxUx$q NPe dz"t . (qNL稣h]ªt:yԷíǫX r>d"S'N}i}SC=WZ~Cj{dXQh ڥyVXqp51Yb1iPƏ(w |;)@'Ueװ*4Z@%&S`eeȄ<PD.z^fn +ƙ^M(x ^L3Zǭ@U)L&# HAEY0ux֥?ܪ K)aTU":9g1 C0~:D{;̤$T|)OxLs/d13 d.^}F[7/꓇=uP݋?qyU,߅>|COކ[.@=_{s? rҘIUVʡ*uJ*+ȏ,r nΆJZр/’?uT%3%C3%;2OP#W c)KM'_& Y j-[*Eq=L(_F!6PidqڨMG+)M(Z\ F//~gu_y@'V2=;*ScA%sngGtVSA㭓;l-l>؄FYz]6׿1x%~,oPuy̢1 P E-JuV2@]3aJ䲝@zu>[(F*iIs(05D[[T NKXn d kcw;P@iE}C(qLt1>wzBmƵ 8~8*tko?#ޖ`P;w.ֽ~Igܠ1uprkOm/:^Ů@ bC*Ό.֙[K`*ܡ<ץԞũ=pKgہ$?k2<ȘHյ b;Rjrp*P)\Z$d?c{{VoG}zF7?2BųLΦ UD(GY3.P1#p2f0 XG=e^P$25e/3q0wUUm?4SG?bSItfX%#A9РSvw4J6|7]}KY B5` Xvd1LTU(\Y|bIQgCH4xb`KFFGZ ;laS9䠇$&e; *JB8 _h D?֙jVhVV <$!Zuz񊑡ީO[״xQwYQ3caF Z\t֙2cPͨUEfOG+_\h=yV" S'ŅʔbXWsvecFֳy:O+we laiVs)dDD)0aYh)*$VbF@B;|X4lYI8TGWb\O( tƒbrGATd ޜ\Nyݖ­>6+ցdFP?N&40$#)fȮ$,^*`a5Ơq jfSe /r7!rlʑ,ra2-@h1k3,o"טkww'^CN(|ڮȪ=өć4kIlg8%(ܑʓT ~UCDĬ-5$-s gX\|cfb.0'9`FLä$ކ T*/}싧+P9sѰ*%piZ|, JzLvOLꇾ|t{[f K A0UFbHl UTk)LkX1(@5PBԃxf/h m~wrusbw!xG~9"*#g0$ܩt*)'^;#`E+^\CeQnZ  4~ 1[l&Q(tD3p1}\:5"w Q 21 6d[ b`T如hmp(n0f\!!uo dw(zZfLC)XP{q:;HŞ0͒g(id:ð=x `XԈsuUHi؂ lMq/aM < &֘S4B@Ỻ/ewwkͧ\>Uf^bǏlqgh>\OY΢F?.ۃYhYeub蝋/ڑQk4z]s[\~}s͑זhQ`*{Ѕ5IE,eZL^-Sc"B|)͟zr.AkYjb>{Zle*[^y{{Ts_. 8dt˪s PP"cLz|/8Sf[e ]7~ãWt(FR L{0!uwhs* ~kϡə9\A6ݰvhUC _SL1|מ;GN=9wlz~~1k5z#}=.xt뗿zkW 襼*/+<, AXsIsu+LՁ5b-XGv-4~Mg|ox;n 4/EnLTHvj'a]ԚIjEԂlp5spv85[c=_''kuzZRKa5N#b"Ԭ1Ο|Ў1si\lӢo|/w4G.ͭP$VQ(0ywaמKOؚ;;ܳqe\,k}[tŦst_ Cc_sc9nh;7*e{=|btxuu{{`(ɜ^+_?;{n"SŽGܸn˙P)1X|ĤbPC/ԹwuSOӪ.O:qhv~lDh=鏞8|ٺ3%RSgNTM*qQ_kM=<=KA+Sv6Q֚m=bb䯳42@ o+O04kc4Wi _bgk{߫Os@ugѶOᑿVL}+y'H)jЮ'Q|$Va lJ>f2?꣕.sOehU]Jʰ XmVũqn4 B_Iw"$fMq:? !5`fL>+ԚbỎ7]V/ҫ%y iCyǍw<eQS4X"h"%u5$FdCy..vnNhE(֨ rHksꩴKwpor'fyNBcR1hU Ƕ?RZ>}PO߼|}sy_:Ed9K)R€lXP^xfPG@kM=|DeȽOkli`=a75SшKNm:  u Щfɯ 'xiPTN"_ ƓDe{C$&u4uBSyOIZԪV5>_U}=q䌩A K!YͥSQpP)Ғ[^+ŶfhVN~z"XYJ ([8c XPaUebCj",!;GS}&Cu|y &9.;{ϵwE't893_GP` V0W;.+P,E7an;>zpn̬Ꝛ[]ǚyvVXCWʺꘉ Vu7I4M( Z`eW~ve3jUZR3auX2#Zt+%!zPYE:rqҢU~oTJP0_~(a[grS:$8j},a9 RMȧOqK_{L/ e Cj)'{JJt[]l1,L96hqkM{]j-`qي;6W\[oUT*ljϟ{K塍_ޚrq͹*(YHk0Ѱ\aǏ_!s']:{_;;;;!cpyrw;_y`#i3 deNIkf 8 +J ʭEY5wN| Y4~ʞ\Ix*7գy9M݄e&PZ 6~l'N{-I5b,C\|dTΊF0[sc m 1=RsXc_lL?u~__ 3m22btdM5|険y 09%w?~_ 4{fY펃w?vqɒ}7=DJ({m j/^>Er0#N0홙_nw>'.#6gh*+}ĸ$ Vo]S|BC-d//e'?ԞG:ǰ9_χf>WsGC(0sWIel0=> B;25Vב PRNLypu(ɕѭw}[|.c /C<ɶ [>ڸb<_w~3߾ypbу^*w;]s]h8j1!M@d"~$'Z:iʖᏽްy%,}={+x'<V.B k yٝ 1Y6RR>Rn$'5݋9 n5PqL̋ɪko c W ! h''$^WaX_H|u~9勱Dpԡ'+b-{Ս@n~xkݸְ{ЫW,}y?8_~o岫*/r"&rހdV㰩`zGYtkHg}XiV'=axk0T$o re9eZ17)GUK (압?HVcbϏ`AK;-8"* 'Vi2_ՈӾ]+`gȈ.P<@N1JJ)U,VFskbaJ:2u"/)U]KYA3'VntGjʧ.`Ugl qWF=Ǥjՙ/@4`2}xKack[yv@%/[h-agy?fHj< %kAaDŽ׵x1ͧ-r۶E8Ycak%:͜9P ^xl/=Û3'iavrijhumfY=&$!ֿ7P{X9}#Mmʸ3JUDg4f)c$I->ա}Q$*7{"@_oSRL03Q+H/Pjo|7kvn(UDGOV;784Fa8.wi ;) ն=/Hܭ{RxaZ)_ KUiJq6d'".[߻l}w;F>T@ bȢu^);7t27x ==kP^;]VcRX4&(yNe|:? S,I r#ٙ)T?F׿zUɠA0?xT8Vة#7vt": Xs4Є$30{bvc'N6lHZ!injޞ_8Ydu"آ1RbMlTtOpT4g7N/_pkLXJZ]B_WGw\Gۚ{qpE<6z{]FMbՅ{U/[Q,q ΡyOּ62İW#0?8˒9͝sw] l]\>lϳkhׁjoeU}|zQGǴ66wo:B;Ɣl!֏")CCzqÚ^I5ҥ6`Z)Z><{?KLS]\`3Gw/N?~9W`{V Zp(lfbX\;I˜K q#8TM\ӓ{e߽OU y*ߓ B@^ѨችKc;}]ΥHWk?0j\V,L흛pQ#,0ҷlnIg>p?VV2W(lK"{vi|`T\OI=6ڻoV"A)#*2>Сntg~k޸\Kkmm7]{}Os݊=עVC 3"|g8Xe}/^9WmU rP]x[$u\W/<ո㗷i(Z_D(Z [e Pxg3MF=y|#Z6Wl%G׮;`??^ꥹo9=a'rc>BE],.#?s{ddDGM+10$rEA],|b#[LJ#MV/QC+AK7)T*h^Deeais^[/NfO=Q#:sme f'y'xѾ7Yvf4T 69 Pb(D T?h%]\mJZVM ޷ &N}=HAڎnzKXvڻh_ ]ܸ+r? Y5Y1 ,q],ud)W#[lxMK.hS  }cpuoOlLYo_`XPAЦ-~a⽗ }F۽bkuMdkePHoֳq.8a}Ǻzɹܿbf-a9O40"N`Gy-.KME$Z~LrAMd/x_ӝ"& gFizV^so+b9)| zyO*kCU; R6 sR 0#ay}SV!43<~۱-gi$u[/uEo7oP!$kqbFg1]nCt/x:ٹܴel,0+ϰ\ʘ*)Az6# )l\oٙhec^'7 ^p5TzHf샫}F>'B[R惧t { ]sv׋+ ^e [NaXqYxˍ^Z;n XAiY'_F{pj$pe]76tZ`_|%NWSƛ2 a B%޽_nR JzrW_//?V*/a0̥Mh_v)kn7<J u%xKS𢕿n1euZ~psBgy[{ʋD3# ]Fꡥ^;q*hx o;#o(g}[VB۶^a^UstToo^?:Qu ?uFOVM0@FǥvSĘLZzol%Ƕ;~UEf$K(TB{F]1kd7\Y6P'\E<_^;h OA"^_2 T+ ɯ]sɭywR"RPmJMj |?qtCӎHz5չRzol&"D %@Ua[6;~ ]k6>P!sa#u*lujOa ؐB& <Ưg25Ks`t⷏^NT&XgN@0m䷇7F7Y Yg6a[HyU$# @0KLMhź_o6;p-W _3\e'*/}+W^vs(C>|va5/'W fu[?~;ҘMzmW_w˲pwuB<=h{l y5"t_f l[7^PXt@z2 E!a?Us.ڸ$|Cj|~hwDh|Ź=?wa^3U#[^?~O;15#*ލ_rN?vj 55W\l}GshJAg5}fťo⇺C_hĞ/Lɂ8B51=@TvwHne~كO==4]+nfssxZHn]H.#(~|+SySS[žU+ltpw?znqÃK9o8CIۿPˇۺo-Kf39Q:Iȋv᷶/b'EQmHܟ)yq$Š Vگ,~}ף](_0stỮ8غJ[A `2b!gpa;oZ/tXMGϟ<4?}<[՞d==+r1` I+G! lȌO:LYrfhКUA7lΟً*EBj +9H+쥸X8* ΏvxA6@,?t 'ಱƯ~@%#DGCEՅ+jw'{&bw;kfcηre Ƅ[la[;1uBOrYѡ׮ph0F+}V UO0Z3`5* a)X.*zL12DQKbMFCzY@ [l6z^7]de),ґrI%ܧ$\^I+cF'MqJ`/Hh#)z3=$v1U#eB&'eqC&*! F`qaԋVlJmPUSeʵ"#*|nɹXl4Ӽi˖'3zLJCWf,(L־;!64ꁾw] DI_( XLaI,"IMy GaA Y5)j*U4Bpmd⠤wεneY@ !.DKbcAțY!M6;!Y+(B0+QuL RP+aU t`%дp]" AArkOZ9T } ;CX `EO\77?uz^w E21wc*O,hB3/#@l~ %) vMI?-L"x@,MV 2&WHY͜, RVrzl SJJcQZT 2Kk+#ơNތ) %ux+$Cidb!JPԀL0v1hv ~!",s@pZ6oː 1B@,42eAb!(Ο%w92'"wxdArV>|Oс<ȗ_}C#ȲoO}*7+ЈJȟXuФ: fU3M,f$`%^18dLsow;X7"BjVP^EQbHZ1NXNZJRYFib}:Xȕ$fXK*rM|vm^9)E@a}i|9zGU*QH }>&U15vi 9x`@:(ĚSND)`#9 DUbZE6ddR '|b(4ag5yDHc*wl!e푗aؙEjwRd¼6wkPYrYpGN:_,3~yu\6W68(<w&151SBtnDϩg))ŰL܀S*ceJ5/)| 4TQ4(XW& X4_aP$ u:һ1RXPJQF vt"'D ^)m]d"3=Lq:;Sl@a,̽zMȍGXgS "|RQ"ufVi}fl>$-T9r,)4= uK6^ߨ°$!zgH7#%&!NPIq(TY$aE>1E^EeOvQ}F(gU0܊r hFR"-Ͱ* t; KΠ%}8O~p:AI1ZsX'"$ֶ!YgyNgKmXYLF[mf(V 'Qd, eBxZ|QcG~c\Βrf,?EM-xx{siz e6e#V3ZBc; E (BPYA<̑1 94ҳx[iѳ #W尵(!F]Ef$I {YFQ$*í~N -͂%B)i]DKGFXD Ѣi22C_mRUgX̔ABBP2ן)MA *'XMEl$A{>Bvga~ ۞/2FXW̕7lpՓi/l]}55y8 S!{2f*~, H`̕(B!w4Q( s7Rf"czO8XAKR}uE)/Hp*yJߖ*S')Ͱye`^# P2!Ĕ_kP9aY02)'PYA5.\Ws4ymKV ȊsC,dY,ʠNrEVPo- SK۔PKv/_C~k@aA=?>R ޞQۀqZZ|f~Ld  ^qa5sGðfsOmĆe\h1%8E^yʸ/(؃;_qMh>CB XZ\ /:&a]Kx@y}YI VJ ̝`MABdH W+-ZǽPW@K+|C7%h9dEG0 N)Z/9Α% % - (jA?yU4\#GF :9|O=bņ4it?u{ڈy"kns'_TȈ w"'u\ 3Y#ŃDxشtJnOA|(Y%S#'uD=U?@hh^ 2:3ewtAu?>={h|JoQPGs-Ne`Ab*JyHB!1Li2e`;7U +明+fcts"AYU8؇0I<WY9s-S&hϾûs|Ggf9ۿ|xt|՛6x+Ɔ# bʹ#W IPyPȪBQ ]l7SS@2Qo:$A1!/AaU¼Q$ŒςLOE4l䉶 VJ] P-Y4wf n }r!p5+*mBXʮb b.iR s 3-5}y Ȱ*P8cb1saf1 be"HykHZT^/r>r50*f[!-,L:2yt@M^jʁ\dk|§*M-V_ D +|2m7TXM!S@+z0NB_\_>$@;Te[uz"NQJGcGA]Rzv|g1siQiR1b L4:Ѹ&REҨS+NЏ," ml=#sHEM1p,](n0H@PpVv}b8"# rL|(@d^?ߐAOWn`haW#K׵Np ~ZKd cb&eH1(^@4ofXSqu1 cy!$]4BEuX\ϦaKrR`kUP)d%R|Kl,ZiPҳ@M9$cд^(}9͋Wܷ!z~@,CNdVWpU:_!HNJ-$n?vC C 1 #et] {Dwd$ 1qd<& y*$!@LvGc(8I~ȋC27e~ŏP0ĈP#TB b_+a5V\ T$Awͤ-2n2lꖘ"9,uPMG!tIXR% QZ -;:2R R QbI*k C YTD5#XM7^;c eɯr]LxP )/< !!} H <W!I"1ICCDWD1 /`PA)^M <#rI"Y P#{%"~2Մ+t e@-ag`*6)@al?N&p3d0t`XîHjj5BɍCZ wٜYGH 9d6{Zna_M& eЧ@'Vˑj<bt#u5JʇTO#Qn .Q:3d E #'s<3`@{;y: 2Ce4ި5Nz]f9DzCQNmɨutPCn%9FK`r`PB&)ȞFv^W=' ĎqtQdUVB/;2zNxBjEo5Mja -6Fgz7M]49ptޭ6̈6u$KapNDe뻳.!wRͧ r>'ԵU(l"$鼍YECcT;!8fqZõ̾L1$&DExEN -mq]'Ԯ&~=hl8G(s Cuag2k#k'`ъ-رPD4#DJ7o(JT\@4%V s>iB5E%Y[2B$Ģݭ/?j'.&E>d )"A- (ʥ%*BIAD| :[EABpF{V`3QH6J 4B-Al.Hlj@c 1c M6tG>!Y: ݯa` c(HXH0l-稇Ne!EPE"(2k DujHB %X44S=ٵJ ։FZs7M\yt薩--X(P,- _6wz`gH {6}ǡ:wyr[N8>,sT"J럕7l~)bEx ~X 0$AIaz{i= u@f1%R֤FQr"`?@^Q;_W" !ڳ'z_6_# pP&&n*R ɒEILdΉbR yՀ(6{4$ G +^"P;1!QFŜ:TdIHoq54iz뮂9$YJpBY5k5`'A¡ 8]Ɓ$~0LJȷ i@)x分P_*B(@|4z8I(? ݉%&@AOI[z:2+5_UB$ )GjL "WR%ƗcD[&(1I0XOu=dkB"GY}6z-\Jt:Sèfy(^>Ȓm>GJMZ1DK0Y hhUMEy-6G> V0=M\qMkұgbgޮ^vGV$iO LK>.Xa`-b_uQW6[qq=֔SV T1Rsiq9wREX 1p6U2E+_ g4zoj-*0< K҈EAz D% J pVlK^Aݿ swb>'/׵v {d3D-W:f9?~IJ,@*Ί9,Haz% P4 (H⟹;3_TaT``!X,-\:E uų4VՂUB9k[_bȊ6%['Wj6~c˻ʼ]k{g8@S UU@iOo2_Hb9re#Oԯ(*ݵ@qs)'~eZ>Q/siR>i )cPB R%aI3!@5'8">\Q0+ v&,3G)Ot:o舚-*( #刲ؖΖq%09`deGHODe祭8(*+5ڮv [%tp4QpA N`Am bLdNHY.:8r?-C-zuu#'sI EPbr !.p*,H^BidSD8mFEۣmF7'n?2흵 N[^ti9Lsu|̥YL?yxa׈99PmevF\g(Wz 34VҸA$;1`"6M=޺xrC-ҬWKPBdx1OɘVĥ q(qaHpV[%kK)~Ŕۼb R s1ğbNY4JՃz*YJNzl16 4p`34*Z(MTH];yT L*xxHs Ywp\f+#DXv+6)qj2WWl%y}` aE 沣=4ɫδgz5r3u e|Ah꥘+L;C_%=VV(/YB՘!fhu,zohos%VqatvŎ>2ۥe}c̷*69s{g(Uկx%q^Li0y>K WD(Q%5pX H(X8@8l ,(9l#s0Dxe93hI+U4 ,m@m݊dž#}c*Sp62TBrVX 5)U>F tNĀ2q׀@ "7,Ei0!>!\knk .~Pұȓ7-aDeIܟ۬ UcJ.i1.a0 hZ@a0q⸎[5 ":1J|&m@ `Qh$fƒS^r*-xͩ[FR+6 j;18؇va3}5'}uR;! &1L{N @<2KNlpO-hhAh6ڵӕ=O+[;eȵW t CA5lja%#;(ɅdQLWG~^%&?i'B.8qoƻ Zˎ<{ "s>}d=<~#+}c Ԑ]alhuoR1!͂(aXҮXH Wup!]Q9ԫ˸ccZDF' O$ x=S.ז=쑁zXuB0ptsJ}H/ )QP,fzb5Tׂ0L|MTGqVwaւE>smVc٩,6+] g!2M[`΀U nU3Z=Z{\qWX9l%iANo\ QNxxVByU9,BU?/[|(+\ AgIbVb妣y, C©)X-?sރ-KNeޮҊ[p^3LzqР 0Y7ǡ2SVҧ;WCXR9Ue8?J ,^O5})#V1Z[jWkYR_E<\чT+aFeL"cF1́(Ч%_@h 4 z_yEQ-v@ 펽x0t-O9)%yl]OhtQڄܖmm:AX5 SF& kfNI& }5<8"]ۛQrZ׸Aͳ컽e\5ofyGGbtekWY(H񡓤$ hIC\抡ץx$z)4򵿪%J(z><_TkB5|̐΍+OЎ^n@]BJ1<0\k*F NAj8!L8siذPV::8$V|y"ҿ*_y> DB_J"rR8|/I9/! 2i~ @@ WY^X} 5"tꋭ@fhWn]Hk"h~"09)K`W<1_NZyb˖.]@u-ɯpI>1Pjq% ؔ"@@x '?8v( Js85.tFKWvۛݕ />ի6 W|jKBD2+Kç} ku%ĦOX DA'PqO 7/Nj:m֊mpTփzBK7ڴw%FI^uke蔡'g`q ߍ)V(E2` c"g("d末9А%mRmo-^.-[l]cMgܢm{RRȆR e]&ph 'lVh/6ZuWf-ϰu9iuR#R~Xe}ksY̎҈ )n5 .L;F0WF۪{pqb3M %Uj` A$ɱ ZK\fI ,h-.l#-9L]h&s=dLNFܬ]:v6r޴7}>3~8vËWny.k6J\%~ ӘsN-4R=1[;:S91gN,V "h{q0ηvxzgt˖6zdm8q%j't05WqR& XEP}?c([t*܉婶<~3cFRrIjdA>ȞL=}4J⹕ލ- %s#g>}zZʴXv/^Q9Zu, k}rT*S!$&մ e&,L]: BY!:9@Fn'SNmlq#5_ ϴcsDI,/c_8CgyQRm6{޴[w_Xtl(S q-wi,ENwX;Kv4iL`Z^(tE4E%uswPڳi*~5'\NN,،ދbC C!7jrD`N#rJ6qw522t{ lbW7v_(Huciǧ ]Us`b;_re@B`6:{S/vsӍr8Dh}H%D)xm+Rm$Z]]ڕGyZ;zK)0(N% C[gjL\3նgO,Z- t!UD#el9޸oTуz8-N`'=Rm:%Ȧe'IE{n?Di6]1PΎo}љN.e:^Z8#,1me@ce4.b @uYdO6g>qOgT6]ɻwT>i5]\vǪ4qe@oô˶4t 82:gʲc=MNգ Y~͞~߳-.M"87Wp Qxqqqzf׾͎耎K?c[V_{94mO`螏~iϾٛ.jorN.į!/H iz5Y^d|q*'g~vvdZ_DQrp7  QtS<2ߒgTqNbRgӥP/'/ I%>T,a&3ypKJTXf%Dl' y`qKR"Gܓ{Ce9`Eڭkfs 09\[j[(5z\4?]aQI@+]RA@mЕTWw-C7+amO(68 Nӧm5vwJ:)=c ֑QwNuѩ4]hψE!K0]>`gGm'|1zky62oWxiqc]sn9dI=eɫ4=W?l7~02s]!g+_m۷CaPDfMWӋ2q%msIlyt7O=wO†|v|6v]w~xr0H:ZT<;R YL: '0V gVID2dPsl\]cB{5@%݅3 ^c\c^%8нf#E=_!^f,o{E)Fd5UR!\h.WkY =pSg]SG^Y%z@moc]CȠ^qiӻ¨@ZZ6A!.= f\u.w *ʒhv83fD+&yVX a)t_xw]tj);w{ g*\F `ܒId3rE "AŅzZ /G?F<WO}G_$8tk$V&$>KVR]$g÷Cj! EDX|ˌQ Nf2*@sG^n&&bTV^,<@]QŲ(T omiUekz7]ӳqkw=O_]mܽ5=R<Ҷ3YUILRLJ%HX_{N[K[~-Ju%(>V"ٓ)m~1)f܉ׇ(GIlLaVyY/@Z`qap'ۿ& ?>|dllz!8ZpVƦnk46YxW}v<翾p }=m?߿^x|p8nm_{Am0/wDBඹkK1 TxRGU?.xR"yNH0¶O^epV E1aA eӅzck2N͜HsVFf (P%$C0u;R5wEv(kr9{דrxh|^3"2U#ޣzEy{3vd2*_|ګrJI$Hmr*D$N ;ٯ=lj\QU \f_lw^zC&Vj|$f5Jq΋iW %>a]Nbۿկl;jɿ>:<43JMoxѵI^-(l]ޒ`rࡷ:i!9PJgO[wҬv)0nRmZ wh}dl/ysG驗_=k=[?ӓ _lYY|=;Oc̵v8Ӈ;xu;u?~sC2f am3J[f0M\.G c8##7~aV{;O* Sngb*wn PY-zҹjy(t(N)RxQRGB<ӫbN(ARQh/> D{K4 bT`/B h/+93!5ב&tF>'cHu,[:ĝEu-U$4dj+,lꏰ{uo{iFU#F'xlz'm5cL7 J D-ݶ{>(F_UMuIL^r=nw>-[~m0+^Lt;Ⱥa%v\20Y"GR"zdJYW'UUoC|\Pֳ8" 7AW;N@ :΅wQ(//-\ǖN2zɆ7*rURZb:>\L=*X@y]-{3;`al|^ZMtY9=im1αϦOɽ)1c9V0C P=-;q gW34 **c#^_oZSXGm 2Y,aXijOP'0=3E% yiճ\ 7",,7l/pMP'F@lkH. J*Fv'YĺJtU %@2USB~(=-/;PEy%ZJ22{ӝUoީt,yj,9"P$"y >uHp l&][QEA%go sVOyw o.$䛇N9Dz *D?;]pCoK0^( B]/n&מ+җn'W_B FuP9$`Hp{6?Ek;2}QRn!@ -u<5|U(*?zhޏ~o]7x A2rb-q Ӡ61'å۶[wP]w}7_8$(08q$QRU" cC͉%nx(l}*_@dk S&HP^"ܙs;R༽NP)y \Y5MVY˄^ٙ_˖B7bnHV;o~&JM6q0Zc+1"M?3 h^s(7J直EpCЖ/?|cw^q QF;=aU7ӱ'V7sYvmz{7z T?8S?:U])$ؐOX"6"!mDciϫ/F?tg_PbymПR:EW ?X':03WM"Z<&mGk1W%Dس6wq R*aFC~FRdqU@_:fVR\#CW_v.35m"SNqeWvl?<g\}շ\7_N4I'&u[e=}Nw*|И"niS*2'%G*6Q{SpW3/eO+܌B|H(B |"C*_1t;iI#{]?i'Vޠ58mEÀ =G"DUw圧?V.ZdwCg $:"LGێ14#S#F@8PM7fSx\Y~ɮ֧s8ήO/ۼyi'NуڶM/몥/Kh e$Oy|\ Tە=w5&Oi)H߄Iҏ,zstBe ԽZMY%5^| XGSWThs|"IPM% e窣SSzyÂ?fB*CȬwE 4W2,se&v&q{[S5=E^L"lZ0R

    -w?Q;6s-]53R_ ;>>c{;,a{/ݶMx Ki;> w?Y}~-dž:X#HEN$@JJ^Td(jrRqDs "eD!uxjTW[1X.iPOG]&rAֶ,1wM|Χ+$ _V8W |!P/ƨ^ B@LRcTgw1o HZ9stkBA7.oZ5,?#g?WUZ+3 D-RΙkە,Xoϯ|yFZ!4ڛ|o'}w~s^v8*۶߁! 1hDp3N֌ e?kh֮Nԙ: sa"<RŁe-k "*z yx:NKMo 1ΰNwA)d\HG^TBkYQc%m+o~ iX7n.Ik2G*i ѐ\ʭbz\XYt~F{/VDeUܹoT* QfIZל h 솫&7B 3نϿwݡ?4s&(_r%x7r h`wl?Ȝ\^z+#f|a7k)> jMу1V1K%U=,8_@M5TIFdh"2;( G_* L [kT|Ii@6~2U~m%??eH8;M̗KoM̅(=!+xHTfGmv|{OKiLa6!DײZ9eC>2_U߫%kD;6Ei?}Ls)mO.<_) osHEr>mHT+"T$bw󔟐o*Os=.ɯ' .DO$ɧR8`SGc5=7cEc0?pH+Ñz:ξ'V'~9n:Ȕ|Xk>sazY}$>g_* kaRLsfo>|G,:iD.=[9)o(m}HNE/Lt ΀ 0߸zKw1vMJ04q'fO?Q7r{.2SGm_3ַpww6RPɥ+Hq'xtr4(F%c N"@EXîA,TDQGkgJ-Ƞh/, TZ!4}Y Ϝ2j=6]YA-sK6?5/%'J$%+dS?5-W}Cx^:Qw<+3UD>"ND|F}|o%OKH2J9JI""vgʋ\7Ej$|]e4:,ۈVvkE=F.3Gg>py^L{֋6VJ4op.Ų =ߟ@&5o~݉BBu|s w=ohgj҅ӝ@g֦TCkL?.,%Ay>Co-m|6x#m5bw~׼/ՇoֆoR/k&]DP̀'E VE9}UF1->2^?2Y}k&4gᨫW/ua~0QH͐4sWag=oOܳn 뽵i>ng hf 좘 ŠX'(=Ӑ}{idc㞩/^e]soom<_ö7|{ b=ږTGę6k^a5M/CC[{sA N=;-hBqWQV rD .:{EDr.AA)Ұv2TP^Zq^ضȗ5M\̛qO鈍A{6ՂM9`Z߾bA%sS2J |;ɃS}KwvAK-Q$"%!0bi;~P}[W Aۛw:* ݧ$$:c}Lq6*; j~r.[#PG9kebQc I*i:ZŁ ЀW-_gdY'oĜXjXa |["41b ֒\\8_3[vl0G9RgҚij}?vU5Y}3&BE:EfTb[СG% :cJF/<zO(EY5DHÅͤC;{0f"Ί8E>35pp|FuԲR,b{ݥ]ⱂxi}n+Cve#U !>刺zP8Ȼ6k.`\Ez+ݦ;Y_ѽ 8?#ڛ_{qb6 CJºLs4VoU38f;ͭDokDlVVF_^S_GB+{&X˻UĭPuZBYZh2K {4șNҷ|ƅkƖ/elWڿLhLxO$[iYdIt!i [jsA`. ^UzHii90S|bT~aԌ"[ $ê'?+􌵡|M<ҥhǮY\:v h!..A"(),! $'=N]lYF ɽ jph^qx1X*P"<\jP` HR*ž؊ΐԏ&i p '6Kڪ<ሤ6qLB=ѽ'ۋvqm×o2* X -/h u)K 8huft+ArnϵFu0mg g<|l_F**{PH)|T_솎YVր2TZR}CwLdFOqLw8vI˺{3:rfaR]/.9L r׺FPDHlE_EfTY3/X_o8[0ykg~/uU)Jꁚ[ne:'ysytn:K5ɓL1f2\ vwuXvr>syekƷ_ٸɕ`\Q 6)؜#..,?>B|G剈B `=HNRBtq X㟼!Li8L"* D:Yܻ1A~2 |{TDo3< PfA4gfu(hBj:y"~m-t,E l ,8TJݘ\;~0}8lw?X8HSIq$c@WGS:fbX4`!xo@%C[\\<__,񋧢IdQ?D4\K^˃*Izţ`-,W ukͫ[{NdV Y4uvY8]tW "aT{<'xp xϷ?g?~;`.┲|*T X=\$<ٻ{rӗN7sbڽP^nN 5CG#ںyjEt t/ҩ`R-IT;䈦``ƶKa e#~.>V.E\G#-;VM*J?CV„gȐqp 2a<[G+ki+[%Xɳ@#Y"WG;^Jv,m<,,@.aK rLsϥYvx8bA(8WG )HkPpǢ;uV2 Mzf(z0 %ps>-nj c X c@XZeQJ4h m.,T6h"{C7f{8kyyÒi<n71,Wo] ||8BfpOtJևWcF,Rc `7BlG_/y~@qJȞ$ts) x+h)zTwl#␷" .g,hy|op`\gH<~^y'E+j;?MJ%f 0˩^TJ ^p 2(ZGso񧏩3  Hݝq@a/V҅uL^ DEIyAkuߊ.F(bB]]f3z#-:y6ࢅi44}y7ODhEԊ@kL*gwXk}Q"Yd0K&&΋"E[ab[7[~yI и" nuŪ"b0nwN ?yݧ~gt0*a=ɜG `wE-\j9yK&lٽg!RZtlMTrmܷRBTAƧj?|߸Ə.zioE;QZHMYk8O1D(9GyYlq*z<[j]3Obe(Xg-/wVM Ja*7}/\9̺q%l-x [{3@Z1~j%|=[T%TEA8l7nWH݀`mѫGXȇ{|?:;zov·mv0iOJ67NM{`I (dm/}V:Y a!㭸mtũ~z-y/!J6m]g#Mj{#gc37IIZwðʟrkR(4@;J?x3ߘoN&'҂hw43tbkn(A UiϢh_jo_;',PzGk{:6HZP%l %lb0ag㈤œ,TQP@Sx/h[)RlVI[x.iZDQ2` ՛vO8Ayk &Ab5rU(4Bq s,^ʝvgߛ$o-D Zw#l Ӌ e Gi/o&xOSo1I@U0,^{X;JK/( z%1f˹(;!Gٞο=ڇ?es8 omHx +!\߅Q@=.! ʡkƹ2=0L2`}<|)ogB \?>5.r,Tzp\?` d9 a4gapd`BN BS*~/O OxP,G|. _%hY'<-956y x@-B1?wk;|=+h弝SK1ޛeX fI7BɪK" ,E,lky}Gi´lРF']iK7h+?$Dd5}{+EdLI[Yk D%TQ U(b=c!)"v 8=f.<H%c[ٌw&4xzrRD궙]4f$DM vp0ro_,'lk_}7wq=: J@ 8O_x/= wʋժd0A쯮{b^v0-TP!AUc=o P dZ!KzQgjwI;0`y e08NFIVܟ 2=LC ^Le&W]3 4D$vl=Q;!D!DO B= rHrJƼo)a3US*\ӡ { f 3 @aAd$:։X'."A WQf8e!AJ蚢z( Pq{3ݴb~0`3a<"€njd4a#uX%A A<_gۭNr_;R'̛UNJhB6Vh {Mޙ[;g񢗜<WTd[{pذӊ9Y[TAF739$k:g:JzQ'&Ut!u39yʙ =~ö,'9P~,3$VA aY{ai9Në n88>$eh7vurk1vPMl[ݝ(ƅ@BZbb%RTo )ىu0* nw-qQ-6EoPyBY݁v( gϽaչR͠yͭZwxG!!AS?peӗ=K!c9g2Z90hkr<[6:7r?4}UL}0,&eL/n$,cbA<+Sq8."˖moD7g򗷿xp%!Yb;|g/0so1yFD7 }IݛXNoֻ cB, Zknܜ=w.WK)7{4I[\,XW$K4U+6+cuRČ3w2*ql0)M[AbJ^Yc+5\ @VI HpB5i֦3|@r`;\zɯfP!ǓE{IXL\ &ͭF֟uE򌁣Χj&TPW[eԾ)~-1V?sO nN.q^%Z28h^=v̨ebUŲ]x'h qhzqc|?n DV"LR>y.̓fg7^>\;X.?mWL{V'O= #-\rNf$,1w'hZʒCVhjL"+1*(!UxoY9p?2tkaӅfi$F$쯈8/q X0o Z[.v!%k0~b{NAy\Lgb .P ;ӓ˧W/ラTKoG6w0<;k)[]n_تNX)4.bmaw`h1̘S%AdbiJ/tqdt:f]G׽Jr+QEtgF2}35sCe\Tbeԟ)0WA:A0QAv9RĊ6ySKKL{j7 EzAʥZ b3Z a$8ԶIt PG ZjvSښE^O-?W_o&On&A.V UAV'浿O?.brђQ~<泌(W2An\nֿu̿}}[މgqPt[ˁTx`T?sPEn'"Id'Q.ǹ0k %HԻeL`%`񸛌ڦjAŪH AˆA"]ފP6&Z9Z + SAx4&LϮ >qi~]a酝h}wTMW{=Ie:yn}j}f[W󛻉LEnYdV A?%I@P6fPDd!ܮ|}ƣd=09Z&% aXDΈ$T¿͕ڎ.ShvKgn7z|n|pn;Ɠͤ}Ej~X2y]Aa 6GJ"SXHZ]QAłaI¡*?-ZU޾`Ra"Zаkk @dy5Y `wQ% CĬ0kɗ+F@M..T+(UN<^LɂZ ͩU.po?~^JN,D.OEYqV #3“'~t{=t6+9ĿG`"Xlv]HtwƁ.pdHU!Kj)8޲ѮiRG%qM=-ɪYgHoUV<]:>qJAf1VT[n,@z:Z;TkaPLR-'9 C[0gFBkyoX"oǹ! $p"z]O@Vţ@ՀE4?; 1_4V0jfp0Ja4e8?@}r|.G[ =y+ޞ8yՕNj=uu2XNaP moӣRvĒ ɽ֐Z gy,FlH̡VфMiZ; (D=?.^:*)U3AVSyO371-ɲ`d,=97+H1C;Tn,"3 li8R^Gr/Mf`D:6]Eg)2NUFo55mC yYZQm2֚K'| hG3`Se)-1h' "˟ֽʋ;pfM!12o +y[n1nUrj 76Q^m.# ޏ6eZnX*2f& $NmԘOU/ Tt.+z^mІZhEfVScm&%Ӫb5sh='L15-rTjME#ZSQۛ*!t"NUf Z&Vr-#>Se0ZѨ WʝړMu9-q+ubX0zj%Z@*$_{!x7` qt߆cڷ^Ol?n)+o6@!B~+3w Z0tߩ2l/mBW,S~@Qun$[y\LGU E+ 1*S!WHCK\IZk 3-!/ZtP&Jtg5yuZZN0Wϕ_u?Y39z㈕T+E G˹pnu,AvB7*ùf2 K[1fApHb<=D{g>vܧ8L}I =L( d;o){dUz3z:UU&ү'J0;8-&Ǯ&;k@6B9]`p`cidI#VR}Ƅ`A\Z"^1g)-zE$VoAj:J@ >~@3`,F H=0kYJy=43m*_DVQ$B[A+E֔Gq֠i/ܜPnTpt Jaձhn>Y"Z<'ɨ֯/D~Z*7.W5;?YKkTEAj̵3{P_Uqg镍JWEǹ},8x⚻eРn VV+`va"bָ^[yXL ])|iGv%B4GbԽv2z;_loI (VtݬҭP}C6+e1 ы|qWۚNd\Y̪c=;%bc(2[i>j_k%w8`N3-FVx]sE%eW*J(:`|`_,E8R)ɮ%(-qKUHVAkih'DECH9QѧH}tv+ TzHj,$<]i\2`wGp~6zpq6{ՇDc{cަؽl`ȀA֑MLygvkѿQeng掂n+_$N4w-}jYfԁ8T2t?d+a:ǧBe ȝEWKxI_GeUGVDaoZӚi7\ YLk[x^Scbz 2M(dޯ"yC<ۄ +{4V?x9-&uu^WN i.*;C$2uԸCY2 -C 6]"lR$rl2lj}9=L͙zdCE LWZB:I[*3bTh&lӪ&MfĘv-S0zMra ̠Gҳ ]X(K*ٱt7 *A._*:i*u2^:eyg]gmYu$;_UEc("_TE(Nڪ?6~D/s̠Z"v\ _1 j 3B7tO+j ) ;jL-'riD0^3QZrG\:ZY\#M5RfA^8ۉcJE`ONL[T^8s9xWjCGf{th4XFy_ڂ\??ijmhEXZ Dd޹qT`퍴 O@8iɸiL[ 7J_:yuç$&2 ang;֫ =DSĜ,퍡e["=23aTmL&^zǶC?_o9yd9L!3|CD"zAaLp48|㈏)Ę`J# ST1ZН3@U8Nfh[YiFoy V-$lV3`GvET ҄B ÿa7zpj| ?i֛ʸW6!CB:Vz,v\+f0ٴ],Rn(/ݬ4:a۸20QlDKYN3_V~6 &j]{<Snuit3]fm8V{6u `!tS==^@tJS$Z0̫e0{Coa -v[U;X.(KyR#ǘ32*!-:Z5S((ͩˀmXx6%`ōʓg0hCx;fC.h `_b+XNSioAŔ@~$7r+R^Ncq1ԫ8?M&mYd֒.owjLR iX{ywA2JhV\+;.fȘIl/v K/?g>'IP KZv2|tG]*q ۀ[2|N}Zkᭃ37Pq2G֝ѣ,XޤU:nՅV.{w- 5Q[<%8 9PJZ 8Q2Q@q"y!.'ϋ.@;)Fa>S]T<˻Vx=Pq[z\5| \vZϟ^[NhIM_o#K'&{cH+''A O_^yÅM7<`G3[k}bC(ϳ@^?P{ɓ A(!v և'Wy}b%p&g&95R*ܧ92۲}b|\ ^*W(bf~9"㟈3fJT'Jg@C Hdp12D;!@/mXv @תxRay?(xF=(7@5q=w޽ַVn/rT boP(D3008@|2~"txw|w|sQ~QWoxګRS%w- $e%,>1( m$/S^z'H0oWv\Kw+'9F:,Uݨ_yŋ8x0g9j0i+utpx VW>P˵s$}i@ ꪒ񛄰$orVDjC3mD6qE?o_OsL/EXWJ$qYj1BjAB{/fN:p9b+aE+ЄÚX[U`cBNѰdəa@m'@i14Ws,nT7sӤL+"FnH4J\r C$c?qD7e'6ؐ?X_*) R`ʁDPYSt=l)GV,4V KQ3Fj qcr,eT^jzu'h%@ַD=WN G%WC`k!ü*TX#{r2C6tb!oX@d"6q,R%;i[d>Y91䜪Wо7R~JuB6w6 AvNbة?e qV40_|v\]G]) ja& osרը+@L D.ǔx@91|fa3k!sKTS,ylg u` T:DZP񰗭\w J?jc͈ݛM4'[rRQGM*1a]V²ǁ6jҊ:t}t+Ň@njԭ[)j+Nuh/qz{:pƉ|CWA0BrVǴF  h; `?9\UUR`[HK:s\(wryU;UwrXoQ'q:%j@j4?C{E(c mѱ &jM.J!MDٓՅ $"!eCBL;/$95 v6`.WDq'Qzka%PSەX \p'zU+Y)bhܔzࢦ@CYpWG cuv4XVWLUkULs9c9%D}wv-%:ޙcOì,Wv $ҒVB(3&L{L2*P#w鸆^s=EXdQ oWTAڐ:AU.,W]tf6KMNQ T*{kSɞT°ކ%©{&7t~3dbP壌JUW 4Zs }4~eY@V+L87g:Ծo*TYj =ކ\MS `J\gf}*Z|J]&Qsӫ:g-2*qKq#Y3pб ܰ9kY ߓ%bKX Il$?ޚ"W +1P R\oypzB~BKJZǴӺ TgZ U],R ^6A3Ëᄚazmu(YZa-q4iS!d3z`(L+)#!hZykP;E1OطP{ օ`O"sc#nr5}-R,A`fXYjae@~3׆ԍt%:>cEHOH͈"I6 MlVt;#BQ:ӟ4Zvf1=nS:MeNv/^y T!NVi*?m [F6 P' W35J9w2 ˜z e:1h K o QoюHf+{KX=) .nz뢃;ڛ~#삖{hbS@T0{ $-U#5 f TЗ(x$,'A!2ATI&3H5&!hzt욉Ca4gt̛ԹZ.#`UG2 Q9}]tja(/i!wu%~܊1\nl +fL*+)M-Xb8 (Ŭ.E6{#~:|Y*n,G!A+ACH:R$\36o, 8ybTAړ \. `UycId!,}vvVjVpClz MPv2̍ط#-5{PKVCLsg:[&׃NP qިkނ# }-VXTW^ j=^WPN`:M-*e/@H_Tu)0k(ZU_*: u5S_U6-<\`]2 M Bk2h[DP iBAᯞ+QjwbAleZuk픵|wGWBK]Dٜ-0furuޣLeVs3x;frBMh|x`ViN'D$NU\ޛef8._ 6[j 䝿uX.`-3t)Ҷ-HiNCȌKA|a-fۦw02 K8v:v*yhm}ShsեACWS[kPZFsE)w329T:cU*+5,>rF4Owؒn2[:W E""T/˄C_VqP%8EYXo:CA.VOUˮ{yy}lSeݼ39z,\:цP5 Ǭ=D90MLJr,ِ&gTTGn E沿Ztx20=@ *] ,Q;193؈MJÿy0ZG;?2..u㫏W)( :ry/?cuJ Ϩ׮q l}ׅ^fa~ٹq(+,\FRZ /F_F.^[~oE+ ~ZWrf{<S׌S]%SR1;hR il]r⩈ *ZJU%8 d Tj8Ik .f9M5TTd#"hX]=[ŝ> ?f|EQ"D"fj[]s|_+*T_fh Ez[bƵq#ol9 k8O=3Sz, UZ؟Yx*f5g6PG8nM^5.u3ċfJVkF_n 8>èj+\+tu !'3i--ĭWX;2vHBr.NWU =E$_ jآ6avk;譁O5/-ol5[`s9$(7`b/^eXc4m 7ayT];K):\N_>kH+A%)Gm>A#~愈"%ZuA)5P żLkj`-6K 6v`ЫM*O?.p{.Wivu.) j$VaNNpѨLwΧ:=W ZY~ƗZheU]Uuhe3yO+~"y5H!Z>TiU- H,2l.–,0_=+ZV%zf68\@ v!+sD`777&ㇺUI$a@;JUq^ ]..`U:n09$7pQsč]^"}nʃd U}W0%'&6[es?B }YEQ QC*%~PCFm5rOD)Z'`G0)  M0BPqP̃ijя .QFrj߀mI$f.t]NˆP*شtPtJUNHʥ^Khp%w3gwjx:8+}cjPVީlfn Xi=GKy6%^Faɡ.ds/ϝ+o @G׶c DK:P"oCW٩ G0AH\Vn sg;LLb.%H.D<0>|{~wR'F,6n*D۳V:ouEw=` |/YfgęѝYaK@4^hқSN>  7xG>.Z:pEe,vMi]F"2yx ;2J d Pt32`ׯx>w^QMV#8  ]#C[[mRk-|G5[:(<"R.Yde:HUލ1 Z XD ${˭Jۭod`x8b(\^0@Α>bĞ-+iquIus+`,9VÁ94[/C-:+DbGT3dAJ HW $PhGh)R>Mu}za6*LP$ݍ2x1Lz4R +=O߸֠ (G8rthrq-nہq;5MM$q0VYKOx&c]wgYzpGۀZEʠ_EA|6+×sfÂ_pAV@> \Q±3;:hCLKT is-K3s;I6gpei@SE)AIWj-*zI3 P#bYw"SX&#H { l'u/[? *ȶ}h C(L 6SdO ]V!]PA1#|r5,c RC+Jc[/ ?ڊ6`HN+]y^PRQĠ+0A} ESpЩ3n fɶC:'9IktqڨB=>j#S.SH+/d!"^i{-[BPT7cv-pW 0U.iʼnjX$96lH++x|64h_|gf29GN=tT4ys4=Ǧ8b;6reGB] ᪅W#O_P̈́b  իyQ oCъٍǮ`k8謟g-\}s{1l9y}|q5 Z7dˍŵ7ǟqU[<;]ȡbe6oXs5^CEdVu}Ozuv~1@- FiBL^F`cnt>Y̠rǀ 5bժ_6v̩0Æo{nS/;n)fԨYQ.$t\Ο?78 O/Vuq W3b 鉊=_=J#Sd`&}eS֭]zWb.f ![y5-7Sx4ЪLѬG:M4> (8LO ,,7i*nJlANMe~6w﹌~C L'dG81G/Lf:8r$.)Eg>[>WV{h`-鹖ޕYx2/ 4ZqX0X:'JqU A,]B#*-8_bԫnwـ+*g^|bnaҢ^iX'a"=$47}WC!@M,ՕMQn~lJd]Kn&>+6O|{8褸&*SK$w`Q]\ 1NJg!`.6=o~ss11,aɩ6Uw(*䱪.0}%"bbA\[% r$:őJb7< V_0ZŲqwӭIt&%;Py*"_"c?oU4wİPxbV;ɉ5=p)V K7hO)`u=mԼS x{%_VjP .ö ~xių f}$Frz <aIt4/5) FH1Vl (MOM|ڲs(52&y/?vLr}!!c`D2IX[3 +/n?˗>+~78DE-4lJEe^-TV9^9\w?x`>9' frohos.{)UUZh wKbм`'M!&ϋ~P~M5.W]=0!n,5Gr a~%bïՈaQ^_f3|Sc˭B2 宋įL{zŏH6=J%7)^iXNV/ hJl7HXS1W 52`~&=4~ǖ}?i܀}=Ei;^&ci!e۵;yMOV]UMtPGux?`ӚH}I5A&Jw޺㒭O"jK~KJ:^L<94PLcEI'4lVDtn=7Gj{**KkyJ!\lt3lY_i0ˈXi)dk'tNl$ļlJlP\ݐ `ms7m;Cn]ͮ!Z8Lۯݶ7kTZ%om{B8ۨNY.'E{stB#5S}wُp}?Ǟ@}K45hKZS$i5Brkre|){;79 J$</<ťn|yqzI Wu*急*hXM!2%-ZnUi2D [Xɟ~~SSQrߴ ǿ{/+?:,86e/98:Nyf51@yi؃(:B[bxްc lv?zx^YW;׆{ $7tG੊\فFCq jp9Cu(CvAh=Y|/mr؉VK2]fBω:,XAuR&{emaq$vXvz{_wOYRk¾<5^ COkeL?zV% EhE:Vdd^u7+l᥯?tϾ`lh[da 2+l(!W: _?ۃf6ΫUND=wL7]S8ok~a))CanEЫܝ `[eBV"RxOBfQg:ݞl{=݃ =J$ 4\q~ay>ǰ|X)xQY)2.U9'c|Z~iRpuCG= ̅O:`N3X:ƐS>`&k ,P2{WIl;C<˃BLzt08|+u^b+kҊfoTOS)L.ݬ_z32#-|EAV1@7 ^ xΔ=n{U{~IN+Pi5^Pӫzh9qZ!P)=tdP$Xl`vY Y9eC0[Bv3уth8'ᜐ`So)gw'L4;7 i^}dAd<:=Lf⼢Ka'c6tC7Dd:LNPW0JVB[hXӓ<ȥiR?nÈ.yOr%ZB"i%:h`*<`DwFJ2Ӭ2vp2#>de/*T?huwi@/ڌTSɤțDck}6 /.r9rtXuKL4;\S"_sjX@r&^عR]MUѴZ@Bc'ZZw3gg0rJ[Ap[j,_unv^մբޮ|s~ jym77kU|=VLUSŽ`/>#˔ֆulQ8Xm)b7>v5*1>qz:8xX~Æ!45C3װB P6 ;pMl=k_ kErcb2h_z6XZ; lAU[sĵpbզ7_snm7V\jLj؃-[Oz%?vZ Xدps[k?ҷ~To2-nn#|pnؾo`?zs/u<ޮUs{\Fkԕ3×\B#;n0wiωW u67ï{σԁ1 `im~ )S]e o3+R؞6쎹|Z_}ĩs=#Co?u#C~`Gwɳι-`IN>D;cHc{3S=DkqrhkCút{?3߰i-lywp>RzZ`nݍehKhq݊YW5 3pխhVS" (i^^[\f;Ll_GOt2~~xW>,CWMqh`}W1دF,Oww^{:!;y`M.03K_ڽHhk|_HX{7"3zuQ0 k[=?IRoT#Wwa2wj q [1^y#Q=9paz,?tRqV{ (Yt2d9^&;)ԇju_|m%/ԋAѥ?|1&FhM\wcB7+V${ă.nyœewha(AIA`PK /K WTz{x;N:U UEP/]Hv,-_:qÉ/jrio&e_؝쟞lqT(kUv9χF z Uǿ? {DR.-]M< %xGa?Qu&O<;3G Y/aeW<"sN:ǠTjYϊ3JN@-l~<|"Uz#_rߨHqE |!bS_λV PMata/3YI|gBo)f*;ufGmCA<Շ7.EI0+TU"XEQZ `QXvq`x4Ͱ=qG_fV^ lr;787.?{#f_2W@N-8/ÿXG_/}GIU`"ʮH'" OS$g!BsD=RdCZĩb}O>TBL (6UNc)3,2ɤ:'"ǞɓC4(C76U.[{=BU!;`O~¥cM{yeoO6ZǞ*Pe![VϼS_Q>Z[00*]Jbn)ud] RF4)/0|k_-yo=U%VV1UZ!z:5IvZƽ37 {29/}'}IK7`5A+G/{/|O~2_x$te~vfXzv!ׄr|ΙR_Ͽ s}9?>, 0Jܦ3bX@1cdeX \-U=~<=7~^stABLNyGS +c G~ԫnD+s8kŅȧQJP,^tz(K' g"}@|suu>; c+v= &"\@w&@^a,OD+5t_uv敯vTP(C4`kAa ƣOqJzހ[\ L8 e|G/ GA)I) xxəO)N̆vU徬h4`A5Yz 9 q[WAۋBߖ|`f Ucl1&џKGd9,DiAkcEdDqiݨJ u+Po%3e߳dᅡhwLa1݇^unQCA5 U]:2PxltdGN/gN)`֩dEވG,AXX<./Sj8[85S V9͐Nƣ0ɰq4,rԤD}ӪM7K6)Bey9E42#@y5< &f?u03OVwҘS%YrVYD)reYCo[k9f*^܀('iJWn3,E0*xL2ldbj'f30M#y}b:27L)Ew(99ēUeBҸ($f({0@Xgշ"7@DvrSVx'm7>tw^?thsqs\N%?6w*ˁ|/\ u8 񯦙GǗ:RPYCvr)=u4 A'sP'8y 8#ۼqpQ5 TsӼd fЏoEPNh!gX<4+X]X1 ;q<0N_Z#T2Tގ#]Fk :]޴61'x \܃>`c }R:f%@2PO䶈DrO>;]7W?3;i_zA2dB:t6COo#gK QOhUe& fxdx5\|y)uEl!x *I-^4ɛ>JsQreVٍ(5dl#yfK-X+S &_ j*ܘ PtЬ4kQ-*mUJ$?@/ŀvNB!fmlJ)usSU ARӃh k= ^%H35_`HhxWh Xׁܼ D(r{nF{k}83{'-,uFGc7f^y@ ІL@ >֯nPb @ƑjĜ jrd"ؐzeKt"Vm,5fw`Yy8+2qvbd$r qE-qѪPTAsj۠6yA%+A k5V=uf:- ˰<{ahhm1Ju.tk]4dVT3@(s[Y`=6brNhTFl8糚LUa!AftסEYa 9,8d3,k@-LB3YJPٖ\|KQ+Ěvp`31q .ZAs ,%Ǿ l9~=Xd!ņ(S(fĻHj<YI"f:=(o~Yj4JE?ŽBKN+Q?sN-V zI@@:7^\Q]󲄆"HO6󝺎z7iHk5XH_B42k;_aȣS ࢜MG!t a!</6ϫzDdV9ڨv քVơ;dbg{L\^\bdGIF~$.ţAt(P™0 RVErH_$I[[3dcO%v$1;VE%+]+c(QW`Cl<8ĉbUEd#B4gS7!k U=}ޒcGD;H "~[4K=gDj]m[rhSM[K<"'CC) CbuHVA/I)5,^VDQMK`P$$.6`7U!`N \62+=$y #cGZI Q)] B3[at9 14}_=[<I`pi IQu SG4ɄJƅ%)q,1L@x*Z)}| Cmb V;d֠؈0ci{We^B,ZT¸H nT[ˣUmxxĭP[jNQXUߋl!quգ?m?|%nCM(v _8D% PIE/(`YkEQ[ )L;ShiŘ`zMpջw|A7GO)DBxz*E9/nXW Ѵqs Yb +ÜRlm@O8RLΘd/h^f6%Q;!Jj^CQuDJJ[ *iZTx50qQ,/8m7K|dƫҘ:ٲ,H&eM;rY9IapI/qx.vV$EWPJz!IRT LX;D >)d!>UCGC"z4$ Q e{QP45x âryf3$lj Vߊ|7MKB}RkBU =x!3`, W Iv'"Ei#   &py֞Ww;"TAHB5h7^6v3;},*O="I[g;+G8ުF}YΪ*QV:d j^+A 2:PϿOH< 7Z-jiUS@.*U(]-/1,FRT2b0Z|QP=ʨ Ej:jZ9܂tS]jԋzWp{ɳ=cW>_[5=q^sfغ9YEh fNá{yݧ ȡZbVJ ǒ]g2-+Ri]6,CyBilU5VNC"`vP>HBmǮNX-($M1hjHRXtu" hoL綃A)DU SE*:-Ҕ)O<>հ /JP{LhB,Y|Zckn-MC&h-8^a_gZgjշ"L}:1 cǟ97'^?xata k'&G__<}3 <ގ6$˥{6BMjZZ5>0bsg5qkx#{'])ꧮC3aQe-STcUIE~'=dzR/:zE&]&.=˚ 5C'n@hS򕋢Pqv))IrG}*>HG(h'5Z'6ܟϩmADe&X⃂+E Q&TWwIO·3@$:ί﨑K<.JJ畕Yר&i=2J'+[+U+oypsL2C:c}yY(N.tShXtuѝH&ؼyzjZo-k7 &YjU-,-3WNAbŠ6!_e0Cr4 <ݡ4@rp&%(-ԅ,Sk-ue6q%^in䨥h<U՝Ga ;%/*AOUTe`턤?~}V,w(8ӀNSkTެcQ}UبGrKV#LByzʹI'|i1W6c_Ri< 5r)7NKf0P,Z$ZΙ ofZOrzHi^pv  UCr.yqSjy&)q6 /ˏciFGG&GFGFF-/vH+˲Noq3tK^MV0- tG6xKa(ȝ=@v5o;̳(U&R2DU),DBj9IY$`!}Y@PʀloRsj0ckoeP\+`3ps:͒Z)f>dxXFڭѵ&&F5ʪkVT=Sr^\ Knǡ䫊=]42QH1DVu:CP>%טjM=qâpA {(|! ]գ5E{W~ ";X=HデpT;*NZ*r:8ĖSb2Ï_s)" t/1Μ9%DN,3sC9vv_6!~c)'OLX#XqJƧSNeOy.8Qtq̏_fIhrD591jjbrblb|(gU}qOq##}YťRw~aiq- &a"J`=ZC b\ֺZeaҺqn7+`?&QkEIaO5)450u9FLZAU4OV@I sJ2OdNBdФ{yV+Y`qZeZnG`޾z5:d @F GRfXUEԦﵪ~1kIGծ&26:jjbɉeTRk]fxULMOM_;땳K KsNדzFGPP HCi8N$@IoQѼ?2} CF%MwSK܋[5Jz0Ÿqb=XBOeopUZ2ƚ.T'yFvC%$܊JQK::ZFnwsK )CXjٔXgL'j׋-ߘGOLf%EWrX$+J`qŰH^"s8 !bZ4Л7vPE,y9=7N5eO =4uW*LbZ#,q+DZNHBrU*]COb2nDռoc=fTNk@2tW|<8b/juk.Jq8lttd˦u797p2Tl2r" +}=[;*Dpft^;^-W^h;Ǫ%IP!7D6]j|s vQ]Y,BJCp֧Kqw*.Dien6~6FٿғDkI )8ektUiﺳx6J?≮i'Y(zVܰv՚ՓR]2еZuk׭_.>;21z# < AL*vr9OYKQrkɜA%CJ ! 2 I &t\%*Rڇ8UJ+ªy8Pc# a ^uL)=8Z#4/@ [&"^O (g h"/+y eaP+/jmd_?WqmjqVpM KYWF~Y}0MaM[v:P鉳N톽x` .!Wa+d_&BԼxQ Fs4LPyNޘ^&0<)$ Є9ΨrI]Q'=3X;!%5ɈW9n,Zlli1QXR5a ¬U(%-2$Y79iuZTpPqd꾺 lj9n@{->x>C*M+i1$8Ξ/oR3G µBi&(T+5lisblM쀑yRh-ϋTS ZÚ*Rԟ.h{$JEih_5mR,GPBPH9QA56=f~Pm`Ia*{  xrU2[@=DPd-9dy_@ B+VkƵS[)BVhHRCNkk EI424yms|# bMFJ e`vnqn~1WMMwUhR}:M&Ö( PrJ'",˷b,8VjzҴz`.4M>c4S@y2rLbƹsc^obnoݞ_$B@lAQ̶BUU2`5Spnvs|pU(B: m}W.-u?gf:*z8#ԏ#z>a6TΞ{h1o2e![qd%iX*d{2`Y4-%hs{=uf--u1Szj%S۫:[&0A&}k yc3a!ĩsKa5RjlR;>:zdB=wS lU9.~LU<5Jbtqltњ*J)Jn5g j#H&@Al?@[q)NNNGG{핝n-/vv;ZԐ%txZu~"f8rVd%YnN2|*2iT9Z©s*vAp  ORt;ݲV[-*Zv1nF7_}u[9,JTTNw`W+|*?CUY~bUk6r^zH3/d,',u{[RATpPP,Nr7-Łiq i.//:=pl!CU1EUܔU}jGڭɱ-m޸vk5dXTCf 3n/ֶTZl8b&@Irw|ui3=3` E.EҮ(RZ?{tf'-ȥ$ģA 0oWq/#2##MU @**322\&(c;AUzQ ; T/hB\v؁ L"4-Nl%B+@xY*6fҩсS\.NLZUHf:ރuh3۱MjuCӌFQ_^X^߲#H# d"2+: NmT-0,CJ2=l>-sb>PqȄzKʞjQZl9(<<FW%'=sb3w E<5 q@w!ljRm.WjjSiYm7VRO&pTζfx1T@Xd;Fk"q;?'U0Z(1dD9 Ӫ7mM:`w +KA?&XIT4$q w$u"݂E&xIgr0,ajB p.?Z:eoJB'] bVHTaO t&f)wUXr/``&\@c >Ed T/m\Xoa\LDs*D\װ/v}$\f`irbxXgL;63R4DĎ'Bzg\ ke-j$Qʠǁ#!n\^ZTTYi9'AW+V-BQbnrb(RI)S~[Hb#} |C'Z[3H"G"E`yX8x6@ TJ2eO/b`SB B mŮdɲl|CUł{xi ðDim;MͲ{z'C la`(w|`e2iRIQ@TiX5mٺnjngxz| ଀pVw0|c̃Uǧ#$T /2@צ,{nq}ڈ@ӝ,QHE,.@pԄH7˄q%_%˴7ՅM&tCu}sP=#gYa//.m<’-ebW@sC2pqjPQxovP-R$(V#"R+d㛴g#J%a1BJŜ,Ioщ:rq+:V˦L QPT1GQATZō@^϶iF ,$|þS|* Q(zB`9n0 ZȐR]؎]s#`R`JLn\FmkT@/Qey&)U\m ;I 6')2[6uz`ښyea C*wJfuY(wƻi֥K3KZ6sicF8M7[YCć!C4SIL7ρ{'eY--כiI+sɉl&!1*TE- hae±luSn$X$͓VNW'fuZ'Uk$)RҪ¤{QB+92 ,_."y0D0J KRma^m\8qHtz8VUE)Ո-Xnq loEC!5xxptl.fR EIr/gF&JlVl " ޿ 9[%gU7p>KFU>ֶ4}{Fim/m4[C  !ܜyT JCM3g6:~=cD`g/teraz0-jafFtE*rf+VtO{F܃[f۾ÂCX aRtJl;j(LB@L.3̀ ppg_1+N$A-$^}F^86!VoٶR뗈LS?gl0M2tZMY Vexӭ/gbiQlqqf܊;Q w~Zݨe7ş?V_S"`[!aF`H\fX:A" <,^]reY7̶fp)V7H*H'Od2@[3fWVTQ\kwtĭl疐e\ojJ+@OrA[v!D #)vʤT$0;>!SlZ!; xBU$8m;z[Dtf+qhp y>vhO!aze]ҋ+>ADU,*ertoOW(ZYڠu"H|֥;xྛw>ptcQ׻9hj+[e(9-z>\!&"%F/uܪ1 oZۓ)d9t ) xOY\\)Wj0bnj/3=|H(XXޜ٬MӦzdþ(rJgʹl7s'X!ξ.=s[g<4ՔeSxR#=bЪ+zHll;5Ziى= żgT{:vnTwWۺ[OT68E}8ښ֌ZuœYVduXrd$~[34%:ҠjTk[[V}u ^!5Z9p.vtlvZeۖeSLҮ~NɊ|1U4t8wqm{ub1%=܋|3&硪tW" x_!dҸ4\79ƢZjJ(1Ԯ[h57%4&LJ8Z-{b!eW WSqeUU2Q\yvJa ܧ:UvS c49 #$ig2*O=@u /+OiUQF:u\8m6[˳:@W*J^Fi&Br0`= \6],lja@_bt:y=3ònTZB1j@|e`&R9%VrwK0ƺi]^ωǰf!+z Oodh;5L>thW?/^0M8P?IR~efWʕzq:){&F*v -rYHLg_ 7sXȊ0duY !GEB$|N ,ܚnxj6VԪH56`u?ų{xS_~h9>313jٶgCd~MO N)azŲ=*0g)UKv4+k;h#^O@gt˦Jy GTwzl_ccۭjs'N_it4\3(0#[Ce{o&l&, e]nɓr]MМ1׶:3T!ZmzXmUWO¸QNva7$#,Ӵ#:K+W̯#w.W~ez f/>;Y@1kofә1nRWPw"m(Aeg&mv6WhijZu5D$:n]^4 k$BU$EmH 'B(Rt^չ?#*'px{l{[?  ww ?>?f5"z0FϝhYu_3'Ͳ)t+&; _cW+X+ k(/\cq78qfyf4}e29>ā!ۋ C! p_o; |Hww7zu0MJ|.}𤫳#I/O JH?R{/^^ZYr 9`ٲiU;nRc|K3K1_88yʑ_8yܥ WĞ! 43:=rPȦSMJ-VkMBT+8(Sx6:H w'h+ٲ,!8YFU7/wi%׋2uphzRIDATf}qrF tTY S잲bw$ #Ivȹn \^]QK0eܐ %2x$xIԓo{Co'zJclKMf~ ᕬf|.SeT Xf9mvi I3a?6-[lE!ɲ(*K}ŋhBA,nJBn_ڔZwܼ?{}>d41O|dd7 ,;(UÉI6-{io>-ROT=]q&Beyj}xUŔy4I=L cJ;mFP/lzjb|eӉb,͸jGH,"4 M^.o1oQ9[̇D|Ҋp:a=}CרdB.eUf =,0/ԁUH+~ vG¼u;-pO-UQ گL8} |f~M^U? .HćtbG㔪0N%E`ĪNj,a׿vyv7s>{Ͷ?f>yfUt*;zr1u{zg@\lUm(خ yDEwV+^2W 3婹 (&|\%qyeZ!kK4Ld"g7mZ- oGNX=FoVsv8>~d,wuqw{v-Gj[7C0Me.-n\^xjٶ,wGBfKfOP5+&+<##Ki}-b @$З{pC»9IB6CZ+8cy_(o5~wJŻ>C ֙S(]ɉF(/(D``'My2Injfm5WQ=1Fh') w/5u.\ZGi]DC:pw|gL!7V誜3+#0WOK{͊Щ7ZtcQUg\S,Ct4i~S:N~&8׽e;(8~#ߺ/8Oo}r_OC}~PjBtC?[8fK4tz;N9]h!&+8BO V^Oc]9,`ecF 5s' oh8׳])羀 zaҊ-#wdc'v`9WZ}gzJ$\0_'};[Ϧ߻ z5l6!o㭉qb!G278Qe7S"}B։xy\ٞ I%N@5bh9x1cUW^(:f0i ^ޓ'UX>y ,<P>Nߍc$65mj>K}#̈́P¸,p^~Xg 1B{vRC떃_ʲ//Rc?Կoc<~c~cG/$0݇ ~?|Rojm1v> ?$>%7-"›8SCܒeYv$M\H/D &iAd'b21*qS~'B DO"Cv [͟<UQ?:u^]+n`gFS mk^֣RR( Q!-tc0Սjɲtܕ/vl~W R`KԔǓj]:_7n,˫夻͋;q\^yW⯿Mx_+P wI# 5:1qk( >!C?&>8~ و`% a z /5LJبqb'5k:hF[Hc2Xv4@Fo'P DI'=?|=yM둻$.e*cLe? A@J[LΑ/pܙ,> F0/J6}=!8rH/r2a>Vv.'1gsYt۝D mIo<_fk|K`A-Mw`ZmXEбL: =6鎻/u $1fG&d2ǟ>/9/BHF}:-tc^^ wD6s3ʧO=wc?HȞZ}ȯCzbyݴ 2XIUA_Xl")X7zC'@yH$n"J¹81@t(}Bf5Chq]q/rM<.BrIBr+A&?:ejpѫSb i_\iJ<#j(h.924B.7SډeYOՓ>"'FM7P B2)_p97#dBhCnS4ݜ*6T Gp֏;Fsy^k"WTrH$<)]b#!/=:1yc;wHU +P- hO; s5?ؤī1=c-jڮ@vv ?ǻ3M Z}譿#o}-4_y㏆-WtN:*8\Bډ'ܮMqY\|]()F0;oCWfF *vHi"cT zw N,9㘆uIӴy=% znJ=?gO_^l4n:<;h߅6/G Ͻ~ߞp:,m[VQtb~hDl5*OlA%yN׶U7gNթ["|{p|NnĽ!e ^;-%$,cNiIշۚ8|93p&o"zDh`ib ݋ ۫mak;ibt`bl[fKkF]tݬ:-Eq)WEdJ\&[rJOW sdwmq$G}0m粌_v C]=Su2vl2@|SϞyK!qo}54)Eb>X!ykL!𕓯46 ]/:Xh="Ne2/>=X! qWEZ UF{Y)ٴvuhk:$0ޠ Aka&Ed$cm|bESn]JxU«[--(G$I*rBγm `A0A'͖nZѧ^_͖&3V_woqHEe;7 Ӛ5pn?Tb*ۂ'9}qfѲ/_M0~-wq@bNtN OR:DLIq'^N03+jر%dεbax%A) sD1$f`ƻCK|pZL"jq Ad߶:AbVlz%_aK14Jr3'd69>>c'.0Bzs} `_|9"?|?u[grfFfȂ&3Q=SOCH$|ecZGњ[uW? kxkƨ> f^Z\}b`XK}?bO %:IP8.4O٬#Fa,zykL eYVw> -s )Jb*QB앟C|ӱUbK|P?VҪi59rI!z`¢Fdkk9?a/|MFK:!e@/8&10UN)DƗ5ϼxu dj|mf~ "_ 3s{(IŽ/cqEdꂗa&R+2!rۺ2$2WB; ,YNʎvo*-9h}S/>qfRk5#Rw <7i5RLzݷްQtyęrqa4W7 aON th!َ{]KMm˹`y0=8+q<)@xl+`CHEcp\kb6pl1{ @QM8:>e=xif  >itcWHcO=XDd3܃IX:bG*jqX{7׶8J[?_4mؔMN,4'ag^]Ŷ'??kt(ü&KخrjǏLrt/Jq+¾1^/FL {^waӴGERtUΤSljdiv`fvV ] B>wA2,-ᕯ4~̕HRS?ox#x\;ib%1R{ǘrFF /<E7_3/r!B{" 0pcq!Aw{{r[Ц/xrbcGȭ>S!L<+2!K0Idij7ZDQUz 5F3U$7kZ(C|لɾ8IM~ą/O5oH>F`g~{pAH$OZ-3@$ J{TN]-BlvǽBslb5QB^ǐ*jkiي4;~v7^_tu^vA 1˰6w')i8vwǴ'>;e#_ΤS⟽ 8jMKQ|_XO&(쭶gs e;?_}ݷeRiR(!Â~i3Ԑۍi9P4 /`nɓsˆ\(dsLK. H`JRǽ$D(l`Wth~^tifϞfE%{C ,-?#Ez }ͭFglikF:ә1S:JoψaZ//<7{EoqcOB ?Neo҆"-&nu'(O;F$j~vmFHr1)UQh!ZBhqust/Im/qk 4@4 ޡf2v&*R"KXB<%QeQxq+xFwFo{O҇C֩PZ7G2 EҊ"*LEsۆeZ$:9WkX_ygπ9{d~X/˶-?iiYX[ERR*3)=IfKDzBkU:TZzL$%J1/]1M |>0֌ʹK sK/˗{{Ƈڳg|0]y ȕD0P~`hb&/MϮHc )NٌJ,iZ;+ NBh_K/9+ |:FٌZgZ@q}3ǏLe3)tmmkطdĿ/NUd/ R{6PW aW4{'U,J1;77x5.A?q`FNgڠp¹{y;Lv **챟);zصDI"@WņaiMMR]ieٖiiljF̅9v< DU0ldҩGnie;K?}+3˲,MM C7Ѫh :"h\QմZWL@iy`J V% "lY\dflv*r167{XUdB&D7jI̮,.oKVLZ<2*T=ͤϦ5˕T"cRgV>g ێ߬|ѧABCLzcYg;l[Ud: мQR#[k=gx-m.^^Fx='zF*Cl_a#?j0% )նmLTjTO5䇗lەVf˕VWښ.W0 Ih c+ۅ,mkO>s'g.놉1#_!5 #YJs S7fW[U6۶|Fg`)CXފS:d4+?zܥƇ&`0d|¹ 5;Y64x/Ȅ#G t.NEU@€iM`.iZl76Hnz+AMVpy%j+]MPMM7-h/m0kfd++v*$uúxy̅s,4ZR]06NJ1R ]Шݎ5Vջ^[۪OpC`A_xV$Of۩unӳ˕jiYmڶW!Bfr|h;&6˫J(O Ȳ,WK~<,V[-fVvH$I)UVB{ni[:Dja}̩N\4jEd sI"IX,+Jq dyHĶb>ϥ%&b1"ERtt!4\>?rͶM#+o)d3i5I,+'d; 0dl X@TeVzZX8ʂiھ}_OY`6Mkf~3MT?~m7 "^lz|B"@.vI,]_R] a\߰Xa\f4? &7𽬃\ނ%膹^.麩ZmR&:8<гg|(NJ&"YVWֶ=nHTZ`: KżQdT|fV?KRDbK~YZ-P1l1 ˴D2\ڲiESp**.bw-zri5 @Isfv-ٌ`M]7l- rl:V)EUd$K Ifdٶ!FYB 9؎Mf羹U8eYQ `>޲~*7I†a:?7\::޷߽{lvvɳphc3Cn6Z[+5m0w:HhgiUSg2{`̞ůDsWXNkWχ8"hSb78lشJY-&ԨgP_ү1͍sl2~yvUaeIR'?߲9\1d-fXlfKs<pՔR5UqC_&BL!ŞӦ*r:>BA)U+* F2ưh˕uâʕAF&qxG J;zph62锒)2P9dAъ*wvdR[UŶn5MŕMxx'"#~Z5EG s=w3Wp% # BiiUmo6+zR7mJVd9fzOJ..rőށ@_!N))űg^xdS,JLnvp)Lju,[lbaYeiHJUl-K R fWwgڠBgW;ӘwO"2gRaZ~E􆻏3jj[uwj4ZNěB KA>{;LJtZŮNjX E$n8iuݚ7[z4q:bc{t;q˛S/ͻ-?ƈO[/6ՍrݴlWG\}p@OC*Zde@I\6=S̲n,pU1} j5ں I;[ ,´)H)D\C.ƈGq\,rB>ゅD5PhiUjMf.pkö.]7ۺS|H1О񡱑>lVtJ2[r~eU=BpL6hVZ<L'euXajg/3kB>;:˄HEPqT{ |.]*抅l1f&Iӊ*˘^LjS8sdA=AZZѮ7ڕZsڨ[[ՆFo@>V%jCaV+UCnHj˭J)X{q^6[3Lst]CL?yð6׶톡*UaYvƮRON%;dV8 ev7ۺ!PE{)%`yc(4c0x(ؒ>ŗU6, %Ԛ6 l2MB 8F_+}I`N ]CB6N(bܓ+\V|Ą"!%ekTeFJuQZ!<8ae%«7%|/>fLT1ml+isbf8E+xvn͓D%/;ͦd MGyԓE7ŕ͹ō{G8e^H ,qf6;d#ܣi@PLC+\~؜$!'*;өÄ;sC{*fiZ4+ hbC*הUNJ"ɲ\e}|XC3})>_:8`*IV7t"&dFl; 5h ݴ@֛iZ 3'BE$aӲ g!! ;}J uf߿:sq:8n+0v MWIVļUJqHTaEDHlJd\S'Fn7>[eәNQ%jQ<~W"rL4 n ӋZXEQlFV ,F~yvyVh4p\[3n9/BgBbfKN޸Qd~mc"w 5Bu@hIWxw }Q+2鍭jYM[혖#TXbd0 4CNR~dWUBAB>D;3Xd€L+a7齸_Ge <^TNmn`{(?x& tCNye >KG/C<ϨCzylbN=6@(O)vF>Z",#fMAŠ/*KF{]rNRR)G%X-6e';xx]wf:p9~BL `3>$3 BT(j5 HIbv׈C~ cxwx:d)p"."G\+@oAPi  1&NqS;@&("!; g; Ixpbr|Z)UV,Ŋ䱘j鍖vW,(ȸahܮ8˦{|l-miQBn=w(:5۶g^'2chm6ܒ0p(9$3!.7@OCq()KZ9]E_߬1[~S@OO1B sw 2=tbD!F"P8߆K[ʀ,Ke'"A[%ZjxaC7Gpr|R?Ri`PS7J*viD0-"KFKŜ,SEvlðV7*+k$xp $JXm`QBK+sF%EI ҹls^)gSƛ[Z~36Zxt7B>#ΘW.uB_0.C$MB}3wM0Н@Gw'LjfKWU9M+N+L-_х ĿE]P?dzuo` pӓ,Kٴj#̕8b$"&]F\Z0Qmvj[7e Y mX0*\IW]&>%Hii^ F@q 2tì7^@R#")T$c4⯷mF<{ij|IC=\&ڎö0Bn0g㐛O~g"2~Y:X-J"9,\W#ȗK+#[V;D^ #W6 ^l;g*&,@"rG4#!n !a{&oC;@i?,G[u%B w#Y߆DP< -"`sB5&H8Mi+Luw4DN-AE8T㬐e˽wDX_ɥ^IR!)s}tJaTaJhj,;T g6+h]*~ڡA`ׄ-\5'm !:Ig7 JB@K'tC )bŖ+( :p,bwB AZqhbݞ M*,U  DlEg% Έ@|;@"h OaQϘBsBgbrxL* ""W"ϡA\! ćfvm'2&\'iM`a6+uI¹L},k|~I"Wf٬.__>ͷ2 k!!h,B?Dכ^bK?\5'~4aoF`_ |#4L`$Z(pW~P͌ݠ×e]<'x O$D .rb} =uqe](Scbڷ/((d7sCc AloI_3S!Ϙ +.lI*6AZëy(CʕBPeTEsaL3vrY f[3h*Bhh'M_[m4| Kom\B 2b*`$%ve>8tM|O$o_5 jawUr|zIO_ܶ/ង, `]"|.}(tXm.'2c-=~2zy .*dab&EPFK;nt|pCg0NDQS̏'>P'Eut2"8 h: ,Ӵj!P(dM2#cmMbpBÃ4tUX|쩟GnؽQ<+,?o=o՛!j( ^Aժ 'O+|%ﻒ)[  X-yZGTwwVu|4DDOl"0ʬh"}#!Jܿ?1Ş?UH2 qȅ; (re!S=|a|"ѮtSvXez.{$wNqbsLIGbzK !Xߪ)I8Vl:-UҚٔ33 ͜otdP*W- <]7t͖e]o{(m;`t! yn$=b E_'?| DrXBIw5B0}*D%A09aG,-o`%R&{ @0 / @h {?d+! Qu=ze0x!u?fjbpA-9/ӏXFeEcr5zs[H$i m# dҪI$x=*BL.j]p_˭ ;!}=c,mn_:uqĮ;h:EhN2~B2 ݓL5ߏEM `";4a%QW:XmUFC_^@& %TYc1>= xp@>T~O͓IDd91> I-$LqW C"]vN&c1SJi$I"=w~pA)DZ&DοD^%b- X2pg-ڶPoBMӴC,MLr}nsoV?ޮ9zWVmɲ?hf7,3g.9q?Ǖg8q'ŀdZ-Vw>BlYK㌉𨺖̪ʯ%VWB\z"f"A)^۠.Fb-rMaZ#ɅMev]AC7\m5 uf/1ԫA˙y֘n5.Br_AjOb&X`Kd(Ph2U߽\tn4޴^")A6"7JuѾ*&hB4g+{^+ r߫/'*FNSXpmiƳjgp^ppx="{ݟ쥢%DT,b{Kn^F-GXFYh" ׶ɈbQVN7'*I"T-=LU-Y"Ho[c4cȰ;\s1: 1"x / qH-nKk~5L+X9nKT! Q2)ӥbٟKcvJRsLw$VVrtt2fXu}p<]Um)> ӯUX!qWwGG7/7uWլVGV,;8X-t1xnoS5k6]ǻW4!x_>\v?=s(|q9#6*l>+, aQ*Vb \ȍeH'^!fn9Xۧ %"pF?Ct)P ) hLFҺ2TV7 w(D,rޟTKl몷?첣-^o[9 LtZŏ@%ݾEAV3 ag(-CUk铒4o~{Gg MhਮOM*6֖;恆aǥ(b-cfבOB8E%kdh`TTl&dm< atȬM[21Q! PqI)H1U ͺdg$vgUŎ)֘8%XYVrN!dC @UjY8/Ó{Jp Zz 3uPZ:]ĴLy|PЬ+X~_Naǻ*1iUk+ƥoW]Ja@:4xQcC1cGP^Y^9_IMgM˃.{(+8p ZZ0g$ /h؁Zd6e4[ʆ4RĈ{W9X[uwд|zB4>_2}>PD ;fH'm`ίJJe)-&嬚 D{Glpq6x$4'/kwvaJ]&/6Xĺ_*jVg?JɿM}^n'3oPAI.Dx-A3g ;vK`&Q!HY7* =N;CNf[OXpH +T 'JHlؖFN@QSK:]<8wT=> O,SZ|m n8'!۝! p=/TfXx|2HP<mW;{Gm1Za/?Ý?=2Q\-b|Fq- +>k."j%k۔SDJS-4uLRÔE)%pV2$X" }av-Nw. 鲬c?V뉵'&8"[1Ǟ@iخ;Ū^ftƙhChMnV+NվmwP[\m;nϥdj2I6`ӗ0wwpRlo>9;HxB櫍s7v8jDZ9f/|F]j!ʓ2Kb?bKCjA)ѩb+_z2'z$47Ͽ JՌ5rW/!k8j%al挳fjqe:Ea9[fv+i&3?ݦ{uZ9i'&xi򋢪ɠza\ێM 1򸿺p];1ھlM 7XJ-[f{n3绷nUJeD 0%@DePA@q۹VVm[@DqЂ"3!H LTJ%;}?g^|9'{w]{ 8N4(L_y:9-|&abc/} <Wf"aHfg _",jŠ?C=Va6Og***p.Sɫ:=u3FOHT"a?5S$lJfPz$S͂z9q| A6 }stG3̬S|a~d"뛾tKN_ŠTݎ9ZQ\"C4EPqF1)<ϧvo5A<Qb&*Jʦ$9y h@8EL-`gӎ);5X|2]snd"05X3%zaъw7]>=w’u4sCRB]KA@bU/bc> 62+ <'xDzp)@O>4 ŧ cezMC5y^;fRpA)Oμw .sD^1W4b|4r1W'DZΊ/CP&H@A[Ý$ y2"֦W F"1#:e F^ЍT vdynPIOȑsf>\MЧA"A./JAl CXkX3#)3x)Bd)"xu4L:wFc2ǒ&Bq!ed+I^B'SKo^6 #;$AbCYYm'SHȚn[3&$ϝ  r9T i/P^` !KWDe`1}% IѝKƉǪg3'ÿQbhz s$$^QbU|^E ?W=7l~H/%MEzƿĬȳD#Lh.f)"{̪|k)PL4Jg'6_J-{1^7녋Kv뱴Wq D˛ޟԖWZ#n霘b|ibREYkUU1z R܇R:%ZQ^Eّ91Nt4N1Ή32.j]\ ,KŢE}T q O։9|4Vm}P]߻2 aUGCRx}BáMO :M"oy( 0)u+'H̛DoӞAބ\ү* G>NWQGs@ЊA& +q-K6o'K+bY ak{>2MDAG UGF ^1A-r; DH%0b8#tƕP0)9f-ڢd ]~} SǯVwp js)ݑǧʹQ/2e;jKVAL^ 4Q{hTs.ŃWT6ips0F h|"D@])&?xGUK!ɉ/TVegClPadL+ djQE2|+n'DS-iz5O-Gq )BKጬ@њ }8e=\Ô {"{H~+E8@†z 4XC' y L(P!)Y2,Pt]ƹhl_~{7qƬuH3jݜK#mZU IMO6RvC)/72 UTKԡ;݂pR:bMht$e*Z \SALnTvG ((p//FM=f1'&|m64Z튨ʦ`rpƨHQj S{W"#kF-L8^W QJn1cF$t^u!^8HpVCQ$ ZxӫHo44FTIeIMQb'HL%*89QKKXI*S +A\L!%bVRNj2d6wN]QvcזZcgʋK2̡+6An]tuN40 ƵD-[nlqlѫvt^77aڣ@5O T$}h!eOd RO@E+Y[Χ#ucRRS ^ZӫVn}E9?zh*CS-hy N c'+3f !lH!{2*YbF*5^&gEO}^Ħj.zv1ē/Pb9H*xb3g) ̉dHѸRVij SΓ1J2c zQ>5!ŠPnQ`N$Ll2d")HIuf`ďz%5@!ļdfn$n X$M!PZ!$EA^/jtgTJZlg)^4rwŠ fРՉ\GnV8 RْjH.kӛ3h&z0WyLsJ6?AG c)/x!J=dXL`c_!JjZ݂c(nжX&YTxtUa ,л\.tѿfV#/Ey[9Mb_ V/FiP֗GDjL` $z }Rl,3{נ88C(ޙiEnhg!& X5eg"xV0}v#G,y,{va=;ڦѫ,k &ҫ|sWm>zmdgS b GjcQTl.^{Bs\wp(fQ@t$]%I+7&U1;W+F`h#L1SnN0Gv}yN3Z6V~E7ffT+%T_H{<S:Dob[l¡l$gH\ iHl9ȕaaQ;ǝ= l@)KWFNXJl!0^ Hlc`J~hiV\TF3+JTzSS7b:i, `WSL5ȳgJz+^ jH(o j^zіᢻB#m(͢LdLKzUdeCN#r;# #ܤӹXK03GSXl'I61UРT%Y_S+oI@:70/ kw*P(Uix6>.rG0R(FVYoR;>RpNƿ21K펔ϩ_c([zE),f"ddZ/e`,z57q%~cg,Tk6Tg;Wt?Hg,ҕ6)#؊W,=v+桵 OhC^1vmZ aN+Em[i`jER ¥+T0NcV fBr69EEEh- Fz sAf%CtAů^tԉ*j7'5 ) }I2ht`A:"XYR7"FKB)XKFСeو^Pӛ##Cc lU)/* جI$S"QdF=TTduӋf>whOygzElZP#p֗#֘wEm:ˇ??qcˇSSm}LJt^i0HٜNR!?'H"Vl^ zX==:*Y^ůM )qbA*y,`Hԉ@'r<ȅ:q`L:FGk⹬O"oʇc%;(9ZA(eti[I֡fj?=y$Lu5lx,V{շ6Cmmul f%b(/ϩX񊌭Ap&L`r]tZ[8`R+L, |zIׁbs5aqN82sB1A@*9o [cʽEDI^(Mvl/ji;`I6::LOI$ZLRhciE472.Z%lGq6, *4M%WQñY41g@ٝ"Zgclz10t8cG6^E;3X5dM=A[g.Ӱe5N|شcXݏ8PYO`|wL#}ԩMgӣu V_ƊÌ.EYh9~[Z$Yq$fdFcbȏ>DSJ;0&٤h*'R*~|o3$a`/F3} 5ki31Y9b`vL57/H51È\мvwm>dsmt);gD#aEilDTĊl:Ș4Z( Gl{RttcJ#3~zQYRo:9[=a%HD; *X9J*f yTTZj~}0.'vמkfV9߻ޯ?xPB`V~+hćI; ZCBf#ˎd24;tt6#"Y/M9vZGiո_l MJYA fL :p]T(cˁ(r~e:sb)_bZ4S| XtLeeYJˍ+leϤg7{tE!Td> 3_e`Qih5*TyqgyMa2N#c,ZןMŮj݌1ۓ R%fkݎމV^MMJ 0s6.Gw&-sZuhnoinZ؍6G^FVÓUp.;vփz:fh"zF2'e[?P}4/!׆{y;|S\ⰃAܤ<:0xuSE$UZGCjV| (7Rc6&z!\¼P]D Xv0>]?vq:BUϘ~ o?>3gŝU10~ZXʼnBd,m;j5kWA|rށ[w~`L,ڪ'Hthf-N4 qZ_[P0­&l}6 μtj꽯v^}t rl.(,`ДzڝLCD(S7CaT8PZܨWp%[̯&I佺:UtQ/=O,Sp\/Gm|S ^呲U EZA l[?[Sn/۲j9BNA(l(-hG&.,0yCmA?b5O'úד_x!$`:,ve Gtch=խ{ͻUL&@]V "(Nڟ]pf`Ǿ~oN>_'\V^&1BS]9WQk_@ >Oz)& Zm">ǘҰ6%>SQu֬@^QԦv:IN"S\(Юff_C]~ x*&Kd5E0-q<$}vJHXuAk/p+`:6NI}wޢvg>ľudA1%kVĒs[^^oAq:1haayɃm0rV< 2D]qX+TyA(d @FK z8. j̪({WČWTq;FACV݄ [=^48^L3r.P8v0VXV"ً5I҂%_un{+߿/\u"PWƟtMqd/Z7[p([DdDVB&<HV OС oz1DrJ򬊌*ƽ'.R+?Dq@+Y>;": +!H?ݛPs3[_MwsgŠAy93gnfc6;o~/U׀I/ hL 2_8Y-kx>iy?r!S:._2(Bt옵Z?&3gVVzt'ר;Z}U- 6P Zq"}lVXEӱ̦M'cС|f 4I=Y`@BD@dQF44tD\ԙWHf'"`h!͊#/ĬʇMaƑ{BP@ݖEw0n"5:"a&Vߘ~NuJV}lxXȦ"pxM|3;~oE ﭗowByjyDHj>Klhf 8S6]%OT?@ii >R^[mp*jIHD`kHr(d*N+(֞ZXP1K= !ֶ!ꓞZ Nե0VgaKܒz 1DV6h܅epľ߽S_{->G@Vž=ǣ$U,iA[U&*2 R mg~빫m0ʲ(UT|y鞥Czr獻WcAQs(4ޫԉ)-lc/qҺU ,~3iֻ~؎4}ZVoy^uikʓnpA6. zڳ\m~=ucFr(! ;Y'}OUϬ-XM9rة0mpkZxc ܊rm1!W[^_aXr >ֽmzimMhս^О B ,9/ۑurs} N_ .^{zalM}`J>GC+b1[ՁF'm~sǻ"3n`͆կھxn;~z[ W9qr`ą$]I_<L?鼟|K^w`\bEUɫ]qۏy?s[o AB/TTPC +9K̐%K^I~..~{cb~pz%$Ead_xImis1'UX:QuҪ{}v-)NawVގ $ȵ< ܪguyKr{TDkހiЇ*hw(n*),7?VWկ׿4\NNdQk5`nZAS1J0{ݠ\Xf׽ ݘ{:`cG9N?|BJAqxYaiqH07GZWo:QWqo[“qiܫw\c_7;-e \sㆉF}HqCl)_GmLF+N$\awj6XX%+Nz鳷ś.?jwvk^}þw~RaҰHkgd4&%@8n/ErDI{bLJ:/7:F23~hvlS]ZVyI]Zϴ]AbV N3 0>=9٫zD[5+zZĤfJduއ {on?A9тĭ}5 fP Hл[V9to_}s۩^GJ驲h(X* T=ڠhߋhCwYkM`/Ζ<~ʜ 7~ ,c)cJT_Ʋ]D +l[WUl i^CҤ JM_mbY1H7Pr{77cpm[MKI0oo ){jX|dx,oľZX ~(x4]w4L!:O*KŨg߽zFlM;lEPQ ZSX+XbeO˱x+5P*I׽rS7W#pj r~P'@C ,lOð~{Ҷ-S.`mKu SVeY!Fɻ6IHH(=7=&r19\2ËG[[ψ,^VQ~|`:Iݖ <+~K PIM|8nJ[MEbX[$#'zO/L+\2$_ca0I8_7;%WfnڵX*p뺯ɵj v>(_xQxKJnR\Kǚq1}J<0+T~ Z^}g-V:mM .jQ%o#% ͸6OUBu^ ]wU5e眖︼Dǜq3p_ZwbI)Ϩn NnDZ2,#H=Y&+KԬ9ԾJ v}cOP &wjK;ԡ c^f蓻qš!4d$d4-2in1Llhã6t=Y+o?k3J=:z?!U pˠi(dvo]kz-Vn{t˓^_&t=ӳ }A=G,u?R՟EesTC)2$N0d~1a]G(-^lXH\p̹>Wj; 4[JxwU Q\:v5~o9]$ 9AMnחU]#'!)<&a:6px%믺ppI N⣙K8V?T{o/7:F=йk֊ +XR!C+"jjAQ= l k_v;X'z٧wow&Euw߹ Cu Y5^!aU ;z~QXN7w}˟PUU?5y[VU|yϩ?G=ks3>1Z_Ry[d &ڋY57]Ov}'+_=Sۿr-HЂٽ>q&e; dflkRrOd~xءKy}h臝ѭ9)2)šG&jK}B%rٱն^9_%v^3Uj5,,ܷ\Uwzߡ{yPJ+T)5?tm)K|[:\_EX">UQ1Чu^blx:>-AGx0݇Ԝ/6^s8Ӫ| Rd\5k'%!m=KMNG1s8EF n$pegQ5"tFoVEinشy[S%ն9g3xfgSȋCAtdt7qjDn_4Іh\7kqnu;ݰ9DĜI5nG_ \޶?i7Uσ"_gҕs%@tg-\_Ctg n2s蝎 @yjl|M蹲hHs<ܫC)* #a0a!,x^BKjEosZqR^A=(F3d.(t:;WI럲ieX`$vu5XsX֯bW~d>[=S#d>/^ZFӺ{wמ>)c@)0xM >*O\yd|bAl TS"amgDVb@f%UPEݴ(+ +ZP>Y!RI}Ey&4#(E^aXJ.99$xj7b˓_'5Tzv ׇDޮ:+u-Rv.3}E ]zaz;?JzG?n9=grYh&pjv3H 2ڑ|K;%seXNPnjNۑ8G q)nRf*N< I|Cd3pdj@X5/{SB}3mX;3A}WÂ!d9:=֘4D45-vٴeQ{nݽIo>~=>ҥ=KkbeZ|\DX!-dpfs5-VPuEDUus 6bXϿg2H^wo⭺IIϡqjw,X" ]j,P&֫xp%x۷ UJb[jD rr7=xwxqcal.{g"3Rj= z7[9EBJ>U3c1zo\щn*FT(Hh{v44qLڭrU=l36ҞwJ=N.66︾s vO}\90__`kحO`f^fǧ N: GK&CB.;YW^Z ]U]*(G4u{p :g]}z>H~ 6`S1wA1ӕa=eաllZmQ_rC}s͜2Wvw>8!~@:@e9fENtoDmO~\O?Wr.cv֋e`񦟞yj͢;[Ae_-,ДB+zwaTG '4Pޛ<,W nWʥhV j]i #0;Ql0mw}vU7s[gva,~g?Ӧ_=:vCCziF/޷w ;!>~˚oW2 Û?w/Ƚcg>´]͵"¬M ؓů\Y/vw}O'cWڪ~g"+Ê-eH-r!iυhXԻ;؎ED:Xzzx wW(7g󿾙="G*b>4["8'"ts|׋s : ȯzm[ y޻E$QO>&O~1[:ӛkjזgn;ړCr̆]XLib[(Yz랛1e O3$䕄f"}[ZU݇PqHc78RWK?vG=uBiu}pl6d7W(;އq}ϡn)sEs_Rk-!m4cqwʭ\~;@껾(=v.I.~4L"I?\l=#޸7.zD&Xz\*k|R=Ұz{>nxGEpD-\amRpy99 R0l0ai6~^Y 7GG3hcX)oU7&P=>tМ2}YK(=r!&.ʂw"ZZh&!Aq@GnuSF'].o~wd-dq*i.ݨ #nɆ1`C i{!rk9_;kT;W,}K@bDb%G -ZDꢧΞryy_>K7I^ѿKţBq s?xWe;ÿ(.BW>x-YҌ̦ Ou뚙Iæ֞ZsPKtre tEa>šbZIba٭>pz7&})BDf܇0x)ZіWr\uIۋğ>S@wTwwkݔ&2\R `"X~FbPA7 nvU#Z-1 90vxM:Z`1FjMt+XL%hpa 4uI}ͳsiw>s۾toV h80,N (JQ@ V#3݋>X_C%V>{ChCA; JHa >:&'VKQaAJ$BQcr,ZYV< ߺ~o  _2"UB!-(Q9<֚aπ80,a w X̬>7vlK]o`jI{}(䊺zčEPo Yz.x2urI魦 \8ʧ5RZVL`lU(J(hb#s0HU+kXy?fZOOՒ8GGeO7:3_\9(4SVu؆lsR\vOH-"Y#!!'+%l_t`jZ "ӈ <VH S^,yX4 0.50pQKrsEXa Y>֬{ ~ﴓsgۻ@\6b_˞?}q`R4v4WA. N#UB{):D\xy\EsEJ]MBiH<|Nk}ĔdQn3Ȟ ocNx9#wzx %i cS,;`bi sA֯"֘^#jp[p`-@[H'U:kEvGb LsY\Z-Qđ%)5ir7Qx/kPOkJ sPSl"s !sk:_­0oIK,Q$A6Beًusoc *C8ЗG'6w pbxAy33束}߿ ?ܔO7~ct9Y-de; <PLԛCIAU׬WEKN4JX5_ugM"=- zSq:@C\"\qd^ÁWֆ 'tʳ3@g3 W’QsrV3L5Wz"GPt 1x퇁h Us:pZ*R b.W Xö]˄vIUTd$+eN8#D I:bx:Oa H ^CHkB@ZA:cj0N9wo~JmׅBsNxe9sYk?gqy~Pmxu' ׾uW2azUDB>C9w׉W9y90.8*#Ffpp@<"h dHb`xs7sl: (x"VTmg%*<]rm [涺TgV9FْۡWl~{A|Fd^,%+&Vʪ\ tfqOƄEњ !ajUɌĦ 2э]&38<1*^:+" 1ql(׬nгabH=|Aڇ uX"d?ka`EC'[~r ;u빧n.jW7D*xJ(\Pd G2piá{عl*;zJy *.a 99.Fdz juT^iso(x@DE'BTl1ڬ\K}=DOCѢWq:ʰ,ȆVT33%b*sV*s;HBN,4`A[O0d"eRM0.BZ L78,jB5 |ò_ ¦gЅ +x7\ 9]O+j;;q 3NΠa(m iɇB`N(vBJ)Y] ozS= d\hQӝP X/*҂ѨPbotDZkrX=f[ZEw(LKPBHCʬSjU6)cJ]&}Ǻ\/XK5Z0J>8[B=vM#aI(j0rab88X|iePkg 5Ad"AUXOrQ9SW^} ϼGvٸsqmy[wrs Whg%BCDQeI`H"QxTI-ԜŠP<'{|Y4SS鰬,ht+0 A\rA7Q}G+4,]C=[9> @JFWȳL B-k5dE\Ot(Jmֆ*뺊 iT# Xj 7Wdqb;RL&ۖuh2B Ķ>!N4 }䚘j66)SU%lX< 8.ŵg~Ƙ&E@ ' LSK0(Oʔ1Bb0u~La.9+Q>E2jR3j8gf2a[u@h5ƺez-gN{֑Dt[_W@ਘM6C3ǒ%3 gг/g烗9o='4 -N//Te b3$Kl DY0aN)$i/oѐL=Μ J8RտT(]AB+UO Mh{F-k]3c?%GkzHhƆZhg<^œ[aj&g9 H-Rq$ha|RD'r0JWOQ:8CEU^T%Ha32šMj8ezUMg5'lEr%S/ *fOy~f| rYb20J%jN>ʰ$_y Hk,fFJ6:d!IeW` J׈l `nȨy$lf@zw1`*-)V'] h``cC2a+޴ǭs̙ҰƠUC^)M6j$mj)4aLkxL*F2ayf͔3εJjvݷۻʒ*(h \\a*HU9I*$F@㚯 Ng-{FhH3,/QI!,^,P%>z#O+eϑ?,Oc[*%eJGgiWGV>2HG `+ُ̐+F H9*H<<(!Wllx! ڌG+k2ŀJ$#l 08YI Z)!֥ 1dDslD'2b3) FPfXoU5A!Azj!:C_հ\&N qn3uI]ie -ý{.;oCuT4P}O{YrW}<3]iW $@# W&`ؘ`0ac@cl IYZiYav'U~]93+w_ist1FaS6Q!HrK̒ 2Ӓܢ+U$L4bLtxpZi7$j'R H^ v4HMqRlKue4흐م|*aa%J8W% Q#;ɘpI1t WW6E%1¸&-k4*2$=3{VB5XTDΕOVtcGYnZ̤4iX,jKIrs$uISXW*p8ְkUKx&dlNtY+1)he*v4D0}8L BaRnKULGNeM  3tz`|&#U8*ݐ SA4M؃yJj/[|*<ڟr*&ӣΨoI@CWLcg&0'-f&0yl̒砕SɉM;(,qo|k#O"a~d햚Y8̲TB#w$ARqCo9\ynB2}[FL"SwUNYg{sh{Yg1<Ś- D9Ohf;ƒH5ZkOi8[qM/F|OMkpQ)sBjy='*ܑ9j(9"qb(ݵӖ2%|!3G 4dc D|D !\L$Bb(^9ʝ~ƚ;h E[Gh<^9$+p#I)j}`Z(Eaq qTY&GdQ:N pYE*nyVDg%zf&O!nviAbOi%DrA'س$[28;|M8WZiq&}ʛߨTF.R,F?;sj( !ƲY=X)b[<@`J=r*>*4+ XFNLu&i>̯\J%'L=,,$*"y)~*JK Qהc=Mqc :&(J͑4zs^YKbKF~ȱEM. L2(J,I,۬ -%1Y]NdTF!?=P0etN}зuRBߎp{hK#ǧϧYOؖƇùgvȿ3iʂP,w8)M !E6;{*e;aepo.xh,*mmetµú˜v)BNh u\B4S U Vh**|90`@zS8vi5> I=**\ ͑!sT)`!B"*pB,vLAd\6^Wv)Qx3A.)MJDްp;}n3ԕ2)bH!.ꕝl)RN-bfE9q;'橁 ;WMt5ӟ+ Za1M) /l%HYc)ni.R*!z ,^1JIPZEk^xN;T~b XV,b}Ή-&aKÐK$TTuu# H0$2%yw eh(Gd=TG(%#r!.82cSkT17DM@UTU8&aNx*H;A%)bfkRA[ː [{LUg@JdpĮfiKE {$&uuGh°[n玿z ]?5u:Rsav=MǤ>ƹFr+Kϲx5ZiNcAmSuUE\WP,1(9Kz~k e̠᭔z(e+*2ɄBG&iۥh_s+"+ 0 FfepH E%!"]P _sw] +"D*@qUnFKJ&~PdړTHN§qb;ytrw! {|i>G)LMfJ P 1Px KYŒhkV, h \ca1fj4fDXVݓa?s(h}S,#j,HKU9V c)0”ubTYtӹ.T*+e.E*t(`rtz:d\0~W )-AMV,@]$`E$ %KjJi")=p O"@+0^WR%,̔BJ dB.0Ӗ1 (NB"*+GTBkBp*'F7JcHBŠ -m/j!gd>sE] [lAcx#j P U$MA CH;)&L1ZP,(T1kNtv(1 3"rƹTĩ;G2J9gg mB.))s1I]*@a J$bR^8curd=]<P┬}/@Ǖn`(D-pVܖT Ɲ=B..iOfSWB Wh*Asb@(:J(*] Pj*SV̻CHdd72P~),hRVсG+>2087JggJD*9e2Ǭ>%נ~t?-K[$E,M,eT„hr8)\̶R%xw:qr̖ pdmER(sg:S-]Կ2,"Gb:v;ϔ")}"$>X,mF9!0pg^\E!>=Y~()e+T=7RA!DPN"RH犠 RtQ r }T1MgRa}įr"_!"9E ʬZ$?Lx%vT53fRZ O+Kcq0aj㯿tMݠHbBXnᔟyg3$X`Baz%lc݃gd#FJI[9bZ";ۘ }TZ b>u%. Oj[6D}n ҂θCbMگ9w1Wi:M%ᑋ67&󺃮_ #ѽ;wsO_:4{i*bvBwOZbmgN/Lk2s4Mƙl[X4`QA΅& o&;Sn"R\:Aצ+ :n畧 4,ccMЈWSDO)[ י]T`hϧgnаJYh,6 ^;@%0-{T^\b *sID *tY`#_+Z&%E8wdUei.sDwc0.hhXr)Y2g&݊ c݂-ə7n⥣*G %߰KwKO~/lr_%e tRre7|FfzZXa׏ZY^.m1x˶M&hbnڹLo\RbЎװSpvi`PZAV@4&R mZk'eV6n.wbEXVEe@P?D(T<1ۅH]X!B6A- ,,2(j9!zlqc9mFJbH̺ JIJBiTmY깮$j rn8t+1p;*R'RC":gegzQ/Z+.KİWz4T9EI_\Wl*knPrCa?{4Cw+G>OvoTiC1u,9(*-gP WXz>+ta"" =B]QI/ـm0{[vܓMRJp[>rV:='LJcQ)I)JWRCr,8U+UFld>l~qRk,U+3rVYH%Prd`((\!륨$ v<3T1=2*t+a W؃cɊ5 `SYe"Ԝ]{! yJTh:8Eb)|Y>$\ PET#U1DM]UE:$ءJTmӯ?؃ʍ!ϯzA0Vyut]&mӌ:K7m˾ n}#G)z B,ck27`,| D9u~ylΜ:sUڃnK#+!>y;PsEzhwrdfA4V0&b{*Z]VTbU*6įA^@pݡa!!;t5i 2EͰ ִ_wpiaOvײd+"ѓ ! Lpfah"B0ڸOefs44© cK`e'ǕAaΏQ ؂qTQ7x\C呪%@vV ~% QC1>VT]NEPEPֽbŅWưʼn`6GpK)_:GIAY`ͯ ?BX T"g"kL+$& p,̑GuY a/{ wh,vQ՘ȬցGV0UxǾ d{bM3/?Ɛ_IecH؋E$f2ؖ8**vTR9CoFUkHBt{\(M!* ƽpQN|괙 -Zn5Λ~`G7R1a񊡪>/~APBU3P:P tW_#!P@+D:B0 j[O `Ƈ!5bKH[ڣ#;~R> :0F(bCIb 21%2`rPiD¥sbZ-?lrZ> @CtdNA%mN)!&ݙ஠ ]8y8'VF`[r2B`DT"+]ц]씋+ 9t[>P z4pfEJ HZc88q'_]P/9R7 B:ޚRb*~r:zmI2FBFCw/K8tƕO_2F؄6%;d2,+y&u+a4jsc ]n!$dGZ_s%!)*+=p2S9&}Jq!=@o¹AlEh"rs*KI;`Qq1-atx[tIMSQ%Zwz] @NUhr]YPQYRU P|?K-l!X XQs$AO nI"&m`3z$B.9eY@!0ZCw ڜN*reSIxME.P_ G)(Htz 2qnOJA zXB~%+>H.,n#X;0%!V0n[.+=0=Un zum_ǡ;س qw $tRt<‹Hxb|LړSRgVz|㪼5Kfy2N~}_~ h]> :(Y-HqxEJu>b/k}а4$UJ=UZxb1D/B8XW'&-/܄R:c83ӘEy 4DHur3ӓ Ǩwɻ 0R_΅;(=[_0<6^aTpjTDq )`j\P 0u="kq"* "I/u *JVaYZ/~Iړ>坅6X!J"u'Q߉zrD4CaU=|іoΚ;JB%:&U@+u8U?o:-*=ځ =Ǟzc;./ (]bHQ W dgmzO_ڭ8RÙ(%AD{kSY4d bg89V83JTaMNA P?Vw䱤X4N'k#bZJ|aJsƎWjyOeužK/څz='`dBYKr]e<+?\&eeKVC 9̆ T"x)>q[!r/}%ˀ&ݕۺ,H1p " \R(r K9 %1 :HCkk-۷}X};Oή)jiP(G:ֿen9#W$ ibPݩ߸`kz$B+I`9Jp[PBX"pt%$c▱:LGDZoux %v8_N7gAqdnWY E'ò_[mؘex<C#*6**HD+UmCS^çBa"( )6`A9%ſCZ7KvtVDV7AZt;?CQ:P YB^xrK:OG)2VaT媠HI͠I#؊@ W@-,T*$eo"ijH\WnXzGC3@^fޣX@=pC.v<\=U1.բWY[=7T<ꅞ*Y-"kUygXW7zޝwۤ<,+M},\PEkGkd*̒rVbK XIy| dm.SSC|_n_O6|zaW͌<#~ryONχ$Pt(/Ae/6uy\]LzB#?C DhuuC_{y8 |tyw&-vaQdȔ,bk"`[c5La;t@op"=,^TAiW 3DUpG )z9>T9:4j67wt9W!uCtFpi!YM`g9w9+ N}Y_h5H/zuhTvJ=wK` p6;5`6縰̖bp %c-̞\ׇ]q8e>jE+cy:gE]oâSKHQP> '8 )HtoJ7#z\L/Ҏ.u~mrMs_7EGR./U~ϩ/8pG6pt*')kJY 3 J VCE 07K#!Fj`$X9c 3\s>$u}އO@wh"[.Ƒ`.{m|!n,Vm*U>)=6R H!Mם`/SXFîPZMS^0kO6vWN cq呹a$~}jŠQ嶎4a-muV}+ӿtc|^"LxSV#;y}$X9Vh&@O`KX/BOrj>'bhxsRϟN< 8R^Zv WJ!js5)$MO?ku]/E7F+֨LЮ^}'z7(ް;Y>W8ª" fΊx-N%нT\"w@Us&}t2ԇZ=TFcą_rɣ>*Xqwyŧ|;G)Wn[)CM娼<"*0:XL๯0c~;7cJ3Z`GCX =jK,$Eh  "^Kpn,db aӉ:ǙQ!FѿfGY܊1Z5J #7NE+N-dՋVf"rեP1+[zuzF]da 2Uy>%s_/c):|CX {?UQgi۱ɒ SN;c7pÖ-[;o _,y*Ɲӆ^JVg1 9=?=#/Drd)gmf% |h)֝d.t-_V {(?9Pê$JhO:\gd8^4@NMi"H`W|sAR2~[Z֧PVR.R^qSNBLQV×](&ɼ*XN-~2hg@]2؄˒t=&rqEX+ĒDYuV+YuՁuuV_Vi9X{E'Gtb a KC.M Ǽ+MCR>]w1(aU78p/AJMW^3to^)=;q!^mb_aFI21UqhL_@7" El`&UBCuÁFF,PT%\c@^ i)9fu̪{?ޠbA6!aK lWm-MSF`}o?ts[ɨc1N#T?t:7DPE}-)ìIZn%OϓH1,xv0*DsCC 4xQpr{=FHMWQ9,+[tl`|oc{V_\|`}PaM>q]7?[ʓw[']&H @u{r/e (MpWg0o~-%,mگ.3|& #2 X +XxA%AF=`sZZg[/|\GY_~yg9;o7ܸ PWF(+Uq]p 0Q%Rθo{]'|ip0}rt O@ng`~צ?}HxCw'DcFG .Ba.E2$w4%[N8E'L1gqsYeU+<ǩ +ry'Vv3Q"i9x7u{D_:Ƽ?Ǝ>-5NiғnOE+KZ@fx)bb!#Gw(ŖŎwxGdäz~h$Yy#o?%F"ylI> FpSx}!5N^XXLK̹#czKx,g2Z} ɓNNW]h=-A*8g⻏|!{ #g%\s_:Ҭ`.)! uA9'r+5R3Lpf^8} Y+Ӓr5Y'N+2K)=mSRY)\ΘPIJgt^^brwYcNy甸h tȩ{< 5*,E6Ԏ̅COp.=Lk.|_g:Ϊo;y ҷ8LGDڹ!76+2ǭ[os kaAp]ˉWroY $?|u۶?|o~s۽[/|/| CI2*.;ػͧJ+kϿM}:w|fo0]#L 87q2ӳ8V|W6d~^| 6R`&nϾ%y+Iͭ%QY1%~Ȝ]bg* bmWsf0+Ei}z 3YȻ:qm}iC70M5jqWgޮW*9Ǔyh?mv5l}_ǭ3r/݇Wd1 ~Gw-u1TR41>o4sbd }ɏ-Lf});͒7h蹮yl-o!$-BKg-6Funݮ8Z:N/ B_U4;7 j:!OqS)?وӳiWWB-$BO ,l%V1ĊZn+kN\;ó(`NȍO߲USWĿe|W3i~<Ft0n!lXb`Y)sh_;wKrHɇË{'^ƁgR5G$Ѭ`%n o:~YgbF">S,-.OL|#뮻~xF(DUWI^p&ևwxI;М\60YV( X\PԲT5ָT`=ќN8I}ɲ請7&98Amx4;gYԂn)rYᯨS,{7wfwe>}V{RFEhNNhL̮//x,b%l᳙ƪ=yc;߀~&1۩ӍTGDdG/o;xYs,+];\:ӭ^G>QJ)a$  AE[g֞sas_Z| r3,}CSh-Myy5p x%7oOi@mAkt2g9'O!FR7eEM+Y\=3ra &}8Ҍ$(@T jpWnkeCg#Wo\d>z!ɺ`7n6`r XfY3*>w? ׿v+zF2/w_xS&IkȉS%-lahoqKm]sqq,ɮ! }6b^)~%$O?$P?qqjb72WFv2/9bGM]/Yvy$HyYSu 5$)YdOS'J/x!%V2y~Lƽq~ҎSy%l3cxz'I*XXÀ;{ӜXZw?5Z?5WheЮ;^3;1y5AX`Ax׉iHiu@m>?GŸ>}Yje/'?*(fDV>*BlgO\?5+}*JggnZ<}Zuܙ-!&Cl9+/2OAOUžDN_F|0#ZZdFrJu;Y}OG R%X5oL'h1zYrz\zf3ͤmw=k+nչg~{Zc ] 7^l΋ѿP #;f29e_?0Zַ'&si2.dmޓt^sߟ)~n .m B,W¤!Ή_@?e9դ24%h鞫<0(eliKXXf͕3v̞+MxU^yWWlnr+H,p 2R83U٫C%bޓNf#+iwC~5w}kX"/e#bƪx]dÎ0?/~ac޿mۋ^x1S=cj?vph(V_pSRB$N|36Fjq3\CaR.w,\\ƜR'1Ԝ5mzj%LVVDZYR]%S[O$? vs`ߖo@ފ^+Gӫ{/++= iA{wO<\C7>]=tԜư$cHz5pzb5/=Tu wC wW_|Ɗ+&qW*LJx w}͛n}}RD. lt΃|ϾsS=Tf-[azVEH L2EKs l%hqY Gٽ0<'Rի+oT~hfi$K.0s^-#-"IYc}>‚ HXuEtxu1I W돍y~2T}sVɅuesjϾA5s6ɗ-_#"/-Ճ[69P'{K8= rZ/ђ]=['ZSŅcsѹ|A{iS~yg='}kvɰ~䱅tL9׾}9p(W9:apS۷ I~7&M~֓` @Mv_lZS=*۟IZJ.w'\F r+ڳYu8[ Sq-a1-p)NLvcX\sPK'l3Vy>kd~9D..yc;}*UQƖ!Fb8x؃o׫>7' k%{뮬~P3z{vp;k-u9t eng˶Ş9q}D eJJYl>qښ&v2u=ԈdD[jJ\7.E~+S QsᙹO\5Y8cKvųmsoyY5 K˚mtoI8 p(G.͗;E^)FfmgTIdΧX+DȅQ|8DpH/Si e'Dg) 2fy[5(A`وCL"tnuT:Q<$r:kp,h WG~IQ%|aVf@٥t]9ϹfUq-,ѽHX>%$-ƞ䇾-';3]wJ !)In))nL)LZX,e/YW@~s.ѥvrߪNttuSՍ*escP.ʗ2+>۳חz89z*)?+'@Nj%4y+8@贽vW|=zљR(Cv}@\0׽G)sId'+}}"uWxVRr >-.ӥ MU}҆-W[^%C2u-o-By*Jr^K縱UC8uuljifzN9g%$\=Z&&[6~V^FOg>݌-]rqEw udM~хAzW\Ϥ Eaw_W>w^rəM U˵RqZ>nro _sn{??nBA|]kn/fN<ml+C|:)mW>mDw+4qf!!̫z^*l:R}E l%LzƕlEQHGY/9n-/IWn 4 Vt38Hn]{~XL[wP^i7rgdI85zԎ^-8yZ"117&a8^g@y'J~`B#ZH7۰{58uy| [1gw9u%NaQ27̼]>xd`78c|߱&wvw\tq1ګ͵#gW58'LlÇ9Lg6M$TKRK@ѳoS' QZ۳akPAΉρ[*ڇRIIJV?zMxptfMd%bju#uFY&:^eRL%z߫\sWuÖݟ85'h}9=qenCP˔x7s&xxmQtN ڳj~H'CGӴg[ltlJ ^6}C/*7֫qﮬy8l>6X8HyšS}W&8)$C鞛F d╨.z>ϱo![)q^ tI\R: p'/Cw-zǣ;kJpq )zAŵGmpGInGضgY{K OE{^54!_E8rjSn8kɟm:9Ztp8v"h!7ʬ6Bmwl-kbdtumrD(*).儢Hk9Pm""#:3Y.ZvXV4#(BQ#G]! ɚ9b( 8Wc57 >v+RBpX\*+XlAfu[0zǑ!)pֽ}<)`A 7Ѿ趱0Ӑ|wY?x~u>{?><_lӇOpi|)Esjږ~1y,Y5W)~pG.0Bdltw$hT> {eΛe|pY>G YVT0@ ߀pY$9rSrrn#I?&jg!JӠHsBFD%Tmн'{Gx4V`,9{Ť{ھ..aP`y΋/˻~bV'gTY88yC]N )?J93DXP]q.ڹ]B- -fkCmJa2Z!0?J@0!BC;K |d.cdͤTHQ4V}^R˴;c-uhǐ$$ [{`IΫ\gfmw{{o%V[mY^^18Me<Č``` fedlx`la۲VkWKޗw[K./Yne2YUYYY_~;9']<`0OJԽ#AOd[NagT[b翹c.z~ nR k+RDBjMB+CjIjH㘨Q_]}ugn;X7jp%V7׏|b[cڴ616AJ 4(YZ鵙0mUVO,|3_%,ZG?Y`X:>iV9J%p1m~k+AO=l۸4KqޘBI_1y77kC/}ޫ\}z ڼʑ5ctMawíȃ*~Um< .p<%d*=kb=PHbds)yuKNMd :HΟhj.XK IxΒ4HQ']Sjiu6"h)3/ yf}X[ރO\Ѽf_ZKРT\mjXN ?,ɘѺ mrD*UNN7b p̠/Om2ꋟV},;}|W-صxe ?=IkSi&V L{AVʑ^ R kb[I:"`EM}wlm{]N?p93Xz2'VC2ȃ!=S\L1h&^[ "F*@  a qHqZ -!:IcS_Z8zoNnj舕HEXgpKtUs^g~?}L#n2*??o}ͯV3ޅZwb}nߵيNQk{3T}pUL,cb&R `1iN;Ї%G&lE [΍Ft@'4rF*Jrf$q1KWWُlZV[MS!Tj-xi+Uz)}LcUِ9*Te G6G TQ,5%4 ,[((숰Y5FQ 0F?q=.N@`CRYZ/-`#F( {W?;7/PwB$`r&,RM+*Gʇ>LV+,a2Xf _[3mM8 s^ \+Ƭg4ĬIYUH:B"FƎ^IuӦ1$KiC%)e=?/ܴ[-0s@ ?_%Zo:ӽ)RM*y 8ZbP(`jOxpGDja.юTvI5teu*F 14g)0 VC<5, XhT@`6+u 4TKY KQFu]$Β~ AJ@jj Ma4jDe09{k|=D%(eP)?7OaFl@i$eR5N ;_g~W s"r|JD!eX]_ U 4 K>r I*쩉LD`#Lf-դxO'poԟ H{^%9_7M>O3gR~WMA-Ѵ]9' >`3C~ӮХnwp ȚBjp՚o FRzUAKp=eX{RRq`éF/?O9R*`0'Y<+Jylܻ߱RvJ@[|.N08a|^w}( ce*0)xE@1洔13AA [$jc#*ؠT#q3ޅ갃8KN2*w4ȡ*myr'͢rW~kw70a mؖ$vCz!)\S+-0z*i nN: _[8v}CS <}ѸV n| ]twF%-0 խ8O}oc澥'Zg΅ LI'nW3JKioa(TJ;=kvnڭWS"kP w~yoc /4/']Y>U[5S_;ޙ 3$XҙC;)۔tHH6HGB qY83k0mU5Kh_%݅#J&)A?Վ hXlh,*ddaK*(<^}tI:T[B[-MY@$`G#׮Qb1 [msʐ"H:cPȅ@ cU^ưŏ30ecmD\nE-̔wc=,Ti*ޅ$49} N>$Fc.5;C>r]~rWs0׈[A1f )jP5G{lD̜İ2EC`!n[wO+j0ȀU nK.=`e^ߘ8SWM6y>|nM&[ltN zQoddlRthR6df2=M7{[r"C!"֘p9D6 դ.µn 7D%P&tޑNMoc̰L X,[s-ϰt?mBPJ ߘm~k8>IqvYŰ%f8ݘVuaJҮ,I8՟[]kĊ=|QCVHJB92a)MG[7 9 m"B+ɠ [8e\PV*i(Ѱ YbPڊ;UOбe~z۲qҳcam`  ڢٌ}S^*T^2AkzkuhΗV0 zؕS wD9l5S-bQ[7QUvEgUp)n;{me FE2d _t$aCVhژ&X {AJjEB ;djv~ppjphe{7΅oe3a΍HDd|LLJk# "t/03Wic`Xm$>LS̰܌Ҝ9lI0 bw{Gw 1aK&5Fξhf],i/. 3Pi fx\:q/l@ KnŘEVt@U8/Ya;dH u__s:Gw"=X*'K=BGcEK[ӪlNreT-i YRKs+cMV%^+#w]&VZ`ӖȚ"R YC4;Dآ Y%$Y:5瞦,X,i#޶g &ۙA,01~ iNOr&3ShP sYsc7KݖYGF)J7:DL+D s5M UǀĖ SAvD**'L1 dž+YBIՇ>0"ji4ʝ*!t-W CfCUhb˽`纀$4Q.\YŊ$PZJO`I%T+34܆ )-3E\a%u44T=bR*SUU[!˔pn:bVݳ?Ѯ~ϼyF2L"(4)sJڴq"Ffg/<=)*_uhe/jDC(xZk쳃=;=G{-HYR }zW-ˬE%Tʋ}>(x*[`h.r4n/-̉ǼMYKǛʞt*Yyb|Uڠ:玑V|a-2ʺ;(ȴ6A*+m{Y) i:4ꁈlT-o];0\ H#ai*Ug+ mfTVOZsG^|kv67v6[8ll2HI}ߞZ%Tr Jc H}xR3LSkҜ:U*_E N8U<r–׼ǻyC7M=3Nkq9R,Ioc?38kU VJMǾ/`I9{v/>;ypR V 0  4GCo)d?ʕ[ f|}{< =BuSSZ*G k Yz1$ m,7qJC#kqOhc*s.vɳ_* Wv!D Αi(9-߰x Ƹ`U&dy]8C)NrQto` ǙM'Gb( g2U<c3/YMŻa3Hu%ƙVxN]S^MPSɜT`٬r5 J`يBPzp1*1*ixwpFtoz&X56*;`Wpj0F F]s"y١{~4H}28>NmkCZA8E`,%8%,SܗG>{z;'<97" h"hZԒ'̑2űpЃz[&T+?G.S՚aJ!!-`,(VA 8R =TF2gٰ"Sswh<:))LPe=7!؋o0+b'o'í'2p(H@lQ,17PʗHVE@Ь3 _4T57LY``*_g9|AQ}raE189h-'ڧQ%HԃU/RIEC:ѕMukf_اJ5|8=ĎSsihaxrwʙ(lXǯwAlE^`?o2MuZ@@ wo$PZ>*%tr߿A{K{9d&)|ŧoڊB]jò!!Yt5=ɇF*ՌeZ;Oݎ^iU8H3ܚ!LM2#+58$@PJU9b߀Jn'Pűa)ٺ!%#W2~=71AsμQ-T<[:1daŬ**^ Pl1(u1\S#R+]fezsՄe[6Y'X=eF 7oiP |j"j lFQAa`<{n|ݎZ[rZF;vNV |_|s;C0H _צIx\?Ѓu?)+Ű-ef2 @ yC*0'_5*r j6!7^:*_&,9.Wgf%r @@$==Fa;+ʱ[;DmlͶ<6\w:_d.k3/@dzܳ *öRhT)PnchniӚ]sI%R~M"Fv_PId,Xc%xC|5le %V,E-;g\9IЫ#ߜI$%F~s46:v_|k3.\N))u - ^BʧـS;Y$6"AJq%g˥ 9 DOfr>&arX1ŕ]&e)Dd\GE܆9⾠vٸ`>ݎA0 U'G=#`lBkJöSڒeM~R6U)+D=Џ&) 㗯2of39fϥCQcpЊPKCs 5jusSAϳtED0;Đf@MQ1~ٯO?Tᡆ+EV\0^yE'=ybhvn55:7 U89Q/}֒ (i҆[V~R'YD[zjmtö f2MGZEDh`sWLjPl2v9xhޚ-\65e^Ȗ$%e?7j<Ы#/>\>6s*ĴoW&jzi'xf6 \+RXM>SIzLz`sJj!\YmCWxD N5knz𞷽'~}z][:G$Śx$/,Bta%瞭d2^v<]t6FO 4(9g4cßlT(\!gi zǧ+3stE` mA >sE m(m*d#!֛}衿z[& ]`8qLum 6 c#Ȍ 퐮&3h;pQcӡ ڨsոM,t6]*شeoa-ԅt{; xB&.uT%qŭecLe:Т50 +0 @@ +;9 X`c-jj/Qt] {rV/ɗ #NҚ*]7z3i7Ak8vIglBgK+Iz.SFb?uҕV©HT?l`5'Os`'2`t_[T-G5rzA$*KSlSO ZYU%|6K=`6d{^/']٩@eܤbvDg^umesn~ME V)3}^03 )W! !Kmgp`rFo·8Խ@ܢ?~҉ | uqրV.Q>zp~`]V>M"b@3½;^ sZq6F7MU&[*ˊ赕eeu tM/XU`B1($;x|j96$̿I#{70?rh&D,>P5Cxו!pI5++Cq0mT#8B"J J+ >J-fSZ=wՊY^*)՘qt{-9xu)xjvWR@d9;ME, V{a| zӵsӯˁ%NbbUKy)7 4&^eB[&*R~R2Nc!a ;ke/Sh#Pl&l-(o\[gUeJہκEEA Ru#+zkPo]N׮t򼆺[š3ۋF޲կ¹ʄ콀DP]I#aƒH]!'P05z#Smrz@Zh;BiBRͭ]lvW t\PSw,B oWePd%WA]$0dS6ET-soU(ʩPd7{d&>dW"UX[XΨLl0 Tc.un [&(m鄼tUD~h7#"]b' +GOoU[CW53Y:sJZUiSjd[_cE%UB|B:V`®Ve _Agff`ܲM6hbyyl5dYZ  K*k=?3{ѷ{G)?& }norf(ž^E?eg|:ã.IiI'r$5<^0>C/-;ԚEHeߘ&(- 7S}*о,vZSF`߃ ,OhGCJ9׿3Bn,g%m[1a>%*V&p rƗ(jTZZY{ۥ+C_ʋ;YkRRNn|-,u] ]+#+&Fq$ʺ{Gۻу|5+l"R&g3hh[Jrj.LJD! sP̨ eSmZleiܦiGa>٠OT4uo81)!3P@E V6c]y]A{ev9>{}_w|'R'`xAMmuPU=rGUt+R.j/)Tau%5(3/@c#ؒw^QY4,,2,,8bS|+2h>{n!WZf}ݬs!k,p`WPg+Txtsz򫣿$߸Փ텧Pi)A[PGzrM*TU4OeHrBOW+>/rĉMq?ʵhvv=#3̳KXxjcuLv0LʶQ1[XK[#Sb7Xv|)g> hvTQT8092{DF_jo@@]n=o?ݗIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_aeaaf23afe6fb4702bd3992426d0cad3.png000066400000000000000000001711411420147000300346240ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx ]Gu&VsȑB )412C%KQ| `sPP O`vKuDRK)XHFNVOVaܘmX+EO Ъyh[GwPU43O$3"[Yp^,^,P=o >:;,j ׳8"MG*@˜mq#Ȃn,eΓJ"2ۃ'M“6և)!,)XHA`ՙ^0 :r FBѐ8 ) wC1>"H gV0)ȹ&@L!} 4 H->a$`,P@f<|b}N>4G;ӀkۉW'd%p2xe@[?#p57V$v"E Jemiq<8L݂Gs@r~ǎW3:8mSFLڀ.,Ѐr۸0u&*1Yܢ?$`,~P-'EaGrDpƵS0 ;gg1+Ezc2]`Nj2` Dh ƇQ9g XK̃a|(èȢw&H1g?I:YlA /[}Qq䳴G1#S3\$F1E9,Frm`\?z()6 C Ry7(?1q &Bhr:[ك'dyCIŦL4 Uk/N/^ :.c(8cL؊LrfPi ه4yo^iPda̤ +sNVrƷ[Rp CD6ɝr]B-I!z#7LZC4O18D1gj:KTGrqy7"Hl bQzdk* "ǵ 邈-B` ˲ )p.>%D9PoK [а/yo-4uC~% Z9%tx5*( B:Æ0+]{(`Ȕ, s4xAsALsEa|1"Dކ@HkU1J TT(OSZE WGҲO6W? '~}[ZQI}帵pop-ŏL :TZaLV8oCj&g|R(0r2z;V"7E*b8Հ/cWֹWB[JsG!`jD(tb(A0\Lz3hM\f9x6h Ҷ~S'rdG-i~ Sh?aVJ!8 cBQ@g|y@^bbAUhE^uCH^h:ɉ"p6!axC|3( )OM Tz('~_r'i[ L|MY(dub`#'tls:PX=H$/#xP$ƋG]%3^q"I,rH,bJH/cq^.6 1La$s,>U-zNJѵr bł迥 C^ay˛~$9Yj]{|=v}rgj3Jn? ^?k%/~_啟dG"1p;Ei[Zl?[iMnĉyo_ vU^PZر*ˡ>L=Ɂ{Y͙=N`}lo^Z[4Ga ^M02@8'bDƹC2gDlR`3+rCh>@YP@0T\P.egHfd?X^ړ軶&4yoV|b#wa٥׷ )Ҁ% Q(]Z.PY(64j)ynM QWo佢 x迮L1P?(z ՝PYZD2O W 4qnEr䛿ʀŢxfLwd1 B# "ŋ—QqXB*V*r@zQ!k!)wch1h<(؈p Gs/1<6"fOla2>V19Qt$< mJ?5M6][Z( W=\@ڞמycҲ5 .o~eS?GնVQG/njS_O=~Zm뛫Ac߫-x7\^{;~K>U$ږY{EGďw/C t,A$ZY^ 1SWStGv `~Ck* p gYM`괪 "![DtI6`F}Ŗ7qWb:1eETKv łWe5f,ˉ;'r'4~+TV7eYZ~dBЬN,/?-ݍ o{ifS0Qa˫׷@3O+:H㓶,~I?? eWv87*OsC~3ffGԦȃd@"c  I/rrZPA@(:H5W0WJ M .ʰȇDHx` @qeg< 8AlbSkcS'P6JEd9~`7(stO2 W,^meBjW*Ch[qHuwGRmepӴTVFP2+# J6CN>PvƮJ+rSG]$`qk`.|R8*XS- Q,_,KʔQ%*~(Hjn|z#7R2 "nT8Z%E-g}A"yƑݳ 52`l-'X:eΣd5^eG8>P:Y$cY4( %7SSm^pV( 6oUFߩ=rk :ĢN}^Xܳ1șHpJl X, >| Y-ttA qTK8I߂f~,n~F2i_A֏R O<K+B73>Ghh|P%ϩ-M ݖY5XSTS@wGfC2+9BrOSж}(G 7`y@EbD}'9u{4kPGӏ̖^3tE뚇ˑo(Or;sd *£A +E%[d9qQx\[ш @1 .k[ʀ%( E^qg/{KQoM-4#˲0IuwnpȌ`NQy9M(HV;o,ygC |@7Bi@}/(~;--/2پZ \!쾤ih(cǙb4fNQ#@ 9h- ˱[c/G[E 5 E2vH! Wyx?!儁*Z.' GIRw"1RI]9Zqr0" hRTz)<Ex@Cü"k4f9mmf`AaM .MWmwq>TZN'd&iݲZtuy?04>no}ɥ<ڮdnmNNeYwAԯW<7=SI,PM=XfVjF#g6E/(SC'_ @> KΣ,! vS9Fb׿П|bxL8\ Ycg bOBhgelT?#;FhmWB){L:6+8`p *E@U 9l ItbYTݥ]WVθU~XYJ2rgR2Κԏ37sS$h_m7J9"NQ SXy:Y с=nGDKY N,N(y bϦ׌0 N$tp Pu3SNn c);W swn êN(VaƵyVZ ]Fn! (Pa#g R ,gP"fs#s5?fYyA3fPɈ!W~ }6aj…8d >vW=`5E+Nظ 8q5c2ÂU!AwRf~W[\gVuS5h23d( wbt`.79!F (mV(;n#`[| ms<.fK ]MA3Tk?]'$V/Zl?BestwDם|f}#"4p'Eƪ= ϯr,V>Z fUdE-+E׽AbIKGWh%]sVnh>؆6Vk26/R.&XT:g(=t,:l{e! R~!eݬij3jR@SN|ϊՋW\[h+?/>c"OƣϢȕ`cIWs'ݎȓ&ʇcX#*XAѦG!ژ ˙r`2YA3Ԝn{9@E2| (k[~WmQ"脩x' E#WY&n!-b}#DW9K:ЍvB [K,:Ar).]&,Z>ʴJL",d(P\St <1S9&FƬ\] i: <([7;HK.l4ʼ^棿جD0 BYl{uyO$sV$7E+f5qR\._6Rr JeD4 $r61 "ʿԖ5C+,mhq靟\W^K:C d5I'~Q0P#l+$yp:AI 2:#vpH$f( I { ~E8%_%f\|cЄuZ${solF^җUk|TH r!\m!Fqwֱ[3*&鉕7DY?/:ݫݫ`|$;k8 F=Pk:&!qBnejUI6IQYٷsKο:#&%æeSexNEPV] cl\N=:PImRLE<25ގ|RF/점0CJ:;+A<eD*IA: Hg!Jz X%0xV$Vo$xuE?mPheCXro#Zu>rx|rݞtC9O#G)Y)a3ŵj;2L[5^$б}g1G+]du6vsqu+iB e f)_ I1IcâS U=SRlH۝ uI$/!\]S 8(L7jfS H#sʙPk3oZU{'%P*fQ$rk} F>95 6i5rKnV?szE-n}|~ ib,&G-52G#nXJ\3k&-`Q A&*}ݧEY6 U:dmXB(lCxJɄXlfYdA|Ki0&!2rMQ;i).~u+eJSzmPܸ]Uq=> 0|~H[-2 :%ȋܞcHx zU]ӄ,Xr 5IZBRllRfYyNO؆ Hs݂ÈI1R1GcIVɼ;xaɗY~ɩK=utcl ӸvD0M)0moItˮ ) f#qHs+IJ ٣ԧ7j#w+;dI%ݘ:b3Cp&i/srJVeD&,p[x9TY~zK'@X_65=v沂!R`wbUF}H yTk.XkX1輁lJREK_}lOmLΐ).40#G\ìs&Ty ~^%'leQgX=Gջ/d %$(:Zr♯>Ǻzh̲2@F U|g Dw9PK]zDwRڵW2y,QMX|9 7!RxA^M?(^KjbKM͌0S9п 8#YtnQ/J`*^(MTINIeΠޒeilZw}]! eXhv?a l>[v]#ϰ=Gd%f e"T=K;HŲ6uOOc/\.Qow~{Ws::1)9Ұ}A :uQCy^/ȍw,ъW19MX"c $Hek=22<$EQ8-}_ N ȁL2icmdnǭ .cz]1ˏQO|l 7J);בS:_wYwQҴ1 `"ЭSY쉥Y]0,' x5 Cc9–;^‚B܂r&ZI+뀠W^pȦo珒T>xНCyK׼eporGmr;\ڋB((G .YY4PMrzѹZR QIU֏}C?Т{;19|x|lHg{EgiZ;LN(rq]CaN6/[n ,Y1oIGOOGWT(ԪGf?1ؾ]O;45)QI^8M]PPd nCдͩ@U:ہsktcNR7]2왥z1mѩ=מ:oswmV%Ą`ֶlޱ_{4_kS(SǭvamX s[_fSrO{yЭ]3B9@}jw&{v>|s+DOn=KԶWa3jb D[S\RKߘL=ߪONi sP՜x^Xcޤ'& Oͪ;3i{9ԫO-S㛹hݷk/J[S#}t{~'"Y8}5^W[.u.z+v|G)Du/&'ǍSt4~g'vQ^~]+%!ʕe ڵ6}wo4VV%YhzMlOt6$1I Rl=s-<]j`5) _?{Na'.. `k,2@{YuVNj囇'yon> ˢnfͽ< WNā޶sr䞘9zrR;_"(5zCVZx.01 qKzT}.R粮Sߝg>ᶭMAlG-ǼϿ ԣfMIxQ^9x6ulM>g7ٞ>|\,5U+G+Oל=:qPm>{yGJrIE : _}9WW&kT/[~/{~o%2?*ӌUY y y"oEY_MpъŃ˙wLX#Q4Z>I={:J̈pO_o{og'ԘeHVi֬P&W *u.u['}薓$9R##4*m*T&^_+u_п湠UPWv LIX-FlM̚+OLP<0DOUjp6IdB%=8KBШ^w/紹Qf,: P]ٮ$JV[/}u翬8ZW5kMME&soEzrjO*4 .ۃjCE!}~/߼j?^swRZ2UwDԹ4MdΊх/pMYcN :(g"A\uRGkZ^5x魇xPOӫ9y iC@=R;\B $u"0Υ?(!CGdcԺ9 ɁF.I{ڥSiW^SM-Ν xzOL O4}`ܻ (ݥo{׆Ϧ]VL֒|HU/RE `qHVa$7( HKDH}j(/vv ٹRrW꾠=Kҥ}}g%%^=#qXL|JyËɋhhEwU% -$\JGp +[٩2pw {"ǤK(˟%ZR)w-XwKb\otƩY>"}xR\ fPrŽ"qћ\%Lܹ0U+0+R (˫cYVM Ik娧wa,ldΊhV̹UijϷ4ܼҿ֟z]`)~J$r$v# ɯ'Tiޤ/R%JB:ƅ^?ʯkE+h&Hi+~X듯3҄%Hv(X ǎߟ)D )\b1պ [&(ίʱY^U鱽#u|8E;E`?eǞ]s_5(P ڐ[%^OyxL0(L+/\t^'(uuͣHA/j_BMWgkZW{gj/YzpC.KL{ @.ׅ%WNl" ^zAjjٖ]m׬ږa@?V3*d'fIFAXf8_*: jB%^6׊8Uoˍ''v~ \r+>1GϿ p`O* f#nD~q~=햐PTm@.hE CIxR㚫KnoKŬSlpl޳Sj-f=׼u/%K;0d^%*>.x4UjgBM#1p-^:?iʎw}?y:g|y[9_|PmؗYchgK)դHiCѿ%S2VaNrR`QNڽx;V$%t.ʗN薛ꄮgrmܣ*=! 6: 6OXN(PO8If}D+rVR-AOޜX#GF~wvc:}^¹%׎zEk"灜Wa>{-_Ŋ|"m-^PRܐ5kكv'uĎ[eRm}`sa3h0OF.>fX65Xt3һz*%t/TrJzlJ7R#,4WШep}?;tdaIٓOϟ9Hc2 &fb뽊u{w<ۏ "뻞'9Պy]@Hn$%'V-\a@պzMAת8Ǔܽ66sxk}z~椒μK(:V Ċv) F;Pz^矝O:RT# rk8Tׂ {ܻ1ΩKǷm1Y54{N̂ ;hx*(DܝŗR< TN'cʾN!rSGGgnþ#Cy`XY8 4"2X,C3^ڑ(,=mvd1xԵ<SCls)5S~bJ(ڑ0{X+!' 4 B^195pʑ#p+bdz9}pmܵ;|8NwPEZ.ցhށ yr0Dpq6Y0\D4+?o CXXicX(eh<x- RRϽH(e29ogV8IۥvuNlЛjsns.1;+NXa‚l@zyjrE߄U gGn,u-l3J!U\+'`G& W7:5{r~dtgk!i]A@@  pS.v6Dw{;kLƜx`*Gβ<# C֗j@Q{}&Mҋ^PuS<=HRaSTGO/\\ .;P}ֻҙLV7jpGҖ&S(F uTC k#xX^ ;j$eDZAlfD0۞@= p*x&>'#4^ܥV] <RHZ|!r?Iwt4I_;16Жۂ+Q4OjL9k渄BL7.d%lu#"0#'4Pȹ3m,u 8Ûqx7e%Fp ڢƒÎϢ^a?APZ <:6;eѪѐߟꑼ5`!C*% ._0,M@jWE|BQNQqHY0/_2gf,uL Y]Ao‰y4Rpϝ`?  ,,H:nl*7ELJ23u\>c(t ܃,L nV+ܖEEfl+:XM)#s/c%تHߜkަRG߼S ٞH[iZ*evjW˗%ؑ ;杽-ti^T. =޵m5(sG@&x?q`6y*MO;Z6p6,2qP{|9B֝޿6!3>KU F]գ6bDgDm٬/䢲f~R߅nMk>>>kKLTv:=Z87߹91;kFjh* E.fcz7 b2C>z^ɄSUeC%TbLap ՞DP=zdokkF=n@ȼuz>m;#4u =6uxeU>&[ OcB.oQ`EUĒ9Lb {Z::ėŚA7l `jfjUwTp|m~ir5ȁ$ц߁z;; &:Z5K {ǏVe5ꕡGwss625ֽuI^h'rZHţc燈T~hșߵt^͜wMU'ׄhbQ1 ^`9s NۣadL_˼.ff$9XSAP\[ NjkAAKfr$-\7SOշ’2+'_`N`Rđ$əWr/_+rjlj_ wC{skp̎n fTz|=<>az)_w;.^]}zz ba輕*{3-Jŗ9kJ9fO䪬)X6eܖcfܭکthqQ9GaeΎVIiۭ?|zW|53Ǎ8~df ]AQ '0mJRD&uoZex$F)CL1<= nS?yplx|jAKEg,߽R ^%.=6Y#wg˔*Aha,Sַ̎>93c-CQ^ᭃ<Τ:E2AQ*uڻ;N$"aYkR鵧榩'doWƦ qCAM(` m!7-C. EkIm\i%8ſ[ٵFCZ,[W{ Ĥ@xrV)e 핶?zÛ.Ynx| Q,7uUrw~zA2p9/X*&C ~E~]g>0\(ow<}pcWJ;/^ڂK?% 9>9_rl ^x’*6+^u=溯i_щ[vl4bӇsޒ[I+W^Qc'vPK?_ic4Q7_N Lw^୷2[e?p^p“U?mykr2vutt޻6=yRw.ې[םm$@[񂎥O-{'wn9mm7C<, OmU`2k]E6~hܫߚs L:deb3c.`SV~ lq j-䮙ůxPe^]m<;w=z<m lQ=>g-0{^wry|nQuY~kσi_?N5M#Tr kd!d؄&@vÏ D/6}艿Cݯˑs6?Bh@j'] iPzLv ]fGd;CߎyS[מZMNtGɇulOzc۹([]DmE7j]A*&b:wGs;oztw?J Kƌ)RH֚>AFcmRڹKfi^B}ll׉=??'z"B^ΉEV.o<Xci[?taޛ''l9ӛbЙz_<%˾Ov!o:}etʆ[ɮ@!t\փ(-L8tdoIfƭ0"/7a~E>Jm>ncK~`1 ~{-R<oal(b6h?/,A[R%d!Lej pd=9ݐЊ3LtiR \OMY8%l4^=_-|WRN;ltc:߹*8E|`|c S^BQxH +9¸(|Iv5?4"xf-/_m}\VnsYd}Ⱦ&<0S~AɑgZ5[! Ml< ϽU(TJl]AL25kꓲ6Yjo$M&=/ Kc%iY~P4C=SW󦎖0>{C_]|ʅ-~VMk C'1c>"Iy}o_pKןu([yקּLJ/<7gnאU|N~/G&\{%W>w7W'u|=G,eӀ(Njt]-w-Z0#b={b7 v6TRPa|:'gn$0 n9Kּս"to~`voP]N<'uMg<3$3DlQ( htl\onsr2U/<KQ#<wM 4i3f+cYZRϊW_eV3jz鯌oN}r3??B;^յ9M`q+zK+!W!GT37dRw١^]zJǒ3/g=N"-.XhqcSooǮ鄴z+&Rtv߾dhCቩ[]yG] .3F/;<@JlzagxsW.d=koGjZ[A `Y`ZR*TgfK HR*fl,u-ֻkPT:PlRKj3õÏP2NNY聄ĕ#l M}¶m &DI&hmн$'ExR>;Qh5u9BR7X^+2js ;]vA@T_wJ7I###ό o~+C%EʑAFTQ*9Z݉俵{\5o}lw VHF̿Z|^oogwT#O" L AU.'y2HUK =\ yk6ߊ䤮`?&T^|p@Ίʧ\%iIfJk CULЁ2R?6b6\4v l<2)rhd|r!B>S2FȥGj-lY6rvV X̥]*9ϔ9w\z)I'7u31]EhZ[@IctTZ"dxC{=eL&'fَx+s/ `ԉ ʕEC(bcXD}-Zeߡ"C ,R)_#Mad& "Iq7yR&V&k\&to>[:.K7 kv pI3,.;L.̼Z#Q= "|zrM:l6yJ4'7Xɒ>āI6u<6 H@G0|\.H‹bc} [L|n7CFgV: Я&`e\y0jФ,7.Zt4dƀ#YB7>))STtw HHHsr+.yYg\ؓ?LLz׮^?؟Ǝ!hwB$C/l _Է-+ B_l"nle// )I"lPq;Ae.dz4Z6=c Z1 +X)G[dRL{07Q({y17K5 u#; 9lzO0Eēxx+$CihbA{] ""#]zwa WL*78wk>* LhA49oona@:ƜQ\yn(6 ?to=C73*bHP (JK7 1пWګ޴{7ΖmKZuʚ [<ӺLLMlڷx,DMuiGV[a0h0.&6Zpx] f,XEC c׹XŦRS1[Ck !'mgX}9<ҝmXedȭH2.EEP [R 3:5 i !;-"}dY\B{i%LCޙ gAҔ@ s5X9Ť]+;"29jX؜g$gX0~LnYDK8_8?bْ˖,DmnCvi6DS&`nӏA.p!Fa cgΒڗ+syLgύ|g&~M*dvae2̽gl Dӽu WJ,1 m +}NIl㖡3ڕ%\Oh0SS)K(jT۟K/PZ&šYH} ݐVR-3h<A24ᩁzH2k[9̒d,PW c"_!EJ@xnr@H¤w`5 e?cGHb]k:}u{L1qsς`l #33VS6Gn4J[cV-A'/d5[%XWcH8`!i&JNgн, ϧ4;PxWWEM;s1,  !Y'=DXqQ"9'f%>g.ҼXxe ՏVB 9B.Xϭ!W!AD8 C1ԊZ:5} Á_3Y{RGXA`R V,䓍Y_sCg™)."!lԓe pD-o⹨ , ЎiMƎ%)H%,=o.MZӮY#ßMCcA*!0S9]:v:B%pa aFz=Yv[ig =Wak^V#$yC D1@X 0Mc_RNYTJLWC\"Z.|$^Q@ Q), f@fsn.Ϯl1͔CD"`NenW~K¤hwwA>V@ฏ:y s"J{{:+/ƕyhl=uڥ};r7ָ;WfvTfC52 /Ć#Y#C@fz(Q(penNK4!x|E7zOk_d"PKד6֯ureO'32Y.5kcBLkfUa'$C "߈-)7wBb#iI m%$Mt8nŌA0-l^VPo-'A0E(RjKLȬSKpP/ $x%o|6aVwt Q j9NIQ DHu3B49vU:I0?ӽ/EL¢`fqNb^b\il0H۽S,fLAX|4k\c\<aTiRXm'#g)-|j=% YY]hI$x@zB-$rUI Lr% DHZګo< ig O&Hjͭ)lh|RR_B8"@+s(+r X:vp+u'~ "=8)i)ܮ{5*a=٤=עSOZY E4 ^! tf' fw@‵Σf`'<8+l )\Oh|17)~}mk SU1 !D S gQ*BCd+nZԭLtSO%EC1{] BU9%/r5p-3ymyYU㇛c0u x}3`  *Q)jVNd%$ti{3Kb8DzPg1^O=6%* X0∣1$8fo)m 1P3jH+˧S@R,2!UmX)w,U*U.Yrx9lΫ"H O0N?s r?c&`Q$rZjlى'N~J=ǥ}FPU]Bmw#Hr <[EPU/D\Vr۹Nb2UY"]dEH'㫔 |\H!OUbØ֜j",KyX{T~m2+Qѥ\K!1At$XHT* Ju\jœƂDSA9A}e2aȠ^civrA`SGLADpY5s0K%l4!(1U0so:F8L&Y1@|M3&7(GIv. Ϣ2_\ΎkYԸثS`TpH Cd4)-ARJt D]-{jk*L)MTXC-T`{fcT@ՆJqd,bZR ژKI ⏨?]n5>" k#J}!*.Vc[Hs0HW`\ b*$"'C[࿂03%Nʝ%"UGIDtk64~\vt]2M5$8HP##@/g3\dAO&~z"!8ß!qq:5hx0ň!kN055PilET#!)Q qm4njliAC!Y璼ReI]QL$:J> "*^E IʸDeEfD58b"^L QNyO! y\W%L *0(ăBDȧD1b02$⼣}8\h Q+(1!p_jbbE/Җ^p%("g -KCƵD >]0-42Kǩ\Tb2T-fD:zP$Zf6:]JD"tROW|ɥs}H#)*^IqPUS^4 d.rt 8JN+d|FfU BQzvvI:~єS0D1IQw&2PQdj֨HT%kuޗs/3DTru:K;QO9xzB`mDNh0eUg1Tz7iLYǑhNKA"Tu ADHyZڠݒȬ(uGO0)O E]4̢R+Գ)9"hd.=eAXU8{+)aGV\+ 5A1EQl(JNqРM)4ug}R%*CyqXyb#¾VmQFrE-!dtU ,*Σ@(VHYO~ "1[4HnyAS)DyxP E'B HiҊbTaC+,rHJ " ϑ"2 'kykEK✎aP'D%=TR$W UepPn5G&4D7/.J-sH5JH/"U@T" Dȗ?N`Qi,6&[$(ysdɕS:Hը̵,xjŃ3ox9dB!x1X{ ~@Ot:IA=_Ej1Y(zNDr>DLPݣCh,YIF,ŸQ#"M81QFN2q\,-0#è>I{+QhN, pB{k׎[&šrFeplC<ľTxI,0A J7An X9.B"K!v|O 'Cҥɋ`2xTO/TГt3+%٧U -#34GjLU[o,ӧfPGB|B!-sO\HF shyǦϕ3Tt#DzrN:mCD]7S%EX|4c #bƊ1§-<%PU a'w(/#!rɸ \ /P!Vp.X iQi <'E_RjkLCA2k*!хX*i5$~w|uMbT׌Պ-/%7!Ty/$#HQ$ 5Ryʨ| :)ڟ:}IR.mgm=xkuXF@w7~σhRV.ms K Ew/H @R|^ɵy4<׳@۹9EoL5y( rP))&z$z2K2cPL v[f NNU(Y(T"Q"=KHv[,9yvR&0㛼"k!qtRY Q(Bۑe0P|ȖL 89kdm伟bM+y&hdYU1WCTNېz_$*"Lȓ1# I׈;SiK"l%FQHNi5ew✓gL1W2 8HT7gZKyD@ΠVƺ]`qPa, Pgg,Cq $!E~+ځ|O-?vSݤ}MQ1>ĨbD֬ JB+(~h3PyV|enX,?93}`un " M. n>-&Lj]O. &V7HW}d =2[ 1!Y6!byXRN< !4GYD BD2&2KY c@ÊLD,ALagF15B,yي:0r+E$0v Q> I c|%ݬ >plfH`E},)G!sUB1;1o+დ*T!(!;+ svw :Sޠa T@LT5ozp#3p^b_aL־y_: A%HTZT?sxK!xx$I+u(xkq.АO*qxΔI?bA 4:S%λۖKlFͥx; D (,>U|C ],Y>o&>-Y,J v0lu &{JWy2ZpJ U@G5"h * ,.B0u69Ia5}"3>M<'˒#+BJ~KW*:{衫Z>P?X3;v{Nl)]y➓NZSg5օ)uu%g%헜~BS(-tr*j(O( 3q +Pgcչ,-{vq$=S-\|| ak_7۞XdKC r J>D5 &I<>譈1]폵~>1y$5<ܪURdJ,P bg K%h^I§$!@b L^ fRdFOT1JT`0(Aš B]4ZTJ(w` Y1ӦDbk{_w]xn ;-mF$f ͠[*ߘ@>JwrJKkbrg®ja;!Uᗴ#CTwA 39lH;WL(y,kRltg߹?/m8UM&F_` A\8]Vt'_ri,b[9d[ʓs*itBR_&k&GZ[a.+; Vg04,L @hMĐaDˮy*y'(N`A ~5)+B,4 3ULE<"1|tl3δIKK#>x'>}x3)l/<_S9=YZ+ԇfݒL@84p ߦAsO~r;-cJ66#~6-7nL`7\ $l4a"r,Eԁ8ԺKsx{jVe Cx1EVt)@EdF P+- {B :6tl[S(s 1#Yv ,yaZsWirIʷMQT ln3N!mYӱT+,vXCcv@̰WE.H<Є$ ^+#eăTd=&yh%k0>d&RɝrňA=E5XRē*^@ "! cKx=๺VAy$YPCX >^?ySZ~]2bD](/M3/SZ&gDrg5073LNANE;D6Nl*P/BצmxFo.XY/A m^4Y&2殅@dZT,n*rs7b|8qݱW:b+ޤ  !`g!1B4|b: 2b,ӥ0YDHepMKbj$*󯷆;jfXZEv䐪laua'Dߏ7ht2u}ږmDc/1F4"450GTUK7=pcڀ[-Cjboc0XMs:gu&w/nY*(uFӧ:K)5DsƂ~6! ʎ;Tnom^dS{Ӡ?XbA0q.@%3o_J9 Bu8,}bg, AWP &ST:ݓ ڨ !pc=iS) VXݹPct ²(y7L3U\[CNVc#01qk;T1Q;, uCZ Kneūmmk\'Z\_4#".Z`! o\5^dj[;=;Ԋ.9Í;ӞYR|QvQ%*s=# !a [1mGF"iGgkAUz:Q.Uue3>wSr' C4Y!T`k\ml_锛"9''PؐU`:a);ư\v&V+h d4q,Mb1V9BzEb+1 RL7i-2N[q['UB0MX b_HPVϢ:lS9m,w†.}H"^Fr0,'=F '=zhԀvgu oSߤ ݢך Z[ 9&`tSVRNh#-{{}o}(1!wNUY-J/@ftez78sJK!=UN, =pjS3+A_,Ago1Zo5M%WYӡQVE("6KlXӊShЙMƃQX*CNO`E?TMESHNrհ@.Y~;ݘRF]\p>t_C`M; gíONta.],hd@‚M6Ǫh BOg4"3q̍h6bmHP!Y%VEUt HZ)09KQ/%b$KpEmzH@b@{@CWE!w/-UXqC7Nݳ27QZ.4V-mA{'tFmVHZawyhVנ̤1 qj, ~zA[{bYS+|BAg{囩4Ԋj3GU,Q(&vzx=m8h@ʇ$9 \E!$^=E'JOkkCׂ inmZ+1UW V?2 Ş{7+*S Waˣ]PX"9逑ǔ,^WHj+"%xx}fwy$ {'G<ĕAöks ˜FN%n.FX܃P_!kAC%+[}JN$"e*5nGrZ#NjwV`xÏA|rH):JZjFfhv:5XK sϻf`J0Y*Uu {Li=#\(36վPOʬxA`EgSfzT e WnB~4AZ(. lFK=Cc ߜ@ntVk2'K~Pםt3hU:o[vXL,;<$*mɘR-j"Ch{&8Mjp&CƝTeVv5=[rEUYF6W4Tϵ O7Ԅ kZ,4a+EKuM̱WodqiPۑ˂W4< IHۋCw,,Yeb+nڕ'SHgǬV`g/׼|whkg^<ӥJK,D V,:\#%((醬cǚ:A& |ൻ(pp旟 anJN,8? I\*jí? ֈJa.]9(S4LT9t 3SxV\(A ڛ&0JQ/ MW }EcX9C\z5SZC[N[e3][;cIj_-t&+\\Y-f*N#P/[*,{r3tϞ~֊_$ Yi^ʂK/;GXt07~fP`RJMdQvfix\GϣIV==wcMfN}HafպJ\"%~ӘSX_shcXkHgj;҇VD*Ay| dpe{rف_({?#v"LfXUZ7L#q++#>Ⱦ7MV`*JȎ2|b/I(vtkó@\k$qiMv"N=Y>&eh&_bF $ޅfí;[>-/٭-CO3 "H#DnN//zgp%=вy0` y ` 6)㚊]0EBޣQ\äYV:V Nٞ?bJlZ/$Ic>_dJtvE8sA^nTJRc6Nw:;@, $5 -mJoj9:}d/"M"\X@@ Q a=MptǠabA\7QE<6c5| Nݩ,,#^g9.Rl>.6a3(KQBJ6b2b pVN\(etӅ9{Gwl-9tb/wl:2R0 l"ZPb%IGW Tql%sZ1cn7[~Ϩl{j5Zrso%k eᖍ3z /@Ƙ5}~Ē7/,S2ٻwﭷ޺{.BȦMS_ٿo߫^%7ɡ/}1vٻ/dajQz,#(EJ+~;?> ! |kr,geCλci$Bɮ|"6 XǑ@T U["E[0ga\]b{u4T-.[C[K'kEoP0VD&Ϭh*x`ȼ_. ')F eh4P G^PöE'T Qd=,.X>*7N7K?t3R7ͳu,A J@ >+(^'8*0ؠ.{(X&kM&#m/>biP0n)&2z^+z=BX&+#O>yѣGϫ!cE?ܼ/ $Ǡ V5 X޺^ALv+⹚舐N󹻟==2e 2y6Sԯ IJOe jdބI+a -[~u t])p^'6$E|Wr23^%3٣q;rR6kU_ʾ/DtimuhǙ9/+/4h wEVY_Z5ܽ+g]={Ι˃aL۪&&(G|>HLح(2d{6]@Z!c##A0r,ŝ V|c~g4rYcD Osk"IU͓#xo:qDyY]]pm_WǷnݪA$枡KvuvZy\0gNYWMБ2*D9##ntR7<.cFxġk/+EB1WE;è[KBfjRA$ 2*DA,X)Ԣ$e(F7X8Ư,?IEdmF&%P3D$U^t 7mpI!u7 b&Ll)[4Tby>;w?纑ʙo?:uU sWT'_kЌr`.BJEBlG$Ia90"E6z[U/m,FyK[smܷ{YR2S}tMa儐QQBUXl1F%A j|K>Hܡ~rruOD)5 3 NWOvr+d枡kNK䛄"a%XAPJ78^O.O,=9keeAJ+3KVWs69hc'Ѿɕb2k\a|H  $ܖ ] 4! )iq %'܄S4+萿"a_:3Ӟd{ POIcmVj,f=/~'y,u 0!8n_8ճt׷]]15ny4œ/n;k?¢RgAalwgo#vflD&$s&_=Ű=YIIa0kٴ}p , %>c'_ݻgfzm? o2== ؔ-~h>rhNiOkyev+.%7\ lgmd'vaVHڇ;Gj_JA<d JUJA|bԫ!D*l-4!fzZ@̒y(=圕Y{çJ D< I{a iz .5>x 6M oΪL>qO1'1tw[.mM cIS#FzHKS/Nuc$Jǥ8쉭V\FR>ƽ U&޻r8yk4\~ɇ'z-댹ַRmlp~=ѻ>0Sa|K_81s-o}7h4-o{q ;9/7Ϝ"zqhKWi{Wy[ڏQq*^DnDMkH$*Q\1WǟCM׏ʹ0{/q+7PYSj@T'nsOI6J0]yN7ysC[RsIL0^<+?y3\$;fJ^KN $iuFi3mFwR:Ş<0z{_> jRtM_r~7^ wu{i wu[7>&''FGFʛno׽N84(}b֝,>8^3A"v:v*ߎR:7wc/L J**(w bv4WGF)3S1 b<I2"nZo]LBRA斠<(#d4  $k#攏G$%7zGye?!@U&_>}?5a@̵9U;{9xO>CJI{rg3lΤ=QmEr{_WYx,ӥXԻsTw'7O~qPnDAvgwN^z*gꘑG}'(O~^wԩ/}KooMccesh1d4":(OR0YHGRi..N :]+?QR$ n*:9T' f:BXVʋ%Js}yPV_8n]C!s:Y9EƎ4w'9*%9FA>'K{+uYPKy̠qܝvi[Rp'T6,αYw4Z>Խ\{_,dGk7uG|**3 BIx_udк**8Q gjt4t84v*usciR'+Vnjnb6UÔ,*P'<F=K¨RX dj"͆ EXJVwDd<%|s[/%jjVҁaHP?(#;V(mEH:mL@"t~+C~sPј3w *ҪW]VO'k7Zp3ɗKcl]rY 8aԪf wo?6@oKhb$fIZTWO$}JX$Y1ɉ.Q8E 5G;n+E9#($z*S _3nc\ֺ ɻ8@0s4e;5~w>!_v ک(l[t Af!湰@ /fs9/:@%+I 18G~y;c揖׫+DM_~Y `?#jlqm={{O' vW8S coz.+ʭ*L2 UQMlNP#!6z,y/bAW^xJIJ̶9by}ПfR:yO[5aNXکHBՃm,Zła=swJu4 h*aJCLf2-hdq쟕C_f(Ao9hth甧:O  h{~?ON5铛x{UWu>WWtNLyަ~/&'*Xۿckܑ4/v?e8PP:< ,QKU^T)KImM)tE$GQ 藯_,D2"_1T[j f^JRߋ>)NXA^p!ZWv`0'5i%bC.TomQKrv=ysZiIc'} !NmwڙLբ`a{ L=Ϳy#7]n_xzӝNgtttǎϺq '/=I9Iy_lt6˭'w5&O)Uo$ +Kơ4GK(Lk5 u;['[WT}%tJs\ *TЩz;9 U! '~LW ETH,,x-K(N$_ Jl֕t3y˞"tZ6HJ6&1 v0rAe풟5 j^Xiqnhv&af=Q5^Kph,ѝ?z2.mg`Cd *R']v%IG:%~ b"<)€:hMIڲ-6=&8:Ml BWcKϰNwQ)dp%;/٠uA*{ߎۧ _9uYH2Vu SRfi [j~ʬbz;؃ӂGŪd 3d<#ۨy IaOR눔V5ï;/.5Z=w @e&;:եWow??zkCXfx7q hήdZaZlìԀjŞj_QYRL=))dJG[;$4 R֛JÀV~n.gH`z%(Zg vOK6}?z (Bڞ36>D&32{I}9闹u\7–_/I ۳ak>jBFW-?GD#tSggܽ%vgѻ||e\^xб<5zPᅠ3"޼_\#3EY֔ c%X*(C5XBB7ָHTIF<9YRH*U۬3lyy!paeѴN~%K+~r&N_\ejUd|Yo7zx\x2XHiiK /GiW#adjiϛ:fe[aE9os6.ikY7YBg5Tp~Wn65q ;h|sar#}MG{'hק~N{*,;'^LfMΥ#@.wJJH10GsLGsQ6J<;8k!AE /9?9]Mr$!b lԟIAS{v[RYQ5pi?u}{򳠭J%F,y[:gpbI!`Z=3ѣ3yz庾c[SCϿKvnPs7I8htu/|nqFrɋe3QE]^HD|J ';]K῎R=0xIߕG7DMZ@zp1~Wnil'L*U>śO~PU =ת;gbQT̰{fc:L Fܪ /5 u+Alx.YՇT 1t+|x^dm'|/)+z0so E5Wk ߽=Y4 m9xrֿ U7^4+s9I>Y'kk=%7L3xFKlbJOb*5;~ώP" }^=_?G&]Zx7lj ̿yXZ@Qup|#Zja:w!>oݪ _f]4'כßSf@sk̢ Ѿ37#zip7{%BMڙ*luh5U8{1$Tf^(B թpedbCEU:Zv\i>k ɣo:w0`b|H|d|q1|Q[A͑knËlZ*bo_[;Z)7`uLM*}7HLpCID\HF\K QJA2'︴:>^a=iS׏>Z>׭wà`Xʳ :( s>dB REA҇V;j|7uZ*gya `V3dV=( iT\VX16ycCР6[C嫷\laʼn+F{pdb}~^(X+Cn~4qJq/]-4Gy{HTT.m5V(`qL}dEZ%V $X^)eq?VN7C4 Rhz4$ Db)=x)XF?t4xϗ{?Y%}CYes-O:_<A&u.wctb'-q볝Ɵ|a6C ~ndύlhRqG[K)i,J'3|f"a &Abҳ> kL\>mvNyd nO+h[xW–˞6^n5ϟm?ӛ 0qgW =Q*Gr\RDY%@:ҽ" )$ڊ4;ϵ'좙1!%R l6I}7X=ӈvoBF?<֒+s]_wf q4EҌl(4r0Ql p` W`Bl8@ #ȫ CVHeΐYHn~v[Vݺ& {S}}q灡Gc<2S9pӝнR?ַ_?H~dwRJg?%lD!D-O3 JsPyIӓet/'n7?_Ԓo;:45v'eL &i 8Em {QkjɢZ+Fa̕{w9[Ge,^DLw' IhbkqPb?7o^{zy?1=v?{*^n>LL\hβ&Fg9쭬>#tw]`^IЙǝo}4h'5(؅5}SFNvS{"t"e ꒘%)y[(YJq4?44_XɎ$K{jv m'i@!e" $K3R @ ޲&1t’dL/<]Sa;}-0P1A Y,a7?$ oK~tW^Olo%3TL3ʴ4Suy%ޟ':d:IEлdzʤl+w}D0~`)\Q*X4&Az@[TVj=4R-d͠VS~K?_}k7Ol-$ {aw7[ @FȈq ys iG7Ƽ5[=xPI)W=!Hxbȶ;4K(AS+= oj-:[e9!׻2[5,ݽz8>hEi%,F6iTlqM H(](MiQ:S/oo4>]^?owR DՂAiO8L4# FtfMGv7/n^\{F}QB$FBیQġxq⏮\ӥt곌Y^(*q@-ײ慿l|~1Y5jDT6k, RQM0m^Y3ErKJ;/}|ge]>Y~+gOK ~V|QO(UzL.J{bpB :|L)XOEB=}//`"c $|ҟL'g<#IV@X) \,Hi#zɭO &\/O`xRbqBa_3%=޻ O*,fθbECUOt8%[ϘQ/l̰f3Llu8s//O=ӝ+WWݣ;*R`w&v i{*ik' xDvnzI%kAg{ֿNTy@61|7xc_ 6-ܲߊw*EAjwK0 o㴱wϖzSޱe*,Kt9w^>~܅΄杣{rٛp|v/?K1LJ}F_XV|`TJ1IoLo6w߇x6W~-@X^bWe҈~  3*GNY +LDiQnܻu_d{6jQbe co}l/<3Hwj;\{ [oyN׶P'hSAq#Y/ݍ2SX#Awfg7攚))yxfƩ]\ӭIz{oPN2qZ(^Lw"u~*NNC#lx=$<ȼthp5~şX}'ZKF[m'}cLYU*,߃A¼YEwi<Y6Aןu(`_\1qt<kJ^^l~_y[~sQ2LWײ5ʏju 9̈2o4Is7Z7]ga1mx#Řhrɻ_Xτǽikߺ{dtۿӛĬx'=D9MD|,ߖ#ow ZkC?$:IUc %)I, 3l&lcaNcLS.婦hoHPYfQ;[taȹF bf҉w㧏D"jH@#lTb_ LϞ~3+KAS,:_71jSQ qiVC!iY1ͭRE,.M|4#9C [J<_]\O#@o#Eh@szO*hP]Z_>=:\ƫqۋZ^,a I$dKAw*0eP+sodGŸQǝ{ke NI7+C|Ȁeg,J^wֿ}?DϝύϭUrsz"x rDꠚyrEt ĭͿWINу0 X:!,R)3 ^TQ%G=U/ELdr,Ǭ2_]QB64 yorx˪XEs0! \d K4ӸΖhѨ=TIF,Pȥ~5ak;hk*5c 2l1BO︴!çO/mu>2 X7ՊTjD)I*ɧPi.7Pd3MM9fgiG4.KJ@R#M꯭X'-Џ,6F qfS̅erS܈?ϟzLkw#,%&OQ;Kg'k'\bo; Xx4O;ӥ+~3Z>%mzڮ}09Yw_ F˿O!utV\IL ӌ>Io4 8&,N,Lf |Yk&+fFJ#Jʮ? Z9r&ePR*0ɀի[I_VWA Hx'K8ϧfȐ6O"Kta(+;}AD@FNf٬HnțHb"C]]3:3_hH3\?y7^10q`KGChݯvO"%8K NB V =*}$qVI-}K1%ٖ_x ;ԮHzbw*ɪL2Hޠ;eZFvg.©VpakQ'>%΍%&wL^s`,<|6&iOu?Z-rx*!́ce𩲀!B*'K`J?q2KxLxY;h>jo9 ñ7X4+ CA2$ GTpDgYӏ[zozfi|~mrzezj9t] X9c,H)6LUi]GMF-,JbVt (ּ}nI'mE^~SՖvɖ]ܫ^loƩ|Y̒0:iJɣ2 (,@Ѐ,Qm>ѹ+ӓ,#SE[<4bb̝y*`PP G)V, =$TPj8Qa%Ev:MH [:; -~" Ю 3NX(sX8A'PC7**=$L3-/?۽?zӐ'Wh $|Ldqs^8J'29Hg۟9}˞JaU`P/| z%G>MV^}wл|n /Fߟ0jnGvLc>,kHaLzaʚA5b(I^KfO20L̂F98Kaڊ6g^oX,kV oQO BU,ɶ0)uapDM~ɦ >r̊ ^{';i!SOAR?H,mQ;ͼXRhe`+a$͘aډF!xT2=jeؚ)9r4Y Zb ] &{ACA(VyAAXjYd[ǥ6p{~2?RY\UdiKLx,+:̰L}ƭ/lꕕ`vYasŒ' Ј JILD]= mϺqOvޥwk1-kbX /zItkg[jkԆ?GS?eQY~Κ~NΆ6Z;^kG ̳W'S:Ya~a3l!F?}@^nT87vuI}]]3g1`j -?<!l㑇 9[މv\?ն$;3쎓$#Fr $tPf?A.fBTHo ҭNT- R10ƱU",,h 3b5qPUR'LD}Y#IT0 [T\մ`K!_[ #8D?ʒ1`!WeOB6 ӑL (17aiN϶v 1~?k4)zL:Z76Tµp4a~kp̈́U$êTCk5t#,9r}34Il+zgzK'|^LJbSJ q$S1Wn=k"?Vqpn`wЂJR7!!Č.pigZRkV3X`HӃDVM~ ӀOsÌ1ճKKoŀBfB&G0XeaN.tf(n/T95x]=}gL(QZlY$iQRؓ #@L}H8&+xgRca,fU.lɣHC[E(>cb)xSQYi$P7ybq8){P%9`yY9L̳*i2VKd#_<q'I0΢F~/'/Y,rxLfӥ`dU~2,:^,Q\Ԯo69P(@JyT['a C6ǘ|?Cs^kMk,8҂U/, 4kt}r}^1=fݠA|GREnP QVnHH&ɄBn `3&'CDnpP6Z. ]pHl5r+L c r W"vO䰭'ISP=^B$HYgҹ)&QJ*Qe+l$8ϳDO~nn`L Cc󬀭P"'‹2o6i0nOEϱ.+=`hjOMw{$g|}}};?1%=H5Q`Ѓguƒe˶&E9AD-"e>WOf8ϐ ]zAͳ¶!+Ԑ3Z À|spbp$%BiJfm&GG{#?Vp+ePs;dYd!Pv2K;tn̸͈LcA*:1”CCm>].;HLWA.arkDsF9RF9 T3ՒDFHv񘼜*$دT'>V8ᾔ,sm-êlvMd4O\po+ZS߻Խ,% ["y1oEԏ7I²pN^=صrX TcNR15(֝nu.g(3YXÇ!x8@(ʪbX+J~C^GuaHI(. 9]NVյ[=1#4#c bYCUKf<  0I m\ĖS%VLA+ *;@Z>ӽt^SH!KZ`kbrH=L<}&&9;a2m߼bL@ZAb*JE-`? >s_d)i# $`689(˗ Ir ^zytHO"n4`eRRy5[Wʕ*yGhŻmn I0lm~-qS!|.h0lּوW'?m)U2xŝEB>m6{҅LݴHOuBFDI&QX\x#WN.lv_9Ѹ}{,C9ieatD;Q>f@;"GIgQYNЍ+[ދyxHA26Ze>=KӉPeLȬA XBTNv6Kh}djdS#H!ȶvB6j.p(:4 Y_R-e-*nx9{VqX9kX5ao4H+_J0^ m"pb"xy9L½;[;_*C]LsZC0,QȺK[o,aFM4"IZ>XRSx/6 Nf DT_acf"IEwX,L0kL'A WzoezHK欪WK W]hy8Q<:)̔g5P[bg0O~:a޽QԺ{ww{o &T+[Kd넌3w4v+Kg>JҌOum/\,k[5@Uߝb|)%EVOU6FTK*JIf 79;:lib"v4Yun]]eBWbYMbVIΞjP+HA3kDAkq<Mx13*K̀Z*Ao#TN3N)% rъRR4xh5% X~,m%aYBT\ozumEBo&^z}pbZ A;=8eaTF;[2/(W))ϺZZX߾b!|%he[b/6+ /Noo]7?7sG7>Ip~QttG.i@ә5,WZud=ˋyj0Ի*GH9qwdŮ+*9 Tq"HG*CCdx$e\HFD1Äɐq]S{6vGWڗG=dQg7a`^ dʥ .-+uIΝ m YF jE"TTj(#JRE 2E=&8 J_6S tNAㅴ1-c1MX?<5"1"4orB/RČH J2,9dȔS1NSE,ߎL`c)smu+i#mCpWp >N6^?w@JUGr |{ .bX_ͣձQb⬹6JB E?Ycֽ>xK=ʭ_KOÄ-8glj3;ʅЍȢV]7&[ji"0 4"%ʙ&9 ()zWODOA#0Rb>6l"X( Z$i;S+?с'r~ktQ 1K3J5Bfkc+Θ jGJ]ܑLR4c~m qB!ЮLU\0\4? B7#lCBA> vZ.G .=F a D)n.V]Ʌk J  ,Sy2xrѦ˳tc;g%@Yp^}]Bi &R2B:( /N'*AVt*[JEHh PL.6ejZU z0]Tk<{>P1#e !`|+z0O+P*x9Uֽ%QIUC*u{ B_u#@xw$u8Q nGV0a-"ZJ ؃{Cg ww_[_c!cJ]pˤ (!A%TFfNcȒw5XjaT!Z#əJFYpP \(m`U\/$˵0+G^8>-JFa1TVT-[tPޢ*a)sPP-+؂! "7|#42Y0^!ޱzXm?nR j@-s q]oK#14j^<Z Xͻ}>McF`~Cv~=$K҆^&_?~ FSFpr |v'3{s9z!Y9=qiKh,sp i35+I#e]X!ڿ25 VLوQ5hT4f6ݨNÞ"QbX9>ع S04z{{- hH#4ǠB~pHk7N`H5SK͛~vp޾׿؉ '^Y|kNCehY\n0^d"/#ZF_l%^;Y~kv2[H|9ՙv#sAI2X6ݦ8R_z8Y֦Y̴# )טE+=ff m Ǖ$fv`J*v :T'O382y8vx [<{JjX95PjO2ZF,V^].~"@+6r([ gάSg!=]h>禧gʶyս71|I7m8~Qrvʽr]ȃnܲDd^ticy("`C M̮46gvDe_+!+hc:,+Zbd5ƞ2֫ ,#A'ZP&L ~:iA]b/Zv GЯ<X19:cT$ϗP iͺOyj4Cj;^y@LJI5\+E1"*\W *`Kkӏ M :G:uJ725SeZU`jסlB2/ˈLC1襤*%PEց% "l*_fdZP6#9SƆamrUAܝ50EUFr\Ә[e`wYMQݧ\q#t= Oe\Lʆƺi8ׂm)W%kWDĒx4J]&J5h=73gvK_$Ng.(}jzց<H2t=ڟ3\`KaYǥBmȒ;u'^-4C'$a&\:bP WdYpc˕pϘŔeΎ5U:&ՀK.+s8JT&C +Ǘ~x>6:u~]$Fipw!$H v}-%0%RنcK{>]-sw1 -[/M5mӎu&=4"kntK{d!]~,4 wDlOCFy~=8 Xi1࢑]ۅY%E!&FQ&ݓnLّ84^~@p Ңv;m%'#F(ɬk>U`0f;Y^N $aue7.^D:d lk( &LDp?8fwC-Qݙg10U1Ll!YGzFn*iB`Ar?iBSrMMwv$*u51ΣJnsLXf= I[e[Ⱦچ+\'VjiOf@A3+YQ*k>qYqЊٯp,谔Z!]@lPurhzN_}!)ntwXF%V4P1.)TҰk%Xa(8$4U䄐h;h;B2D`}qLR:3g-- rwm/ /ǀS- +kTTɭ Xcͻ(p lDpڍH Oy& OoEDp}ńI6xfO؃q$:/tQ^HH#侯dwQ!Y 6d`cơ7ud;m93VA6!H TA Y T%$$QPP1AFP K|Fzd,j!42BJC0:Do&gp;4+rLЕ&g*T5aCUPhQux}gB=+Tɭa;Cb@]gʹ𸳹w ӥA)k[F )LzY} s}7NӶ?7z%-B_%իEOv:jt]v.zpXML9z$*vS@c 4iY-=PAB$ <:VW'z9d e0)H2xW )\`jK'ija ;) 'Hdvh!MjlItcGSjpWyq|‘? H;ji}by"t!`w"zX?zvS".1\u1Eь7 w3ߠdJ@7$p+rRNNd'qv0=YWr~LmYdҒ._t[5Q`e5E pӠhdí qFIkuL}SENt\:\THzG 'VX)%i;Qzeg{9$es3a?V,6B\{+*x܇a]܂Ͳ]7jb?g1, >74뼳["Akj?7m9byi+Mog* Th?:J傂4_-+v*TbZM]fd#nOC.RҞ;e4%"1Nj_bTf;!@/X ckY#]xk.0?#nÇ({_ya?IENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_bdde5e36f15689c1451933f92fd357b3.png000066400000000000000000001632411420147000300343050ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx eGu'/TjQ .,`f3vxo0n/ol`Ӟ|a/lH*]Uj_r88'NĽݛ*I=@_-ƽ7;KgG`ذ˿_? |m$"Cya;C RE?r?/ /YtA/Ed:_#C;rwjsGe>rgqOm9+ .›$o|A\)|rdw)|7 obD,Bx}?kTOD ߺ 7:;jDC[~ [TAQ|8H&?AIb_P?A6~!|ėS<] y'OQJhriO>OK, "r_sm~($w>Ѓw(8h X-k]F f擄E'<) w_ȜD ARO60f(PFduT% |6|Tpp'ŵa\HTDO@6 cGUUZmVE0 ģpCWBmd4 ɜQ\ 5qEMy⼵ I.*k)IJGFF@3F*o ꫳmOY4d8ox5 fLJ ˞z XqtR))z{1gqe(@kGxj%P:H]rnSQWA s=:`3%TN`5SkQbY BI31 tkySZfF%rI"2JuQrN[oivOԫ)JD3Q^_cŚWs;:|j! ⛚^}F "vFنrp/pOzALt1z6ʷUZmJRzFZЋ?]Vk%#?HTPUAς&bLD~&-pG)ps(yjr D.m2Uq6%P%fQ*ܵUp4C8!\QJL'Jv"!`!dT!ʟAbltZ6jvE/r7Hq EҠf3^Ir4-=h*rhBW~ ʒylʭܞ4 )"` 5: C<)=I 85I:XX@2ۡy8 "YJ[D)%v h , Ϣ?8^"0FVgj"Rhb_ @+&ObP S,IZLr1S:dFV(#QLqit#*F1"Ibm)?b_E4 8 -! %i۱ԖL0UHBM*,Vku7{b U"H&"gE آCse=Q9\nJ'%-&AQ@Ԁp푪Eٛm ڿZRBH6ubTV(t Y续j-u&J^$ƁIhc3w~D S2=MaD8H/j$,S- L-5 ) H )~k* 0u}2DR4^i;(8\ I. VmNF0Fw532e1YӱDp"U )(ƻ#'v HomŰ{ AQ)QEa= 2$ N$6P6ܒ л)bf#?SL),s<ʰV[#+Jzų!-sL  (0!tcP:(qS 4iDQlb%'c1AaYRZyrc7KN''$TS:H U!AMlͶ X/,ꍊ3UmI)2&_}l dH2c;/AIEmјJ>SRV!qJ+UҒ`pϧ0Wv&ώD(?FboVke1l@(pOd~+Aa= Ԣer4T4XK}Z0bty v(E\/i, JJ X΄aŏ C`TŅ$0b.(ˆ eb?mV[*hk$N,k (ugJ02%ia4l7.TT.aCàJQXL"rDz%eK%t2$Iy3_(PbBĝ "{*``[yTL'ulsHMI@I2PVUeU@t]e)@ GPU9@$em$ݐ8/%3 cr1(&jt$zk7#Q$RΡḃKHF='mV[Rb"/y9:iFki>HM0*R14!EUucTCt?XYPuUbs*7mIB7-wzȐZjHeXu]V^Ll އU3ݝRDrTXJ0-%N# M\dayyO}͈@.O>6@IqM˵L0DU9IP-٣FI`JʷUBnĪg**zG)/D-Qi);H(rDSuŔ2%HTxJKQV)&9p1X9Vj7@v\FL&j;[K4*]r%}& rm^-ӭ$v4բ*pH$ZM() I"U LꄀVeR?q^y*FOQJC*ɔ%Pa 1"aR@U-Vı@WEmREFVLKUES`֫B\U*;jYZ=ޡ-D_~ ,h[aoN9o S2DcV9F1,e^$&$eS=^+9,K9Ò.z@+] *lUzt^yPaV2%F U H&gO%NlJ\0H\)hs;bJO!3J%v H 2ĚaZ Ӥ$( GџUU|WYr<\Y;=d ~+V 28|2IĶ*To,8C%0 Bېn=zz A U 9AeHAd%! I =/ke7yJ+(h֣?}h?U\J;S!jƪJVTh{Z 0 otLfT+iTpb&YL%1X׀#$;CbXBJc0ՙPDVr,zZm`,J;bL =YRB k;Uu>I_Z ŬCG$ThD`U1.j0UӱC^^|/1u=j];8yԞSq'*\'-NBJ8:c9Bbt"%c6 PP 2lRbKm(?J5ETHmH50(cK,dWw$] 5$W-E"DLxE9XȔj=](Ȧ珀V弭dSOyΑNm;S>V~RҤ mjN Qҍ}Ӛ bMc1fB=%D65iQdde3 +rd?Hd `3`&)Vq2"Ÿ`nT8XOsX0D駽oOfv9o`?{ ݾ [*_cJύQ|r* R5rݓ$ !+ "j(pr}hUĻi_$@BPPn&uiI>3dO7du"Y ̰YH mMՀw|ЫgNZ鱭5L䜶&ݎ>S Q5!9:\; IkT8TbOQR@JS'*ALDi.: BoKHOa)BsI("WșWVH$D,xbxNTJ@q.7'xBKn"E A.`=ݱ!jBb8h a>R"[;-+@ +c  lTcRDq&RQ$XK6@au-"EfW)-S=|X*o eJEѺqJ  ~J0+uʼnS,uj滨Co;> 0).F(6bHb"b&R@:JIYPA%3bRƂ6/8!P\q@)ryS$rܲk|d՚]jM<2ெx`J W<V7T=\KboPώUVpRV]D aE>>ӱXчIGkp@CLTN%"h ٬0>RkiҒ;@,P!]&\x ЋV?}E?rٮCz+яx#mO8*0@`Ц\I?_ΰ)xQe-&w<_1J7mT;][ik0dm+ngO.Y}u.O jX!&3]*@.1iNrQcbB~qH-;-ڈ!9@c@,b1Zh%U$J|5ts3SzP<8,C{[q͞cewſS_GvDܦ4\rnz)SR1ka0wC8F H@mK4  'aa \wt=p"-3ޭܷ?[X$EvJBKQdtI g^xKEєL=~yyBggN/kv+0qGr0zPme̮.P tf[N8&lJϠI7uTMgd )\_l螷|mTq"IiE: c0!tAb b"4'1YZ㞟u$NZ.Pp;WozQws X8;o0gz᭰࡟b";f0;L*\7-2Rl79&:spAqlCܑl,mR1 P M+H=* eMa :~`#TJ2W)`uClZInk\4h^7O}~쒳lr+?/^0~ORy²[Y{7 *wP<*"yF`L$9ꡯXwwdtј wI<yS|aJMBK6 &MV %*PF (D<{TDƠu1H+~LՒ3s =θhO؅c(<1C_ +dɠruA{VG~k,u𢟃^.fn=b(]usEɜROCr ]lJ,B0[s%tQqYQI 1vl.k`tv:F\TKM{l't NYv&rMϞ4 9U$1]JM" ~ LUAeIP(1u# !a!`j;WCgl7}|[{xјE*ܡ Y=ي2nwmΔ+/cTŖ> >l WGI8ۉU EtT$CUs|C”J\3ՠVDΏP ^h2c߂9?av)hOtU1&r|CY*z0qYUE)|noq 7L3>ba;  /X8si1i f"am>ZC3~ u; $!FiLy!PY<[y;++P%$p4 !h*?"!d{}/ڹۓO>13ڃ0aaUZDF'EcP8\PsX|73Zul~6g=I;u7%ـh7*DJ_.b2Ug%oa؂ui5,BkNxU'JMJZx 1(M!bq :oo!)oE@` ݐB+BP@@@I~+1LBQJ]7Y5#vͱ.mp; }_W^wp>+w>:'Xdž~wFOxn,crxEzR%̍A:tC^:%,>4)3n\e&cjMuA+j4bbX2!`ˬa9v4c"eS (;r)ePTӊ.ɑj#h-! D~#?3>%g:~L(fXJHanE! @BLIk]XIeD(Ua'G2T#oݳuc}} '͓'!KsgRͥ-M*I+5 8b0a(VZ:^LrI7/K0۹0Ccy t2A tz4q2V+2p3ZeL""0ZeLs"s`E8HdDD@0"#יu9&OX[TYd; !ڡY&xb$hhy5JIG`g-BCN]a^EIL|PPҡi( ;Gig[SK?vX|bEb)ZG9@7Q̡AWKPi!+ '^Z t9a+ŬsXe % Hcۤ 6KstLkĈ2W]x l=l,#c0؄D6XF%JKw: 7W?J[m4` t7lL $G$IړeDT,_;FW\Raک\\:hJDېXFKakĻ!dYPϼNb+,> ] },9 >%qT"z ҀNJ`c Cćʢ$""t FEY6x5j[j}˜`+T߁V]{fUTNݚhmgm|YMo~\,ODbɯΝ*>A=_;~$8L`U(FZU0v5^C; (}~߆{ƑBoY4 RvoE5҄&;Cv>38zS:&%03y:_7 8&8q̡3ORB|8ފmUV&hCDޜܾmغҾM08ƹۋpvbbx酩\9p׍'NZu(Z@EImfݼ{V_ggN:zln΢HD.7{cA|81T~/_شvh@\̣&SgvbF*)Bu\!RL?.|u/4zFZ*ۏ?<5籙Mcr(tGf om ΏIrDϝ>_iT%w-:{ꞹm; l?}Էv0dL5JzYFa[a`K5 [`7ګa[`m[ J镥VLqº.1Sc[>&@Ek^KʮGYOhlnq铏~'֞iuMukv^uwKm wmq'wƘ֭/w97;|4O}T&ܺf/醭T1vN}'&+,!\d{S AxYduyM`j~q-_c="R|M}r_ VHjU;Wn#'>侩X6W¬gX=MY/=>!AY҉Z0-^9E2\Acw_+᭰;=18A(&2fnU8-X`_jXa r:2k+#;;h#&npЮ|kuνX#iS=v _h6]W] 'j[.x1m9I,7?hvy-k1c߲un/??\DaEZ$ ~b24x>p˅`ۿiSP45*)Isy0XbFXqoYw—EzD*,咬YV D0xK0{kAMBWsbjUv \TQ1lt_ud(aBQ8ؕ 7g4g]0m@ v5Ԣ>u޴tEǖ"ئ_wN9K)q7󎻍DE*xW.tO}?JYD 4.t䗍Zu! LX\Jj:ֿ \?t嶟t3h)M&^ڸ=S` V/r0ޝEfpk=_^"?nA?p.UUFlU2_sq\#/l!I{|]wZݺ" &WDpKi͚xc{5QC[&1 "d%|;ta٭OF!KN /%^zí׼朝rx_7~Ol M+$WU`UX=10ZI#Qv];oQV`߯t=xT={Ydsae-m5(#8^ArY9TSR15#ӴK6|N/`ۛ, y],%,'pԴ?m"p3,WM?@irT#bJ0ڡXI>0Y}x.Ĵks?2]`GS K2E@&rd3PwE^z*vx{ Xȡ ;;/vsOt%w:t3`߹A SD QJ]7!81^i {dݸ>f`NҊ:UtmF+̕r4||Vyl%Ikm};I.PY: F bg ` #::+zEE"V7Ш8 Rq޵QBŋʗ󢿷C;u }mVonZGۅ5:^]fk/فh/mrߞ PGtG@qZ{;}bUCW7]cai axu90:]Jn-3%U*?#J?Ҋ{'} 3]ʪдHèˆv{[,SY57"lWoʼګPs?WM&@!J%ߘ{\v)BT?ФQK\?cP}>_@5oJɬ"x_ڃL9_RLVf~YRr2/[x_C+O{t *Hyy-;G['?)%k?/>C96Χ qh2c *Q+:3oT6O ,E|OH5Gg5X*mkO}k|q!DZR[0]ᩌ\XF)%k2%hVd gw %jmں±}~EElAC_X:Hm0OG.PQ}Ch]Щa ?+l@(`Q܏lcº@6B>O'ʺa>tŖj{~쬓}xY\£pۚ5!"X$1WڲhxyT h\?7^#+$2_GkF׍"TEuBN=+Ui$R`˨,GT6^C*6T{hX\^Cuj kV˔̄躲ͼ6TFU!==MϞ^*l:D})`͵GS@:>yT7 1@'d }DC'bIƥ*cCmԩPA[@t̢Ø 8 cJ&a7lZV#&VxR s5p%Zox[˦4:p5 mO3Ϡ"TGr"C'A(.H6 @C܌-"i:1yXm 3,7彇 G<]õCCQձz]ĜAYg-$E'^6;:5r0톁>?dA@:ͺ>XT(.#4#8 ogl{jj =@{@ كksy 5&qa4mܗ!RjR&jZ _? sc `= g@_-Z};9 $ 5]B*fDZ؊MoJS{ @UΛc }WXmG^Tۑ>ZINcEw4#Db],w׀ۃ'dX)M!B8YM\#3,ȝc5hB*jm'$Brz/y1ouLvN!2}dTa|_,.ȇ{REv3-|ؚuڌ 0 :!l"SYrӐQ)0Alsf~dul]ۖ8C~*.__~qZl,UYij&6y!OGS` kM [m)Ov#Q!V;%7$\kڒ썆~G# IkPe4Z82X5A:zxPܭ<O=+!IaY` Y1c(l,n.@ZjN13K~LNrJ9+ /Zj[fX|_кY`8gN>D5q^.5F+4-G1&miz~:({S*rrj^w(^P0\X.6hDӒBup |? }lG,͵%d-4}w&${Ak`}m!x1(Ӱ9E'Iw\q eZQcl7mU ߨ<<5-rVݽ~Ӫeg!b }$)iBR2ۈiF[>dae5Y0rMQ\ 3;e5KqX*_Y_/} |qMtjhlp"*Ŏf/~-Cf.͟H2´,bRZyݘ{6]Q`^G+R fSXX C#ĭ+Z_6|5t:V@DMߴ޹9(A a!8*|-, ?I ߄ D9Tc,`cg#h^\(_EzҸ_1D"-7ĸ3GGb-KV$^PҸ[Zzk^ !Us]ھ8w"UM:ǐKP:aoɏ7!Azm/yc.nM@Xkn.?236צpK,Q.ƣ[W[;>4XX8xfn e"})֮RpcMuk L/.dUUi5P{NUTKAQUb}[<(/ߞw w献}i$)zvrrZƺbqcȕ!utɒEbQ ^ ևz+ұaf.-ľHU.Cy*  5 .ڴid 2tb OXoxQo^E:{*9a f_ $cX_7k.dRfnzh,XISP,>mz87_MN aWqSGkݗ(;uz}|vV*H1q۫vj6<7oLẅ́&vkegt=ýnۺù5곚Niֿe4/k|,"9Љ,6u ?l}dz*9`pzE峕p&E\ݿ§V_=/L[/[_pçg> z_i3:'0 X/w7뢾k/zk='dCݓ*كX04ٻg`o߱8P{P8g0n ݰ)jXرak}Gų}k k~@I.;*1.ܐf3Nd 2j|oc4ÝJK9hχںoFV͛Q%ʩ&Zw5r@ tӁ? uk?o}%F4׭ˡF|IJ d=JO.8,kYau2N85W,k+.0lۮ C9=Nay2Z_~ Ea>>]gcP ktES D:_^XF%(&=}xeg6iqCCtAgb63 M5P;\w[~uz C\p^7*5ptzSOl]nA?qSMx~ƽG0ڳw$ anjd٥;Eu@+}hC chQSֽLz%UzoȽ˹71.!wl}eC_cʸ6|Ҟܿ-aW1ܒ0ٺ+j UB78++=>ʠ-w3pc)Mkt˺(]Q^Љ݆#_?q| 9T,+ b*P,[am(YJ8_m8şlsؤ#q4 } l|miAݯ,lLs.x2jΊ7D6 jz,$8) 8P$>9EC">c#_9tMg_hZ>w 屈՝/CzJ{;pp<12n7W Ms߰pfoܰi*hrr_{+0aot{/^Np~׍kNӌ=e#/|Sp`{1ъe꾯BfNNꗿ*^:XiuI!-g*ݥٳ'TN?svo|\v@p2K{7`d.&5Dc׎;2o_MM^i>y꫅4jÏg,q!P(Uxr[|1P(/,tԉoāsp7V:"&_Mgr3:ss¹O<>5M{tbqqT#tӕ^6Ө6)7̭ D7i?C9(w ˦s[[٘ExN~6g-QIJIK3gf=cQN,*ʨ=5t UTVM+I\p&G5e~ש{o9CA2~̹}V*,?"(.΄)a&L>s>NT\B؆%Flm$Q\nG_|}æmn 1yvR< f8| ٥_puWP$~PS bycr MxMM4x?ve./՜x1GD .\O#g~?c~";EcY"0XCO?=ưGǬvo==3ks_?1 E[WY,(u zm+S'_ןP+_Yrֵ ^ti%Ouzuk; \xl 9n8v=yԡ/9M*ΔF-H_߿EooaNm9YB:t{F^*\)(tb>\UR(\4*ta$|Fw57ac>m5r惈wى3y>'ojKaƜC9pOL슺-;OdR' h*W7]uݕ{MG{Sg<h)H BfٶulcU~>abVPsu]̴!ޗ;A.v6~z>q\w_IUhO}G'A 'HآxFc3-{)esufl8,ȻuJǐ7]yo`C?nwxYk蚫τAЉrjơoLY;/ZF"XVXK\KiE@f|,_( YˀE [P# (yF7XipxDrUKwTyV1l%:]38zF7e饳'N}lv\~QTZ.eK"%#hq@ɏRy`/D&.Onf 6ݸfͶ5-Μ:5䩉Gx I5^aN` 7o\ r'n/7 }x#2_kwܖKzE`ډ?GEƸ[㜒P:,@x[/X36>4jcg|ib`"hٰdBIhO?A-CCtڱva8>yǑEK, &{̓9,d.Zb9hTg]@z ?i@ٶvȦ5CXʼn3 ~YW+!X Xҳ%u v\%``U2Ǜ$D/q@*ko!"̞*BFyH8M򒅎)#(~ sT&A)h$v+5>x9R k5 F; "@IcN[.Ǐ}h_X B1$xӽ"Dco~ MuKPCDrAMԡ"CS0QRCC/*v>]jA.$La\"/?2#yzNPGerPBL &,#S _\MNpϊ躆u/IKra+ r"f2H DS@uL;׏#]]GY1#Ze2113\ZabwAʞ<~<5"EL7g`붳7 {A- %m]01l'740ruogBTA{]WxOa+CB%i:#E-x@>:2x^) S͏2 |P vR9PB!7>%T &i%[Q 0Y/^j}ٖ0T[RxҰ$EUm RxJ鋪,(1$qf')e !9V-T &r;&HZAC _r5W%R ʙ&nMM𢬍- 7ە= t '$yȿ#B9(,^O0BiW\=6@7^u}{>;;Vy"_7k:#%-ug\ݰô$ U3|r{DjC/^w[Sb^ O*UC)!y\-[U$)1+RREjQr_H K!HYďz"5&VPUBuם^alB+ផ+l+,Qn(o~-7nb-mBcpb6&qdFd dDS% JeHXxpWcM`[=@)SM]1@+:zېK=WX6`Vƽ__Ǟ9߱qmaƮcTw=%ɥh 2[ YO^Qbeܝ5^hGf4,} n(ciT-U?d8:@cV /~Y$憞:K, [&ck:\c۰J[TVUV$( Êd:dJ јү#Aq( B n7#;d-HKH xqWˠ\qA uHi0WJ{*$k0r39؜^V8NgabM P7ꘓ 0aTq@cVÈ+YA|m0KA3eҮ42K&|2oH'ʘ z0Avm1 ŕY?3G}8|}%]0BFV1h8Q~b8 xH{2a.njTϊ":J8v* }FJ38VZ,(J.ibG7KPO\&ò6ߖ1r߬dUP:ޗ0@{IlS} e- `,3u")q+K$ @1@ƞ  F3_(pPR[ h xk62'd.:p [!8V1 , EBb#~4ojEW^tޫސg&'~>~lfRЄ( CdţtT ,wi= uy9BD=FJAEYH?tR)^¹09z$E^[.7*VڜDba0!rAH²*~1 ߬@d*?|pluɨTYnQLjLҢ)dE+($P]2q HQZF;{ygN$.6N}|2b < b6 @<vqhTZUD>JI:4 ё\m 2Q"*DZq#)*j%}Nƺ$pjQ6DGx2 2_Gt̹Yp及"B| 91S6$uSp\MaTHdn32 y߿S:ܮZ2N3`\FlL"$@$2mX($#)!l8RVFR$8m!'-E#Bȹz"tsm@](s@~:uo"3d)*(  B iU״o_㧎x\yF0-rd:6eX]Ѻ;̀5KIg*Pfۂ}(n G{dIH 0(֊CԀL8 DCLS$ATVkCCB5+*o) 3K9CĀ”ە8&LJD`P} '7@{J0fEVVN@v7inV1)5!+.i@j[)UG6dcbqӂ|3:`.¥.W]ĬK]cwl]ZX\gOO=u̇eq &LyPPF- OVtHG0Q"__ qIb([6p5ntúCC-m[Y?01;}l٥@PۀF0s+:o%|l ~A ó0J> QѬQ:fĚʯk]2#$P{Vy-NJ +΂3ҽG绋YwTC~$ HhXhs]~/.cRa1A)S8 ZaVQ[?D5IdS0F FT0=Sc8C{ټŷ*DVOs)v\DzpvG-)Ñ띕IHKSH V@jR|<@q!P؄(vDmǙ +aI .F;U&;Q7nR$]>JxfD' 7Ll1I}֞<7b$'=0ZWHRI|H S!&F&2J\S&%3:`hŀAF nX׺үԲP%HFMrͮ$w;B1Mv fQbzYf[O|I&gD.R --( *qWjA- SGx" /R: bf2BqN\@1+TPx#G!\y@L-pg7k->Ot$1f䑉0f&%1C+Cr@)%?=W^1Q( ,>e JegeT5(lzdN"Iచ]Z:rm@JŦD`Z ll }[0Hѷآ>{(GY|rãFΌȄuVU1YrlKNF'%Ki 2*H^٦s2N+>xJ qR\W޾31[ .C6& $,/$9q@aD񘢔Sru:/ عSa Q--LT\H qt5Kp8#vLұ&ԬMֆ"&'(U5#,qVg#/7 4ISfb`bĪOX-l_Z).6L9UCWYøchQGڭh]3Zl]:~ncjk"%@Vň"i !t*+~A&Zҷ#˽< DjV,?lG ) Pٜ(`biP2rlT2~YneΠ0-BFl *Imv_KCYqe=)irԍB%J+Wx(V6¥X0=Qh9=T0)7"D)$+2kGʶ`:"5`M1KU%805/|zhOKۨ4iZoS&<׿HH/-_7 Y|Ϟ + i+&4JnZ4(ʑVmLmImR;sR+֭ZTCX9 sxփζ:&W3K%%@یacAXI>eТ3䲎"@r"ڂ"\3Oug*~],FPyo,'&s*(Ym`͛b\(_@Fq]IXQ+)PnlL5̲Y$k5)>Wd;SO%nNxdK&i%*qYXjO _31|ơ{?7,lќJ 0&ǁIqai9RK[iu q0؆[ j7S#[ܢ >[#񂱞3bw!%ZN.j0DrN&!POw*)ϡ0 J,HJ^)0V-1P_(=E_ .^0G"AUa6Ә/' kT)eðˢCx8bbj-RJߖY}d! ZFۿ}eIԷ̂oozx vtn⣙L 2T4Br7[& s)呣Wt]Rlb#v ($t d! %Ak[mly[_(-Veo bZ٣(h1XL6qX U CaBU3*tubm\*'[  dHv9ú\@漃W_?G͐$&܀%G5˨ĩM5z0xӋp7 fSJtoYx䷆t秇.b84=\m5@Тmco6m %QJP_}_ɮYph!W XNSsDBFD;Lurh[Ki8A_ޒOUur  $B;CV 9qE2,ۃț Z`F( j+vx*@㡤["ф=,H# &h GTQW9L܂3 dX6YBJ w:Io BǢT C\I+[4[DX+I<&˺h[4/ DT -*&[o`Wy禱]>qSS:0iKW Q: a(a:V\TbHAP0WE?2_y D‚9 I@"_X<& Ry1ZRK`q;.y`@&ža*$gqaDd&8iaZ(VD 2"@XKz ̧H B%ax`wxdV Q8 7(s|hIHx t-LвB e' 9 &] lb1%M&D9x`y5lؒat=Wpف7=# 襌%}IUy0Nya>0|! -·:7pA"q  Qh54V&5 lC-fА>%cbI.!2) %a2A8,_aIʚSj sGnQģg0Uy,*AC=p{e/ C' /t.ؘOqU!sE6P(PVRF$ LDz%h^b6}_Т7.v2(ϲU}ZAZ Q%Y o>>Wǹ9rB0}xh5P-w!NYi&$ i"PB~BM=3 @,B=KQ2u 0UwMsǺWc"#ʱ9*y`) W=Cik"$i%k'D#`.aF: !o@& 'hfVW3SBɛb(HJpev e=f $ɬ8կ/8{S%\iSDk*n3(Dp|Ra8[.J|&OȒ0 @$y|,QGCmY ը<\\Iv릥ZP ;H+( )x=aQ|# "i[q|Dufpa$LZ100 YUE Xa- +BOd0@ CW,܋HjcTA(ŜWTQAkEu6+YEqa"@ $V2d IOj-4z }g,(fAtN1t/5;ʵ dLqϊ#_Y)O#!ghJC‘opi!$@%'qwq/$S:G !:j*%t72?q~xH#[ngbSA`L1P)A#(s9V' ٔ#9ȺBbd aZ zmpA<I[Lir[9RPWl) )+LYrJK8 >yTbCL0{BౕAPd1kw 0)_f<\dAB6qt2A/9HB((0J)(10 Q&*e@+*Q(JuH}h'[q# wT(rzD hbڟM:upb)زsQqu:uG8 V0ê_~!/TqYwεXuOTy"(J̛D4dXWG~کt=``Pg 0!* &*J&D@)KFtpPŎcT(<^;dgbHՂevĕ}!&dh!ڎ*Ό~=w ̪'IJ,)> fm]`~ǦBSw7f* [ce#C]FWꡅ?zPwU+.6г4X|$@A".=$Wl,eɣ~`CL rܝqTo*3JB$ij;oӜ:Zlt&J ީ`(tCX((HʐrG&\0U)Ѽ+?\ml*D r-Ӷ4we+#hɢVAi qgŒ Z) ,w@v0`@w_"?*pMc9 [Z0A#W\#E9GzM4'AX@GmY+)4E!f8չzj8q]UKuRqg5klK$ 䣀"TL!)2di{״5F&=JAP_h+A#X'|UzF!+)eU3U EA#VzT9{AE n \Op7?uQ}䲪q\k3=S[DY3yr-!AێY{Ϙ5o\g ;ׁpE*V4]B*hgܧ,jp`t5dE^O)V<r.'gfQ<X^- ~<$[p ûe ;5 Ba&͘ ~U}{α#˓D*VCgNju`99vpT 0'ӱΈ8PXQ1ZMG.o(Aˇ*|f =Q:/]|k kZršn<`+@AR-YSlQnw<s]1W`۾c`6mtdC ) N c6Ldu㚇s9LavƦ氽|JX yzB'G] V\@N_4u7],u,Oq+\#U1)ϓ a("C +RzQJ*A!bA^;r I& .&l0>۲' #?3vpR;n` PKw۲;ǞuԐњ%(+vE1iPV`qww8ڢZTQ\_Zz=kن.ԭ a%X&5ۏN^^Y @$ '5Q/vYiHY`f\IDATuX\NDi}]BfMc#֡A  |>p֚TOTTcvv7[{KGgd ١* k6d,kr=Zgg4]e9q,[J}-ؔ2$L\(=abeYٞbH -7EڑWV%"d=L8_6i̓9eL"T+Z#vglh-Ne+cz) ̽>0F8Cij9jvbgҩ'go>*~C ,oQ`qyg@ &emulްX ؓ8U}4[:/wK&<7gnp,P?ym),-y({Aٮ2A5+fgC˾04 lǰ[`ŕsd8yT 2G}:"6-LV1&LRw=@wvQpWdt'CzGzPvbSwbd';}UZjaO dP\+IF>59mrySi8|1?JC I\S;*4v w 5w G:99f:_k34 _tpS\K#*( zS7Dbf2$TG WTaGvù@,Gd0~N,Aw[OO,ٱBv^lՑc 6}d~)"l)FMTz`@ວXs]**7ldE"  <Ǧ N&D`W0W{V ޽6ݢN82At>qEQm:x'Z'1X#זfwևv0蔡 BlLJ wvf ]Ψ] &´iBo'}~91XB"-Vq^MJ骺RSaӗxyjOg[_;4tL+8?_=ŇO cN#;q||5uL`Nb^y~?pPFUbbex}PuUP`!u}|q_S·_#E%V_"cvdۈBrMdv"yK'mOTdij^.%_mQ /-\mFV׮PDnIsm5xB8!o׌B| w6{|RW}\HF-8~0x*.Y"[w2&nE 8$T0dQqd߻2Zfdk=Gp[IAzM?h NF-م_,4Nj`u m  dG77R| 8 0VW댂1O@ h{mμt+KW7+ A$6UI46#2Dr_aö9猱Ri|h譯{OG( 6S߽XtH>l_Ywv|чk\qJHoz6Vm!W)-t,ZvOY5Y^r{,gQo*;_Y( Tsq?Ohh,ԧX?!H~ GCQU0E,HwDjCKgm*X(se(PR͒"F(Mc+3jR-08fo\mErg,cfsfW(W'Zt;X_0BMp\]r]q CX5+b`EiؓV=,xT2O]uAWVuw>rh2#,aޡc foOZkPmqZXFeef>0x%umppKUX<g9hHk6h斁w-n{/T"gۭ c`c,6@ہV?8w4'˳_~e"D^_6[TVk,SCXMTi -EJV( ( QUTno(`+`aTe%aZp~ca#OcX 6IU0XfX\lt9AΛaIÉKCc2y"ЕAkOo{_rݷF~]8rSKN6sgB`P lˬW,ЀI!Vs!i\-+][—nu9r8fU充H)^"yOSG1zZ%~w֕\:g'ޗ~+_?y׻_h svGo%cR(9t"Og5.u2#ڡOeDr>Q&4g/ w),tgMY}F ċAXQ& /hR<( OTyߛ~/}fN,xbdR]/*X\ ,x7 ^R\.@q!Ac.8`{ *`Y-y6`=}iW*`"XzT0POs!N_7PJ?x*w5wL).}8ĘQ ߥIsK#Bʋ'/ȥVVNNOWu%lIΑ?ҮyۃRĠܠΫ(j{Ф%voCwbUS߰gC/uDƔ+@ ⶜r'dĕ,rE%)mH(o@9C9iD$l3.%Z~8> Q{ j2E9Kܯ"t}!k<*O{/kX͍"}}xF7u̅tu~T781+W l%"S|TG g20Ͳcp]30VzgP|`J}739ATELSsiW8ʘw='G:ߛ-*K@0Bgff)lZg;oUSտZ̅=SS,^Cݟѝ\ؔ gSW.Wa`1Z밊I/ԝ3]-gZ6Mg5L5m2a ?zE1^>0΂Lr1 0 6z?C(9)]ʒJ|nihgcA fekխ^3ldcD pRl 7^9W^FS&^F~vɴ*}^#'W$A5H Y t-_.,}*Gvv(C^ LW\_1F⛷<\qQ ]|wףlt|jtJj1 ! !,-A)ӯ|{:Or2l#Ybg1+!/ ;@y6:v5ӹаfk5Lηenh8aTh *ty{qc~gaqV.K_wXÃT֎CCS^ED OP5"_Mf~D4ߪ㱍=v?qġ.waۋO죳FRdH.2]J\2۟]8!#}gBɒGh&ke]z޺s:KO^p"le;KW<Ε {Nsfx)3r+zKA~$d&{H>)a*ΥcQOJ<ԻeaɃvQY/KVouݎڷ6R<%m]pLI0TUd^~g^4iSzNj_|p}<>poyՏ_{i w~8ܫz4d8f?fmÀN _c<~cݽjşscUz\#iNq5"kHq$ Oc|Q-wa[+h%ިōɲ ;N|ePm.^Ja_7,znSDq;ys07wk_;])$92,w~s_0aǑ|:L`p>y-3 gHA4|sc|qaw?qϳ;3<14pP2ӦNJZAeXc 6Uq c&P\n( y bYX")9}$s%ucPX)*[ð;[J_`5݅sI w[ABqGJW;aȧqVUk~KG C86]UHy#ww uU]e BuHelY\ΐ}VXtu:׀K+?M:(cw,rN dk R 9gBUr?݌H%ԝ )1Jݬo L/hc\SDZoH=k1 s(VZyڂu.v ި1-:dw>G[pjVJinrVs,G`8+|e>؅?՜j&_וֹ]rÚ8 Jv!/߼G&{ʵ'c@e=n\s#F H?+HcFr$ĮOq-;328WVz$~c]o߾,Ev# OJz]MbiEA Yl Tn&blJ.h)Bo#,(JJ2]jZ~S>}G%3ZجȅVDpMr?3Ki˯}o~xCs,!eϮW5nSeʼxR^e*bйub{zj; i89L1OrkcW8wo|9]ՓݦQF%zk$ W]"~ ^~떎c_=?t^fw%Xy>?[?KUv:δs}e~1Qm0r) wwU|<. GF t2 -ş`HZcHE%sK6?Iǂ MT.FIKjPĩ"d q_F 3)i_ЅK9nۗ88g(s?"IfōGv*)2VZBme\$pJ"on8՟&cS0/zz4fzcO=֮>/?kvulYnJ. N^;ϾH_ꭄJǟSGxb FbA2o^yOY ;5걧m/i+*y189\Kd^-.gʑQ˞K(ˏVYZ'1yTD`; )"~M~X_D&g^.L /mVkEW.!S-Q"$";=\9=B/\X[<~%fx>FqKpkHŷ{E(6X[8KC] {((>[nMj?PM['/(Ћ畅wY 'Zs¹PYP'vGkBTgz8=`Gk^C= emK³"PSU׵Wtld>y]}f O7!F~r_v?-$\ |cd=pu!>A?@{fpc%qI$_p{J7Ҙ g?Ѝp{$僿C v~WLpSZ9uMͲUlҸxJQpգӳNYۦ蚲m|՗_cr( s滭ܨ)W\~бkZä!8Ot酻foOu[ΦO8y Eid)DD%MEXX7eoҗ^pDW;i~K$ ަ[dtn<tq͎IEpߵ9eQ+cG/L{'lj.L/z+,.ՔL#0 N1[,wNQ +s\n^:IM T ye(2 }%}˲YNT3i# ԄB8zpD΄P`r'tӮR)R8QxwIZ/d*0w7䣤yKl|8 JL ‘}rr-|ОcIvg^5mSWvpr} eOLD#^^6ᲷAf05pa>X!$-;}`P>[m`.?|% NSȍ:x)S)gc+&+;,`zgݪ^;u0axb~~lg][&UGK|] |iQj\>qeo ^`Xp#+&\^Ah6mFe QN|d|eX΃'3l=.);\?3]ͫG.a6*#׌ܺ#Ng6e.oVu*/ڌCw!?0kv?ծ 9Nf']r~zua!vPuXLqP2Frҵt6ʓ0{7.Ejy1T N $z .rm30nwUT\& -4fާq1HsǯXzamQB- _<|hd##s8mvқbc6st=W<0RjWڎHJS$Do;!Ks9a/g6 8@Hugc 09P> e|K^ }<0 =|gۿꑊdYM~eoy e =3v2jFsSql}y=akS?TBسM'LF W^9\ALwͪǥ=(1a5!!Hn81ʵVۮ\eы3cTgotƝ}cV_a۟1)3KC;[Fkynzzi 0DԜhGm%#4Zl?o^o iL(m.@ք+1+7~dRfSsSWfx=<[?һ:DU՘S+C}f ^l;6b3NXOzpۮ.~/_m2mޏM6 Ŏ,3DjIu]Tf~o [U?9gXČ; i蕭G5#ђζwk ':_/ΨtIѐkua۫i+H %q;z ڤZԜS iX◭WC3j1a bqʼn9euU jqշcKǖ?QJڨ_Mzz#'8#P1l )Ӏu;'`82j ~{Ow\.P{SN4+~E. 0q H"nu pJʪQ2޺;m, :S(eAh7u]ҽoЬ*v }s @Ҫbgґd@C1_[o]K.'-x܏6+]O,?U\=0:˗nam]ԢUe9QPGlK~g#X[x.#zP\ \Pu\`gcQelgQ1HI04Y"]9vr qu+[s5 VL_Yg*,trճK1Œqlut5*ƍ:i O295ܾc; ylN]K6e1Q-i\5녦ұRH#D[w~`£ovիG/TD[i_[pbH Nj:TC\"G o  " ؁/CcК' 2| T>DkÅCR8ps+qUh7U%"!G<bMٟc+U[86`Ԝ,OU /4o)Y*` ?R0(V{D<Ǎ֍OlB PR'úe#FIt8|< ^f;~ wι흣oC ֧Ep5-^hlkXX6r=K,*͐'`42WLcϒt_l3%}"ٓ_8c T!:&m m@؊bN]" ZRCݶlێ7=!] Z}p6Ӥ\GݫԴ*!ـvWU` K劯,hЌ'0l,}6\(d=KrO.1Nv9՟|Mhȵ[ ]݊„6ȷ\BGXHlOV1 b9:CXX )Hx # !.(& )\()3j鸥cS!l=+#Rx{ɲ.ι[,YUYU=]{x-l$d^$x<  Y`13ؚ1{vwUWwUee]=]wj"n8w9~߶ٺ-ƇWUѣI\ FU"Xȳj!Noo0 (olŕT3 H "J#ʖXw++kq?fk1 wF+Rp²RF4f`mՕ Dlš9Yx%s =JWS̪ :U8WTHBB~5 U`$8)a.  ZaZf8I93d 5xmßyfp'mA<Lޅ e! ` QY_ U<q=ڻ=z6j@,"tΞ/6|J}/3$nX ѬJxgGhZ&g3^T=/{0k%~ހl/Xb~Wu;,4 TJDiFi*޹;ߺLv yXÖzʋ(3;^55TJ&"9)eQXꏇW bf"95Ap1eA΢Tɍ⯽+;o\`e;!Ul!p}8?8uGpM V$$ɐ )9_25F 13zg՟][=91SL̾_Φs̐)JlI,=at.E=Mga握ZBDM(VtHf:lYUki_:摺=8*|pRb&RIJDՑEZ*T?:yt嬨!9bB>f+02|n3$a++%lg- *eAcZt L5ABPA̘1l ~t[MR-–V_KgUΈMIsNޓPlO`a!Yhw_N&Wz<೘W5!B:نI+aMH' XxVC QvX~~᫇El|BcpzG>/yx󿽵q{/|3o]'E!kJJ77腙 *íp+Oh\z9=j\߸u6/^6km0z~{՝^SɈ[B>#E~Zz{7ď>w3+ ,dLB[^FqFqGM`:4a(M=tRſ$D׿|yV2G( /]_ջ`do\d,ˤ̻ew2$WČ(Y gaIh$Q?wXug(bjb" ,*շCqmb@ű܎D8&XDX%&hwOLwX]KMJ"&0 =5iD|'ݠ~_ʣD$l0iw>h`S>9dy}~'6zvL/~xL=ty7ܲG<bTI۳<{ގ6$V!BoAX!raЫ &c΋ϪȔVht6w;rʯ-bB])Lئd1Vd4s^.;nE$g0ouvz|9:IQ4dP"Jqov,V2a^*VUHC5f[u%!y nx:L[U aߚ|ǰlt&ӂi| )KՄGzT Q2*adȓȘ.ԧ[6lCAAX9_U Unc[IMz $8 ⦒`IUERʓR6+e6ƊegyEZ3^ yV4;Kн^-E _Y;{gkxOYqT([B]_T 9o!ѴJ"9.ew/__+ys>VZjczXO 3>/w6>8?9|{R!&CUtkԛǥ/a\5[ vsnM F!olTb9Tm 5$Wf~n߹bys%g%/ O@VJQ,%7)e**T??~8 5 2f0xV?R[h\tT2^Q*:~s'F"(UOLKIj06i!DD A#uirK3P/ZdQ1d)ͺ\5fII5B>TQvm]%pS5)éZfq<- Rac$uwǛ?O߽VlS/k<@D YDrRt[BCjςVX|-lO )J<]s~tЕoݍ'k/,hg!ij8jcekFjl|ͤR,s=샧RQ S ԺTY>_G}9I()'Vd?*U&תXS-u"0GN/ Z1i'4dJೠWۻFN 'YBTA,k ]ZlUcip9+k^(E+S 9%X5 ֫0ٵ 3͘)KaZuN%O!IҵP ufdNTQ Sh4) U 7]ϧQ%iJ 5,+lil6дQ>q?ף"*"V|TuΪt?뿲<[QcVaxPRiD]J3XaI՚_y.D.EgTԭSqg'_/}Zw%H!y\]E |gvil{-BכDChT6LA5"1kӍgZb6*V%WD*+SU=q㊄Y2*ӝ5s3>ZeŖIRPmEְrUm Rg/ƽ|c&ED:Q!js5nfǙ !3M27h\mƍ3:\ffדYD5 /se* f/vfs*P{ L!/{rҙqhCU[jgºض!-||up/G~nWz6z<ϰxs!L'E鋿R V{ڡi€(?ݸs;cHFG2wr JIyxV7^_\CVTpfdpy @Oa>yY./9UB{-07a`BQ0Eyj>?X!]x/&gΜt.`в19Y+kXUjׄEgo="i(!ѱ>#+YڌDSiFM3CUz9;RD[g9;Xk 8#=:b4wJ&eO;edO*畹.51\"nCy>XXwEKX2Ӻ*Xh1aKM&ziDX _ڟ\=64Jȼ[L3aj3fV{̲mC&G1弡g?S-iYh1V䈍 U[qﭱ:c^UY=BEr}n )o&j@B;4#/|g{.%gXV[{[ksѴIC|W;Pc=}ڳn)ZX'wv^RLϨ4Ý8$*Usejh.~WownQ~-UhnFX&pi>h]7lZDh#C1_)8>B^GBӚ-2FN=]ݘ4} T$|mkXd#*5 &?)¢ ZO~uŠϟ#˫9SiUIjJkH\=#00FH(MtbP5].p.P. w!)fe0u pI' CU8mD 318>,?]V5ŵpF&}ěF_ 6W󈕀E{]m2eh->}!]p:҃<$nNˣqui/~m(kI@ceJZ&> ze~{7)X]SOAVb)  !CADPh''jlMc6U2?fyeu`a^)v rqг<#MU{vP 6#1؅VRs-@VD/d/]ChWcV/{mޱ>A!1p {Ae.XBhu.`qɈ'xFܝ:OA#deY#JKaL<ۻ_'/ཟzEE~h*9[hf||ih4w6y } "I;*J3)`+jf&LDf` hESL1)0;yvCnUU.D!+c^;Fߤ\OCC`b5*Ǘsc بwaLJǰG,QG+cf)UE %i 2pvaX3v;=SAtfc[,{ Vcbu.Zah & wS#U?ۈAB/NS F QC3Q1/?Zs_|YQ^lE۵e:A@wgF@K5W+F[ IEBփtSʭ挍We #3,fga-/\ ),mAh s2/\&Pb$}/ԧcn,-hMS–GFbrf`Ep 9R Ƕ#E2lW|¶}sr"T)T*{c+km y^p}p4lϞÑxW|zO|*+6b3;7-c3+>rԝ-(ymZÞ{PN%Jp6}Fu+a~؈HّKV^?hVo.SczT@sYLXyԇ%U.tY㎔OבE{>#t:fv W_p5^2bBP\m Bc8t\w-Py5WH# &%{Zm,TcUԠvA/mPh7K*h\f<ޙ>0)>6Ni2[ p0HXfH`u?/.ǂ{T/0p,l@ F`|mIp$,+}aϣ1 nK}~{S7D-A&?黄UH@Np/\Ж1?P0;Z7dsƎp|<s,6vyu49sN'o6tc'TB`\ymdc#j}:><;A6gWꃘByL$`e}'6M{:A !!ƌ7>Zb-n,~-=rv%jVq9;UAp13bJo+;#`%dX`^AmtlUa\ |7.[epim/Pm]2Qc фGAN*h5)D^DACCC IA]УKiٹk@ %Achg>UіX& d`3SF<Zé!& Rن+ )eQgfj@gd2&= w&6QfqRTG\ UK1O {ԾH xrE5ܝ[#"}}>n[X$J%3f%=x%aK$TS7ǍGOny7|I^lwط0MYTwpt:3ϊ¤ƞ9F:HS-c\F.ES2)UO3@J "t/p{|VM^?ev12@v;$D;y|ǻt]cbˍ:+N@ǧ19'KG 1+ƃ>6FDHԕz-2b!tX,,;fX?\ـS88 ,~;hE _+9I*P2ޝ jyp3`R+6?mj*.Ygܭw7HpLJ cHaoLXOv}Ou o*73X1R4:F wМd=΄Ak'*~N487D?/b[Vhegf$Oa)`<Aj6t\vvOXm`E| 1 ٭6`]ߪ۬1|x1CRU~brm:H-G'wApYsK ? ]vJ_51qfTNwMT@3Y{:> 0ǐ\F^R:/d WL~Cv xqt2d32.H_\͌L UZCaCX*S7":و߷Q CףU|(L lj\Kw^QɃE\S8;g Uz[X(d)1b\bug$Ok?IR]5b@+kszFEΎeg$^ak=!p宰$zxsC6i|XNHFc0;4fWXjL-`8rpw(: 0͔&a%W%Bk+ :=\jI6EXLZ{feI`,J"l2t,f7~OUh=ڮoZ;V+䝣1tS ۍw =Wի CW.A^HXt|G{O;%})-f"O*bS78ԨyIu75\$-~^1-!l6+GG+UIAq{$dJz<9zN@1B=KzQ} k7F >c t1+ e2w=ѤL%Zp@2_˦yPu^m?¡9 W Jo X)b4p#oB?~6)ص\^gfcC'%M D(5^׶N\"}hOH[C"4:6.c 2`ag1@Zs8[x\pX#LS),(t{isy^ B 794A:XHŐ( ]-n4sixG |n枮= n-nSna¨je{@$@0^lHBcuswҕgxp+rX[/΢d,H78QW` D.&<Ix W+54*{L|/60>o=m/Eb\Z|kv]~EZD-2~eD#P% s0!ߊjK;s&Wm^tQp<".;#O!;L'-Ь>]S_tI&X擂Yko[c>;+OfV6vԜ3Ƀ@N{T$ @VصYM"`S8-r!l!yCgӚp{Hj#xl|)|m4 |888AhQ5w#H;+GGĠ2/\n4=r]|Z-)}Eo]mΟF /}_cW )XV?08Zxv5BG3܊BӕইA&z|dogdAAfE}Li<^X!1 p`fP4I8t4кEY_%wm*u @a7؉jc^fwy#%Xu=>5p5`AIX f,ʸO<ZZֱ-R)TS wd JUjˎa*83P׌A8壻Xj,X]>C[aI#:sJ&8V{,k^-H`@LWC/6R}S\.. Jq4 uӓϴ7 AbsFBEw`ǻ`tsӞȔi %5C -;q,n x,q8,VliO=sqKiԶ˹>M#FIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_d111079da5d8d143b6cae10d6fedbc24.png000066400000000000000000001270351420147000300345440ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx E/^Lf̚! Dp Ypr{^%MUM cK<3+ae?_FNjnМ4՞ڝA%{ĴHy&c!c {,)(/m"#T91s`O-$^3#/Q86AmAY Ia%UNBC9X'&r7UhQ% fO9W ѨoX8r*mr[p&}PBPJUP bVu5c0) `DΎ:f ,j: PP2.0}̧$y Fip F BQ'xZ ^FD4MN:EX :!Dj“֑ i۰@G^rr@ EH2-kY|"9DD/Cd&ڹQ>~GA5׼{儗`]UIo1\E4Pǟ iwPjnA2(r鰩V]rh*mQȔK`X'EB+!*-"Ζd4ø RdWcL3lT>^R bzJ僱W(LOtl 1*P!hfpZ:~8%`=0%$jE=neq@v)549+dǂ%y!;:ɌbV`ǬLTRiŋ:c?rVL`h5`0C= 2n̈rRicTg_&9 U+\!8)EI$J|MNֳ]saoj禘g'rD0N+`F,LmQxwP\(X[y:UBR6/q`={v!Y僐nmPLK2h|!m r#b .֍@Y5OoQЭE!SQ x8  Xt (zF"cqrB'ĽT0y͙r,W 2s:T6 zmZU|?!jQAa̺{=N1d LOg!7z̓.ĔQVfT"*oL9vjή/BuU9%zVkMW ,fA'= VӈY'ⰞբF*& =:ԥ"D8\$(2)g)JkFͰ*D'j|"Y$fzڭ$ 3x`z(bH3dx z{ 1ƋFXU@ǀA߅ \ ޢU9Rj>,p8 o#< `v3ۭ$E8@y*^mTbÙ6}eL 'Tg ;Z5Ē,K^o@37jhcK9᯿#5Q*&pYi4 GSW.]E;9ҍ)LmC7GiS OֳN R)&GHB%'M Ij[MIzTLfx<,¡L{@w ~Ы _Ql8t$D9GM|RkuC!;ڪqe+d⁙X-wzP `glDD,  zvTs ltHncQHA[@[46u!E9⫦w'0Q-h dSĩKy:͎Ŭp|%b]{jX%DcUI1.v`:ϰ?Ym;X287 6d2s K>dW=\:[+A̒INֳT@s$t:v ;IX5p ʤ~8bǠfc!_ '9'!Yy(ATXGvD]G?sq?Nr]}M4YܣFU.Eir~@}P˧hIP>էL@# ^W5=/ m옃 *wu6 jmHUDgf=+p "dX&P}\5BKDzbՀa} iOE\RW EXj:+)+Za,`TgJG{+5>gpv4=QV҇fDJ72b0=I 5O00u2:-BJi BDڽO9)ȞPXb`[>EMַ`R7{9ހӅ\TP=WG]b(# ؁قh"OOթQ"LsE]7.>f[r w~XTJoڝ0b&em@HxEJL@HY垠,xVrn+,:P' H)u~LR46i.'"pa6/i>x n]Klu.ȇL8~3<1xLW|ëڲ!/__ؾ}xvZ{f\'類oyyr@0- ,"+Da E{GᅧNd*}rV5e/R>%ҙFC-YP)y"'8dPJ&SLNHP.R]{;ޱLS5d2u׭b8Bd0!K ; f{z|d,npZeHe߾pe׮IƪBO",g+0X!94>DDgbIXېg"Թ8e׍ʩKJlEz<&|pFcA{(1+Bl$K eF&)yNV 2W]n5(%O׋AZc3R J@ Kr| //Zښr*?Ν6 9*PFz'sa+N0:^rIך5Mi|'⏘YKߑR:9|OMODIedGmWJaö5Vp^ 55| J;4wYd"2$yX+Tl8A6״Baiww^WՒ\tQM71yq!;WtI3g57U?ZIĊ1/\`'o6kuw绻^w,(pŘg9PZ4uZv9ZIMeu_qŢ\= o[U0ER1_A&ms@%y,}b%'B4M*-ZZO< ީ*Zs6Ag"#=}3/턬ZĘ*e{tKA@!Q %>cނ\xolopé=4OnoYItvL F Hԉcw "-w$- ]^˧yquE?ŀ)*% 6n!r],dqA2nApq2gQ~h\AY!bՎOI-!7>\N/ٰz$Ԟ#͋xלHȟm^E\s\;߹|ݺK5&ljӝ^Y1ƔBhlJΆD^ N`qMiE4aZbb$G@#T`UˠO?L^C&tEe!D^!üņ71cb‰wy$Hēo9(T;"u8.d/lw?vYx'ƃoaJBH3 'Ň% Rhwz& j1ܢR=eҐp**D`$:S+_ӧ/J2eeh6+)1ZErA?0oLaAZ$"RM0<(I%1Aj/']>,CP%3Ir>04@PH( z**pX8*_DeyuPE"?_!̠Ep cpR[N }Hz-s`ħO{QoLYdxLG`maֱ!l}'ϟ9.-[X%\$M) \,z,_d4D#1L@dՒXh% pUu=Uk{S(\b#V䙉֙gvuViʷS)['.ǧ g1- xbllcVhz>lyuZ.-Xښ7/N[5Eg|ٳgjyRi@YTg@ФKkiIZã &qPTg54[3Z֮m^(?~&l{ew|ڵkyd`|| zEcV"J> ȟ!TVR0:Z+ J co7/|rjP.d>}˽\жn]k6]Ei`/\]/8r?q֭Ht2=D6|r@ww/'Nk*!pJ?d/|'׻L*G¬rW\袋x?ZWjzK}t?mϞ}5{oIn㱣5KJVWW˺KnJl6ښYrxb[u׾Je4(#Ue׮P5u&)Λg;')Ǚ)Z/^Wt>9jԑ_Vss' %;vLgNy2gϳk$SpnpԯM1Os~0)OgQJ۳{]^{]Se ڰVf__ ۛ?f:  {[s )4# l0t/X?穱-ٲYgyLGC7lXveW^ٓ<99sZ''\{C۷'h#MQڹ.X ׬i''\#V' ?S#!$U>ȚH|̊'Y28č!`uv66&cDŽЉ'6rYM!-[ϟ6~u?iܤ,bEdQRր|=ٓD{R`!W8FKƼ/^O|ܥ,W xԂgqZP(Ǭw{W/ݼ׿~@c΁'r/ϡr  0'kRJ_ oh%3+ kl&Hw]1Emo϶groDNF8<Q3.[okl<*y9_BI&Ey B1=9QUqrC± 6m޼~1jWj\p ֯_t;Iňp  g[#% \/xш0|1 (X1kyիxbY7 <-BBՖ|-V/c,\*WqFZe.YҽhQ|I'Nwv8 }D4 d!i^ɼL8yTL]%)åYA 2G fb׈eu'IqRSIȺuK7+Q΋"x!IDFݙ|"VĶb-TJkkf/|PH-/N" Y<ľq/oN1+uX[KKb+uo]]c;963[̼7 6VZ)ALZg&q a|^!oiM7>cοmI'Q6SK/J /|a$G894z[_/"{{9gA|,Bqx([<1^[P>{5s]|9Ksb+{9{aB/CTS>J"/}G?s睏9_Zmٲ|*)!HjtLM:PmD USK };Krg[ߺI]Ƽ3lA''k}rr'*~;5 Uk0A_!D|Sɧpe<0pg`t6m/~1f@Bg-M1UA=HG*ޖx}QlҌ鞒Yvt9hRF)IdӦJ%&l%JZCrA,BrACBG-6!V{J\ a[La`txǓT3ypP샋@Σ+MCc_-Kvwҥݹn~?8NLN/nЃ]cD2%T,p8XMsϞrؼWcOG?hty)PpĴ]W>"/!ВlEKWFK2V}d* b'?{531>K<|=d46?!lTQJRvU3 Xddi@P6$f9]椽=f`!<(x۶zi.&D.F,Gk'@"& ȐW{$dXpt+sP X}p k(n,i&uT>Ӛd_>D|DqgTy+ & (+Ztj*~1JmŠnxzXrզOTg v*UKuב/B1\M4Y,W&\TyvI jP?$r=+b#ƪPo›E" 3aI8 (gRHejO?-ˉRv bjpoqC<rrha(p+oܮeϜ zgu淿.*7,lcx߄W`X?Qǝ%I aqY&~-F6!"D7]$k ?)\k 4XӕMR v}hICO:-y:qX,P#/tȑx9Ғ Xmk)'.$*鴥c^pkk @ZV@P8a `[ɑŶN!)ղL%MB-L832? vE<`FTpF鴕˵]=}hUF(jwX5kin^ 6ҸP=;3-!ɀVzzTĵU;Mp{7o^zu/nf@d:+g ^]K!]k=Vѽ(Tg`K#~եKzӛψdgEۈcF `:Ӣ\ .Hh$0ΨN/[)/_7Oc_`prroyseД64|OY΋oWʌ5k,ƮO],gkb?e= 9~E.$TG8aK!Zy^|}3>_uXCK9uѢ֬yߝ^2oώ(ee??.*!m`A=k^!X!`9`qFK6>kQdM/0hMOZlFhr_$_g~#wwj `-r]X| XP ˢ:hXTٲe\Z_xuW7* 4W/y_7G?zÆx]wimm}._򕯼l{HbI&MK>rógY7bW/-VOnէuJw{PgEF۷moxX-ֽ39%If\BIRڅ4*9|hh޽؉ǩ}k{/m˖EumBnhH-]ZHU?۴i'f1K_ڰuԔܜzۓ)%)&KHX]E5bљv!/YJ^PEAnrJs?j<2Uij}gWN[=餆/]~~]˖;ry=(ķ,я+83DwƉm[N&c]w+޾kה?COSSÌ}LC͆uEk̒ Hmϫ~[񍳓䯫+o3U04ᗿzׯNugTA6i7a r+G7ȁo0pug+jhqw(Ԕz '@$ 7l8;oC.zEf 9@`]B=6v@'SS4fK ĘŔGF,(KtǎmIC+ ㉖hF.byyԟr0j-er|>RO7ڐTjکTcBk&CwR;7WIAEY6] ue3 ƐwӱHAMvO~7Iir)ܛn@'Z4|\ɯU[)e1[Z=zoy衹DW[+71ԩHa&_M({ŻMRD22νXռֿ^s0S-Ɯ믿}{se/MǨ;ڇځJDL,1|d^ʿ&l6qw;?+_k ޔAC1Ze omk^ \\}ts`׮S8я/%I֍8/9qP@קbэf)]5| 12=)2=*9cv᪫z. d߳~=_YQYA;m;QE\ӓGQG#?RХ*z <2RעL#Gʯ}+_ٕ|oCJ_o>De-}S}v_r9(54J@9NO<С?cW_}ް8rc7no7hJ\"=} M LDS&1Js\oEX<n8UKL'O_[jZQq؞=SŁo?<1/u{kjIg" R_W1Tq8ZRM\8b}#Gf9\%ܻͶ]{_ܥBS?پM|<쥗>ɷV5#w?B B+& ]ke|߳H/^pdrE 8 WG bSBl%/Y^dZVthr݃w2VJrW|`5\b`w=c_WS;܋::_GG'T?^IfqegbZury}o8,]]Ks fi+ժ76V=rs~@L3 &z{1i{*:O Brކt mڪ7l.S]Հ_a%˯xܵk o-c"/ ޅTcG)ٖL:M]JޡCӇ,ʮHii'\էUeKh2SEj:' llGWNE+DzuEdDF+Rϻʊ썘{GUZsF)(sE$z`%P~J p7/Xz\.܆ EL0 pxG\n㺤g0/T}M4;; p/G]xڇT3KPe>4U^z7g UZe(2T+ ͡1eʒWX> W4C/w E3P ^-%3ExWGLlŀt5eod M-x'9R5 .@iMW]u^|lr"ŋψ]i۶ R.en[|G3n%DT+-$QO`xKX>&2O$hm4b$eOIQq P`ȓhAeCEY(U,X2 ib%fʡrn{PYxQ *N7F,6MbO*yVIZ_,3嗟Y oXӟVGѰ^SZ"wjkOpJ :*bGūB"/8VQaoWx3],BE!&SF1="}PA+KX#oR_У`lZvyb45E?* O2&QE{ij=Wq`L?l=cI_ }/BL&F*I-R?J4uَ<2_*l^3[b/%`O(!}RyD †QxJ{S,ш{n@z{"/Kǿ$Ob]öZCf,sS;*XI [,z en Z* Zu{u\ ~٤=@5 T]A-IɡޤqX(|a`ԵQ$-R*GzM\e9lYӔlo,?8^0¿``ڙ%cJ-48dۓiZrI2z'4ߠ,0YS1:`Wp_R{NP;E,Dp=!:h`lCDQP2ְHjCO: !M_T6Т< [Dk誅@n1KٜN^ҳ>WIO.Ţ{-<0T*4H'r}C4h$ j9r3Tbtu!wɀ ){ LԠ'׎TbHn‡:DMl\pI"!Co/P D2Ľ@֑_V ([E?Tgf[c"VρQ+]xD+CrAS+Tذn`ϠXU,slrSyAC(81`,}/) SC/LBl=6ؕ O2&JLLoT1i |J-*J?>T)&si{ ba,%:9< E-$]J$(&z`)y$'W1^dç`X{XۢW bv sBdNTK3YËSj6:D g9>t֥`2(Ɵ:P``|^&!C <_T5IOj6IoDe ԥj4M8`r #.p4@ UK j)fWj6rB6mv]E-O<1o=JkeJ Kt9N\itEXdyALܠ9$ka"˽b]'Fۈ쉒:!Dn Hj,%$,Fj?OiٟfoLy+2$pvXS)0>@,O Q̉!g]ˏF1,ܛo x i<Ӳ#_sDIG)$HPԨaĔb4"T3c aL^nڰFU7|)`_TlSЦe0F^I>R؍!RʂE%/pUW">E4b2ɁZ1q% LtW:45+:ʁGch ڳ`qG+ov7{v[r(7su}b/jIOπσɋϝ 9bMu*{5Ɨ"S-^zh)䔲nD1RH=@[U_E")%'ՙP: >Oǎ zM5C+Y:,8)]~d<(%`%HC,+xڅpPM_Яo_{hJӼE;vqEm*ZUK FqaQ]U.T"I,sk1%;W 3|뽮bxڒo>( S2"jRګ8ѶrxUKc+iPm^ib`wLTsK %V+Gh އߢQ<0׌jt*$DX;)Y RU+P-ۭs uh hbǰjWuF&Ckx&Y .*Yc{uq](xA oIYzXvCSӂ+۳& VmlL56R];1ግUw)U*$W1Q,h^+NRm)^!x4.hO؂Ej\eBkX#s% :(YT2!~&!rc`3.00Pϸ=͕'Wh J:Nh\Wmt'xQ P&356L[%*lA#?ٹ֖]P,:ccmvM:4^yڅ ]KSS*l xY,ނ-W! %.1b/d|[hg KIWLiU€7k'ZKQ`ZJ )t, 0H6#QH%9%+Ta,mz<̏Al24"nC:F,pm"CMg17mwds]w6~]5Ti%*?4>~HAIۣL5U(ҮXbj1 }^SRj5C+R#" 1Yj,N@p~e`B2wT2Q LHeVJ$x/ȭӞ]\ m^ҋɬfޔCqQh0&1@oaK_T:mXX(́급wr)^ uTmb6 q *Z.mNlFP*"1$\j5͝s R۶mGv2Ʒ iuQ${it!pt<NeC-f(VÛn $ᠮzO@ *8rMO1=ŔlO^AZϣe% QR= T}f?:4i'$$Y%ScJ\wju"8#ɠXRM*5TCu o2dg2-LK*hYU|Ȟ)WY u=T@bas u,#DC 1!Fy|= 9]`/ Q(Jm@SP,bA=i:=/*Nf;x=QDʭYj cv9;_a <qơO⯉REG8'H, M1m PM MM)q<#5tVlzzğQ ڙ`P 9 R&*(m;?=}R $ILf>Ԯ;J>} %|jϫx#`>m; Y#6:B6ZViMSR8ڍÇJ}}%'M8*g͆dW`XB(%@T#IpZF-OmR ĉ]Ziu=[-4][V:ZR&'˕JqʞWvݪ:LS?qrWj)4拓4`Xa6>4*j)#Nu-ҞW.&HgR/û8g|@2%pE|//_%8@]0|8D4'S]Ud4?3==Vep<_+ŕ.绫+˙2,?8&<+KttÂ28X5n2 |Zs"}5KY|~Qkka|q݊'J}Ǧ4kX\.U,NgxCP(htŀ%VqB5j Cvnrr'Z&P:=^Qree&^3Z>%)WduOWC*UE*{*5FJuw311Ó)_\3@dy$JS6qR*`qV9;?9g$lJf*Tծi}<(J567w.V;3T+~0ee(Mv6GG8Τȭ"6At:(SRZ5t?Ε9$3+k"KAts"Xi\R;jfhcP%2Iiie:i3G[sr9qn||s2 I`i$ b( `ۿ=|30Uݫ72:Z~p.Jwt2?%:Q\QLQ=Ul[&c5G{\TTL}Fx FDcZB,@]z&ަJe\jf\CstU[rRtbP)=Y;a)?(-m@ \22]IpWmg\wo'3Zjj`._ V6[|qF &9H:OhSVXekͦS)+x)\!'o2<7םa( -Ce:ܟɃdoBa^{{nݺLƲ}嗱bzk@|nMP1i,y:=ӪtA[±**7Όދ-6gRnYi$ SSSӜBnoZJ)mGDa#:c.bqތҚɴ4)* YV_`~ZGfޛfH|̌>lAЧR͔`0 1hbRNOȿ8B!ٙ;Y 719RV$=C54QP-S잲5duVޙv!nΟvڼt*E5=q劉jQ, ^m|1y3KC×8W2eO=5S t+92-%= `4#l6ۑؕJz-d!YbEWC-aVrZ[,:v@i(5LLe0=ԎSBh/(5QzB jHE L*~)d{|Y+D6,Ԏ3N$w@҆2R n| H2hHR2=0#_ظuKǩQ*n57#OUad>\+۫ۖ?8נ4^W]ס X3i tKKK&R)ZxŢ[.3Ds:=l;xq ^&7tCq66VR U&̢&.Sh&yrrFi,dZEd4Y##&Yol-*\,+ ds/1,ļIObPL<s `TdY?|wJgL5suJeF2Bx,…|qPQRi C=d>p%-g%74dyF:LF2ֵ[֖mlLW3}Z gtrpytHejj$x0AtI-qfN썎Ve\R)jYPsYB\i1 )ו+}n?ɄYj+SU!^.49Yxqݲ\NI'8H Cb?E`nzzȍX,%^`x(Y3.[](B % +SW o 9q3ok-J[:ݚɴ4Rr W7f Z1(80ccSS*juԟG32G;h5` g+)Ғih|-vtd٦5fht20P뛚ptlѪ7W𳑥<\k}gXtBayb4 MEgpq eT߸Zc[$x=,<|Ӓ% k4rKX-[$55 |n}J25^Tf_/RSSju·Et/nSd?Vx'T}2wIGݻV\:GraNϛ'NF*]&}PT(3NrY5f#s+;B.eYi0(J뗿uyN+?};go0ԘOoz5yN*`X/Ѫ#rnErLGG6H!d 7lXՕȶ4_x@FGeuEgޤS 5,u5&yշeM.g*+{SOMΛ~K;Vn,֖E}Νc`'}62ao]|q EȌb?*)H㏳<9i8ya x1tl챛o}χe [jw(LKn)pp^O"!$>SB{,[ӳ'VㄸRƪ|?Wٓ}(ɢDWiSU<14 ԏ\/D'~Gtw9ngw@)g<\2)^Ѫ%ёc0ϝezQbtŊoՎHGҒnnN[,gyH?+;=4Q:YڵM7sAqswռybο'=7W}2կث^u]w <8XN~8F 3+W*8ɴ45eׯ_0~F.۷/-q&^Quss, >orї0ƐmFАAPR+raF0Gq g2kG5fwYʈG1}a&Xܫx-ȲE,Ȝw!T̶.-"%ee ЎGI%J+܊%vC&3k]ub$˖nK_^* lh-˃e R[[Ol;]Z(P#VV\/o|;8lBVl7n喃ժ'bY 呑ZV׭44NNGMڀ=뒺$e M|r[zNJ˒%K]3:Zʇ>ᦛ^;5XVY>od~%7ttx;OM2hAcN|Tb]:|+W6lr|l#끶aYT6hw,y2A폟y`d8ukѢlV,"F<1'4o~{JR }BC )Y]+-p nъx?ɓ_5 Ų+_E)F{d2sE:y,(3Aq?M=BmlLq-c+wՋyzыmׇaR֖tU,Stvܹߣ2Aa5T<{zG]{/ |Xu pçwg?EX9yY39%mׅyTd d/OAnn2z}[GUd`ٶ>MMi=&'?[Aw}xr#j !˸7:?(ö MM֓{j ?>x&͑)bIVJQUWHْ8Y E}\Y8OCS}@v.딡*.WϜ5Z o<7FEwvZ —^l6֖ΖRjU>vъm#Y-0SY0#,)fu5-+smթ7q839sӦa~?ôo˶G>VVۈxnu Rs(K9 ӟ>i-e\ַwy Ȯ]ʻL5-Sox@+q#HOOkvDclt%= (/l10I@B!W⯠Wf&lBI"`+te2:_J|`ϋɉ x`G)Fܹtik_;ϟH_DRaXk$=yW'S|&o@ڲ~12<\ٱcrǎIgPHGGKiKj&Pzn޽===y,䡇F@%|J>ڛnzmmr|X#>gSO]yifXgժSNҒ sGGLW+ ''_4Zfpm?qo%qzK3=;0 A,H@I3$E[%QQ(DZljȒ섿BYV񱎬H )(EJ(R EA3g홞{zykLU[{TTի޺w~g;E%gT~nf0  pC/D!fβt61FdreJdH$z Bi 6uPהuf +R#ī$RCJAk@a%Y{vE(W^YOg}vvqqߊwo]w>cۗolDx 3bî2ŎMpԽ+Ѫ^_|qhZB $l喾͛w+\`yRz!GYtXd)_qE@!Ç?Mnx^pU]G"FnW׺M7%z#$L4:;!˽RWƖϜn"MC$>I w\edTOFUjQ$eP\6kmI _`)"YP{:::8EU4HYȊ`%D 9Q4.u烖 YOF%e3g ]p0+^pW])*S@wm7f7B cc˟쮁:T(/Y7#),~b3F;[xGgfIUُ>:16{E2{"EN?\tt=122OiWc\8_)edR)Gﳣ߭4#wΝɓ_ qz{g?{ӆ 1(5ޡP{l9rmI.D5y6HЧF簈뿈A#=- 6OjĂk[ۃdI#M'G#oYKW_Wtu ja8şaqS@[j9>~ofСEҗ~hC3M}}7/D!TrO9I8cDJu:?AJVg# dzPvjr8;xvNap!O}V9 ʦG#P{#+/PZ{dOZ-Dc'8L733z$ u,&mc|mCtK7+*^*1PB!`[~)ZWz5ΥJE%&JպJ@A7I+i=:/`\"4( p'#IUf H3kE\vn II /4޸ysUbwެzҙy<]oF88s{8NdhL#IV@|^d wQ.4M '4,\{'K&u&PqPD!ĝT<ʋm4їxIE~E"%j//K(PVE1Nؼ7qcF~O~2#%QH _Hkj(čWϞ%HI 解XbXKbR<2^M&O852rҲ:;ק{{]]5sZ 7ףnxZV f!l 8 dufm2vY0:^ry/.kBj'WW5h9 \:PjuSς Rx$̮J揌 H*Dpi:> IOSƩ:I,8٢D h|&&Dl~ %'zDƔ6 t]ܜ#޳HTJX.YF#|7%2dLD!P8 k 7fvG?3 nݿvC}8$͋y^ӎL 'OF'k\U%RZ<0P޵8*qleJEm"PY җǷWzTÄ*=E#[ iJJœix5*YE]>Zm?c۳D bo~剉wj7O} r~WaaOK"J&>!ao`7TT~X WLۮ/H T6;@T|^isNӦ͉ޒtʬԊrt"6J%X1nH%C:m3(DܞȸJ1Ies϶{wF,&P ok{nis(wp?o[O fl 0͗Y'+% Fr@G:גPE|OaQLGrmq:m QhXa);A-[MJmo޿?o/=[qZ.a I2Trݺ޽\ud>3_GB|מyf|5jkצ};|rI+gu׆LƠʠejx^/ B2S$!qnXIb.ߡ[@sn_ ?8`#[" -j@ -w5)Bɿn|^,Omؐ?SC)pq%s(W%.KH-zm\1fMY,݋"Ea*]w]ϵv}<;kON'XZrS+Y֥;;M鮚LtkM7fvL$b0+~pc2hh(=4nny[Zrm;8xp ,?Yf`7?+s7^#iO7ںu6l 8t̙/~17??Nr A9#_y?*\|*=(rK̺B :G̱&$pc(s=Wk+C(dD]mAHDP9{VAqv׾6|VQz(HѺa I!QOMՅW^۲cllYF!2::1^]~̌*%Y`q/XWNOשsSh9Z:5r?裩Ri ij9qǎ=T `M#O$HЬoTTo*41&d|;eCPV˻9@y;xN-WLQ4d"PDݥ$酫 2Ir<6\.{7G>u_a;gJ;%vG?N893c;]njN(Mfer9sز̸ EvuY{(bMOשƒQ%b Bhv֦4br&z۞yY֓vuqzz챩ry$"HYTT vېW XZ=/7cJvvRp–29IJMhdiE]u "݈'W A.)qaHJ+^VR!,_7YK/Ϳ\wl|[$=߹Z245*.L \śoShOnHw d- vKQimS|W-pT}yK$nЇvut ,rJ,O bЊz`9"L MЪ®$MFeINWt8ʋUݹ)_`MWMhr.i-=K?߸op+ ?$Z9tlXԠ6G]_Y;ƾxu7+w1;.tQHX403o\ngD.4s-a|6{ߙHiD)DO}ſ{hxU\v/tʱ@b=KQhH=mb6)lE#3SiB) ۷bh{(yCx-fbCR 4A ㏟qv}ٸq{-8B?[)93Y@8^РBٷ/Gt,@Euv//oߞOi}PӴY'?a n7\|1ۡ6 زt9[o[n~թb5Hgׯs߾! t]p͚A~׮]:gV%E5I$׿{w=]mR6A)K(P##)x,tU>_,m&O YFW]:-IDAT:Ml/Zɳĉ&R¥V @ҽ!%_>¥r?1UW5mYvTd#q|{ 7<5IdvdM=aCSC>T%mQ Q$+0ۢ] x>:5)BZqc…I]c棧ʂC3/^H$(VxU==5kRԂ)_);=}A(#&(uEV\6Ct9 zb%ؐe;UiWn송-4X3g*t}w߽#H|0Mtr cT$?ysV`}[S?b_jk΁O~r[<8Q̗Â5V2V0'>Qݝ̎/9SaӐYGuk;ѿ}{2ӯ~pPsa*c J_ox>̅O?=a]ww_6U#p]\,DW4V]7hh⩫U+ժO|))j%\%PfG|"j U]7cZV-.vE|~28?aO|b+y] #s׿b= ~3 7uKa (?qU4Pnw߾{޳ԩ婩zRƚ5oݶCG\&$6aˠ8F5gVxFFJ?>A?59~4;kWmemڔF%9{zbI*%㾊b~=t\, !ò:oapvwp1O'ggB~5RiF#h rd䯾7C^%T0sXcVH?wm[>ud{vƷԩR /5w^WjX N88s{;t]eePӴ'gjT[2`ӄ)m@-qM4_ѿ˫ TԺ>*,|+' )k(va)Hgxqf ɒUJ<?Ta` ES%)J>E9ͳ5r~ީVxeMXfRG?㡹9fY|3AJ[Ķm{taqRɝ]P; 3%z(P]#yp`Y|Q(]_r٬ɨgj90trC`t24a_{7^Xpyd b6 G/4?IyL*EU?Q{3ovRhjߎ=x*ӂcxOZ*xTB6ϙ:SOztcBi7>?FhEqܮ]|JV<}z~d}ۛlȠ2]G},KMAw'r934d Wfgsͺ])/H\@Z^Fp( 0ŸW]H+KWA2J@x^|q%%nW_]ժ766Kj2baY:{ps4!m܆ <?<~LVDVB!20ZEӕNk` ŬTréܢA,.TQ yn&ry@C}N)KXߑܱۛ14:vaj##^:" .ZgO%VV>s͕sXE9_RAB"K@'1}0[*%;;$q^_we^{ X&&6Z$vc9 gP"8 <" %(0Z|-klQT^{g)Z6N=@]5z!G~bEO$ Vt=I.D#-K߼9fg>sxX\@3OexAS‹ J ~0hDp_~ylSg~ef\7ϝ=[%QY)laզal{^ 74i8H2_b1hr?_u#n7ܰ~֬L"\6kRZ*KkssΉRbŶ8N(`os(dste)XpEK%iۮ\ju)0cm}}+kc"_sMıc%?>sgR-SԔx4Mu%{Zkt'ٽ J4s-9~ucpy4 19n:(do2϶az[owޮ 2L(K>:1?O{FaZ>y`i)$='==oetQ1X+:;SUlW6kۗ;yռZϟ?_}vRc4pvv]}$V:%')EW,6P_xX.6͎\_CU=ߺ"P*2h9PPykd'^gZj4()XT$&'ϫK`в0^^B7jSOO EǙ#*FRIe+6h*W)3hAm)Ԃ˧h ]O3r_lvK*55vN_A"}:&ȃ)'^h.}\?, :LHiHp>vJڔZT%"߲::ָ^@+ӽ`l@-c>>sp&\ peAӲr'![*){nXd̀5?DpVi "2{g_C(8 Kha2M':q)0ٛfRCQآ -B)d2zl:VT7ӧ.#(OglqhsXݎxu+lJێ-:tćAdwnb3-A`./,8]-b J25O-Tifr9k۶3Nc:NG(C|!Nƚ|Fc #\ 2 OŦZ?8ӧρ @A7 rHH2}1>G NF:\߯?$-\Z ۞eAe@ؒq X8tu2HdRb itJ$zB+fm\,[B*MuRE`sR]zvd3t"sn˲t91TGv4AՊW8:Z~q-F:zی"E" 1d&c`j` OY1U$)>..B}r9y_+=KXxŢʲdLI%2,+]C`yr֭K= BvplR"#d$ZmP?D(y^Q9cbm腽f G5t@^FnRAIx"XEf@tsڲ:-;2Ų8HdY HZ1YWM`=,T>aI=KMK X݉|ފR 1֊E{i<^қd\PcNJJbīXG?ѱ pu=il6fMjDBna\R$:0!V|5k'&ND,bdȗAƄNHpB@-2+ӳ~y:=x^޴)C͵wc<:\*]`k8qN痗ϴ$Cg?_Xs$8p)B72"uE`>u+AUTB^<""R>-9"tUѶg2 ]!M@^QI|> $Rݶfm(t[e'ih\= #4BnfkRiDZDXj_z-A@p.[_(nJ|`ĮdgbC)  +2p 2{n IfdTH3LnAZ'1l0tJMPmz,@7a%TZ6P[ 1 {VxKlRt=IrAhaLޡv@X 3iMh 4Jk U̐o|e]7 ueO0ke"dr ~%ZIVq-}*ƶ>85U`:y|14<$d УC#VѐTQ)0d_"q[^(c^ir(AQ0v<!}X0Q˶6*LZ#nzd?G3P #E T\aI~bEHX$jl8U*ehI"lt=˥_ǀT ZlI(u_v뚦=ֽ{eyŕe;D7!AW]3TR_ *idaZo5߯jߓ9 YXZc&4Ħc?\ 2Qmh,CB®!1k=_<Y"]lȱd$>ގaNʐz,$a@,.1#,?# ,@ (Kmg=ż`Wd>O0;[eLHB&Xb-]]\[gYrdBċTh_ .^b?^3g*ڤ|~>Vf}obyyl}ur-B'p$BUi%1fvMknY:3`W|scC;Q|5 KtMH,lPJc}+BSKu7N])&;;A)3~u3^78T3C5>7畤*pYギjŘ) ~z@?Ôivvu%yˢ.0D8QV to^oY /\E.vNp߃Ҍ\&D00DD7UdnGy@T ;WnqNض**?`oԩ x1*[K2x5֪Zr @=J%zBCW_W1z"+ě"^c ] 5o)m(%.'?g:P_&ߟ0 iM3NhGd|.;.5lk}9(_[,G wgc<{)ŸRBC9!(Z5ֱ%f1Vold 4w&F9'5(&DZ\QMiMZ+%YdKB74AP Q}0(8,O~2S._Ȗ՝w]0ƹugTeRhb:`3sϞ##%۞)ǿ;ֿ5an,D_Gq3 bŘ,=@ǜjdִ>\jiP(3/"BL0=ؐhǔn .LQ80*| PY,-HGk^3w  7T3#?" K]Ek*#G.H|KGZU\,d29xݺ4 .J%zTX>P.gɾ躶aCk,3g}Ck/1I|qj^H[p-H@.Y:0` 7Y'aGCQ{ FB+rm`e!!C-)Rx8c Arn&/8#OxyExTU6ko(6*B pZtmu_P__SڜY;>^?|cm߾.tMN]Zx-[oU(@%S^ÅUN/`B&L^H(ck佁/AS 0 EVx d5tAbLd@ڛgN"׈ >~ &Jr0/WJ" GԕUB#(ٚE)LjॣU$`4\4!E,ɺj0==\dLX&СZmEIΦR[Ϟg9cnm߯`Lu|0_Ml-!MT2mq`(GK!{ A%pRC+M76*AA1dr  LSJP CҁC7(̑&-@d,}FEZmM0!VwԢ'нrKAK*׫I5lGKRaΜr:#p~t#60N 4(׬In)W*3Ǐy Bqbkz24^1bdgE6p.kR 9xX ȹ!ɢz-@ Ky @?n׀z&0fh 'gQ~dXXW^k[{4RL2(AJ\SOs^z* *y@͈E7H&|ĉ2B0ReQC ϥB+=ev4McGnhh=_wOyeffOW%Fum}&Au] pZk$"K1| qMxI+ݾb46;C 9np!6`MR-l2DPؔ;{2g.:x*Gz2pl5҄󀱟tp PwGUYj _'.DJXrDnU_ݹ95`yފ LO0ƍju`~~OOש rӦKY #V^}E;eH#Xa AOǨkKsp4">P?\>yA(H6UjA6@Ɇ%oJU̹Ԓ# >ů'%F;GAŀi[Ta-/˫eWLj{pii DSV`HO XIXmʤql~މ2V*4Bb‚6autJaoB} Ƅ:EHR'#-( M`<T!^A2dEOIxLw>xgͿ`ya_ZScf LD )-vvB6A4l[ޢi|QZ9&5%TFw5h X$ѫY&i`e|fYaIA@bdME-4KOJ0d3;&h "W4bZt4/)+RV((.q@!R+.g${l1/ cɢ'{o7:(VM; @0JIZę6q*RQN"pAtU*ֲ櫂UU$`8QYy;;|k& \vgf%wiukS锖Z_\TI O֥/Kzg@iM*Z]{#a.3V֬I 50H3;5dy~nΞxT6³nry'$5ï"'J­Q0ǣV/Ў%$jLE-ͲJl jgpK9 kr+ m9JAfǿ !Q nG슾9\e.iحoZ/hQKXzIӐif=wk|BOLkצ֮_ΓԪiHXI-3լIԐJ| P4.HP:k4^2`%T†%tgBGPMuXix d"@Qk֠X4z(.])TL&"_V.K^m+rƽ L5`x2UM4A׮MJNO_zi~p0חr9+Ƌjj8eIzķSu&'uq4Vx^ͤ(rJG(v&ij.L,I̝  Ac;G1;2UWaO@Wr>mOFCOHy481TR0bZ!BDQ,WU 8J(2.a/O3E"{,a^>wOe2f&ctvZ}}|>ߟYߟej#Ask#t6klؐY\\LKKV-_!(R<*VZI_S] yjA⪘4)d> +Dl:¦@-R J-A ^ Vshf閬ˎS;%"Z<#̯ hQHX l4gPȦ&]6;kR*ojFW^/+]l;)I:;su+ͦc9!,BL _޻@'T+>!+ F+D[7x3Z2dH ,YnGle9m`@ ( I@rYJlEˣnhP/zv׊v&;®Ci t۠լNJ6ց61k _'hy`W4beP!=e[6KF3Ѭ 301e2VP_C.f1̫Pg='aֳ b^{lpgp^z?*GOV =˙W8Xv^뻄ӽB\yżc;7| eU/Aj^RUX^l)j("#jŠ7Al$ۺ:vnxoEůH;hI= uQzO\z|T$')UDL,\hUF/3hxF]Y󤲙Q)Q94Bݳ>zMp̄_eΝRێJjs敗GG8xyS[ >E0𓩫$MJN81dRɻC P2#X>ZY[(0!!AUE/iwBV f:qp˂+D]p❈Pޭ9X2oS:д-YyJec^ݮk-L-TsɵhbGcvbBZaEJqk`U}˞8i)A`໡n{fKl\l"4 /:д٫ I[ PЄ<8,węy8Ӊ>Ub.*T-gp6܇L1SцbӲeh3oz jA.OѻbQ2@hD;)S[d9hsK`}r :?չ݁׊v&b:>WPj$-H8(9[I89[eR?㦲xƯΔ/n-_w1YIwF&f+rRjxY`{='rԢ_IٱTך; dPWwv$۔XxP6⵹,⨑8!J}=H kg08>43[O#5HΜ{&u.Oh=qK TR_z>1:,c X_}!\VV4$s2 ;2@vϠEWׅVwb^0ļLii&$!UA غiAC.ІbuAYވ+_Md^`E~lEeM7`.SWq^Ra'N!{0>Yq:\[OS8B%iR9CU|̎dM YTHZ,ZoiQ$Y-VO(vMp$Μ=U89k zTyl^ {EU"BǼE_RNRb7%;n F@¢Ik;W_="OjH2Q>V xfzޔ:Jb{ 9UZY[:MNKZGŒ~ VaYpur Hth@޽3DZ nMY+ɔe8|Sq4dr'W4LUPʡ<%ܥ۟45wv Ȥzy*Ra+TʦUI1}rTQ3BGT\$,<;zj,9P(2@.@CTy]<' Nss/Q)"wIWn b65]5Cv3k(L6:VK(U:c'OPdYK ;EPil)?кV#. 0f1̗:(Hj&+ C5sA[HklF6Κzk ӟd:Xy͜=$&n lΈl-4V܃Kql>7Y)KnT7ْu\c&dzc(XԌRT󁲙c⠹\PҳWdkUaHxHU\B4nA-!I۹=U,m^9ћB&Tq:WH${>w\B\ wf`[)Rث-/uCD:rd>3Rzd85%Je̓EN ޱDԚ)OZ7CC}y| fK>(a2J#GFiYP> ͔SsFMddUiD8=55Gs^v^&+D"1f.kur3C+Y7*01KiI 边-h/kf\|@i.!8s#ImI[utUar{5=yvY94 P/Zv$- rNO(? X' J7ԫv1d*Q.%֨Tg_/VK"KE:ؤ⣚ Wh@r+zb>CU gtwoGI?:\v̚yʓ,A˷)Ip6N*GAcUe[x (Y6W6/v0\M)Yӧ||:sdKx%YC 473G1ZM~&3vTR؛lP юS1v$1Swgys"lYټ bU%>!On6Dڭ|bw9޸K6Ho}][?{ܤ0aW{ܦuW֠E3%$ }<0L] Igu6j)e _hh5O4/ њCb2[lMβ[JXFV%M"@L?}mŢ(c#hNz(nפ# Ԯ)E @T},z:p_o= =Vhdjs]3N\%[,ucSÞWظy|h8/&`óyceYE{Hw*8ZWKTDKvSrU ,I!cs5 dy\B<*C@ PܴQscT}HQFuvM8A+PcR׿u <+>c~~NGG0cqBhABu !:kt?9=U}׸ңS@ÖP1 y rppݩ1^bX3JwR1=fo\Ru!S7` m @Q Zo0hKŃ׫"`"[*b`P KM7w ZY~i`,WT˺!cc..e<t7X1#΃π8pմ4v 謧hcIe~{̒vAd|={Z^vrkm?8PSI䟅G~oa=W}jzvaVZH$mi}`Ë 4xx {~oqTڬ 4؋:ܒԈ)a T\!& /LذܧDYAWAV'k-u`g^#re)旡kμ},WS쬾}1b{J=wfKJ &uVchET,#,pkNd ݎ[4Yk2<%K;u5(DhiꈺRŭqr?3_VpK1ǖ[4FA؎ꌱ$5ی*( )B+<%HS:~,STZ\!wozU r:rf-` }*n9 .okgb-Г}f[p GA#ތ2?>ʶB J~EZ(q̱,^NJLE LِN٢ /'f.IY' ц*g۹ĸ##1'=4jUPj.P-0M$Q '<&HxÏ:ʑ&d󪵭 YWR9AB=}k#N{r3<Ų`βNr{kr Y@g6C`|'yzGTP#iV*S=)d+zGsE)7dJ> 6՗. 5RKj=?AQd<>3sX=DEƪĠ[٦ Vd|&@t;be s?MpQ\\^E p :3 =󊭳<+ovj_0ٛI'Yz0~6Jydf[p%'۝0v5ֆ4҇nhe(f)h5ΒWnfqED@y+vr?) `*ĻunLT'U,D(љ{mUe ;RT 'm̈y+#?@EؾwogΠ_k() P"YA{Ϩz٩h W\|`kLAW{G /jùS-|8? )'') 7ot ;a}>Ęf׿>өW[rWPP Z];=UZ_^d_J9o$[ud+عx`:NjoLM,g8DO>S4C)VRV@&3rpr[xwKǿ_z'@~x+448)@zQI&q"i/"2բ]aj-5ȪtdV//ϡۆg\rʹLG)~8/0 #VJ.3޼lXbX YU+@t(Ťv<̕u֓YmDzˤŞRv,'W.s`s-;Dvg𱱖3,"[|9Sᒑ+SX0#6ևDrQ$8#0eBPIr&RJ2;_xfl [|ґ}_>0k7r۬-eIs1+ fZKi Jf .YCQ˥ȥ˷@XpY.40'ae +\{WrŽV/{*Z. uĢ̀)&UuCڄD]Q!Wl( &!h`ltk( bus&d`"%D\VDe&cԈPT5;Y&^Oҳ.^ lO}N\!naTX9EGvdE>UF[ Fyd=ͬK1:?%L4tO!{^B%-`1[]";a D\*|G)%:!c2GOQmASSČÖZ{Yaa`YY1cw?]v[Ьpp!0\*!Ȭ3pKW8@wz0{"Da82$2U{|joykqNY2IR;~b 4^uLPld 3Y:u0%M4 AdH`N$U\uu?5t\聾C1UȤHU0'1)TB΍\L*: hgi7DfrZT?.L PWn |T$ĽHnNܕ<jR EvƶVg<Jijk̐X%>|ށ*1uҫ[T!|x/Axi߄7NSFU/ ̡m Ú%j䰒;5>Pٺd+dOÞMCmoSXbsһU04arGox䑯h V.Fi.䚥C R8Ͻ7l׿mXȳNn+^Vw_yN6T U  !1ҥxƑ:gi0͟/uݏmIT05=d CEBs/8kj&J9|;65%m1X>]Rz ~䶍;J;2Cd$Sf ㌬\gr4bZg;4jY``[ p;~nYĭ)׸HpO@9F_?o>>5kWG^K+0c7n\Jw.v)p9-~c`XGʕ'|l9ǹIT>GԡbrʈG:"\:gno_xl|3dim@)Ap Ypzp~'o\/?cQ4bܴGAހZe\RBE@ʰ`ۿ9_z)_|3w/g`wJX4M%Eb7Cm͊_?e8Cu][_maI%(:5%xҽC<]zEV?.ja֕^oXIp~]F=,_enOүɛ``p˿Wwr(kT.d1~"i@f& 5Z;kd<f{(Op+BkРMVYss3 خa4 %fVvůp͠M=(S'?N~_󏟸̖TWD/>"F뤨Y&DsCxŹޚWm߼M5l*׏~ix咮dx}WFXMY9.Z,jy+MuQ}_h=pO%YwpyJ׫Ra_ a8nBm]v@v5.ߨP8lD#jT yql=[b Q$qiHi!va_Vc[E)jE-iA*'̋׼mh]?k`qlK;1:f h.wܩ<;J&G:=O?v{Vo9ӦpJӲ&kiKǵskMX;1)r1FS.ANb7t$b/wQN CVR#1tw_TOTQdE bEX]+ $Td%W)H4pB8W_wb$" 㡫W.c!_L!#*`96%oYY1L,Q+>:lMF(kP"@#m?}' @Lj?xg_;dFl;*uM fךGmYLU%uC裓rҿu-Zq;T i$#@dg6~lW2KӸ [IiZ hGddX-6Zg+O;uE0e\Z, ʧ`1<4?~-gS1Q1s&*jXYC۳S}`{lIŪsj^]}5Reget󒌬&ne:##G:xkD`?ނ3MlP 'kNf߷ɗJ{Db"VزܞTl%2FAC;hV1("/-P0\g8"qg H)2RI"ߚW#q2/{'H_"=x孴3O|l\K^Vt6խXw9]Z?o}WPEsei^ IG"jԴӏ.>K`a-qF ҩfQhK>YsR,&- +}E7>Y ,@uRAR ^dA4)KsӎCzp5pkGx݀S3%orDتbn$PMm+v#YIoZ:!-}Y;v=0>}_z!$,!{B]:#%8a*fk[\uc~q#j9?Y#\Bn=v*xXV9,fusJٽժbm o <P^Գ1L <1%Q{5FHFp)Rsmkgӈ7߻{&p{ kDT!7G1W}Z2|!#67} t%1!AeQi}Rđ2g%CvޑSgw삭jOmv%l%ܙaePڃzE.$dcJ3={>fAdճ]{tjم +*S\ <xO3YXC]dt͚)~my|-Uh}SNBy]dXe f7ϣ`%՚gn8DW8.r `%;{@T/+48^ޱ xCg_b+{ر  'wfǮ4L3Jޱ}L{`#Z&ZǶ XD`)dodEܹigo^FUR^ ;@i]xOݶ +;wv _ b=Z>K>V/4,|bĥ>")FZ: 4Z #C[7q氿H!3j׆PH;e#2 EW5s rJV r \ fa@!?qvxLe7ihۚC*sFM? FPw^-sW| ;qJMȼVTezU,M?:Kܰlܺz,ԹcEЈM0DxqC'T)9xͮO0_9{&^NMR&\0^ޙz9=8Gm=5](Q_k^7^0{OfC9I޸HrE81F49ݑ'5NT8C5!22MHGh~\&'䣧( XL*Jό 5fZSܥf^inA͈B¥͵/c\f^1Zue8>W?s1O<8V|ttM՟e*m)>&kZZ:aTRs}N Ē(1mPb'i͎Jr8i&lj?p6ITxcssNX?2*.\2Ȍ:#x=ZV딥Hϩr1׷HѤ8 5iTA*:s7FDZ`(XcPj1g:&qX/gmc:Y֪/;8Jd/dxS7rm/V?{]Er .\vb՗p)͊V|B3?io gU}fب}b&bxZpwۯ JqIyZe)xP;cE4>ȟ<ÊqRu+!8]L){,GWcSZ=>{maTvQ8QI+y)ժۤhoݏǚ2aϛu -yuœT!Wև/2 gP~c+G3t%+=N7wێwau"I i!ר]ȀŘdv9AbW; T ?2߬|qJ+nd{#b`jD|zbkd%j4RЉ1~{eTny8N̦Ƭs#²G}@"颏߉n=V j3!ذvl XVAθc`v3v C3Wm%Ԗ;;rLizudg1dUH/ޔ׮\S3|ygw 昶9 זdغsCy..Յw2|jDH}V%xHny|`~mknVG#*Xb;u{͏`#[c(x xަ46vjk65ϩ5'iqL|<oy]O_;vMZcxQʑiʹsnj{+1l{Zkg&nݕE'ʓαX-$!gߨc QUС#&6A't5<Ãψ(4=*@lx=*3 /|k:qD`ZS'pmou^KM?+.ֳfnxϦMlBӘkxyC篻 lZU쪁g6܈om=kegCr,y8jh >} O5( Ǿcf >tEovlv%s:9?gNΖǩBrfvțn?{N q׺=\-HRp]-Ċ0M_Mf=_#xcm+YAcƀAI1x!ҡ '6-ȿs.\?#CcNɗrb4kWuS> ~N/΍/_pk;H?YA l}gj|oݿV5ųwݡ=,z0{k&6]঱bzA v<i9X}(Y+fЯvvS/Չsy`8tHhi8ú@gu5xWw/yի{6m9cOY5 1tRϚZ /ݎuA0VCoo`f:gE ߸gbJ?Y^<]}Suz\74NˬË'~^^9aU\ ;?/'xLcYD-DKFu)@c=~y D?2c3;o!V\Hy>cuLT\sdnV5w+԰lk<ⷶ#O6iB{}Zz{gTI(Wmq בbu&k`U߿]L n֑hlڒ?dޚMCU`jUG53iM"K `gHAD'2a㷶~ZC{A"'_e?- ŞyN^k󒝨Ubq'{n%⌶#x o[E9vtzA c9R<{͌ rv٥Bʿ$;+@#VAxQ Q/PaV y vMwKeK\'WC QԬHg_W;FT9.?"`g\(Oo 0*b>7ȧ`O>jv8 )ݧHF1ζ|e\?[7k{Ȥl.:Sl`?1P߽Ud ZiV#"s-1FoA(Qn%pO:< dE)[?BdB 96wygh\29a#wtW6AH*~|ǾgWj'>sxQ߱A5K%K:X[!ѯK{{&5V|Zus1|x|q7pUPոסvcqJGՈjTzPVؔ_ֽM׌/`=ڒ&(eLy]Ĵ<2}NBh<`Dn(9=_Z[7ۻٱ諹 ؋@Ub~qJO3hXVc]w6M2ڟk棁Tk+ȟ۳ 4}@ZkfygJls]sšwOba)r%ǺJMtS^m@ ܈mXHy3˖Iv<ٝ7=r;?mE8vGggv>wp"^Gc AKD &O? ݧXXFl{4Q[Xi2ui{'b8hl }s~W` ŋ6-ovnڕ?ql:_#\ p+,=&H ߰g4ܽ5vO#V'dow67_ǷC0}Lh65j\cL?~C^_rL'IJ@4ɠg}`ð{q,d~s/ywk!ƂV!C/t_ BG} %BF}s]p5>=[:!87\srHXFE=TnFNvr|fLv[9ٽ (Id(I).wv|ž;cwin}^%Ls_ }p;eGat`%%=t̝m%,s7:<\w㿼[\P\j+pbc{ar?w{V!F3Jxt nrH`d{ !+̴ )ǔ2W?.8煇;fn~;o͏mF]7[Cl \ [R֞7=)zC8aQ'we}ߤ!|OԜ'螌􇯾'w~/OmHN~._>3L[6\͠ JaeEsCVҳc7gopM_S5qT1ID:(m1*Z-t s5~Xx#N+f =OبJ&Q=Ubʌ_k"[#(r|,fcBt[/i>v{j27GXl_eRw^=eс̼j/zc:<7Q}U so0yTǥ@zZ VY[ Z2eWPEԜ tyU%&܀ۘh[nJ͋$S)iU4沶A`gY- u4̈́jgYdT/r'9 e.CXyљ9#vK9]_LZh'>c1KhRO)ڛ5 hUF4܋ ~BlB10cB1k>`VڰXA+ֽտvڱ]_s[s!g }'<-whK1D9Krdb);Ao?GHEe 4یJ5t~4͊7g^|ze}GELC'V'8Ggjq@ ?*hO :T+A(Q[.sFFoU|`X HAmXX =dxHx-1[͕N)`_ FT6ы=ENIGZ-7i6\ k,?(}j@(lO gxx"4Uwe)  (`-@v#lf}$QD8 ؂(l*.L&Klkhd(E|v{1DB6P bi%)GO?5;`[t߶WX}I篝W+۾ʱ*O4jk1#]ц)`1ѨG Ʀ'-ÓmoTjCgTbcT l:|&װ%ЊC$v6ǩ\&P* hPS_ii[{+^ 1w/!Y1)i/D,zbQ o**ev$gs$Ha:Xk%jxwa BUu)e$qj5‘z1`j ֜":a dqV,ĉČM#SԂ<XgJ8q}.91dՄjD\ Tg(,;y&>@d&#kO0~kޕʇR bxP ǽcА,K5-XI纶H V;L(Bj5ixf6(hceD9xg \qC!O9wqɗ".^rr(=$>fohM+ &a0$qLZk4(}k+6AuJڛv[{AMHr]{L1AU$OBIQi J:Ifa'170*n6A½q]랬Gj&wGH:68l,TΠhpBp|ȀjóW{64lbq]/)ꠕs!+gp{!`jmz+ pټm``ZR :J)hxjS_Ǝm_5H`MIRe6 f ݳgLL9Ck%E="PưI AӚ-DN$vb . '9|woyZz|YE~(Mk+r4 "{6Y KFz|YǼYq\{xq6?nQT UD 6:,g"UKlul&;\Gh.a(| &ł|jFW<`ˑmٚhD[T=vzړݿ ~I:pr^u4G.8)/B&[Gb: D=%Enwb;p6~ `yIǴw|op'4 `i9 0&YS6AX6B!o" sdmuz'_$[h2mqU"LP v}/e敠,=!Cg5X(bYiQg&gz~\MI'֏$v{ԢLSL 8A'e¨?%a*^t,K1} k6hTNxԅZ fQ)UMB:,u97 RBLnp{n(9!Tj&).KE) g!Ǵ)/,D /syɄ>ǿYVMy MC4M z4_!!XO>/{IaSX#ԀmL\-_QQ?}p#IOV׵%e0J U& t> ЊS$ cDX 0 :&{qk0 X`A >w dwD{x}nNcREtq*aQHmMRkJ!h!u9I!*2Rvr%[eE'Xaa3EJYhaq!q)=kmWuwߜIM&~hZ@3tfAҹBW& FCzڈjsUJ]A(-h=[>)gm%ԕǬ(@0hnϽevϓ)tO@Z'P,!{g+cX0t2l2c͵;aw-ܾXS 4.MU(6ebXi'?hɖ a0L߰YTq!Pgc?^pY铚"5- ݱOr6h+N$jeI$6_!aP} P;.{H$ f * =gCFfHQSVY 65'JܛkȬȭ!աvycT vIUaXTISXXbZ\C)+}؉G~AYUawZ|l֭;xpCwo]OPoMnĞ"j21; x}JnϽ>c1tEi[ 0+,9`}oqȰ ^`k8}{uzUhhT ]LⰬ9y6R57_"ع;9`>rZstף-:m0)$^ue.g;$c:Qӹuh{-0Iˢ:LEDDQ6i _;n(%!ڥv(Cphbm?p-}KnDX$SMD -lI醤\t謹`&z暍t_~q  s3ld\PqyP()vU);b\j8 쇢MGojC5ljFtיa MZ]\-Ayf6Ggo-N/XTrs~pGl} B/ S"V*ʌxQ9Ȳ 7pt QD :%Ow@i0MxAѴ e5dBUeY"3uP"Z4YR͒&k csTvPV`у42Gi14<-qB<;<EF`"0 rxD"b#qD3ٺT_8i"bb*иg],po<c7PM5K: Q=[\\O阃Q"Dt))%bx",Q[v?Ck, 3U aͪ+N8C/B1Vvoyc 5=wN?{M%F h _nyJ:P\B)lyڝ/9%cvtFlDr`g&Ғ$5bP˜cC!E.P# M_Ď!A EdIc.Dox=EK}FvO-LLɽ1v_ch=5ZuM!Io! ` \HtӟsqL 2]'b P\ϣ8uwӛ>ܘkNsa-O{oa;yrGNpzA)iOW }P;ǯsb$3\A(Z}K扠¡YBsr ,Y"i(6\;[M&u(%4)E&QIqfXH4bNX'Hz.,wRO @I6\Qnq>7|U3cHaylXReSrI3|}[FZ BG7<.3`-_ii,{Mb.RyJ]hS&_UQaªyL.‡76;#^䖥!hCwn|[(k+ G5SWG"S(5C!y*YND|2f",(*1;[LuRmR̰y8ME.ST@&tc3 (w+ )㬔c$U1aKE;cQ(R_bf ` n^ЊQmܹ2ěҕݮ-Lt4 D0 (\!jl6~me߂=3}p΋cs[oiomdg͑ȥBJXlբ^8gJI`Rf(tV8L`H2RCppSIreA2XE*[:8% ?U ! &` qHA~":/$,CPKeMl<(+c(F.e<5e,3DT} h*2A%!MWcTfdNX!'.;vQ~5|NQ֞Uqc .Fz]7Qgh+AG ާbߥ-+!BFD(/SJXޤ rE|h"&*c9 g^QX'8 Y\Z逊k/Km2hkD*S 7P]|xRyH :Cs)9HN&2b1 ZfR9 `EHu[OsR\mڋZ jm|doLq*\W`AJtwC(u.x3fqSUP^RPZLrXēD]fn,ANN].0J8" p%KcqGZ*e+5B׃ѐP7.+0˅ D!B*.sO*H5]Kf-00 NB3;mb4|f(N5xĨf:ѮS@X I[i%gD/C3 3>.# qDkQ,*!Uő˖w WE%wc)ẵznV98`L"`^3Pe6+hoprmGe;3*ai3MT”#[DaّPacl7|,NI HHJSyrAotJIweYÖ!EDz "a,x@ |Տh3VJ" OLI暃E_˔C]]80)åxijhyP 1&Ƭ>.n^2 f i+Ozji-AԻ= 2OJz8,WSM 1SFv `<:K@ri޶.=R]2B2[wBD̿>:QKS5U;X<)%Ǹ(WP@ەdmS,w_lVXǗ$![ JVB$Ӎ-l앏_;¡B!(*nd9{!/`HVTFZoXTF^vOnk"IPڊ!N.`뱨J(9 9c#Dl%XEckPJլY'<e)XsWW˗uJ4 !pb H0Ӣ1Nejy*G'wPm'!DQﭭey6Pͧ{(uk\oUWd5O)C%á%.5Exy)-rJ=ZˎqP˜"j@ \lI3e7J* ꚠ,j$╞e4NuIݯ_CgJ<˵FQr3Z_u^Ҵ/:ɨrbh+'lKl-!AY)6("W+eЌ46 |1* g 3s=m[GEYnoͽe#>8&xU`Lu@8@fd7Mʴ]XJڒ"jg7]p9) v`4``TyYPXA^u W^q )5-`߄JdsͶoڲԊ@@@؇ejy?YD#qܿc%AJc$f$RϬ"?[gNقd d <14Zgř,ÖQ g.>XVX"*'< tw@VF4Gl Vonsʕcd{E<50䲕;Bmv!Wr~8;"qs*HԳj#Ǧ|]UJr](2K y *u;RIlA&(W`w 8&lÓ#nj╡q!)mi˞|?d˽G51)j`kQQGBBۆMaٙݨ>7w8ު*y /,r!tVX}>YOU5z<97XFFTJ0`]><L Ff-^<28f3KDLa7=2.eX)RGixU롟[Vfu׬kDsbgrv ,EMK9(*nƟ^4^ +x I3t*ƷJU[A.gY@a7n:*D.UQT.b{`"-54)kz<ɅTHzV7C9 [B`xeԺ1I$`Z!H]v/_ڷ}Ma| [Hi f\' E(JHQʥۆUltw^H0PN_ҁ Fkdk'D"'2ewn㒉:ye!fOh_emv \;4ϒVYQK"BHk)FqJoY|@ڮ\" K͉Ys*$MR` {Gg1Qªw՜+N^15AT`9TT, !E-iaökXFC˟,sn%˙7T\JZ lw5Wu5Fڹ;UYO堊ͧI!v l)w['fwnܿ8eu4o"q*a G~Uh 1SڠL']H)a95!vNH):ϝeyl8˹8p(.c.57AxfEϕ74."WxRi2\ALd\"Θ Z) c$U1/6*M )-b&S$(i$Zܩ`e?eLx!BPo,)TS7N ccWveSIDATBpBo D#mz?!UG7e;_Z2v5Z`Vߙ >Eo;Tk\;'k1[dѠYC NWNOE&q ]xJx4٨uW..|o=YiTDTDEaw=O.xtnsupr]:`&̗Rc+L0ѵ0_C!WA˴$lj2=eٶLV3H}ʠASNp/|+N艕"[Loe2 &,+"Ђ L)W-__qluar qY`*n}(&C. ӺInZ`y͟0 Qr/[s[!p% 0YXTː|4&ʶ;` ZwڅɅй]>sY򓈰soЯ"A|8d[WLsaَ$c =iwv>8ىBbm^GRum4W'Ō+}=زa5̆]_[pփ2Wp82كt=g=\*pJUId>* aECfy%1K!!Wb.OFzpaT Ty 'n4jfjS;i#GW*"Ɩ~  8oγpg?zٵct0C{+( uORs:^uO0Z/s"̄dDH-րN՞Lv޶%qfփLk35,Xr'#jbn?a\:7<IǜD)5Q% l Ցr@6hɩQA__iDgZ:Gޞy_,Ķ%0)i;Qsivf1=+x R]~@:MS_t j 8g矩1Лړ2j:ELJO_%.kt G)pDx93X'hwJ%D!lzuͿϨ`; HTpm嵝] OgqV'Ӎ,cE=uI.U2%Z۷ ILmE뼮eW ٽCeO;y*#ûDuމI>K[+(̡hV 7X]_U@:J<Ϡl`Tr'ʹ+^jv:*˹swMϰ'<e=cLd[| >E@#vkA 6nh9cdZBH_rx*8~55gp^4do|ۍ'o6ڻ0VygU X5*܊o?z{BjTү0;c_ZIWZ 4!j 2ۛcIdQLP_;fӱ.Bg"2is9r|5%NLZIĪx?rٗ--_'aKC3>ܴw0'8~oKic/9 ^jr9[<:>~Қ"hߠ! a18]F'8`ggei?Pr>??a+,EHtV}2Jxc{-?#1)BZ e`ձGNyͮd 85c6d=`3PnL}g~yNFz򲣟 X9Y A9+Jy_ n1їO Н (͈-SZ Oht{!"0S)Pֲ{Gos)/;gOYϻ]lŊB-dʻmw7~Qg܋HI2ݯ)~hikZю(fMaZSdW6.jy=OkDZ28Nowz^Og3.뉙zeQ ǂsY )u]mɁo__dh*JEKϰ4je$鎾!OkN|x3#t$D dn"xPrΊ8@>t[$YGcEB@g^FȨX <܆DRhICW\qӋC+Ѷ/̎L| xÅ/﯋x;Uԭ0VZu/(%9}:)._]7EhCךxDAKW? >#{W7/_R7+bUmmHG\_~'zS8.beҁYkC-f = P 'E@%+rW RF1 KHspk7kig;Jdc3$|vh$Pq'=g{^LՊ)'PƟ:0qĒWb8F* +eBꙅr3M~'5PHiy-c#{Wjs|l'سw<+U]&='LZX*]o [}͇v\|޸M+h&Ú/T->Cǘ)TkAjd(h@$BҍP }9L 0c.* O #s@`hNBAok R!o$Cj2t_y14 ^`E)a}sG,fL)m1?f$u2Թ;E\{U} )N\v3i)({$ |WbC~ۣ'?k˖7l_sֆ[/\w^'O/Bb@"iW2Y] Z`cePO!G|ӻb+ރ/.979T\~{ }%/aɣ=޿q?anOxX+l8cE7er(^]tI. i$̡+⿫.ŒFgDRݻ]ON͘īxW]}Ҹrqc \k'$gPh1ҡ|Wy>f|afՅ,uOQJ|Am5UWB5/KPJD9;^N= Hؾ 5 J\ )PO lb- ꒺R=u)3,ª˦kH^~:7Oď5Js/߮<\oEHC*Sg`' y=w尦"h~?^b0=m ]`j`z0Z(f%g,ja%nǧw>Sd?;}Ўg껯ۿTv}s]w]~+f_ȇ[7DQ3g5sՊd5!Ur<`8ޛqW2Ld,vO\ɜP`I)apA5 ]!>|,esXh@-l%4|f쵿?bqtO_^q"𐆞ZHZ=mx){yu1}+ʡlQe,_fo۫/Jo:o3_OZzcG+>xje>ܶ7upAA+>I9ukF6a/\Mg1> dxpC:!75nhF0+$ꢊeM.i$g腿콫9׾y0-?α~}\9 8v  ,x"TeϠ;7l=<R՞˿o._m{}yu .\w5Oon_+Kni曨Jtط-^4K~j3.B?o8ʔ5*H|0dkLw@Qb,#4A>XTh6S5%GмOXԵ?o#aEu\]uSOf!!tX̰]0~s9Ð_kI` q{`E /5?J[`b(5e&e[ 0k䷞׫ށBǵ}]/D /}f[Rv2?k_ӏ035UCGC}SHMbҦ(3J-jTC}TVTSdtRٴAWh#~l_m"TKT"[ wGlbfE8Vn-[VWq?g<1榻QSh&]Do !jo֗>;Ҟ4D?ٜچb9phC4.Ea[4tibYt+[V:.:t55 y/L,b@ȦŚ> Umbo i:o4» >"P_6sq w>m` ; -vՊ`p;eo#,N;j=&r+? WhYWGoa~[nuxi4w=xݏpNX?]+[V(?=XMc{540B2).yHc3vVMC|VJEaMm.:gc nxHR ޾u뜝b%U,EB:?s=?WG"BP4@?}]x^ }I\;9|{۹sgTZrֳ_z5 ?矙dT{S{U1Q>{ܑbEFFyOdsVUB',vQ#ti謁\ uxk쓷b*$ g荵!tlf Z[) ፀPZmAɓ N1ۋm4Z5bߔkZ~k6#F q'iG:5_*^LOgl8 ғIgNbX0:[<k4Ѧ_~+UEЪ{6BcuE6k6]v.6{|1`V-OIX$ng G+:5;ց:-WVr:O_(rE"u"uM!mIPrIsX`;Ob蚪vMnyٚ+>=ƻWM0PapRVr.r'0F]mwM>8F{4A+eJЦgCsJI/Z Зiџ!U3ʣ.h=uBHvH0yDS-a!BH-F4W LyU3c!2&5f cYCH\1@r:Vc}ުξW|i>or$Fڨh=4P3xfD{ Xrbl՞ۻgFbt͌y?u˷;.|O<! 3g߽tӂ(3-{UV)l|+E4&RT@f3Yl3$@*3Uc1*ΖQyv;DjbH4%jDoU_+ڂG#[M-3OV"&]G?b82 JӠ/ԝhZ_s1_\ZXN mO_ V&o\6}Ipo`i}ϯu+5Lg&{d`o_n6wd0Wh%Um1A]|eքO[spe*U#8NO(7_ofl JE Gp)*!SkXul@ JGLb.DS)G1d=me0h@5򈨭AZœ_zDvd$ 4xob`!O'^0YSn1/VzBv{>!=H b$,vJZZ>̰p힯w 6lNz3}5n9.Im~+y).uw?3OOdH +3e\ɛc3 d!7:J-Sm{+V_t8ИC'i5^z4L× Aƣm }t&|+EiQIT<&EH$AǬoxL{şn$[#tT~߆wNÿe!Pz7rD #jq{cokk~ne-7> j/e,w[t%.x':s%Fji<mzĵuŰV[73 /I%2긮p}?]MVڈ]7ЦD#w25[33Q tN9\^f}-Wퟸ2 :#(TU'"sPk" /Oo Qߺ׽#֪)v߳]_>ԬU™K9ؔ8([  v)؝1P~7o㏆5L?_"^h~Nյk{Qz{GKѫ6O\=%blpv#d'd<}M)pmEP[an$]CMTf1vۀӻͫ!)+`SUO]{ލ[!?k^uDH}),r3eE6:O u^wq [< 1NӟFi&*iE~ W,ap |ou^uĉZťݻ}hf xɄm<./C0P"AXESZ_zpEjcΛ:~݊2be.Ⱥ3F֝ bzFuΚi'0Zp14m~o-׷k,>HܡA̠s o4*F.yQCiZԑwh{ˎ2x̷F)W&^5<&R,0Mj0o|0~z|:M1岞;Y M_T骡;'W}m?rG~$u Wul~ ?Sl2tnBh#f>{ZY}\#^].4+Mg.bb/'ˈ O"Aå%&07PEG_l5!|J)8ȘI_1%R"3(` @rrax`N ◨8o8n\ͬ/1Xށ=b0Ұշ!eHS|C`*T\^PJ;2|;joȟFss8"MSLۥIqdxoslv<>ߩJl\TnfouĔ`ehh0\$*+;v}߱߹&9}Mem[/JX2v#7;~`md!upNԟ!Y̭ݚ[u)޹0HIٞrٞF? =MzS "!Y~ڋ?2&&;4ZZ'dޢpLOgJY}LwXvJ#EK;<ƋR{n#c7`YXHa5 ,\\ =D7>S_z;-b۳q1[ ].LV(O9>[lA5KcHSa;v+}na>Hj(?Xr<m4a C(_͞gt1;hZ@}/7~L%k!{[a*4d%WS sq-R<4uW2Kx1#lZ!U"/΍_rQzewe>W<}j#?kO_p5@|I užM?y(a$=Pqi|Ԗ|הFM Lܣ>J9IZĀQG~dGot-m‰΢`:Z)jy FMLf-`B %\y^VI۴?U")׻xRm9f58 UU1=` dqxp|k :Rnuݭv3S`BՕ4p3x%xw|_{ ;0_is+Bzv`W$q5f|Rd cΑѱ31619jL@.ߺj߻Vknǃ{v ~v,_am3:iQˁk.k׎9ZZ ͹ w] w?VRYywp@s⯂ (J8ؠSȔ}IxV|Ͽv}qŵWEx18[ yK V3` ̛~˝G߷l)$O,s z`R;"#=dH?E3XRn#_w輒{0|Ml<9pԘF=b.bW{ s{W &C\a_VΠn?h[is ItJMcPk?_m6]Y̕0x3S&i \ HM?%)t'=JױmtJ%c\+À%7$`q 2A/LUi-aH'2Ƌ%țHBV\Gvo-tXpuEI'XjҪuZ/9~dHozK_Fjyv,lEJE::Lߜx<6“;FL8 B=h Y1 g)[A$geeHHq׍dLDVť IHjҪY \C+W JL7u]79b:G+$07 ;H, j-{=R j8^9{^sW.o gP0`ƒ U ?Og[[z_u?bv0ŹYMQUE2Pn/|xsZt~h`).Ӏ<Q7&S;7b(py5rW`D2=+)OZH$^tbE$hݭ9 #@d+d+ʃ9}*5`f1mNu~o(I&&$rTb#5+Qnt7CN>][U-4^8UNA=ʅ7\azBcNi1fd@Uky[I>8pҞiu#5rgJCd]=; q &]0R%ȕWji]M$}S LQt$m.[Yv}Qe5~=Xᯛq.X72YU ÖC=&;Bs;a|!gG*}3iljhCo~0#~C%OܖFط4[B͓SjɫK#=aɮu>Y?MJ` T~6dB=y+r3i)M&mҦٗ,84Zu?|ϯD-_X򓻢fB*E=!]> ):vJJeADx0`fubiR4]EUGY02UUjo>d Ba0Ӥ5Ö.۔ZQa&F'KՃ<X W V]R $zȔHVA*`/`2 DU˄E)_ڷm(7E-_ӞN[ YKma#㵞o\{kQKMgT}* J W~OH0t7Xz42vdjZw2=V;,3Il9P, %v1[/ٔݕeps)S.%k:nbaNzg&JrjOW*)%X(3%4/'a s#J !m1ž3nt\Mpʕ{_X>:")响,SZ+:%ƫt||~f5XUn[G.2]N~=2LεK&aTA㲕ipȱ {kl4|($lŹ kAJIUf:3t1˻[C-aRۂږG.͏N"Pip9h%`+a /Ǧ(9ls@7NgQxT}s;oZK.qҖS+<=fePT=# *'G&<J$>"?*/Jj,8h 3LOg'KiO/LO'62վڒʾʲҞƒb/au4G[Ɉ2RH7ggsG& r#iT Tê`MZ'RUh=WtC]+lXsq6tG| yHtPz+`T3urPZQ/?vɡ)p ^%pp'2X2<ami 413&kKW+4-1b&Մ8^+u-ht<а̝ EMC=2N2ؤ ?'7M _G~L[9Z(PuQq< 耜h0WtJ XLm2Kz1Z} n).]V=pF%9dR3II3=ٝ%C|))#1N"䏝A(QK؊dNJ"hRC]rIwvgvuoPqVu.9 ٙ{ws#0"(;ocs[\s\[Ycf[M@S)wsuK/:t{ڼa}_coˣl@Gu8 "w[G]@ʕ~7T*ɀI 9P%+Z}Vj81q@qbsmTdTcDۊ;øccqu, (֤T`˹JU?~/SBQfxVOsB YD.6=fwa8$VCr&1nD;L* mlc|e֝WT~ycBpds%n[Jh[ BxZC+re4H*o \O*tvL`.k* ũdTSq*Fl}~}nlGlX81:`f^< Kַqa^vyoz!;IT8+7ջXehvXE4ln=nӏVf_A XE_ Xtqn( E@qc3k`F)99BgF2VS OU)X~} ?r$2Vb [hR;Zotqy,ǀdYpٹ^"etog%5ѠwIU4ujt0zCB2<7qGg]xW?Jۿ2ob>Fă XHnx%>ʒ{,[TDǡ+#~uw)a@"hD1++hW6M<:6ϷK`)z|a% {>F7ۺCo|x2HHC<0f nEEˋ!+ 1$΅>ȭr,唨w goEo_X|Kc]ezh7܅A?'ɰ%zh,P /I1l5F\v;7;xs{⥵߽|gtcXOKj3@ h R.bt?:yϜiaǿTkSVh( gM:+nKKW2r>ej=ƙԜ!HD@u9 mԐE4"馵qsLc+7"L m[ Zh@ss.[e̛l?4;͙`DuZDiPyeU 0#2p֨q0a`6Vf1߅69aOޔVt7\OB0̯'?o]9̍!z]\7\_kGgʕؠA+[%y1@k oaeM[ Ӈ^2ͼO"- ok[kx߯~'ߵpטּ+ P0Nl1y*Z>|96{qXxwnxzsm2F<EYO:|yXIRP'L&|FShDd.K#DR21rQHV(GOrGOw<˷/Mt=Ʊ{Lt°meb,~C X.,B)ocx}b54io˽ffNVn%}T* z ]h1./l?'9^9־:;Fd},S7-l} N)K)ҫt\W7v Ȕ1}ǿq٥sMg0Nq8zK[uogwmPNl?;Ar]SnJ*Q,Kv\]D#ZBB0@e:M;]39x[nmX֝ .퇞W`mY9nɗV `au J dzy "%szvŭy[.ƋhezsA'H"#izC% 9Z6aG/d91 ACEk&`i6X:)TF[ mHiaU`KXr3չ ֳacиԙ]ܞGpp(ʖHb B5,#"ZE@u5E@s xsjG S2AwP%IH3,n/տԯm}=g4.ؿ%drx<+ZU:'8 b\+e!d>6vg $ÓTčq92r 3kg8>\ln;dλ`.[ҕ{gֈ9 %qYţ"`GA4X$VQdyA@$3β F۷'G.-OSz4zZKf?c5dxG˒!O4+Ґ0܈fN!r?_6&hm2V~4,6'(2ͅUT*[^qJnT=GH5 ^Q#;~Gn3M5;c. @'k-hoHCPaE!fU=A\0y3/ 'sO.z6VYlNÌÔs*gWf>_ZI'6זkReH6TQ#uEg*qdJ(ZbeDT\4POx3Buu_ KwS5zd51PizS ­_$h[bUSČfE@Ց:bh13Øp`Ϭ :j`m̖ k jd *J!WAIW$ 5PlJ BL r]zql;t1_5Hr{]4.ͩGET gWcɩ/X<ܺ==q{.˾ ̳*VPG[½x)קL7pG|^N$Vqs@'l؄oa.w%V'WS +3}ږlYJY(4Yx}>!Sa+dx7 Da1OG!vKY)]úXVe!hEVR_GU UsnE2]$<^y:>1@A2')Lf(ŃqST,84gE xpNUC~C1QSCC]qeH>T9WMX.;N3JzIJ䔣AV#j,aho~i6q`,~^|/215S 7G&w7?Xc[['ލDc#frba$Ir|O+?KCW/M%&sMaV,!Y{hț|Nw6\ Ǚ7r\KJOX:7G0%%%SZ#K "oR9hfY*E͇tFbI o5dF 1BK'!0:OO,lsXԙlt1QR)DQ uxFV;PTe`A bfra5s1β;@#_7ZQdhL&JjYdD [dӊNr˭|I~P]!uG1L9&U&:+P>/D2B|)Ԅ8QQΎC?38BeTF[CaHz-8m #\}ߢ U(ѭ:> S//IJ۰Q1},n6`ZМrKt=/?ѝÀFe[^xrxidjG/ 1ΗG@'Hɣ#PTeȨ(|Lʏj VHV0LgXHij ~Y [r'%?͸n/#!O #x*NC0N5H $e.'R-^bBPE#iX)TUJH4Jŧh#E.CE%Rt**G^׵ҫJNg]MigrC5Z-5ZygSϝo}L[vn7O?w^{̵|}ĹXwVtʪQatOrT44Lq S~9rĪAF<'3V7;qq6EY]><--ȋ մ怌n6󀎹C{3CI -#CF°!V'Ό^T@>wV- ySX!u[ST]<!c&wʹbħ+ ](LF}yX1Z,Sh:n-U]0yے%1ﶸf6mbWV:Ml|ɳz)~E釗#SPQl>D^O6i$TX:x<Lr]:s!8FP M҉2ENt˙VJZH,9s t"C|R^vKYLhDlF"qrb~1ÈY_%MP+ċ#O]S-^o DkoxVPk >7 j^/)HiEJ 8e+T<LhKKˡgtevXYaa+-Bnhu [=`y! 3G4^`m__yt뾔[p\cfc$` ,}ȕꋆd$U!bQ;ttj`В62GKIeUȍW :]P}ȯdzc+q5-cv# |vA+O@B#QeY35,T U3!`S+(b*7K!h *UIWĪ|c_m28v* 6[x՝>""mboe 3;wn~#g]k7SOKibbeJOx>^ʆ#ժ¢Dd'><2(Z%u-cEB)*Q񧜓tECYUY>DEX!3VBKi/ s=)ih 1 Ӛ-ӀU%!u3:N\% F /9S*#C򜯾6Ô{\Zuh!!ϼ|o- m`9zVS'{N_ש:ǖ[u#,Ny=Mas/m?F[ .H,yiS5K@2iELC3kezc7qde86TDHꄹٳE`sL1KcLbH'Oj'OBS4$.J}] @GW,ʺ܉%rI6Ljڧ$+]+VrܐʠɳBlueJ5*D99Gx0mìjX/pj>]zɕ+Twt"ޭx 5+h--M!N ̟dJh`N;~&JV-2(-̩I&FAuψn!܎2/XEYzMgMRQ63_x@6$tȡ<+H&Xz(!)/wT lU%)O. ٘։t )vR s=s[rgK:X̩Qz|lPCJʙA )$U&|MY9ќCEh VTs4tP/*nX3w }xq/y"&PÍԹkqpH(z54N=2rM=Xg&73z`E}xc\6=g❵,k +> 5P(`Z ߬G@m&. auDQB& 'LѬs2XoisAgBN9TC?+%bkH9uAȴQd n3ܶ8jmi\Q1BGu/]ZjKćniq, 临5e IPx|`ٛO/zn5nHdDb@GW2YEJ*>󠊸\J=#+n܀P‚ ,޽4y KH>SN"bJBҊ* kDm%;Lx- QOKea7T!lU!Vq,?> I}jvippOm.vU'1X{Ք`JSҵ[N{ fU<$/O! 5J,FsL9 I6_z[үZW\# X9A(;&L§d BuRHȓz3僨ڞ`uY6˨/*\tċs|&جTD*BÛ"5RsRX2'b!:Px~&%\t3))i.?yS3sUdxU}ǡ>sL5:3},okngE~VG} 骫?s-,9)ZŻ>^L'G#S%;i-ks)s1VFqJo%z15)gC| :˙$$^6FYF2eGNW`5E@F ʘh&CepI$Vo+eəe*0kmƽr${%Zj_DëWEA]!L md i>[ Vz#$i~y򉑃["$j #A(]yb^Q=*X)ػL bd[JE2d{S17R n-/MNEPzU*j\ni{Syox,y8ph׽s|_Mk޶ɾkҴ¯5gO7^|ןN6K\M" VlH]fGe-.uwM$#I}b`hV(*CƐJz^@8Dߑ/%n,#PT˝K|)X`5NXCEȏY~ڭ> ޛh,^X*gVG*WL^i3HB]P!&F PtC}KV 6ТQ1KCHrn"q!f2:/^w/QGgMpe 2]IX0}X#YEL%c$G!.2zW7l/^-lncdž t%%A@ڬ^W- <:E!6IbʛdL$,3b@i?I QSĬJr`2Y"JPx"|/d} >7Zv OmٮiXJ*>_./mrX+?Z=5ƚ"_OMHV,-)l%–"Ƙ173Jyj2᪊\QtV_U `fEs('Tbyjt;d}&7{dt璩#z6XE{R|[EyVx=)b _Dgrh)bvQ⟛+XpFx9r(+ҸH.\$vWRr$[v$Yem" pH ;0 ft3):ӷ><|pM)ϣo>l4WW%Lde JC1uD˿4i/Kj]byMc)q6 uJFNLNcS?HϨK]h=3ɭetEz~)zLI`f=tg2F31G.@Z<+QPEK--)7JD/c% h|.MYF>WJD#1a(X,Ӣ+"Jrn FCa>8Ŕ)I6+Pl<"yM!hu($PYnڰn/d|(ZѡlX:'uuSJ3L3]+Q Kg)В1QP n2r J;ca[̼$U1K)|*+2%ѣE 7Xr'ɢH2ѥ̰.?J[/ub*oے0rk:c(H]*it)*BM2fQCef al7Jg!Rּ>u(9>΢dX7E+@Ưl &xzUce@)roJѼ~;)#&dXoSrK_#A.1%(tLag&+ͪtE6w bˤeSn2ja4u~x(Do8-M9ԕVsKU(#;Kj=EU[ZyYtM&`XWѮ|\LdtCd_bȆ̈_L9(efM)KN~'xE0RG*CBDEL~LT`]f!&)Qf kÐ#_ Xb>UR].,&8``<7&3Lt"F)yZ_)3dC:+n#Bޔ*)t̨SWX:lEǿxS%fRh >* X7BP6$V/} WKBdHvxVB kIyϰetkm+zoI]5&ndZ+%_GCbUsYf`~raVKA],jn8xk%QD1ɘR(%Fڒ 䵖(|t1BucWJPBZÛ"SoodJB0PRk'7NbŐH }uIϡP$J -ˇ\hɰnG&qŝqbq򟘘o 4~R];c˔bH*P8 WkdaY9 XuŒd/XTIQQ0B* BL gR* 1]ZӫbtQ\ ͕;bQ%(KA7g]| X8ˣnk!7olr_ zD1:t fh-Od_ ݥUEe|#*|M-F ̌=a92&V)g/چg( Q:Vtp@ %J>B?U O( L>J21I|u7=;A" & /"؍(0)`e[XʍC>b:U^BRG#9|C̫M&CU7 Tz3!Tlgp:^Y(@axٍ ,8arZy/Xk*6{K2Ǥsg*eVm6.?2eySK9ȥ夥 SB`4IcSB^]k2<=1 COthzO:G%!υ<0РVb\ Z#k X& a* " mci ?4E;\*a~isր~չGã2ZKeI-R7)kX-S&ODА^)R( 1 3it(5? c3"f:JtgC%JH`4 %蜰nTT˰_PС%Ȝd'Pt?<˂t.9! 7uotK(02`)?pijlgkXUrWݐkM&YH72--fYN1IKΏɆ4y,2hd(Esk2*ueLlrS땮[NZ^@mm-RYYrRPww*%e7&Zz'I]1(MHDLGB gH\ ZWA>t^a@Uxx޹s(G288+$hrxUIIӟFǠU]KۆNLw(hmEazռ$(NAPWD~2s> :19 K9Qs<,?< Q7mڔJ3nLYJeV6$BJnKx3/=+O&])UNVt Yũ b8>Z-s 'jb"Yv={um{=tP&U?N Ƙe(ﮇ Kɉt:|.tvQ|>Ng2d2sctEa)se#J9CT&-]6UxbPI&?)Sgz,Q#-'c.p84YӟT |w<%G%,ʣLBCPuuuقx<\.LDX,@բ,%fA+yt8MMMLT}}}Hj0lnnvݺHlwww6lD7iٕY5%L0ءJބ fTUUUTTXɭ+<] !KXBnfd k׮u\:c"&&&D|>%`Ӡ3YIbteeeGG7==[lYkk+1ĭDQ7iGbN#S0a):eHPZ عQҴNUIIICCrќ{DJtYbVz[~ADx<۶m醉|-[LLLtuueYAuZ-u!ƬVYKX6[Zr_re{{ӹdYSS{~g1,2@hd(Ŀ!dbFrpc0V“n"-2&t<&X6}IISb9r UѰu7?GԴz%̹X,655,9K"&9`)<ԃ@m^V]umt*R(˥ gn;򔶲ƒɤ5"ȅ  $>s*n_nfU|>|u]t:D1K+zheGkYBX" "!aQfI):Tz޺,:aF Ò֘nf/Hk=)l^R ZCmHaTkeYĢʕ+ԒH>4 <^c= OUEA;K(ab-Ud(jl`aQ@úJhՁ.t9gL|ʿ*c7X~իuMᩩ)˵1uLވc20kW xh2??aK6[dcǎMOO Yb!Dˢk!˙u꾏,LG.cm{7|۶mrx_N;w>YSSrիW;x<_bnnN,W8`0nဨr\6MRx|ff&a=ҩInFrxD'.S8 5 "~BKuhuX___[[|>]6bpxhhonn ۂ4;22277ӦUUUmmm555>t2 CCCt P*Z{W.--UYIIx#"Iʵk׶466VTTқ3L"  jĐkf1$Y\m"P0hO$GM$ɖ񩩩x<^]]vD~n755UWW;+P\. BMMMDbdANDxu$lӦMHRo-6B굵;v`_]0<ǙB+Wk2NԬZjxxv}߾}{{{_}UJuʠM/_^SSCtҪM6 >}>H&wȓ_ʭ:::>!s,###_W"]߿k׮ 6_UUU;w=vXgg8:+LxВSB_r%[]͖Ξ= vIˋer)Ĕ~v| rL&C+rV ug3)4%_YYt#[ZZ {EVUUK̵1VX,fkjjzGgffch{{.usʻٳuVf39ݶ 0%NW#S{{;: ISSS @jRwրfkhhxzʅxꝣf dKE{b†~e}^<!@ ! nݺ+Vزe췁 G|xPr9CHr Ro!Y֬Yk.l6{;v0G+Y<ϓO>eJme :PdrǸ뮻ysr=SO?R51ǰ^ ʕ N'ol|JVSe[n:`ARSSsǏ%YF(+,RC- P1G"r;X-(uz]l_z?xKKbzfȖ',Y k>b*W SO=uwU_ɮ]R+H$dK,YJVRPx<2 C4 'b7[nhR]]~zJ 9a)0%@[#HY<ώ;RSh6mڴHq:kjju6ʢ Y0j8ȭz]w-Iu]wqv4r(b/P{ a6d"@So/Sn=zrKAp:444<<,&.x+VXueJƐe$0`4}F˝w#e+͛,>_RDO)VdI ;jxGyeHPY|:b2鴬U)GFGL^&|>lf.˖-8C̙,HbjCn a0˯zzWZe"DiA/7nܸ$ZH0JGˈ4@ч+OhO*f^dmiiz*5r)[gad^vᇩT*Nn~{H XfX`%4&%Q-aF,,y~І;vX\TCjj+ X`zHΟ?ÇNs޽;wJJZ'zM]6Gٳg?VVV-h&-9yl5pX*v~nz)QJ3/\"'(&s3gzzz4|;<< m qO}a+Tq"H+Z2>X,{HRko.sKK\L&o +rˤ+**xS"jR|](iO(8Afe\.g:|+=,DG4: Qtʓ&^\K|S~%3g" nL16ͤ뎔1l6檐Ȫex*~k֬̉M6,:MtǛ HdcoA)P¨,I>ڤx)ܚFf3}(K٘;=tXV8xOjrzjErT`f,J+5VP&5 o^BC J0 3,l u,x<府6P7w' \)Ծhhu<dZل!z<4ϯ]֤d6b>:+N#4ȑ]]ǘ71eӛؔ{@ߚLWsssTg5g*!JP׳ fT̰TH&EqrekME3P KΊP 'G߈ͧ jw.($ p7g,e6Һ:D":7s!&MGLmXW HGѩ)K+V[h1D@`'iq*XZOr\,c2ia&~1,&KB _|-[Hxee锝Dp ˙_leZohG`a={ȍ2;;gϞe`Pb&:JջzAS CwKQߩ3=j:7!wmxЅ"bĖ[ ZQo~S49K\??{PgyfAG'e2 Z[[~O#M*ajtN;-s/_krrR(bFP ÑH6{}D ǿ{BanDG}-^#@!yYarozX>`0#>n  Rh(\|Y>W)n駟["f,-Ɔt.7onoog>l>ShSn/CCC<`9xvUTT~&NpL )tƀU(fڌk=R  epa@ bh4!z`R&^&#xN\aÆ%OWR|+7Ojr_ `(KCTCd2ϟqQLDIAKA0] )7XX쮮.qRɉ'.]7mUֿfƦK.9rD. oݢtbA Lp#ﻻ={6 N$ xRFk>,!JFo}X,v-R"[j⟚3Q If]ϑ[BF8zʧIX%W ƒC9:;;|Mz(^ uJv/~ JL rae;Rd2%,aD222brTB ){3,U\rZT9"E7񍉉 eypnQ ")4\}}}_WMMѣGU9l6?[o]&e7F1 QbB7DI#i LRr7###nA UafxC:thxooW\Qߎ֧… fjdxxΏ&WLnhPE,2JRLRSSSN [lvxxҥK'O<{,l @ bp*07%N)Giiiss3_!J$`- &WB8>v؉'ۙJ{=Zczz/LAxB{/mV.rl\zullt֚[H7O~2>>+)J:[N1˝8q?_07ndf_yT*[rjwww744t:;G?QUqAg^~e HѺ!ր.,t.&-4!"m477[Aŋ85S$V3؋/&IgrZ[[~Qbt#^o߾zjzӧO8d ŭ[.r*W^Ie;ě`0G:!O~6mƗeECn@0ܺumt===FgYTp@޽{''133|ٳJ 1[8*^+(9x7o޻wu)%wyQ偠*J ,tg*!ZE)Ab`N:~rL&HMOOgYٲ ˷F (--r\2\NįD+YJXj Ბ|x,R2{<8v09] uD@nP{gybl) @>d2Hdbbbxx(@ق`2 @}B%deYJ ʕ+&D˗/чBq,'SHKڥ~P]$lz iQo&39Qe#[ @#TDQUz0q%C"ɐ!*ݪ"jc l6K]X^cr% \*m&t?*,X,v ZE4{?["G]vww*tc8qW 6uL3sK]rLWrNDk)RR&j.r r0TKe%vz6|.0 esњQnYy<;wYܹs.rJ}###JԦծA%bBh;xG~I<khluDK'$_M'GMtCvM_*KK2t< C!%X:8 ʩӜ(ST֒ViQzE?7a@tD r8讱Bo߾{nN[n}}]zPn߹s磏>j/^ZRtp S8K] ?нrt8+Ut4NfP2A"چ%DG C:&,{}B]ËHdʢsR+V/!9'SB<ˣb^z۶m*^x!%KJD9E.[,I}B(E(3l]96 š֭AR)ŨLE:-Y_dIb TMkCU,-kp"I! .'7===00Pܝ]T^~剉 B-J4%Pr*9MsbT`jӒ(3La(/ZY&(f{hGDe=1*G|0B;II-N oW(:= '^JzfJy;뮻f2d3R*Z:s%URQ':74?3)̶Qؒtċ[CF`J/j:="uK2nO, 9d]"[( 5HçO޷oʕ+8]L4J%-EPƑRȲDW|F!^*dX&]e2/uQ`Us2jt uƃ%b*r=L4X)r0x݀cNƊF?~kkk}}}]]](*++z5 Ep8<:::<<#zF ZKLU(&;P+-CKC] {R IhX%.T(W\*: %-J"~:tzbbb||Zh1X*1Vh)aYaU[d+e-0b* MDyQer"] |S/i&ѲPoˆS Vg!+z6ER.#nVGFIeDԌߒ V4ʧ(~ {(yYh1a -S$(RF=/t:J,"@Qr*z\A@S4i|AaHrT\Y))3h90ԌSuhŌd.l,V74h$2:g&T:Q_Bz+H4ݥn;Rz)l2^/y#S-⧊ ϱtlP`K7G ..(&7TiE/ ^J:W[Ԧh65d7:p,(II9Lз`d̉v˙9VtDs:eeeD"+U()wN$'Pfا)BtTc!k ʁ8׍%QhRsTܲi΢/~ERg͠5P(ҙ7U\LY*r >k 2i84NÝbQF+]hKfNU=cQIy0L&~|(B4aπ}*Wӄx,C@6,Ád9.&"%Z)?kL׉)3S ]YeL3`(-S%`:2'K(-0UG([eee333h*WfѐJC> 'd׽Wr1%LɅUV27+CMQ[s0/ZOtэ,KP*qSW3&X[BuK.o bn9$p8J麂͇!_D_h'yz))077H$ >[itX朚۔2$1 bS`vp:EVaT>>22NŴ0vأvCвeRVMb(vP Ж/Hii֑YuN3:_káo@!nq+LcSVPGO>J8D`nB!qzzzdd$L bn0lhh8>BA)z !rSSS22,ta[7 h@#yxxx||\@TVV655BepppzzZv$"Eh3a/RZE$`Vc+ W2aAӉL2yb pAsp%ԇuXlnn'u}FW'pC  j,\CzAhoo!f$l ,],2Ap8UUUeeeRqpTV!B 53a'tMřL&^N(o~%{>t*B㝛t<0EzuêlmCCCq]`kk|(~AYRԔ( PHC9nPt@8<{D{<Zt:)aQ*PhCeU Ԡ4V(,ZVԴrJTpTpYynnn:/aׇh4=33,Y1d2:3,8ʠ50I8tz׬Yy*N^_!a, t/nq-\zuvv86hmbԤ4|/d8+d/-- Bp#rfd&(~ֶpFF(FaqI(rB2F9ܔ >!2TTTY\ʖu8^eI@a[PK. u C䗿o5kTVV *bӱXl||<NOO+weI&]]]%%%6l`z-d &7r9>Gpz1n v|>FdH"uOWzPMDth4:888;; \ 葍EK&@OMM ]ª\.F4Z @X!SljV8zDeB KII+L@UU"r98HlǓEԉ뤨h}>lW lB8Kc8dr0A]Rl`S&%9 ViiR?H$"ٳg?l6PP(}Fp8&''^ń4 555UUUeee gBNϝ;WRRаqF 3iLgN/\H-v{SSSuu0 =쳨r9C(":00G^Cz˖-![ҘB@TD(YYE`CkXȫ"BQQv}ժU7nlnnb$9|pOO#Of% !ÂHݶm,-,@vf577766Ǡ߿|r8օToiD4zjOO̭<_l6}vOMMuww 6466:ʽ{Ǐ?tP>v{$9v.SW\9w0xj?ҁD"|>GWWW:8f ?CzhT鿧PU 11Ê&$w\+V(>xG[M>}'|Aߟfkkk}ѽ{9s7ߜA]nᇹ\ndٳ/_D"`)( "+kʊ;IGG Np˘@A; 3,Busu: /LOOˤza ضme_q#2̷J0D(  UERe ,cL |ĄQ X7зѮ Qlګ}ѢJڵk{1)SH DP B۶m+@mٲEG-p&u:~.hQ|_^y1j?t}n7@˗[[[ihhشiSggZjUkkk{{{0 Cu ws4|Je5eH$Ǖ5Cʬ^C3/Vw20z/G #σjL0+z+3 Ț&۳gO{{^qiH hllܰaC[[mG}Wf#)ȅ-MCҵk**͎NMME"+//_l=eˀ8sZН*#BC<0yDYelH8RʒW\yI~󍍍;wܸqW!{L@almSSS\$d/ i2ec+T-r犥" Ju+9tHi-Bںyf>˝;wرcّSlww nvd<D#4%mr~vvvpppddD!466Rt}}0YYq\.39߼ysGGG?jjmmmoK*X^^GGpr{D_ѣpvm۳gzjX?z#G4&t:+NGb3 +''TK^.c(7ZZt DZG&O<㡇`.{燆h&,H{w"~N Hy:vy`j755xɓD7z뭨.kڵNR~XP_-¡oq\O~7[1Qd2/| Jp:}}}~Oyzx饗~/| >h,{?)kFt:]QQ#ɟɪUɖTjtttppprr MU!J0^It͔35~k1h+tȋRAFÇ+TxB_~F8<NN:SSSϟ U,.ةp+Ovڿۿ]f ؼEl6[]]gg?tuu|in[o/}?O<}_*8}?'>DN?Oo߾] GD|>?44$ @k 4%Ѯeile Tt:ue%+++L&sYjʤӧOZHMM mI1 aZ^^;n@-Ν;wᑑă˗{zzV^o߾??g% bptuu?\6c9ziϝ;;w>S/_:^x3 ߅-mLr exR%KyB ~96{ꩧP Y'q7^  _ 9w .Nk.k"Ⱥ:&NX~ٱ1UVV&_u}gOw}7U3j]paӦM[n]fFG؆&''x'Nt50OLLjWW%N:<<\[[2Na=^~ Zt)Wau]dye/p+o7 ⢥fS& jF6)\b=7\($ wv^ gϞ P(cI6222>>[?g}Vn(--*:ګv3g7{dJ(ob8&SI\kѭ7:QBg[੡LFުoجNY< Gi)r#g,[: K._n9zwx|E8J!H  Wq[!:յqFÚGy^йVu-_\n }5??cc*! %Dy >˂T̳`ܢj FGt@F»[ 8'1;yk Kyn_N)fZe>kCK@9{ؘR&Kϵaufpi<+`La9\ }>hggodVZ>\vѣE 0+K ۶m[|yMM lG589O/Xߨƺ}իWS z m#cڵk`it&aBsx<% و2 <,w(|2RTy"s!S v;W/"CK-H"׾Z__5k}IT|>?<<(Դ_.\.ovuu E$pwttt( ?2 { 吖VX|1ۖ+*7tjrP~R,(p[R&1d(++D"PG :^q8|GN#gff`p,{JN:+_ڵkxCK1ptuuuvv[pL;8#-۷U7͗LJ9J&Ro=P F~?"e[o=|X ݑ#Gh`Ki oj% rݕ)Uf9E$d]jWB[1&&&`sRfffooݻiӦ3g  gQ9H3ѮK˗/ߺukYYŕRy3)ҝo9hH>Kh>iWMF]$N9sFiNq- 7Wyp566f2˗/OOON}ժU0r߁@U ?𕟞/aʽu]^;y|/6YR鱱1&^ (;P J$/?qS[[ۧ>) Ǐ3 raϒprrl<@KKK2gѸnsf%B,mlwmA*'IZ0dm$d!{zu>`Lzu8rHGGƍO~~{ſm/@-B\}﮻> I,;|s9ϮA7l˹]2ṕwr:%zLRŋuWe@MFt:-X$]4GY6#UWWW__H$Y~%7,21 `:iiiN6\7I&E胆˱J3fxU]]].,2gպtzzz oF@U 38ҳ2 v j_ŷmWDL&կwlp8q4ZSn?ӟ>~Q>ӓ@a[+ـqVݻwW0=i$ǏPo~r i<G@tHT*(b /*:@Ao >[D?)R)p@u:יn:f/^9CJ(:e>_גk;88 8 Ç8:<{>YأG͸blZJv"Vx\"&M{%Iu?8fLJwKL&ڰBH$^qO9~/0_^^}6"p8 9t, .Vry}}=HR)Fõ X(QI ?I E@P&%Mӫ`@ -ԘT*\.NM $ ,rqp8~n5 [Jt_(poɓMOk1p8p"ѥ 4b fiSzxxH> +6.&ߵȅtvvVI=vvv̇F2źORC0nlla7\ w8- [|>0dB.GPri+ O0k:.b؋\ H$ğJ P fk $ E: 믿ŃV XwXTl6׿_]]b> f1` zn.4 O‡|XR@4R\.CcWNfi>DbEd2 r˰' ԇ'Z49փTL& 8-//omm ǜQ]Z],!jf4'u++pV~tbUtX,X.OHAЋmtw-Fʉd,57/.2PL&ϟ·iX7"拠|:u΁T\0UX*VaO_j\M՝o_~j2LTCü fSgYX7Bo.- HlAu~0|;~K8L%\POEkF0f hlT.eJ8??o4X@}mmM (#bkXnTXmUB_$v $X\C# WOk Bm2\(=m d2;;;#c<5^a ;b$oyRVy?ǛR{xL&sPAyc>nP@2?7ߤmC'T-w=?W<$k>!OJ͂,z"'V=4q"7*>R:i~>\<[B7,P)[d0/8Vf04ͧO& ibS0f!{y>a}W".xPؔ( ڔǝi ?vz?CPdAZR3VW,ag2jkv U 9XQ 8lj-S<acs9f.m6 . "VY[_ro` @5T]\\FvH+ NR@{pp0y8HX ;E@ w맸M@* t>X^ 14WVVuD1D9]\4qy6AT`g{'EN<,V0\~#y>i k;kgbz%<`D+\4 #ޞ''' ,=1w:vN74Gؾ@Kxk"6/Vb7r\<;;t:/^FO. lPx/JDVADP|lww'? T-l`o~DFbW*?{w~F+Z% ^[pb5t=z P~f#P6WzA#G/=tRWw]zFW 8fq%"VVGdX,ę8 T*L&]. J!b j: ׿u90 1I&[:r2ZǍ&"{"Vbވx D GzYKQ'OW36MCXYFAX+9 j\lGBd~eqX~f{^VoC|~; G-8 ~yF^kzHFWSԕӵ. ʼsP]y?]jo#(/U.\6{CLZQ…S'32+ZહCrV,kZp Se4tvvf|fX.gW_}ROOO>~}vWE'nbh%9 1f3B\򿾾3fI}Zn?쳯>*˷nEr`MJ=.NڊdJLkBF.M? F<54FvӄOTlӄg22O ~ ?yMvQiXl:v?nG}n[oExB4e`ߥ^g13 v#ͺE ]"qfc]DetO)Mdp1 ~땙5Tu'Ou0N53lllnu^d2t M?X,ػ2cbuBjJ,3ВP΢E&xW3q3I&(]Zk>K5ɩ=YZσ/cu+7=zȾDpS]7z?ـH]ܑO$q3BYcV˥ϯ_'~e8Z(tu2Wfw/Z[>r]'ɓST|O\3^r} /zCR\sśihy:9Bp Qj^%犢,/ƪx2k>S+GgXYY =)Ln\'qj9!hȝTͽ~.VkK?u?[ Ydz-j~Mq|lss?^kkkR)#*fXE9cΰt/[d:xM+,b7zV@V\2i $K.\6/Eoй.vmI&؏L}p2 ~O>#{.+J+++RP(x]^'ぇv߾mdT*Z&̻Lud? xDzEo4D 0+l䏦\_%zC̺*^וq$ Ao4T Fsf}>{׮]Uʓts d> (B}$cZJ;2?B&oa L=?u`R{KD_ Ϭ+IBTJ_Bk.-qJ\O*ߚӚKɝk3țAM@~>d OjO?nuCVCwʳ:tO OCAۡ) ؟]{Qwq|v 1L51~8EXs5o! 5#  *0@1u #5Fw *@3C¥Ce0\M*~@V'%Vm&0Ap4X{wG:lP(p[ی1_|A ںqAt[Жmh G(/cC( za AU k扠EKČ qʞFm0FNp4Df/{/a*fT1d + v a@ c H{O;ϡWs%.$ O _yJ{a$g/pg02E)!Ib(8Hsv-3Q \Ȧ<݅`jnjڋJ $;C€Y 8/CzCʳ92a( EI1Bv1RPT07H8"t| >ysQ$H! 뤽)j.msŁ!Hbt8ʔ3,ܲ0qꧻ"τ֋Is3YXS8Aԙ_0 :B9Ix*LhH߈!3\LyפW͔O) OG*0aW)Z4~29շ.;|U{6ebH$Y*|Ln79f,a $&$e4b$q,Qݝbj41Legg pID+ B?8rhqȩ.JlCgI)|z$|"\LnFb?r6\eb;ƉĞ@(W1)&?p-a2&<О=FLu6 aNnb3:̵0|"eD%Ɨ-Y+I4<a8A3QJ"]@2$"੍`$ߝ3@)xf'"=1.uHL o9ڂ0V `6 猂Vb 뻀GF%D7#GaTK w7|0E:5Ua-5c|ipUG@.>RC+`Q?/}~uYx)q1-SR|C"RE2i{hQwe:h`nOzKqb!ZpA>gqAARN !pp\s8sqDždQEcdPʍ {GG971\փFB= l(?Q$Vadޜ SMQ|82H_^}qqO6-J3klWÖ0kq^' dEo>5/==|m^\4+K!h 7yŵ `o7,92ɏ[;/ #v@\ U2gQawwv%F 9 B|)19Fw(z b} A/XڡQx ; (UE-krw3)VY.3q+O2da}qKR3=u?m =Twͧ>ش߯]w;ys\RS׼Lr\oo^Foƀ~TQt} kމ9 |za7CT!b(lֳ;I. _DG =AwG?!#E| p$oBrdB;Ơ=*"Z1f[9I#E1ހ+k6C קìaOw?_{j>V5xk;6hU;{Uo]#*WkՄG1%a\_ 2$nl~} n gINNA ( $aC' b57xHtc ",j/ Rxa{WCfg gڛ䅧26!:s;D?FB" L!PD)Pn4% ξOg?/>_;=Ԛ`V`N}f:fsxRa892gsmtN;g] ҽ[wPa4,D.G6x7/aj k&gB…/A-U0H m(jayG9.\\Vd^Z\upҶpfŅtb$!R3:he h[g;N5oCO|WU`L4CIAł=56삽sq28 Z8N>en5[y:ׄ#mz~EtW!2ǝ-#6Z'QS.P&IcqB 7Lg\D9i݇,  r%HA"B 1&g}ylH 5vk4FFw9da @k Z v α&8">uMF>gL}IP mǯ*򟄯[VBN'6rcBb !@mqUB*0 `p]Q̘z Wq#AXġY'Y}+mL8/-G3&gfCVh fQt, Ƙ ܘްFo;n?ɿ =䖚99otO;uĎڇltǿs *t]SW_ߵS]{QTM> J>% p'#GZ4L'b扰a.<IF 0ob+ 8hAнE-2'#-/z?"!J4)cdgF,3a<}V&/.n`p]kNWto<#Yd㞬SKck@qϼ:j\ڇr4xZLep(ĦtP\[!ịg։yٓ?$){Z+S3pfA0lY˛e ~Z|3^_y5Tz87f,k}J>7т=scaFu-3ɛ~?y>~%IsN8*WKo/pqWvA_/vziFq[_T_8^ud7L$?*e/@_ЭgU4¦4;3f#RzVޭ.2π) z?0Y tFbE`8Ud~Cg*Z n Êk֙tĞMtL)eiVD9} x,F=f/9*$>,&'~%>Aޢ7J@ݩ <좳SumPc<O'Kk Pҥ'F]꪿O>77}{7~xE54eN_ qSW^[8D}ٌy t|O~Ej*a^\`q!: 1&'kNr!#S*5fߠk4zpŽd9\0w$Df _|]J8t0N"0 1>Y"0]B`ϫEA=v5˰q1C #7\˂;HGdWf ,%+[wO-5.z^B1vC8,֩3靘.Y"(Z#Pl)v-1BEց^Do-I.2~7qg{(E Q~9q;'Qv۞x pu%8sEkO֤.fl[!X}4̈Sr@GkCX&/N8AJ{tP֫mD`qUU3|bS}+ŐM j['*)ELN/,I_gџ|Xp800/a~}cR#nT Y%DU%rz'P~n frBJ.xH8 `..3uR+EJ,TQlRgsR"(l2 u֣ OQjAQWjr0C2y$`0"׳^:kq'$>:pBx@*y:ˡ,:v\\C+3/zUdBC+O[ s& EN7021=A|G4Co?tIPIʃ29 AL b" 9n=*$dA[1#H^4Va[mrI>˄x ?~vS`zkBϕC@)qϖqRj(Tqٞ$Əшb C /bJ1[︭ < #.G[|dh˽{r펤9'n_0.b< ge>Pe!5'^|\yJ5, b"@H! _n#=45cؒŏA #HBDhH\A0bU'wH\ D$Hڿ$4`r܄z.^oK٪ȼHN 5> syo86hϕ9Aj6B33WÒNAH?XG@1Łx_MWÞy'dUB{&RqQfM EdO=AQFPčlO?`HΞe R`6Hj]f,IH_P OQ)Ӊ3X l:A.-6+K07k#`$ ȺV⺞O !WIq C{zX5L 60O7r=Em@SxoT:=8&€ebGd9n}Ӽx-JESʦYGJ_&Ytba(nаQԊ;$bo,,n΃${>|E>tfOc9܀=tSijcBѢqÌ\┥.ì(TXa@L@x1PjB̉%1 4+&[$Tw QX*2{*7pikr-,YoLPB c䆞1 #[nܨonMBXK@L gB93tɃO2C\^CFRi #Ή39^tD30 Oa ;Yo с{(t^#A+qbqڥᒖ71=r#4#¸ąR@(.FYd,x f)$9._yKYuaT*"VL}AUʭF.pX9k73e{-d e%<< AQ"f3#3:ms~q'o{}.G($#A }6a<÷~_U lRiڽ%e;Nrډ$5&mw([4(W<:  (Rz]}?HQdk08-̬rH+=t#A‡~4s:A1q@>$)Yъ$d!rmP pˋq.oVTj^f{; +%I;U2@@S$.!Y Rō+b3GKY-%y#Yxa"y1{N쎌dNHJ)e'-;e+/h.G ݼ sCpOKr!q(ݗXuъ+6n-T b&9&3,8GZ5ߘqa.eao_ x5p< E Pё)23dq$~G` 5:")t !.$saq۱* AdҔ+He)QC׬|+V͛z=k?|󶽕L^N0tKom>kVq*Wj;ֺ#qAϪ˭:;T(2^9r=枆|"Drb׈>;I82>DGs$\0Sm9)p1[]Φsv;XTC=cUJOL% CS;ax.(F2l3t!߯>zus;Zn.cEX*a壕bVYP*vȢt%p%׼蛷+<kĒV0S0wh%]njMQ 6dƈre^Ŧ(" ̒2aCa 8CqcRۀ92\j#@R60ϚlsE{*~ݏ6~/^rĢ?;uu\Jq1_H\ eUƂf4 ѽZQ M1+Ե&i]Lfaf=)5=5: YA;Z9@E2|(zjX[~wP"HeksP(2(!ؚK9&FƬ\] i K/1$1NjNkjev{{O];6hLAWE. XHfv!c`&? v+j;=g4ϾԵuRe`Ȩ:^]:~zuD/ mYV6ZhT4/zs{moJew[ԱuɛYYUA'?JAP듸*aO'_H8șێG$E"ȃc,<)4q% _yhhRk $S>B8zطĬB TuXKr;)+fu,ߐe+~wS"+ȇp92ՅT["lD+M*+;o$=- ^߹aSrrrX?Wu|SɵYi,T C,)XYM.l?KN`ٔS*/uٟ7䞛&Rkб6@$ pm}?@X8ؤx>"b 7U(`Q<9 czWT>:q3[l1N<7݊˄tVEo[HgYhIhBk BJ&mO 8))<{|=`:&!q$rcƪ퀵 i:{wzN<w[FfWuy\ѓ*蹋 8,"X`M󘖧Z;% <&K QQT3ލ|ƥC܇JNAΰl$)^"J#eP19I8& }ȸU)W0D!AR v  dq~'q/&c 68W|] C] k! 7EP`eYJ9OAKۑXXd:ebۿN[gHVz=#H3K=Z{-DP۞ <,XJaXhZ0d:/3 pXPUPtNMDu*P2AFe;~och?J~G+ ̆)El :7P0t(G+([Lr4; Oȅڀ@׿3!A ]_a{ob(T؟JnTa%y X%x. _` ?kRh9,<B0-џ>wxtr%',閍j?I{wYdτ%RatXK`eLo&έj/z_uAG+S]=yѭLC ؖ+|2ZǬU[U%ΣyJڕm[jQ/[`Brh 䶩c)qd[y30Av֩r;q|%6˅@,"959 6t89W7Gu݆&xi TOix6]+6` J0ӸqDRb S`I˭ JMĂܸMd"9KգTj;TIo^+t|Cf,L\CVP,ϭ,d+Q" rhN+< IU|/m@F>K3C\"EH B>{e[% `I:9[8W[G9*Ѝ/]YW6}lyё.:qNDz处X%ON?94ۇ1tqץ"Ц_YL۰g4W7.X=Ue|[ɫ~m=wWƶ}M܉ pn&_ Q哛"Igˢ4ϻyXjjXYj[4k-,zuu|M$McAV3y)i<5ij]L[oGS~+Ɔ7pѺ{YN\Ss]#}pf0h=Erj7qm5Uݺ&IJ56Lwҳz1kc'=B Rc^˗]|]㏘,[p\|$[㖭|ި$J#:O8h5Xwآ4?jӎUY <جo&8mقގxZ6L8#S4:֢3";+w~W_ -/@MzHf^qԺ~t<Bؙ#U;2B6NU5kSz^=c_-Vm1bkc_%?ej%zSQdMUI9?T] ׮R%wQ uأ^y*{Թv~jUL@ʰ]ETYE;.=ъ斏䕗zn2-|8,yPK@(l =fEfѿ_hKK1VcLJCTRn|;ƹR7!oŘt6RǬ1Ngfb -?-V̻jjH ?Mf%L 17TM*y_j(,+iU0L,\pi'\kWhAY"K7͋lբAhi/?~HēЇ|dmhU@.G >}^|k8+.=50ח(#`qH0Il %- r# ,p/@sqJ Z2՟j]8 ,&>ʔRys%1>w:ԉxpR\ fPŃ+e7|WLA˝ 3!YSZ R"E[^sŶ VfzO,B؜YJI?4uθꔎ2G;607k1Xʷ_2 ~KsSTdnR'PZ!B O_wk(h6Ji;S_vO⏿ e7bGw"].KjN 3wky-Bow^}ZKYRG?<"9+a>ϙ/m .R~59\4M0 X eWfvuN7N+Tږe9UQi[*6;*JE&?L M<\\Lք ˈtJiqU=li= O_ŪTvq{(N:Y\?e˭Y$ag7>Y 7ZsF4A>Eg_tB+S[nR!V=J?Q ܭm1,9ga=ʈu,<*5i#8i}[E?pt,s6(_:ecۮ)B>둎6\2E4,UcX1c,W8x']:J˖`tCI!E`Yz]|̪;6ojR ڐ_=UX(@$0BB5bC &8}aϋVQy֊[eϴV l%><QE]St@i'X):Fq.^ڮ%%__::1/#j>PgTurKͥ ISG3FXaE, /2{`X[hOCI|?ѥR\yȯqːŮӕhkn?uɹ'ٰmӧֽz-f/.g؊\sEmo\ kCkD<+*nm7!æM("Hf5^"?iʦ+_oS +O^מ\ů];vk k l;bRPAgX`Xv/NՀ1)m󥓾}oTFyFw\Os7E&a+  [iD]_лFx+csAWWN,վ}Zr855rӭ-t\RkGFUV&INȷ\}~/od}w$Vܶ7WWb4)k$Dn>,CjEB_⡤< sgl|Uܽ3^*lNU6'RpI(dO3la ?:tһztv,nj (ٸ[J P ~u˷ʯ_M4ClG/>* ?=F<Ƒ~0 yr8dp51-*j#kL6A\ԓ#+""-W9ղ@Hn$%'V \2+j] kT<](wuM}29%g29899JBMv"1Qż*g:|0b)hk{=ʴXP{+p3psj|ySꌬm᜶6 7hx*(DܝŗR< T^'c$aj f~ ;MQNmM+J3(I"e`ѴO`vW Kuk|Y,af//=?Dc}lmS~xqQ} :+!& R1:6qʓ#RgkbTz9p,{!ڱwo[mZBiXrF}JL r0Dpq69P."ݞǷapUEj˞j)[ƬQXqoy4j%&1CUGgWK'Opծ)S#gMӣs4ukYq π˵md|2tOS+,]MXpV*:55a,KdogC^W{NpZn\h[e՝EdLa1s@R R(XbX.}@?یe-M9A6㓓}G`tZV; :pYteCôI)ny]; :~yp`cZ)Fkt:|LM!$jXdhEYo%OlҠRSGt^`)g~OCҾ0PZ:aK,g~}7NW{Kz_S3L&'o{cĶ9F>@ RȂu[2m>& .Un1*< }}etIqF)} sMֶb?4FEQ*jd [(λ\*=<6995M@cѳguV{dr.}'ihjSӹ\ԕ;;?8;c;6mdX}0:<(ݣ\GWpz=wҥwK=<V(ҶV(S#Q? c 'rkvsFPe-=9.* ; L(5brK_xs>[{f ?^QD.r(ɉC 3QՊRI&u)N5l ,WER^߿zWW^݄}QG_&ݰ-?%ySOxߺj[巼N0]<}'q0!v4/=nav^r)y˙?g72B9/n[(uû64;f_~|רZJN[KO˽OsFLq!ɖ)UPX\oY|xb`ckkIyptCScYGsQа@q/X߃թrkwQ/iw/qAAHg!\"K+rS#wBW7l%kGv?`gziWNL $|~bT1hx0p5WkiͼxlMdLSM׭9Cp]“H uv]c[Aŧ>@Rjv3,|_[x J na z.z~,Gn~|D6/_D˃[\yPÐکb2k\ꦗE6Ŏd4lkF߅$bc;oOQ220PƔ)z{}-[\Baw 21=/ˮ >^y⺢~ke`ӈn_s롸͏>QZuGdvC/+g.͇v3Xj2XtP%& {J>d}LrAMhdbMп?@i<%zL>\oJjP$z'] &vӠ"%ٟ5orpw~J*HbGv`hۺ~qh.\{z6y}և}rǖ{xX"5@\ty›(}7Aus oݟ_f\3+ðT̘r)@zC 2lTw0ڧ~F-#~w/wW=$>AAyL)1`lwݳ .m~w_=/?a^n],5b',;?{+BL8(+dn~'wسo_o{Ljƭ ABX"^/7avE>J]wS7 Rv)V 62w) EE%KP*_%E>X㜨Yv>牃 HM9oK^t^/#?ko>G &Vp>[~VȀX>5orr*2KN0=;&'>zk+U8E:geGQ,n uEN%5uqHkj=\^*n;+B[yj`uᱧc1/knݲ=tϷ*Εڎ?劤!5@nݱdk"Pz$Uc2!agK-ʓSS}{wm؈wķ}(>ndl䭟}iod\ykIott`?#/Vthtލwwn2^%^k.(5}SG|DHhNk_m-B'{׏o~%Qpu+9g^ܿ}'i!,=y@Jlz^[̕'1){[vד׬:0uiWo Re9u]{]jPJ RC~3r["E 7>wmsׂޤRmNW'NO콏C씅.$$1aGfoJ-6w-k$)tebpztDI' %!}Q!i59Hi*|?&Êb);aNsj͸M ^UV ?1P[Y*aM-Ҏ =fUeJNdLR;kmDfG|Ô,Z*\43*honYh쮞RMU*}#[<ڷ0i(}}!1S[浵|JE=s-[?39^`[9% ƈ󡛎l1AyKz֤)OMW18㊤h5CUL@Xe%2+v@ ֖JF#Vk]&ETyN䔥r&!|,@[ΠN arᡳH8'L`1.)s_XW5jSNOnMk31]E:[@IchtTZ!j[##LNs ^x+r*/`4 M]nx6*_V[cNcMW^[mdmfF+wmdd&"Iq7N)K N&ݝ66k-ץۅMO;SeaED-'v^&A: PDv$ zYl*4GTpmdwkupd"0vAD^ F es2z30IaJ `b(S/ʃ]U6.>eq⠧iLDbh5'% aJi!)))3XN.q^}<[~h_GLqՊ5=9[`l3v @&q*a;Ex<0Hy߂}m"DvyOe+HRړ E,R;Ae.dzn-^Av63c'I0s ЊiXيr%L&ʴ3Gk#4YBaY) u &$`mT"p-"[!$°MD Dv@ z]_B5 (k[gVNa [@ Qb+ z(J/9v)OYXߓ 3DS^~9AEqKXwͿvt|~IR~?'"!0u@?u%ۤNp̎bUN JЃ}N82~r9mwd:H7"AlV`EQRZHZNX\R)Y@)S }X%fPK*sMLv$ۄt C.` gƗ#۪9eb7ߣʔP'7~>>"U09(ƿ@tFsFqɉ^&?7yt}TiP.0)\{bVܗ\xŋ.x[7o08grj\n^4o+kЧMylǓ'%h4H> r qZu*bb_'`ƂQ?$i8Xkյ۽gSbHMl 7-?  Q-;` n6-r7 =\d d`, <; O־\g;gn#f=#nfxL5y5YHy+d{Jن Dӽu+S ÊB[oRF5ene 0/LnǔiU$@\Q`%h>wӳXCk#MR|#Y H$MveDo HvΏqlb136^yΚU3H[&&nY{>eLP V!߄9 "qd I_Z)3=HRUe%Lχf,&cWaBSDnzy, =7:$hΤ3[˸d#_͌paΐmyq)m"!6 kr:D=p7v|xWytx*$ tx 8Ta0HXW&$%X<3_aYP$ Ձ"һ0Rv gh;ILk"{ "XǸ̓"2Bos0NAw!qzPy6s/l e rgc ЩE&N 651Bx`3!i6JIcZпNX:+khK2C9ik.i* .RuwĜabh!o.=1$u?Iv(dI v%>oY. Ҽ8 2څK#V!|MVȐKhED@V2:#Ah)ۭeY\iq/!w8{&gS!L7wR S|+Bknt&̐GHqx\؆,pͷD` !<%(tcD~fI=" 12!>ˌd[3x8sP$=b|O1!0uc1*{8 AzpkM|ވQ@$Z& %*6gᲳQյ-D3m$յ#jc(Lʁnx˜b5a 8o9Ѽgab]wpueڶqGYiϨlܱ}`$lpzyqjgG0n.0'cQW͍0Q$ C$$0Ǖ0@hFc9-yof/>؃}4u3aPpx@up]"D8Z6RdfX< 2X0]b^s7`6aY( 2n*|#~9TRB=|.A+$9R4ږ_YBFGW̸Zs4&6s"™B4+WJm$L|IM dW%8hߨ*TUH1 ~s߸j`%z9NI D(1fЀ^h_u?VYpfZ{0Qd }.M?аNrζ%8% SyL|J lK CplRl8Z1 Z#`E`Kܩ6DYD$(aJ`T >5ao.1wWnP*j{. |(??LI—DGCX#KbW=ZQ< H!ՂUFj Uj r'9} э~7m%Hzͭ)}R_̢B8@+{ [QVX tįŃx4S9R1<6kCU>e{<=עWOY-,"aW»Ą Ъ8`=~uكi30y~b )\Oh|X1WTzdFqHkԩĆ)[ų( C禰rD戎V̆k_EfRc |@iX20g٢Z^Uq9=EY[XbheYB`ݵ?,9{atҜqw6UD[D $lc'{m` l |?\L0X(@9vi6ēOztwY>stzP,v"m.a̦@AȯDهrR* y$>RD>@SU0a5gi'Rgc%gF鞭:_?.zTt)cH?oELV9Rե F2Z䶱 єtPNP_̷z2h/X#ES9E`\(R pJL`2q;"! ItLl(!!_ƌI Q3KgƳhW#<ׁZV*5-U";-McJAKR,Bc>f(QW eŞi Sjt<֐<@ ^٘Dy7UlGo>(kv%Y}0ֿ%䁬ԯ 6f4Rw#OW c_HƠ.ڈRG՟V&CĜ" Ң+U:02Cy, Pau LɀS!rgI;äCQ81Z _-]<]WLzS -T˙C 6YSHgi v0$${H\*N&Gh+#L1bZŅSD.tME .f+j[EHE)+C\[6-2ErZ`)'mPHֹ$8T%}YGRk@AW|=:::*!#!Hi'H;W!;$k2.QYc sA?Πc*8B@HSxD$S2xפU?9 =4()"Q B* I8A@B)D" "&~CTz|pGXQ񋢴%W\"kKҡqmQOL ( hqj& k ,5ul'j8IͨàD"A@)!o!!E<ѧUF<_r霢v투CG窨WRTU}9(M,y+y13n Y|U3$:G]Ҡ_4 D {3v4D 3Tف5*UIOzxs$Q(L>"ܶȨ!y"&wPuW^ $RU 0yȠHReSެS,ڞRLP&v ֞arlVNhAvɶ=]/l;6X`!R֚ 5X VX+zj籒wLMa AdAK=\mRNDS$z2P0@E6i":#LYՙdj1qqL( DSq2Z-giRr(UDCb0AxE+6(s$2+J1&tHQe?=" l"q;D1K@1D!|Yxe:V&yJ"i,rBMB3DQ4ۼ.?*s4(ASJ+MYTIPzqV+)xHom{[h\hs 0r@ˮ9FY-]?g%@{3%J.R=䓟tBj @ &y^9D} Q%Fc:vBaщ'h(A{D}'8p ß"R3FDR`yHs(HL8pZђ8#l|Xq!0$**A$QEI(5Ob=$$ j8.ΒuEE)Eg_&_0WBAf<ޕh-5p9{Y$Hzf=r'6N6-,*YԠN05.DžUb!/[<^<, hz oSݵ&r9? Wd硾{ddf5' TR)> t]RJY[Y{btbDu.hs$f|L)HOF47x bJNuOd" q n`E{HG0w('P%P&b)6"Lҩ jڙb"2"} F}zȊc5؉ *#,}VSKQj"DRHc7T!r(4$Z$53/\s,˕gWohgod!"jUtŁcí۪,I1, @C4Enpm󈼷~bJPh(|wȻ=9=qe)CY|ؠ{@}=EGbG3_^7vA!ucJ^`ct؎OBU$7r͑ M0-(@o^+vc^BNHл"P!aA'bì ^wB*{tbYW .FL "dO6+gžxIiy.r9{MY?=Cfzp0U|X/۰(kX D*p/AIx+K$@$:jI8%%{*:!UwD63"=P$Yٚ$@sSp W*"Qo0իmi G|DcEaR-R)D<U+-/HC*QF$X'+~ 8%f cnt(Jޜ*YrT`j"&f:*s5j&smx2 ZF^'Pme-o^ k|{jsíP'oR. APWZLG(J'ѹEq!Tmbe$K@VK1.@zT}NLD`@!SL"Kbz9G0OR AF9K$#VQ$(!/;^|3zqxs#2~PF&Cs[<.VHRߓɐti"L((zD$#J/m_UBD L͑*ӆh3AV $z2ԑkg_P}AH\-Q>7s/iޱis%$0:u;0 .$NQ T1~xErI&|G(b)A_e O ThvB ]8dH$0Gg2-F30B8K/,}ȱ&?& #oe*o?oZTar?O mӤP&JHt,JF D|z=5#fbKlɍofH>w2U I/RIBM!T=-2j6t!CDDdR$C9sKYco)u1^Zck3VQ<,]:,v.4}DNQ S0tqM@E ¨BJ}D ).%YAj>s9gXamgv:9h_VU6jW-#B5q=d btEH†E5"NT$DAI 6QD*R)rZ{k8$™+Sƕ ~B(9U!Rѭ73(բGmc?0XT"D9D+C825ԙ8Pj&)bt:Eߊryv S'i o!ŏ7s_.a{᭤1dѵ5kh2 !D~%> T"_~ ?7Oi̽slCBo}i1E wקSK¿ 90!${YBOzDBLsd!c@C^0`T_>ObH!Qdn9Ql"0+RpVDCPk"K*fY%vQLl4APK^1JI]CTp`R_I7+'[Y-XA}hat @A+\U'dLvN̯|72Fǃ$J*Ufe,Jʦ\"©l(7(aa%P&U͛܈.)W@X/o^}BbkG +bO?(j~^?)I/Ojo**2& ~o_PŴ5`>>EgI&>%dcXa@<)(ʭTiDuL+IQi(`z) eGbt:Mv=f"YPwӇN Ϣ!A2O6ݳmnQaS_4E%}mSO^8{#A[q?(KB.J}U)MFg~i3eұXz+$MTɥA`)Qs)4QH&BJ(!K  ,@4̀E@@҆g%`tMe<0hI貤Ŋ(?_j-+^;z'V8ԏ޾[JW޽dsVq4Yua ,"|6D]Y_ ae~%aД5JK@-ʇZj.-"g" L#H Th٘xbu. EK/Fj7IT@"!a2B,a!`}nXͶ'0ܸ8D-Q%${ aOŹFz+"ALqc_2E'`OL)a {jvwfl@? H,YR$'W) EuH%?B?SǬ¦U+Į% `Э&PW4Mcլ]3**6CV̴#x][Nlv˦knhB3(,v7gl]~%t,o)mggyk$cHU%2<] ~.Ε JK:ĚT2%]-Yu(,03 4@ȅ\:6K;u2ޞZpYP)^L{8 4ʜï!h֣0'K^XA?U\@8aS-L|gk!Ā$* a0M!X<Nuw,+hĊ7Ai&÷B0YaH XAhNê t)vDV,*R$}ӒFZ wᎱZĦ8V]9*[`4q]b #!1 C]e[-1Ѫ#5qQ8M DM\6X6`VtK0 Vӱ;&e蜠hY݋o?wp[J B)ƽRJM6QƜcFhl~H{[[W/4e L\k~ vW{aPkKD!'KńD A$N$ȅŶ6j.w…ԋжS<'BR:g<\TL=` Y75T8U +rIDAT EԠܿ2Nɱ` 6=ڷ۬bG+ f$"JL!H:nFC&E9̛b +!PN!P) #GO۬AARMTR-#It8?vj'bQW@rX3}&=K[C ;o?P=1^ۭA]6e˳i`Ӏcn}2[&&ba(u!3<4jf,U<ey2؊rJ!ZWJ+k",g/8 ! $2c}M=c]p~&,=?'j_!dd2KR:dS:(KakQ8r\~bSWA$mNZV2~ Ţp-:ձ~1ƞB?Ҙoc2fBW/mh-Gh*]g}(?]z;b.c5ͱHX.AZ.񃞆H!0" т"ޖ'BMy8H2x$;XPk`fN4ctl@zH|'\턪XOZDJ(Uh7yA9Vw-ݡ!,J^4 LW֐3~ `sڎ3qLv1:ˀHV/4[Y*G[[?ljz,Wf;MȬX@a`,.w.Z~ddeO?bKNpδgEE]Tʸ+8+A`|OCad@!}VC[QrHcYZCU&NKU!@bٌ`T  dVȬ ,/WW:H *6d;NXΩ1lǽ]b >>B4Y,M mqUg xJ &6xMZ } V$FeLzVBBiפ!3T%Uoh۔kN<$˝0qwFb+EH;צQ((iIQng_=5`fY݂7)C&DH~"h U>bHl-}^}[8x4J eȝSUV Y,]`^ N6zHhyKCTJWKhP[+;yMiSzIUt%$EBUQpd|%ʟ /tfvxt(EX)CvS5,8PKB7)_0gfzS-_*7y'HpݩzXicE !11д`DZj-Zà)8Lsc Ͱ%e@<&.THd|2Ujr]3VA FR xɬ/I&lQۤ> 8ОznАqUm݋u*w!oЍSMV AguKgF qQ~AVa^0Z5(3ihs2Gڮ9ª_iBz֞jG *ºPnIDɑqeаZ\20檢GhSFɡ˦F`9f~$P #f_ҩӀ%HC:tJ7=džֈӨڝ)^c;`,;#RZ+Ā>jN+B}8RAbpp %ޤ~tC>8?S"Eψ##&:E@M/2+/^GX٩TY'Մ*HB[&GMV4BD4$0@a|ϐjFB7'0$"A,ZzFd|h |u. 7DUd{l%N rD{+y0-J[y2&j|C,}x6u( qU7]@ d \cQ;$yр Usm% 5!.vZDl%Vodo= 1pJlAwEX@@:6{R:c @,tX~K>OCjrCЙ :Sfq?Q m ߂1ȃڟ9uunL88\("Z ,=V촴ŶG͗J/tjj31Wye}ubߏ?}6MIuf˻>q7='vUEJр%@mj첂Zc :k'bh4gA*n4\l_ntڂ+^K@L/ʾGYZ;y(R$Ez'$^C$&99m:㐮A-* ]uP'W.Ox#-/iRdZ-{ᡕgXp/ <irK], bĊ#DnS{1It;P}57]' [hЩ>~_lڛ?OOIYl9ڠbQIwpOKvkp{Ӷ6{C(:ˋn@Ap3\ ym l%EBj jbLЪhqv0iUiS'$,I~Ҙ9)E7]2p|~k4EF*\PԘӝFa+$IaMBFuқZdzw; yGS-#$$4Ъ}COzBM]Q4v!>lbcqVW0d޸_̡igy;ϻ-Q{16#\m83HG\bL>4l7V"M25H-k(l%{YUޅ_qwOF^ڮ+ Fu ׎}nov;Ju&2q={=}ﹹy0,"^Vĉu^W{!Tҫ _LHaGsdž9@co#`|7 fxC'Dkй.^+ d8L]V2pʵ*ⲉh;jJ,}b;$P`"EފOXO1h؆X |dMT~Qu:O=Ĵjs@@ 0Z1<()X42on˯竇g>Co;&IQB(3B)mщ"UkY;C?'֮φʍ{? TM el'a7 WI+? nmg66(&K>0 ?V,lcAHpkKl h[ Wʼ^ke9fsIƊwȓO=n>77wjF;X` 7CK-u%1hłe%n@W0Ӡw|x&:"d|gOLwY`Lޟ͔'+*BgSY$7a|As >n2]W>M,AǎDbWL(`NTM*mZW닭*]b|[qf(s ;Z@QU&s֗V}6wʙ{WϞls'l$Ӷ Q='_,n,v+ 9iMVXHHP;̼ˠ(Fysq_=\֘QF 'ܚsG"~dȲ{0 N8g^VWW%7`zx[jg]ݯVo SecUtL Q(F+ jxmqƺƚ1%c,zgvdDQ0T",IL %3e ,%v&(IYv 4V 9ζ0K .ORaQ@}*c>| *1AM\cRlhdM6"S6`r@@8Ϲnd{n%~r}wĩN]ƜWo-4#p_Rk.ő!CRl) IvO1lϦ.DVCD3o6m\sB+G W=i{9l[LOO86%v_ cO,iFYR{U/X#A,n=0 "<%b{K, %1q-A|}^Pzj;!dc.tO9gd)"R/Q.HfE^BjZK^rM@c}*"SO~'}??I ֫ n[SFXT Ĉ%Ta˲>l4q5{bk}*+q;t5Cկ.zŹ@kޚ% W1h}a r:c.A_O|ǁ't2̔a_җn|+N̜z[v77/}+z>|ftCdgM3H^"UڇUny斾cyʴWe7QӤyJwL*i|2"r.KJM",n)T)B6:3ɀۜS-LWӆͨb\1yЖazpoD(">ۋ's.w XqPLpDsSH+I1ڛ֣JkRsr^-fD|I̜3i?Z~J >>0q"G FGF~_A`{ǩm'XH}֕$LҶo~?g?׼[n>°P,|o꯽~euU Ğ7oޓa|;R2%_?yS: կb' -$#Ux91FלzӊQJxSQzSJf9WD~\&͎VW-e5!gYOe>O[~u JAخu'KAgA|Nn'aķ͝: z 9]4kd +QT̂X!xERj'[lrС%h8$?J qI%Z9#&d M,Q"c>c5PɗO}|Ms-y>_c{4=-)q 3>jk"1FT[anQĵܣוg9t~8\3U͓ou'Ԇax9Q{Pl :f$&G{'Jӧ}_ם:uK_89ag>o~Xx9ZL1<$N 蓔m3?)LđT%DZdA tƳK*g¯*kFJnTTIg"BN+!3 NP%;9"Ab`j_?<=~[WP\NVNi#EfbIΪpIQR'0J]TR393hw]z/} ˲s,g]@0 /|/j:_݆bi@H<×(!Ȭv* ?v3*{hP"cy.)i3B: ŋ\KN#P0~JR@ *Αyu{w}9r4 Qr?tǫobӗv4*XFfj}o~\[?>>PLFǶ?| 5؛K@r+J:̺bacTӣ&HHK~^{1XЕR|AR_?mDX^lz{auͮdXv7ru[*˱V`X*y)cܝb5 JS?şL Yg)%bP?|Ct7/ 9>ӿzM9k'l~^UG7w:zij˩I ou.ly'~w$OeO2KԒeW+Um ':n~%}[>rS ]2rQDtW> H%WE +Ֆ"-4崙D$VFк\ՠ305 I j&,?@ZP [/ig}}Olz\iVZn( xBev&==nh au{;tO0iohHMn66A7ᡇ>}tݱcq0 >{jKOpARN@W/ݠir ] Si8Iʒq(ђ"J+ ZF7H/>։#9b| = U-t+N4xo¼ljUBEl!2K! ^+uR?35{Ɨ…$u9A c޲'] q>RI#s. \|YgM(wo_VZŅt|\n@ݼ @XErOTWRg?(5KGt⏞ <:<>8yF'p .u-ɌER{O^˺rp۶mvy+4}gcUO?Cf(3٤>^R>+HE^cT Hɠ-wd0(9(3zvX`YABGiS.jC7Oф@PP1뾛zRl/ m-/7X <R20xG'_̯ge'kmGrK#-Me?k\hreĉIVvG*ݑ &HQ  !ʔg3cKǼ)l}G篿klGdL ͭecu[tT?Խb9ۧi̤s_⽿#\p{VJ1ВD VUJ>#I *, F>]ZK8pWO[>ؐ.JAb]cNeir"OUbPCn1K$WACN؜1*ZgkrhY9i5g OYף *JL dhHc?*+?)iE ~Cw޿w^)M & ϷێwvG,JL@!gvڌ[r5;ڐڸO>3ud†= .@0NZSq 7BM':z _:5N[طDkE3,]D٬3sIK6(E}]h޷FWN}{u,ԁ9pBV!-2Τ6c)5`Qq8 Y#6*lBCؓ:"d~NŋKMVA0F?yF-.,u~ku[}^:ګ?{н3V'$MܦB*9=石>3ٿFج1[-x0@A,5Zg)WTl>m&-SpJ RQ% 'D' Mhp/Tm#0(+tD8X^} J߇VY>±SүM_0J`Ƨ?:'ﷶL8O&LhjG2^Rs(l1uNaemagn ͷKRlؚU$iѕ#sOݱurwsIݙm3ߪ.jn=;=-^3t,.Od;T>߮>/L)!7o{Lg'(|5%/&X /(Pͼ4PPM5.R=UR=Qf ON|J6 +n^8@^ȧ~+2\XgYt{4'ew >ӗ=oli_[*03}cZˑbAH<)Zfjl籎?YVzQۜ KrkA֍y'"Y6}M+MnBZ;Gm\9{_}ӑ q 7>x=Yds) ]xRD?LSx<'%BOZHPw l?G*O3]lɯ'@h|J*L6,v<! 6_=vixi^ Ǩq4V4;s<'S-\iuvy-re;3>\:bպN_h>w`Q/`Rȏ6DvQ2ѵR$BF"H݄5ByzugXd>+TjfAF`%g`I̤Ҋ PRfa*@?uˤnfRzrHq1V@nR 8t`ڠRWBB"%Y~O4 ^we~>=Q5;#DES^ 6\̽[;: oOxߤ,TCj;(92x3sDpΦ3ӃgnpFqQ>j<+vK-CJP-$!x9kx8޹jndV!)UB .[(* pwʊ\c@UZ~'Hnwodm`r[trMMshkZOI R,{燘Mdǎ߳4b!Ez߁d|W|fI^8 [se4/gV,/DaT(,ְA@}[ha45ruGg/ =!4b旙C T/i.f@j!(C)Ml\rg|@Puv [myGmw!'D # d)-9Pzjujpe0\ٽ&z'0`xQU#㾖]"4cÚo"@!d@ƛD{]? l%34_"E _Djfs(*"(JD[ci+~a#?k6SSwEuM;)|FҤ>0$+>HeCRqІL(#,;.r؟go}cu0(D-*F&gέG5Bܺ4T6FoğZw;3+lʙ|t9~. =fuOn@bkk;'>-#: Bn- D"ե-!*UA7VM|>4(_rp1 [rq⊑Dmm%1Єk w\d3RmoK} Qށe[r (9:h04Dr}\9S&'*pVIUB#I2-ֹWqY M1ڰ&&E !xϟ6^@ .G8?.M<^2;k}/u:DɺyPV$|D\ӇΗyD~zx] lKc@lǿ_Cs#ڦc_Rt/3Fw OoRY3BF{5%Vio`!'1Ytܔ[ ;S/H¼Cpb*YE .`@AXIXOCz+OoScwx[9u{_o-`#D*岧,W,dsgFv .L\diJ\qWQV P9"oto <E!"NF s>hfmk|p7[MzFRu V4ݛQd&&EJy{xW z ؝P]I汖\}SUM6gH͈,fdkFQDeKH'bbIlE^E-pBru{gT}M6Yh>{}Zί~O?1??ԷrYO.CI +-Q}K~$LҜ0T^d݋ĉq?mͯO᷿eMIfp14BgiybQtۦ,'A^~sypݿ)=CN~QK? @(C+Z-XZ<ģ?fk/{^oLO-ݺŧϞ[ll",IldY{+OH2ݼzk{Ftfqg+[ ZA{f/vMwߔѠԞDY$fpJA2Vc:JpR`"qlMx#V#*ҞZh/d{$PF'H, Lv6qB ,I 9Y= O{|_8le#T/c2H}z4K#Om#c%> z8m2ݯ_f|7k/o #U;ӌ2!Tc]q&p}|(NҩGgq;2ie.&]z#'';/;n5D p e8 Is^=:PVUUZ9T8Y3?ߟ}﬽|WZ?yg'[˸v"t::^]V2bHޜ?HM?91oV^ClUEtrRo,|J{GkOn[ZN,VYNV/A2KwfZQdI#lM1*#Upw zJSDź!MOׄWo#2&fE`_$N2SE#͈GB`;ݟY*;:F? ?mx}w};ndPF3IPhe6cq$p^ܽ+Wt),(|W(J&JP~Kl|y//~&|MK7xy1LvtyGqfNcKgY"zw_mYsB:_/JbC㶱Ɓ0Ǫ:\PnBp=StJ-@-ScfO$Ș '%`)P!Vaj Rw="$)EHv:Ƴ^rGE%!X3X@P@LIz}S% YF73nXPr3N 3fA<3l٤轭#) C?l{axKgStU7o|莳 #؝i]_kڞ,:Dډ<^`IcZٞ/du^n _ Xm>W/{ l|{z❯;mJwнLD›e8mT?wdY Kwlfw3!y\10]|y RaV_4REE[]6~_lFE , 2/&?ݹx7ci͠`;q'Vxw֒iGۿIߘ*wiF;lkb a0o֢ sQ]Z7O~Gopg? XWL?.y_Wa\ lp%ltZw`~.o3b&~܍M}'YXL^4r15ځ\.#3qo~ڷ^p4n-|/|r&1k"džeOt<nNkS/$oț} rDD&}P5INCUC`AJ| nc&60X`X;k6rꅄvyi61ڛw㣩TAYNV:8~luXx.r'XY{t飴314R29*WC;'_9JR?Kz{o TuB`*pH|CBs+` K_0͈x@gdWW>C%PFGQ69Pb^0;3 %ԺfשwOjcKB|2irݧ LY Gcll~㝧f4|z}y~HWS4㳄OC> S>K0S%fZ;J+YRH`!>&<,kODVI<ԯ b2`.nVU.&Rl9x >l`i)g2dS,R)]X,ʊ!pF_/Ъ&a6&'?~0&PWz! WOލ"j(LRZuӼf ΒPUſx)tOdh_8IU"ƬjEKn.;hL%fI}>x!Cǎ+RpkJ*! Rg7NeYVjQ]?˿ph#rؚ6y2eOdi~s#GgɄn!KIv?nݏEK}+J}s X*|,`}H6?x?cO?39̒"!^>z(j7[w{p"g, P:#yVޛY_^Z{h,|şmFVy +| &SEZQ4G Ck&$5o[lI#g[8{'arw]}e o0x0oq**_d~6$LN{?5(L)J;K.4`$KhO~{t$”|95MX:sg^J3G(TBQ!K7=H2ITZ}EnTXd yNDS-–Ύr9.kg8 ,/f3:b ЍJ."cv4FO4Id1;zv1Y\R̟ mY |}3gb߲R0hXU%9H?`ƑOWo.#[7K'Q7GѴOc>K 4n/7^,fcMeGRR4S8?QzGA$@τ/0KiNfgF3/ZE+)cY*؊DXa8#I3fx7=}/9qvbhDQ^|~qJ pHBa¤?hА(uUo`PD{bf:@<,Yq)d a5ܞOTօ#W@&` 9 JsNA)3,w>q o>ze%5]sj0t<2G3?]{~a=OYb߷hn֎j')*m7D+j38-E*ɔNCX*,Ʊߟq {E6v/`1Pw-%*Mq7]EqDt_W} +YyXFOuA',xa1CVw4=Oi-4Ɏ $Ɉ,n%I+?;jx2OPY '$E?UGk;'t+9/+U,-&& '|&d2#xӥB>4ӀŜ0cpҩe1 7Gw ( VY$n f-)JG[B> UN Ą{gO$5 bj 5zs `cSɊ?^fY6ԘeY [:һPV$JXTxc/vZj&o:u䣽XN.T iX^hN:}ZL繕z+_7O6r moOͺ,Y~fr9K?˼QAU'gE=ZJPUYp<؄yIvr$L3Gg߽xV,K\*Yt)=d*CD 19㜵ZA,E4'G`U B#"n%i+Go_WiLY7h3ߑQCpu2#z{|*L BQ[+$ ¬pW%%[@D (XfsȆ]A9l+hIgT<G;?`=7 !Ev, kFըuuVO2G>͈EXſXe~"mP'+C8Ls[ W1%rISJ¤3Pot/ݼ-`$R":ؚXROƀ|INXA <)y7+X|&Pj,EoPzJRQb&-(eilJ`ZH*/ ظM3?hh,et\%^?=]w6A$?Ӧ<ͩkXT(i {ky8rAaZ.`E[88ABB G_kKoT"Zj79p4̼4n-7h5oth63O|JL<^q'{QsPOtz S7mSЬQһI"r(1HWN4ucPNnhi()PEцrxnhFYz4t#DJħvRP8㹌 Vqϟmt"TY+2`P8ZZ>%=Y:o%>N< 9B֗T tC;5^^*> UsVnVMlX[a4 _<ʗ6ׂa۟u/}e(mp/Ζ~Ηs>P~P~@0z? Kns{'V><&ff+]o?Azc;i?ʯ}yfX qm:D h,pQ; w;*G:@)Ft" 4)T zcP> ǽ3[,M«-7+$ {)U2e|EMxRS%R𗃱) *R؝/"G hee)i!KbS8O4020kQ(ͪ<-GR@(֦2| Lb SKƴ5D\4Fŭo'1lM"I򴁣ʧ*7L(B!&|kJ9ʧG[>{yp^عOh~'~<sdQuĪe#;7a! xot,vpw) {>v[^5}{ee\d;?̭_*s6L^> 'vcnLt0 w̋Z0tF{߭T+-9lA(rHIY}e={&qHpښUk}"iukf҅zi$FX8c;D<*,67J}\cHM.{fY47$@n,M$B+VBz-4;F9B嘶Ғ9Ւ?C.>~kZ7B93k7N 3%y l1!eXEwo|f o4Y:! |`;Mv~+,9柼ݹv_Rj4DqKpb˚z)Cj ,%vw._JI+SQ`(@#?U0ŒJRFgMqMV'z]GWWUXiitS#*>Xm,}mZ2=7 R2zLFwQКd~1C%FLbJ+3֮JЛ)z<ӄ EJB\"& 7Z`bF &,$#etIwEbhX5r{m40כ^][jF뻗^ع/yAx:oNGYyV UAʳlVƷXel lc_V=  Og.7lQ~O+_TQKZ'e*t1E8'Kr;yVG]>Yb30"Q1R`z,DGx#(Y") JmA!U,ґʐ40)>IAc!.m!QL08m2$zS>L/’ dle/52᭪ܠ*Js;*k2Ѿ Lh ^ib‹$H E²ve!ULֵ8qu5,tь _:xf0X ̯\P8\#yl?YvlW0`$`O\GW>>Tx^r8ͯ]ѕhdYY i}BriýlKJ]lsBAC3QZH?)"4RTLQfO NW+Sx!eLXL叵0hHL \ЋT"1< R:LK*2e,%iTd˷#}i()8Xʜb[JZ"@A܆;S+WRGՑ\ C%8VWhutulԳ8knǻ x.>epA*`u{0^dR3#vw-r_~90a[vf|r&t#l0|#dU׍IZH$xvrID. y#3;S-4ѓF%cn)󷺔庲 dC!-ƫ%H&B%Ix Ot@7`BҌRXʪ3&'ڑuF0w$(E."br/ph@GPw#k Stհ+8͏ȵ +hPPxVEnAk?CXjhQ @˼dqr}{e_BC>Kxc7\)&,,ݘNYɺP0mq_jZIԃd$N2ǮCIġJ4ݟJ>`RR S MaV,8`LU4ZD|BlX9ߊ^<#ӊ ^EU?u/&pnITRGЫJ{]+I]`~=,:x4f5{>Uz>c/w҂17^'׮ֻwF-؆Rw2)'JHvP S]!Zأ)eHnkhrfRQ\.D?T.+J*XK4r-0④OKm%?*xGE A&U ph0.Դ(jJXcଶ1TJsrȂê  aLWw,rh[T-炚0F\t\+`z ZbnOXQXÐ]_0B p߂є\݉`_\NsxH|cFdNOA@sZEj =}\d:0BhڢLJRHY<@:63uxL y.BSz6bTfF(,Z)$M+Ge7*!'HjANvn: 'lcBe.)}#I M[T5n,D=4l)8+*V^rf`dE*֗ Ry*rjڄ%$rճ`޷5RTvyR]//?v}EAWz5q.,p2D5xPlZ׳L?W?@ kis"c ڿ]1*ߥ>GNufFPҹl(jEM{BkjG^1Nl3-ej5fъ;DdjBC,q%Afʥ]l. LV_/Of'Vr#Se.a֡Q%3`׹47ĭ䶈aA=*Њpܠ)Jւ3+߀1v{gOfzkZ/km}yuMty _M2_{ܶ]sr#h5F#0ciX^ʄE):&FB#x Y @WJHd ژ@VbdX!Y -'*GyKHЉ-Tq 4<SCZPׯ؋V!,Ѣ0+ߺ/VLXbe.U,ĢT#;܂VٷG{ |p#,|!X%m!NyC&?k2UHHV醂q-Y㌻ޢtoUq)ޠF^If&DaĔ^c. ٯ`hpu<+yX ,x*A+$])̼C0,'mΒ.|S Ń 1mW5l vYQ'q?P,NZj H50t{ ELƎZA.w|-£ I|Z=[=`Yxo A]6`@|^cEm2͐aڎWahemR<8$JQ̨ +ו|覅 XcBӂNgĆNhL#e{iأu(Kk2b$SDP e?z)f Tu`h9a=*{,C!2۲;V3H딱FX\Ux>/wg. LQч)04f9VuXƝwr}E.e)9Wf~SS#}GAкyg q֪mx܄ W޹ )*[m>"De3si+wx1;"g} XVd/e^՛0+9hRxw~,툚I˥@:C)kC.l!JV+.cnZ1Nǵ hm[~ UQ,$0.}lReWC gsXS6u YtQ\tb.7r/Z8k1T?a榆yAITXԄ\4mn!ZJVExlIӟl-í8}46wf;JQ*rMdrj=׉_3WЃ`2S?ٵ&JqZ`u,C5e:&҆ ]u}g 3XcRFVqzNFW9I_'eeG =4yv1Tire&3f1mxMI5Ryh2;oJs_\zhҟlcU$gtCǺ{2JA*E9o{c:\yPɑJya?t[ `a&j&zn\U>Z,Q9ɥszFInNvQ{ \XzJK2 er E[5ďS^E*3(״J^v?@֧`f8 ٩ ~JɖKImꇤ{еLȥA{tDiuu }QiIzr41 h:ZMaYNQ9p673 +*5{:{Oy򾠪6ZĹlϩ1_h!4ӐQ_|}pvNzVy hdva@c{ f`I>qlӃpv$<4N[我'J_|s2O( vV9&!IX]퍡˩W-[qŚ0J¶ $'=e aDwY|9t L.0E`̪*1[qvHt 1ۻ-@jXP6Ot>lڄДgu8:~zS]<IJ]Mh#a`p zOCV!6A0 l'U8Z>qS3Y,PJqʚO9w_|v%b+K;:,VH5п-fp꼞WdH[&6QaU$ /@9!$N5ڎPL#:f_';lA`u^\3pRǎC@bqھv>z|.c8~֏)݇<>ħqK'0{lE W{]#oD4c ȹ]*7(Ѝɽ1܊S3 bstVꕜ:o~|F&Y$6 ]Vq) zY d/@GQr4(:YZ)sDuܪQd-qr1SFFߔt{g]:!1Nx|o꾄jdǷU3A DIG9sAN^ި}O^ua ! ^nNgA߿):O@ٯ.rA_W0PqhQK1 U(@s:Ar'3Drr`!ӷbN+Zk;;1E˭%̒īf^HrTBON.;.W=׀IA\-nj=h؏0UKß6%WnDފ >w7aXW@,`lYDh|v5 C:HКM[mX^J[9U7ϩΆR`?nnĸJA UعVt~Y"ЦK'Nk M Hd"NP=Kk>V%ZHޚK80ۃ!!Wad䏾nIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_00cd4ff18b53ecbd78e42aefe5fbf522.png000066400000000000000000000577421420147000300352100ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖\IDATxlSg/[s?4\!(3[CPϮ)%뻑>/zDrt8IzQ.0zۋ >BPEC(j FGPn?GDBBAy;L#oG@;? H/H&D2ǟɄd/4 Å0a8~{\ٍ(Z(ԌG(& wqtMGSh ef LG\"H8!>TRbƃ0p! BAGo0hC;b< Q K;T:6!CXfЬ@ `m }Jdr!;~S?A^ƏQhs6z)Bi+`Q$,q<-*>a~$L @Mb F J`BHSB= {` ٍW2,-`h h <=I|M9&q $z;zxr,L(j`@Q0Xr 1nd0(FCzFEL{$9픏$$-VqL\otP#j(5`c<(A4V0Yֶ{30~Z%NqH~*L(C`ɲCvB!{,= K?a,Rq,$! ~7I8t0W2?8&BSLC M~= F(@(6y_H{ wFj/%Dw?h`0qXI7ՠ0pP3h70C){daDѨe;i{9nI;xCH8"ɤa)([Q?QO_ FQF!Iҩc,A*CD!#in3Y>d C<AFUk?*,po;CXB!Fm.(ɤ3ʵ XqßLONyF{z xR5XR2:*! a"R`@( P(Ԍ"D!zMJ[ 1 5~gCxYe̜,*SILAl0 ^pHzBýA7`gw q(2V &i"]=3;$([AAq=&b:,?ʏBx?؋}^Hd @T"*$ e1 B9%1D9ӻe8ӛ> cȨTI?)l^((͛9+jS4qy%(h 8 ONFI2*""ǥ0Dұ%ɺ&)A0Q oP (y_!3I3ABl ECW̕DwGO8?JJY,I'A˂D?.VotJh ͚ +e:X#p0ąFќèxIq8w{JM3&xYt0Z8nG!LG6E4kL B=jj\:Hwz` w  X4@wACrer]D%w*s*q!b-w @ϏȜ$}@3`UDʤvh6x9"% slN捃^N]nCyT`  FC6C6k14hXR%iŀ&we|ԉQ㿜f˃'.ɜ!BAR2*裒48Z {ۃ va{3W;ҠPh;6Zx\\(u\veؑd!ze^e@f?{Pa 4ll`GxZwOYw.K\-r&=MI2U])AEY9qᅩ;&Ňe)R'&Eysxh&sUQ-`H rjdÜsmVy2SiWXp<?r2R%dy?o8f1a y@ imzi$/xx/[N˕s9tiJ9zd=-(q(C 0F(Q( {xP@ K$T ԟ+-G:Unê%!Sxt!xwTғ*>JUXU$) 8( \J02i DŽrOWY0 $[CΜS'.8AW$ϫ,@24J-&R;/$`m PP*PhXǫe ͰXڝ:|@T{  AϹpp"=<B?XT*T<,GrQaz%lǙ ,ҏ04PxkS8uUp$CQr![ف#Jc+S) Ԅ]V0~!(L"C{R2Y҃j-^pj=]'A8NTqy!XdB;kh7v&2A ˀ8X¦Vmٍo,|6יwz7 $a݊sxs#k 'rX\p/T;%ivK/"Ddv8WOHr?vo0jA;VȚk Stm~XzIԕk뼺ȱJ^^-D"99F*MBgPJB 10$D1`#* A07BѴχ)<>Cd6+SS.gcznzLeE\m*rSUOCRt%Ԭb"Gaѭ?kڍ1 XޝńDB4`*C5WF aL6gUWW[ıl z,g݈<u񝮗%~Y~Ώ$R0޸QǨ@cR b+hC 4ޟ_J>04b,ЙvДЅ!r6Bcҋ⥇դWvTi4)825n!ˋ=,B,бѫ[Wp zM5Ey. QCYe+.|ȹ|,!!]D^qp78Zdt B(68$ D1!ERtFBF ) (GlcYt"y z9\A$6Ք1ɏ+g}>f !IQ'.o;XnlCKU$1vyaT3h7(QWG#k»ݑa Ԍk0Ի`$`[BJuD("g3FtFܳOH'+`( 5h`{!dDG %/k  KH բ`Hм<CV&rYo0<ኾ*U) \Y.dEy]V sUP\,$"~nBVA1B( :ޖX4mBRX!\z{@xy\b >+)fK1D$E$W!(J)]I9rPDb!p(FqtD3`E֣g2id 0kiP( b*@:N (Ҵ kz702$ |/rDVD_"H"R^GfPS2*cb Q QFrireN{tE̐ QI [-q^aq84 on sLƣ,E[C,;I H+"*"*LݱH10|d"1ݽ 6"ep\c$z37fӡtc]X(j3iuGMZIbAV bsōրIE莞]C^.")"XvAMtfJ uk܄LNOO7=t>_Mj&=jh%=*!XNnā*!x5G* #HY~̪&22yR^2!D6V  ibX "Чp@P_,V`HSB8PeqC0I"J>bt~H?GtI"<$ Tl0cB $B!oHlvvdv3t# /4P2F&5:bKQ*7`/fԝ&؜G e A.v KN,!@$L`Ke}L@xY*TIJX>JZ2ȘX4ѣ*>xf/!9xs>rŧq뺂G:{0>42fҠܖeGWqlƧGFFF)AXύ)[@R1HZUX<\tFEbܨeH$+!S"WUxt9WcN !R0 ub=2M\W.񑑑ّ+{.?I?+;Ah0+&oIz,2 mkf&+Qnufĕ+9$iA:oe!󱵜C!jMd%L)}1l~j7e -~2AGZKFh4ܧCha-J/TWI&"B#xDZ/:F!4Y]rmg=>ɱ>9E y~QW}{y8ҟtx4ˣ(@?%!}|87)]r+e4Ye,I$VdDYI Kc/ (̔-yK-۬IBb G+-[ża@>7Ctwiν!ZU7bqxCɒ>Gr"5+ H>ECiа`Ry37{*C# 9JV:/M-Ģ;D</9biQ'E׺'}Wm Q9s'>4&K@bNO%IqPd4%[~N*uÝM{h/V㑺'DYJC^ Kv:yLrkn$հ3v(AMV2< ),nb5S칾433HJqj|k5|6˲P!׳%E,!l & /[NqDR<]/b-#G-RlgM]BB0YrVl{`L%Ŕ ?P\!Xϊ,eiܧdl+uj'ux¯pPu9xzRcSrwX8W~#I'ݻ|/4¦Wʀ|q%Q4D!Hԉ@|]2RQ҉ߢ*q7w~,ArhfثQ静Ar|sPodmEaB*iz3Z4WZTg'2fD 򆲇;iL 'lwfɟ E7f1H-8cfKI3IHKb]&x_!hfx 00dwX64hxAϐϖv0pH-=\jꎳ&WmMnP0O0&cwt $|P=G{epq2!" `@nZar C{m؁-o6zg:ۆ$k {3)3Jav^^h!%uA3E_WBoDcG3[Q>FFkU L\ ^d7}ٞlﴉO  G\'M*3S_0a kp=S>F >ޢt 1VpХi-!Y7!L 6sYݹ"(O(wmbٌ֐MO86J&ohDƙX`Ha=33hO[(d!@,EД"|geH\iTdR!L8kI;  |lm?jv5= o̠ 4|B3 (p 4R$7 ^ 4'~< qL%lȹ)#.ςu!|4/H".V4m䇇/"o[( <"^S)'as9 %^(V</0JSq3ab[13ܸ&@ G[\A'-JlJ묻賝MH8{zIӯ4_uu+h\&h\ƒάa²NiCYvy)D&+P9J$)fǝa-nf-~Ӝ8Ohn 9?P-S [.#wjo}jMNb2~(q&<#ۇīˑՔ"x\tع[~X``[uSaJ,"'O9Gd?^]`;i / ڃݤ7a/xң+:9}G2 AZ5c~3՘hy4Bb}nSi#) CMVDJVpH`H@¶ygǝڎ_mGV516/8D`3 /\\\liRf !k:#Øh :(ʰAQuK)>m>t@KޱΝڝz`fӶÇf7TAaR9R*',K@7DZ}dxA>C, ga4 AVhe#҉ô9=47O`H;&`7K65+5Uǡ4fMRJR 2ʒ*5FR1ol9?Ҙiϣƙa4MIme0CHn JRlg@;wjCp4=e \ͨDڿSQɨ9+,fe^ҡN^^0b耵UǹSA9DvNITTɦ`%ٜl# Ә);Y54Fqh$ix1~ykMovKמZI|/l%|(O0Q- WD A]s(VNIAvP@Fo#a hd tY(OYbM:Z n].x$mٱCI;d0ոb =Px\niP-Gϲ&)2\qbLA$E?Za&^^,"yDGT8x`s*C% \]TɨOa`jvWՕ.J$g$:l_QhB ~( 1CfaBg|F)c[iEmbwwePV,tk_O'\LvJ.;VQbh1Sto߾}ҡSL@͸S.oF-ҕ+W qҘ9A[[it,q5apbȜ,j2<_a6mc'R^̗zPI<)XfoV-VI J%.ݮIE/)hZ,9oL4ff3h}`OK0lZ! Ab@i^r9h5q _GOaׁm4R@vHhJtk%uQcVιpM[*)oVpۿo@)J+ryAc ݆= qat≄KGpRԅܾ k~P- 4!8yЎ Ljb`ڝhbF| ŵDŪQpn4[T&v2-*Xtu:}{~NR@ BHBY2O 1G hF:Z84[9prmK1$htF:?k@<+E*?G~9ƮZO1T0L5xILܺv'מ4,,W8M>k֪?)1BsgVD' + q6/~$ =vӝdWHqQD&*򱂇caiC ]㰛¡nl9w`Շ=`aXoUKvTWtZXi dc+=|rڵ mva#a|s5{1~B&x$n@'=ex`5 *Q"" @T"Bu"6upob6+B*C\A A{Eeܪc}$gre| UDY]Cc:p[-l.l:&1XkckO(i*qޫRO٭b_P].~gC7`#o!!FQ!C_\졣HOvgpS ĽK6(-}b^%Tl8Uk[O}NYp&2>VA\ CoWD! ӐW@n1C>0 W"Н&-C2/jǦq,;"б%ƾX-='"`* LSٿBaD/kN&PD}۳hFObu7E&&HC<2OQzqcSwvڝ=H_ݻٲOɢ9FV"Ᏺ0ZCL}$40DdU>Ll&㋏/y$EI1W\tS1ðRT2{d\xhB w7vbd qҌ̋WZ"}iw=Ξ!qj*Ԑ*""z3dȦq{%d^R? ptk!u]t#!s/Cf eմ̮uCp;Ehw@-qg`pA{b?Lb&CjZu HxW'M,U<Aa#`% >R}sͧliΐ+wtξo8t@bPGGx,fY0 [@B'':hwrV~cNbZ !~\1m(YZ|BccCv# plod4\@D:BϳH(PS ^\t3ĭ!1/eQv]} |[i0vyJUd鴏.(,i:bpČ1ž6L(Q[^n|keOޟcEI X^֩ͽ&m&$M ?5jw%2wSM++2eݤ!eȊʐ>OE+zfA.2L{H {SNw?k,q !EV8uvGkC?V""ᝢMW^|"ZqYi'ιqxcHw) R^'C˪ʀļƔK$w}4֝6e*fw uGD#wvW^#v|8!,[Voɿ^|aZTpkD?$IU,ZeԿ%\QS-9!y̐[,'R$Y: P 7!kT=8|?x}tk4/,ER:\[57VR$YCF.k_&`,^|x\{r/> &B!0)j+З%Rm@VhJb˲ޗNyi$u*G˵6$wOґ T`H+ޢPў Hh&zge$-RcԵZ!Wg"Z+_|qOځwI$q_l)%:K.z!oA6D|1՘CYd~~,WC"aymd+#D@؏%iGQ^1!7}U &//RPe1xӃi+d%"htWG_CʛOD}gfL&`i)6,#uX6gBOYӛu#U +Cks? bdXPUPN -.v1i=`..?|XQcAƽ̎㹬ۢw! }Y{4hrDdM̑o7m=B -ś:hY܃߾? 5 R rL4rDXWNj>~U~YKJj.zg}yuyΛxl5r !Ip*tDtԗEc:Y2ZP"tFb%ǻ&^WwH?u_F$2gi]7?xcdTkV|C_Ցɜ| OR{ᤄEA Ho~2l>ېt/Gdŋ!pᑊ!,'cM4-L9C#M']اzo 6y~сb+ Giz{ӧ$, P,8{Ie@=Lm4ٺ'ɹb( D-if]R%Mk<.IzNST{N,zg۫su7j˳x6:a}^=*#}>(@zb4ɑPeVb;, t9O ¸(Mf6$dN /"yR_nҞ䥯EPSb;WWD2*||?^SJ, YH32w|lv}!Yu`}?K|Z5G۫8S)2A*U/A_(Ӆ+{80W6s(C<[ ݿU J,̻#P$o"F$/]\\2D8d"L=?ܐ k;Hq1>ڷ7-P }r;gnoi7~a31[HID~єay۫cc!b\S8&wKt n|> j |SU:m#rҿH0aۏڽ{ͳ}G!]rN>چu#XoH͕40nR Hx/m' 8~xe :ZILQ}cieSVX/-|VTa?zbK"5VWw@O?$ط@燴GvﺹlёNhhh]ADŽ '?\h80K[/ي׿EרS;wܜ,eQu la:/@f_R Y4a8,p iIoRqH#ћq͏>G0;}e$ȑ.-"4ļAt'r;l WT*U-Z^Z/-y}Iȩd B2C0/_2$+W8lnΚggߟB-:pzDS~}{׮7gǭ>G?v+w@A" "C`k,Xໟb_ZJQCfCT*UŭJPRDH&'o{D/_ _wB=}}7cp9~y&/$ #6fҩXYR9ttc@u[:57/.$H;шVqCԛϝUbb.\(\5XƱŚiOQTG_#+ C#)Bjb;Gl>iN Q.0$)2E~ 7fgǧ''?u Xd`KڶmE\vڵ[CΧҎ! Kr8'zIݧAKwtJR^LrnӽNVO w9)-sWzz֪@PqƍӍj2D|bXM2d+ [*@}}D\44yg̦ =qWW&=8CĎ-E9i6g<@̒җr:1lkM o&^hMӜ4O".؎˜0{cth1<=ܸ<}q2ʣ)Ԣ3aHL<qPod`HAc2kk\ KodQC <$~hI '';gsTDyEzxY~Ffʜ4oSdzR`nLD'p-؇-d 652i]^% Ǽ&Z)P6EL_Ӳ# vG9F}n^=wk)ڔ%>& 8{ 7ݘ%R޸q#tc:Q tyQj)+Z3i]6a;ҽ əfTS_s)XpΦY縝ܑ )%ύcAeQK'/=)|`0Yq>DZRp!xv(EAFQ;8Ƒv h¹eDV L? .$>_ @b,~"NUl(I6lSl떂|? `6Ƣq 'j8"*CwEΙ%>+M3Xg&,RXLE/HË^d:w ? +`;hs:82pd`ME667 ,F:<31Y_/i,=拕e_/ {ڵfË1 sIi\\jVVw&E~;7H# ڽ!Qm i2$9÷UM[FMeZ\螄;ZYtlÒH^=($kO*\&,)ʼn^\͊?N+U: GݿR̃b{ EQv`~\&xә)4;Qb|FJ=|iIN^!Vk-;D.֬uj@8 J.+) +^% IymRv0Py9 vо!;B(:*l]DPʤ,~ w+,2I8SW@3am-% )wT~7!nqT=ܒ.^l;;7#[Sh03B%*z BogP@ȸ6scG%YB Gža;:Zz2heq#yUEg "BQD/8?+k7P3d7!4_3u F5ʠe4bX/_jЃxcK>WM! H&t)-Vo ]Z,]>?(VtE66EЫ'!`W |" ͉Ő`LdW_>x+Pb;ϱ:ŐD_*DƱAN$0 QTaV0VvraA;jc5`6jcAb𽖱 s%ܩ?zYR7KzS9px@v]JUGe+)dA; 6lt<, U$NcJNֆNmVu?ѹhc*y6u]EJp8 n7h3jAG ?G?GoC4 RD3 8)l*fay5ǝ>褠&KH B\./(OO򃆃4ޕ!wX9@ -~_Q&IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_100x100_fill_box_center_3.png000066400000000000000000000135211420147000300346060ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRddG7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖ IDATx LS_Dz(Tb P Ao 2( r//r T.P)RDH* '0 Gl 7pD|ȑϝV5Ҁ0 q!B !˅ +A"[!hȾCZB8, 9M?ȢY!" %9?cZȷBaBlW o|E-o}5"NB\xe]ZV|dyD,:-NebGqXIFDA0cxEFlWnr}]j!-(a?D8QS3|K ն=X^#Ŋ Hg[o 4DرС[ 8@X&m۱)oӡߖ1~I]A;vdĎCy-7l8(ٱi{(&### PH 6۷/_|$¬m=WH-m!'О=8)lRcy=b.\\ SXUxt|s+ad3OO1ĴG/_tqq pqpszj'~ccccpPZbbl``dM̸S?}vqqq10\|||<<<#>>u'߿0CCCC+461qm`djV|ZIk[OO_Ox꒷KSNN ~3=6=s~̅u`9<:=>=:B NM`%hfrNaUc==d"( e{x$&&zCYsH=ftQHh>Wr" Xp 1Q_?!GYkxZWj,۴autt|,u44%&fK$ޜz!!E {:;111Z4mNѱYEQ :@z7 W y㘾,D濖*^WJJ)mHJ1PeTTTԮ]hn](;0d2Q20@J{fGf FTRTJGgSvo|>(0jlLx}PRZZ:!ߞɑJ񧚕cjTTLGov3\~]-#{6Xrii ~lggNTÇG?řQ~2!~AOOedtwM?{F$&tgK ECl} )򌌌 :&Ϟ0JqΖ⮆,P}G!$3=]&e>p8 ˗/^| 7499yg콖:&O1DSH?.m4p6J}!H011'>ZkHVVVaD b2J e~Dݸ)۾= ]3$1ƒ8IGF(OЯ|؏_<'҆[_dm_3J^gd7 f:!|.ͳ9!W$,6MԶ͛}OWyEFFEFŠVdFV5FGr4K՝QQ*9K޼LfBj>ҟ\mhhhHDŽϹIwwEm-q*g%#ÄEԬ>bR#.zms a2f;:^5oʻ k+*^A̅ӯg!5+Je(PC|lF6ېq\C.CBd2Yaw! (%V\V,;ki W*ʇʇFMM Ą ;omm%ځgπQZVV2iiiyBt8?((( Ń+դjj14䚙6̬,<<< ޅ% %4@)7o&Ԝ R*IHHHEiiii@ \cSbZ{Z{### jkKʀ!'8++ b8M' aDi{[[lRz"QRP V!7o޼QVTEX,gEGG#302My߾}8ť';V$OXi H``pepeejj*@233! o 6嵓yMOO"P`Cwf|DDDl9|~;:DE#=bbv6`?zN ;S%]#@bc;srT>|PAg_d>( qD FL#0(v);S ϫ7 ޚ.2B& fuB€_ihx R,QSH@0i(!zG !>B؄!K* j T Q+h`1"ooH!a֌X`4ǴQ!% 5׬" tImlllPD BI=yC%|">RlypDǸzDs4sCBBe 拐Q!Oj찇U,jɥ )?>777#fgtZ ݥJ5tuwSj%a,<ݤ3J!GdwIAJVC y5$d::sqj~_(cI>ݻ1`%<BܵЏМVca#FLhC@YDz[:+(љCg_GGGV3]jwKbZĄgiwΝ;^^$B*a3,B5bwZZ$QBCe~ qhdED[P f[D(Bbhw:5#0D!QL W\'dZQ1K"EלLAvvh$tG3 !4cR8x!EqEQBFI? jHk`%}(jw)U  <4x8:x*V2 xNt}L79tG<ʻ+%$|р,$}-9 \0e?EG/"=* fxjQ]]]7lذn-zJjq an_GF nG阘77l}Æu֭۸]w!.0C{bLV}Ӫ1|C 09/_9sۆm\q-[{+R}A= xrdݱ?q 'w/1gbĜ{w#-ׯ_%b{ o<8P駟~̙3g}n݂Ͽ~֭"[77bk{>o<>)SqY_ߊܢq\qsprsƔ?~COs'vڵ8{[zjl!j!n}ܜ<€ao 9qchE[g}CVӄU߭Bׯ1+KD?1ؽ{VŒ"[.?X?L8 i/,M]?^{m}w"&>IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_200x0_resize_q50_r90_box_3.png000066400000000000000000000614021420147000300346410ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDR,߂PLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖_IDATx XU+J1 M[ Hp r x{h^/4 !ZGsTgyYs6O}o *~1s̹Ѽ'fO<۲{;}>nmio'͗_h/!H{焇q?SgS7 Q*Fa}ߧye?7b?;\DVQDB٪$$@1? DIa =: K&O"NAԢSΡ*X T@dj-`%-(I{AT8W>2Gq>:ۢYVQM݋ {&f(֒@Q<9$qO}%' 2 Kaffiƌ4L8 l O$$-aP3I(Ϫ<MmH?gP!W7|/|;@g{@~:ъaYУ3o 3% p;&nxӟ?[&y`n,)4 rrٻӟO~9~EcRW1R@Qu|%q 1{{@qg$̻O~NÆ}{@bCI" B܅=p EFg @8Ȍ BSHNѣ3q #|l=tѻ`τ8 UK! GDs}NkU*ݺ9jI ܼ31ED1*IAQU4PLҤT`r=S WKrmJ^fz 3ݵ6tRMA'PmqTϜ͙(R̹zG.3lA=ZY`Ԩ16k\"rxb m^=Ҭ^}89.|{'6|:rd;rda)Hbii\.@yҬNAIlYHNCFl#ҐWg%Hekk98wx겥3.>v sf,I3!u=I4V<ގ-`U 9o ~h ?zi'}OG (,F0J4C8I뜒gM.mDIF-;|# "71 :pa$/h 2e1g6¡41;MtJ+Cς#~wmJT"(?&) / 2U8t׾@q%UpĆcu0U7h#cntab&|DDyfH(5KW_+6Iҍ͌l }>L%._\Wi4y~ҁ;$$,eQw1剙t*/_o[^r޽H"$"}\-֑01=9 A_QD_|r_%L|ˆ\ DA F opϻ " (gɹ,-%HҢ"f|;X%%/y 'Ff ĻF/dO6s.)J$Ҍ2~KT @ܻE,r דe.|a1s(Vi 'C`Y)RoVl0dCuSӏ0/qȌ% +a:"(٦yX7~c,\HԯWqk cƂ~Ԣx!oQ 3Ϙ!. CRJ[C_w"f4AzZWnyK>ldC?=̬Z1:a b=2|#l:eZGC\1!$B-ܿ_ PĬlH|V3} ! FGRv37ơovVxי"a_>0DD$!NXއ͇DzV3}3IyR ow#$ グ( iDg4/--?fAX ZJEC$a)l(s=z M?l'LW',BXoCCe4e l…GTHdt(,8?>4ͽkk @e%Ud s-|ix==Mi")rdoZr$XQdC:ߣ?Yw{UU0gjn3q BAl5F9c΢E{yp&:H4-!1Lw(E0C;Җs` KÜ1q+lv( Xl+#x4mD3o%*b)տPa 8m-׋2a2sS*.R@Ǒ ,}'B2WC#ua4AذqV6#pc ff^EE),wii$!Ae#Pk$ֲ&$( 3)fufoCzeTg|)HTF1v =JOp*)C{2". dx }o: w\Ey>tˮ6r[ãGLM;0}Q;F yg;]]]]Wdx-obeVԹ$0:btn7H&TPġPN"̟aڌc9;~**pn9ua2BآQҾ;F-9=&2C .YOt|wzy9 #6RNq`֘1G ?2}:fԂaihB4B?y>kkdHo47 #(nnmdc$I >~f.93p&Z J`WUn4RP('ϟ(]]Id$%Ljݴq@M}noңGgҬÆ C1ݼ| ni}Aޚ X0VUd-h&@O0H`B-/x\m ΃+/F#cu  e m>9JJoziWzkEg7gA$֯7ٿ7Sp-gyˆ}΢"u I-1R20$a~.4-yhɢu:hsrsscH!!{B8X73DTPsU"%Ph6fߙ\:8-R$UMr}F@A nn;x`كg>#YY"Lu* Ce5|:JRp\ٛ) 4Kt\{ggganx?O~ B L,݀܈Z9J; H ( 0eɓEF +BPk+$b}zmOn~B(럈"j&Ċ<KB^C>VjsWX>=Np{m'/ƌ0IwS39""a"l翮 }de.&K g~q'#w+w>]d&$cxOc## ΅ؚ ,= 'mIlvhʺQ42RPem nyIyJhsq'%D55wmI#`iD">!g޹+#Q"H9܈c}:__!; eyK'NY%a~BBdBMѳpndD tc 1`]jZr0Q2l h +[@DP%7B9V_ZtdscV(BLSdcyK]18ah~h7sQJк! r5VWyS+%I 5ァ"Ŋ3Q CE 7n߈_U#Pr[饚Jo$WLDW@18>8}F<* u!!+,&:V=w) ,4̹0 |K곿eJ*`DGGI|d|HWH2kqSIyބ$"~RV: }qSci)M\7q[GE" 0΃s,vZB~$D+oZ cfܸqwƽA{kVChb#G|u&XuKƺ7o^VZZZYZZzfs!!qkYףyb[6#M",҅:39`,PY׺uKJ^]z}I7oO uH&$K&S8 kQ]8v!}mӖgu:>[VSI|"Mҿ!*Z$so {uIqKnjԭt$::~cF⊥~d|w,{Bac%TRer{Wp1aD%76vuf]&EthrZw[o8ꫯ,ƃ8Xȴ%!Sc0% $a"  n=qR @D*$}wɻ!BB;IVC ecgEEkUAI)kǩ4&E^}]d^H&dZȒ%!7[9m۶m0TI-~_?@ rM/& !7׾[RH2N ֎$a,8 3ŸBRA'66#1oi@9BjZ.W0T$8A,G5IM6" \ݹ=`ռ&Gø,xhۡmWc9p1>X. zCA_VK@;w!Cyvo*QƩBDyJgPmWOSpW~JI~ϖBYu[wܐC a$KHqHqH4kBJ>+y$,E$+ *$gŅZnF,?9Fy ykhr1X BBn?L(Jlhc#&?7Qnҙ^[+4&-;遇L4I QF8^{!A~>ߎvX诐l^O%o'$AAA!KT2FRMRMȥ4YҖ$[u]"̞m@"ǯɾu))N8JC@Ip0ICbhtn=;Ky+#]A)\ k"2i&NDD@ r B؏A AR顸NP]NUyW4Ft^cQ:" I+9VP  Lް GNSN>;Ys𐖓LE,JB^ 8w" v&N\Ȝ9,`Z8HR#ÇOn_uJ>|aҕrܖ-R[n_LԋnV:d'0h .*Z6%ס&'2Q4s̥(S cE& U$<<|3 =vv>|ac8p-,9z #Kƒ"Fn(;`IQ/y([z IS]:')֐s[wkB/ޱEEi|k(hs&}7<|s%S$Sy1;wHE@ m-l!k;R[$JK9e Dp D Di6t& [ GPuCxhbccisu[ *"" "}GKq'9|]5P%kkpF:@0R~a$}b͎}i-RLQu0*/XppaS XcMCiv|F@ -xq޽{ё^;@K+;Kb[ֽȢEs%2 8So۔1Qp!),ZBRv4{aQj5-Lr I[2Wh9tS@5OXڟ:USC$T2d9-YދOqዿSzA އ, P4f (#gQOOXؚ5k5IepܹªU<<0u{I./Y cd) v젠llM[BEfT`\1Xd a>ak|yj4ESv\@jUd&KNlWDDCXi䢊̚%g!#\ L CEbbb|JeN̩؝֞Z(sղʇ;W \$JvWuk^<ݵ޴BB(2w<L [ƦMMMڹs-A`˅ ɫʓYةV(wCK3j(CQ cE!Ĭ\63sڬk׮ݹvڵ be-[ .@Mâ$zu2V h7NQOi<(DtcMLLfLffVZj; NneZxV]XE"q4Xk4ׄa=7T$䐤f1EEAE233r@8YYY;e-²eH(dE F 6k0R̡ (QзfZL`2x:(_| V˓"RT BPޝ5fEUE@@5D (PMVZ‘leQˢ [ao%lZxH 5C,ɂXQ?p.?D+) ͛7/,QQs#eUryb]KJKr,mbBA,P4cƌ3JQCPHddd09JDy͛7G " תt۫7\40{ŋO"{B2EUesй}dIfU$S]YdsbpB899[K~{}RBŭ.> $'%brPQ0څJ9~~~Tn@I87SeQ$JVhPo$ rXdI _bbbbX&7edbdpZ*;$&ح[Oxqa2(ᐎ1Eh 3t벾:33#3pp)&+;w<*hup|0kijQfMue!݃3^5k $D_sJ޺8dqhE%E%EA% Fyayr d߫oUἧђ( Þ~~~lAcY_ $ #6g- :`̜g%UpR5@ > Ip;?;r$I!_lP~P.I+Qd"v̜9ofjN\Ư3A23c"Io/T)Ν;?iA ,99yU5 &DQ kv\9o<siϥ="H$ q)3##cMᚬA:¹Dψ aL'a X=|p*lQׯ>oyԵ$ E_ด&1L$PI|HpE)WPd rUEQNHm Gt.ǥČ5tQYIb";wlJ>z$J@A ~SM*aӦM@` ( ys(1'$Vq)1@(-gdC 9ŋ=V-L*_|.HN9q}Z٥K R5Rs%+37Muqqq1}BHrfbg$5̿Ɏ O8R$93fm7ar{W]xyu5wem$`DE0 _Pa5؉'N\?{gd\''RI!Fjwm&.G9Bxu#GPdٲeˢ 7@~FRDg#'ƜؽzkoR>Xb~__j_ $I #mx pm}eQ]0~6Zy4UYF~b7QE=ER8 %i`uP#$v"" eCDjP ~ĉw7["[Ҟ={@@$Y&&#&&ŋS 0> :WԲ(@NAy\," ݻիc}ݺj(`1Dt-ĐHMx#J#M\LйG AQ$)dFFF6ުI1) /11qMFƚ{`Kk ̿N5x睴yg$eB K> $ig%ޑtѰb$!6Qc@HwPƣrb1XtizzRRRE0ݞ=iiiiRgp<u?d_񞕕,ks&߈zAkT$ıc# K*dDgCŞ ii'g" )T{z]Fv`҇wGWF`nwTxxTx(r^} R5}LٙKCCC***6$m, yRͣeI Le<9iɿt*n]nşQe7GEa+okcy5xkY[!)++ -czm۰Aኤ/'d& +ĵΟd₂ZHd|ߜ%u_ p!-0I^#X_IP!(IiiQ)P@T;2a^c,m߲PG~F|2 1 $I_|9`Q }$OZ/!n//*k5G#@Akd՘NA HZj~MRq-\ubbb6K#m /BK r٘A3͛0m{%1zϙ1l;EEymĈ6ȀV.4~CY & IZjZ{ZJ51Enlt0_l#I[@ k/]~fܹ`tLKK?ZQ)A@j]H̘߰5kGOĪ PQ.] wMU7tVb#CZZyE#&1mbA(ș3gvs^ mS/~&&l/~M' 5, ]̙3;@ݻ%K` rDյFL5t<݂7!m!J{]+ t)F݂$iOΟ:FUWeF!{>n[cdU} oРv0P߭>:::.#43G}l & Q$-\AK nBRS|Lʪ{ Z[K# @8k( -;Svcw8APɮ|W{H*MO?ȈX(CH=F"}ѱkW s"RE@ 3GA:,_Vk=\ v@sc$HSBgf>H1%AkcE!oP::zcN;APй/g)}xq,K:sJ]kJ|kogggaXF9zر9ct ICI\FR2Rn][.# #1@7LJak|Nc'ƈ\!X["iIi.$Sao[B _5TҺIdIr1bEbƈ~"vvgգwcYY_03gvHZڮ ( :(9r$ILPO@v)H?~ (ҵ+U/I9 J$ILL ]Bt"яACmy^ZZ$eH1BA̻vسѾGs W%IOKڵ }mC d]! O97_ /IKt՜)ñlP~G6~Jskj ı@Kij sIڡg¤^WuK::EcPHkyzzzҮK0*N5iD IRf@~s-T  = w>}0M@@]D*HgSSSSS's#:+4::9_ߣHRR s-]#K2d⹁~siȋOBA NkBsU@&  &&S) r&ZތmbA@'{VJrf)$U#߮{hvSS%x !B8Rx$%%=Av*2)I^Ezb{w++Aw\iO7 ?oO>I>IJ6!d]o@YǑ\ +0 ɓ{Σy=TA ;i3 GLq+,bU}wGERU3KC/MJڐq۳gO=iii@2/6i~3Z Iaeec%N$vC1vUk׮]{ٮ]{wdB+?AR 4)[tizRR@RR  (ڵkOڮ]i楁fQsZ]Lo! #dI>s&tiR$GYr62óSa k eE+ *%{J\eIhh:G%7^HKtd&yPi#[ ҽOc} ]t$ذ %>/}y 0%;Q2 *2 V#Ѯ=n,MRRd˗^ui '>8sۏ8 baѵkԳ\1F796X_ ۏHprDف(;8ɼ6H΅$%GIJ䫈+& |>=ڷLG Dqҩ-OgL@x3gOG] ]{St-ae} < ѾQ<GKJ ZEå5 DH?!1  $ԃ8Z\@Z@@:\Kі/e;c*"I$,HeH(ıp Bo~1.Ĵ4`)3Q 2 :鷏( Ch߾e9#\. 4;p(~ YٳԳjL[Hw<d@ۯ_hҳё+<$.bmQJwqԳr%_A+M,-E%aA+4ѱуZyG",TQiDN"}=/l%+s.YtA@xV*xrSЋXZ " oDFeG^GGA= t'j(Pcǐ,T4 0m預|.]i%O꘳TNOǞJ,,NRHOOo r0esnd$,ҙ >(# XB=(KEA)I>u-q5ؙ[`b W R~2`][1pP dmM8Uƙxc;)۱0]¨oO^eFs 2pjG #] >V1mgw2N?ϚT*0&`SU8487(a 0Jo 6m|"GEGSt.8kk?^_EhgmnsAT@a!M钌<,=<<h:E5ܺ]9yZ5|hmmn H_u1UYе&s 8 88g\yk"0"m0#$"%l%i"W=%9P(,<<.N:~E^$qB9!\"0R!Go53s `̟UsA6\@3[]Mp,!`X&.qqqO,ktuxeiWG9h@8CPx0OFqѳeB)@vh;tAcW'(:žJs;ks^8 nVU|'͘@>"(IUnhѳ`+WD5лR7cJXY\6W)`ZkMFv!F8 ѯ(GǛ1Ե!ZնORJZk"Hd3B6ZT Xoή?ágvv)ZUTFtHh8 baaqtn?5;u8Wkk?C$=[|˩ $iQE#_1E$ޤY<9kQ Υ0'N9қsUuѷjU ڈӮU]irڏұd/;{-WCZGJ5A#ϫ,l0ua|\WYbn^Q VLG.P4>/[8ګV6Tj5wye bUjU1pyQguwE[Wmݟr0A; sskcM\7n<v,bzEꐐӆƆj { d)wxAږh><^'Wj{[EVt5)]\Pb7SZOQ,+ 0 7ɽ{Oo211qe>\LLB;ڈxgxD^oA$ĝ*4J;ń cɛs uMvw\uj[;Aۓ'ssHRq8ȍܨR {oƍ\6es=5DSXRRn)=#0?p֍W_M1C oT =5,)cI\P{\_BP %0PnUIc&7d !kKaƑ8[IQBk(HAߚ(Mޒm/#Í6H%!DBW(}P xlU#pS &qQtA|B B.` I4O6U@a9)Ho.H\01 AMkm jMgwa]<4zEwGCjn]k"ud 0yKlΎJoܼZT,|X)Zvb8@Z Dܱљ{5 '̨ 7e*K7~t{ RsݓΜv(ez Uh3J6䡓@rEv_Hk4lk)QUj2"N1JDILn9 M Z5BrSqRF/I ɳu#3H$BM?5M2U7++O.uv2=\U(#dﭩY89=ϧ_~+$/ q0UuphkQb\qrz鯿qrt?JFa@l`C)!_U "|@j*rɩSL0c!CGV%vu֤K[i!qDZՆ!Ī?N(YHUX0E "Ǫg-PJ쭩y㿰l&Ap5u[k7TTW76Ci& GCGrR!޹S%-;G1Jw%orLLnfa.Wng9*y0r/ʫXG9b^z/7ikY oy'`uLyxh jVǎU5"Hm!۷o}J[2]p7caũ*qCULn$vչE a{pQl RE?LL.%IJk4#pK—M8RU$,c߀&Zâ];{1m{J+gG.WYs0J_R4{/YobX({oݻ g-߱8m`d\'&o"|۱/W"$+K/}n}N44\ʻu37Ʊ B:"RLCmǎ~_~ = b `?~QÍN/F`7?C+_ <9H&UߊC:$$c@7ٿߏ.x5;t$I<.ߚ\xE1CT۱˴| CNO%bgTwfU:> ,iua-ŀFw߽W60/G<)I$ȷU "M ㍪ibHɕ0sQ44BY 0H4{Ƈݩa:^{XX,4HxHД/F_&I  ua݁H-+\ˍ*rzj{@L+qE] zMMUE+&u%u |+ aE' n8Zӝ*PDC״~0ꯂ| >HB1([d;/,Q_}&(rc\^b?~4X+|zlt1/ҳ#45_!q_`C閌~"^/-~x駿=NX@n: *TlyQV|! 8V:]Qng#vwiMJ"/-r ʃd/]!9G<¾?spyڟ~ۢ?ї)yV!ٔm!(R y0]=ŀr"LВ s_omWC]:*+?е(@~D-d}vOk$ /mbU*M[ QEIĔiҺ5&ly0YOr!0/*;w>4V [eABn @&Eiǝ ) 7 )|\E'I$M@.t]*623߾G<["tK'1^,8f`Ҭ L{kؕ"ZP%:zRO3HCGVk |l9TE}( ޚM\^12٪#t Os\n0uw)J8ƻk,7 fzQZٗD 벬6X=}j$Ga7*2EY6U@V#K9FA9TANL /$GFA:)r.,w[x-π8%nnڏ'dBQGIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_200x100_resize_box_3.png000066400000000000000000000237261420147000300336320ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRdX9PLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖$IDATxĜy\Sy5pD[5tH @DADE'P@H,z( 1\ P[}?k}20xG^Ӑ[0oM׮7oǤIN;̙hѢ%|3w̙3OL2m|oW_}g}?>hc?Yf}_|7nܠC{d-xhp2L# -¡!x d,7G"}9>d KԂL%6 cQYB8 p&C|*A6~2r[z ] :Lz Ӑ#K-CqQCZ)Z]-Ho@%:5CPsFE,/+֐D:E}b8 }!:Ջ_2P{@z;dd ~+۝LOm|%p 7oDL7bo{n_q@VVC~8M':7Qsv8?qyw'hQLxs„7'(ow5DS ^PZ}@77/H77 FMEƄ 8~_wh_w2[ ÞϣR^ tz˜Q  o1a(řT),j He[fg  ccIRJ%z .;#c^%+?8˲lmJJ@Ÿ!kƿ0&'UV aڕQFuWUW+͍ͥUUQ8[ 7E7ȅ2d0ovaepTu5:YB1U6666*B*2&M:7_WZS|IY|aRR , D &4el]EPqF _7!qst"̙sq^pB|t߷}3BjcǾZ/uSXX B !BkMB=җ&Bw!qJ Ϝ_ٳ.\p\>˧/]jU1\appرcK~lnʊG72 S;6'PAEޜUiJmld(cM.3667qc읜,-,>}̙s~޽{ ,!111QXXq[?q,]lٲev{z9@b`ffffGlPj m(H^H8_99ژԍU*Rs8K,%*RvΑ}#]4o3U3gr߷v(;:?uw;Z:[ljE}(;/b$nBr$+5111 sss 1UmllQJ"XE 宝߰3[}|֬YY e]qQ?Z?^h|\QWQ $" J;)yǎРbOONNeiij1iꉛ*K]B@@ۑ5 "bgN>}˗Ww cټy:ٷ1$;;81>>>~tYe\`hhh`hoАFmk3ȀC: &e"HX:# m36gΜo/ݻwg޹s֭R_K@""VlW(8$(hiDٴip HJnJJJfQ073@s $dP_tgd![r'7l._$}}}7oX] I]ʁr JJI 0 083#2P7R70 8{vvTsG8sKf9.m+I9t;4֯_ ؾzkQADP{@޵FP gyFƹs{g]Rb6ȶm'] "BI59A,@rX rС@XQ׉pC$E$vjV1E= ˗ɪU11UICAi  Gmt95 :|yy|~c}g] -Ml!D͑AN_s!AȾ5VTTthKZZhhh jEQjE,]_ xF$&u<~c}]p"HA8d !]܉ tos\[8!HlMs8$% ,.c<Z_aEgu_ :&,1r9˜ >_1.PBvnp#IZZvZ~}bddMPi%^730Sc`A/ܔ7Z$L}Bm.kQ1~+V̧=B>[}KĠp Ⓛ$_.^2Q\#pppp0u0 9 "a^5(K\gqOo%PBVzu⸸4Ex·ʺ'W TCc21@i4 BDD*iZO/^L~Mh͛%!2LWDVPeHHHrhsrs S@!.3gILJյ0%Ku',5hhs˗33wxE/Ѽۗk6#Ƕd19QAB&N8rMsW!%V9ytѣ$AJPSSsN[+yL<%q|d@麄ؽZ]^ VVì<SqO1p۳G",@ T䜹r$13 J]RR!TӰLxSjɀK~c~Z:j0+ƌI..).! 0`@wwwq].پsN]-JGO.Yϑp( Z(3Zu}IAUU'Oý[y^ןx9bX S  zahP\\]\\V-$2uILq1<^sg箮7C4ݹީpz^66lAƟ &zyܺ^7"IT0BC+9 kkSwKO]׽x*p 9GyHsi dxǏ5Lյ@$OA&O~*"=:م=1a A1} Ң`ʖGղ M&hW0LRs'$Y{rA{x5]]G#d( Sד H`tV$K$~pE B`h |_$6l\ Va A~.^kdZxt{X0R0URI=&R Ls'G@<6 ]#O~r~L@"IOb*x! (2/( wW0jk=jxll>*"U0L%0*=鼓3Ŧdn`PQiǓ'Mx4#4$ꚛmMȮD2CQޭ{nd p^￿JB <2j(*bŁaf`P=6v'(b(> 6zMϟ?~92]D<~]3sIfX~p# U -oQr.5{?~G _ȕ'1 f&:"#|~nGP1d>gnN`m=cƌrMhQ Zý"$G rw_(HX)JaIG Uzz > 6urihZw9?< Ƴ#GRxP#/a-P䪖GUd;!TrپBKɲU<|ĘHm̭Gښ?S=_ДU}H[[ P+ bhy{sТfeKK {lIv5 d~v?Kh//W|~Y'@CZ ~-(9TQcđS\}cuJL&;~axYLUٹPP4(B!YY*ru+4߼11׮]\HO6D+5G 䈍;1y⦕d+ z:Vh#_޻/Diiq끭-Q$ID,B/PY[l)!w;D U_倇ꑑ6l˭ݢV[3)##k"[v>.,(x޲Ad=pkB.@ PZo{Free^|4¤ !95r |棠Kf/^ >n dnQQ)8 SpFxBHN;-,,, k8HcbW ;aoaxi[DH@pUVA!]Ԧ ?aYn>< <5Wζ!O+sx6m`ޠw="H0) ȴi1|Pu6û"Ǐ/r$7!Cᗆ:  a~{yoL%DXK@L,XI,Vdt ;eZ̴.CǾjK?[lOcl@g~ `A 8jAnCD6~V%f6uф(BAVB}ܹ3gN>}﫯e~^>?xRȊ A6D۽oqz[XTZ+\sg7~}>~"P#n5 J&XW+"IIHɁ^;!qwBg8H{jHsС}@-ξPfʑ;ק9|u@2KC0j.|?F;gIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_276650b97daa7ae98e79b929d7f87c19.png000066400000000000000000001031071420147000300346040ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖IDATx LT,]$;Xqmj‹IaT(3 KL"X; M1XC9a"e~8d$#9|~5{s,xmk] tM{7mڴM۸q]vjq7444޽{krN pn(--G}}}}eeeV8֯_~3epc;|>ضm[EEEEQEQQQUpVVVWWWTԔQX^ǫ:/8~A@k @ ly?A'É<$R ǖRQ_Y_Yr@d͛63d;l@x*$R[k< _-|0<6@6geafz] %OHj,k2G;[ Ms CWHZk̢څXS .DtKS8~I@M]!9M 1+A *0k^!L4!?  (?,DLK jbM9ekHMtòwvB5OK&YMXMz]7!f;˱H#A*#>jҚʐXK dXkk1ac dږ֥E)dn$O @wSFK 1`ų#udbf[5!إuzZ¦&{ȮY5/8- zE>S s9VFWX)&', @7"}=B< "Ycۥ[ R @қY%;Vò ޭMa+ǬpsO u˪JSHu\Z@~!@1+}iEYb5syK=Ȭ$9xO[ c=Kdv7;1kd0M %A>ce`+=_/_tibHԤlgռų2K/KZce:me B} b $}dSF3AD蕙n4VD c0M is޿ >ZKd+ @{ԤxCcՄ5Ԥv )|@1JfԼz7|S9&g/lOKӰf-jHL  f ^[Gׂ;{5{' Ɗ; ˚]bpO0A~&%8Pf]}AZג =)šBs5Xql16)|gO}GH@؍eXMVrẔe)}bz[PeZHuz`|v䥮B4,%s&ThbMM漳>}svce z)7r@f].4^Ý? E ђ @hwXMaf5yԤ@2̽&?IY iW"0?2MߙIgbs Q>O iMժ4}ИblR@z}YߒпV{fy{̅BKe]s)=m%ܮhH8"酖V[YѴ^f9%<G:@4pbtD,}^Yn6Y<{up9X$$Z)7䧁X/P^R|]K1<_05j=A&[H̥s@" * lKX/? LymHDy< 2Ӱ$Ӱn 4N^jpXbXERUVQ$hL42cQK/ON8\^3~—d{% 1)]_((^3]S s%݁`u,c{ֆ5){X "Mf$mFA"՚Up?TcC%Y(,eҒ/>$6m:8Υmmx/] M =a$}f] u%%BTP$H3Z6IiZrOaFo$0WFY"$KůHdzD1xڻwҵI?h5B23==A&&NJL HͤR hDYYܳpE+j9K\<OW ̡%Dc Ss[Z.~l v){E?p8)ܝJ5镳eA˲M,jڌJ)xHZ*deʚ򅞅 +ԍW齟 d%@L7!XɺuۡN,!ATo@hZI٫lڤa1oSCA@~B9NWR!U$+Dy_Scz᫅+iA^?O!LK2B`(]9$.}pL}tHLq+& yڴIٻi8g$;65||0}v2>5{Nw H!`jP ѴZzVzB W$M {'PGơ_:Z눈^etK1 bí!Q6I1ıq:n9 bjvS!-L͊ ڐ&Au05RS6iԬ3,d#•xp/V eN MDG2XG}ߺ%]{ [Id,s߿qь%>*H]sMY-¦Pb 2f#v, ʚ: TL ̍d i k; "4-rf'Imʺ]먴MkךRFyGa8?*+)7c.iWBhhI/y\\,o ֗mHۋ~ xR: )(*$R`*; a^Wה{ 2BPJK)@t&,FKSÞvdɺ.Sηɝ&?){Hz{оѦ&ٕn1,);CR޲[2͛edZ&mQ'Y"䴥 @ ElĢIZZ+k k 5JmeҤ5g5.\UB8<oޮuI9be%u{CA$B" AqqFI!qp M\C;NttnKRy˖-r}\ ITYM%ԺK{R>"I$(yl,P!5XhԬH40ן$xQLuXAg`ҵġwzNYg8Vƕ߄b"}{KP45qvwxGyP!SAfD6ejR-S˒lGo0)T-fu 4"Z~M~MyMM\+ʵB8)\Yr@X ҥ(n,"\AǺu]s5x&uiJSt.kuܮert9eKv"ON8䭕ʭ[!͛olV7GIL*7i̎朗tA^IjXtC i0--F5Z@ʵ 8膵,X2Pbv{z?oE8*{oJ(d"ax҄0[ir8%NWs rKtR8Agii4gukZW 7H4R!@tF="H3Hv*PjOMAthx)^//dɾ'XKX+ hgS(#KXphT0"Qxϭ77r܀xt BCCj3,i.bilXZ(.KIi2R_)ZDEedjDeU*Kۍ mE,ҽTU Ig )ZH5`Ht.5S X,0ARY55 >a<N.<z!2B8bbH 2NvkD _2ׂE!5%Xa.H$!Ӫo.$қp~I(l`02hN 8b#(M [# zUVedDFHJM%UU!͘,Q!W*f$TtBՎVk!Hi7S7ꠦ2*ʚrY>o!9G?>F[B;nhaZZ$Bm4T 8 łStP"Vb1%D"H$**DHiDEj"&D`HjB"t+[%i؇e Fquh!͡JT X$,oy5#FfY`%]K[wa\&wֻub4NZʱ D`@"(9ES%QPE\28FF+HBM$ID IڶM_&k}XB*MjפGJKS7՛7ס+/BB%XY]`*L nIE_n Q5Sń/4w nm1Bq8c1` Gځ)FȰ"ф&x"Mģq IACmM -kϪ` V`R)1888=Ȑ45BmW$2/S Asrx ट`m6n"Xj\ @33gݳ06車XD8cb "PH*KDxOxB@P$BzZB$h6*IJ$`=(\7U0GF8H K@X4+҅p qwF8-i?!׭u;sB O 1s ,6<6DM#CUDh}" tx̶mXm_QHRJJ!HJKH>77xFoAD;3*dݒu-y҉C"6 "tt )k#Љg]LR)@) `#h|4v4>cDH$ ~xFo@)(X,`-ЊRǢQW4xp3 Tk攕 gBȺuX4G[4DWhנQP8OhZ@6""2.Db~YnpE0bpEL)ؖ,dfX(}YyPn */`_66' TI.HFѫ/(j*< [q` ~1ĵ^X-y>Pz#M"" Qd6dDd435ߜƚ .,FL  7űRrha }($遢XopAJl̮0HEZǣ7c‰*Hn>04=|!裼paBkctytk[؄XAȶfbVW.&5d2j `WݨI 8|@tX*ʂSa2Yl-hR=8zWM@>{ A&"җ)DqxZx|0J$lS7 ȃ= sa|ηJdbfeMo(oU,ư^E)C WnDgMx"zb݊>A*>tQCcpz*X{\fDF$G9V+a1:JqNɞSYh2J _ϣiԌU4,CDv<z d0gp1d^S^|΃MufN8b=-+eBX4H 2c` K71Y z0MxݡDˊС0CQq(ԨKmN[X%Bxvʬ}PgCK ӻ'z3;o)7%2v[7ݲ(Na5,}bkfK͑eM(5((J}Pu/[FTWe%TAbm Z( BԮHez<>E\*T6 A{x{Lf4Yg kcf,LousoeQLUY1ݭ-SpzvkHo&В!zˈ08]KlJ*Asl0%d:Q1/~U!LDP!BBv !•Ac- ǃNbmĺ1 _N/[oc-WV +J۝aY4>aӧq VC!FW}۬}H\"PQdK&Fk&c(#tj>?ǓQXbEInH.^L[UU%Jlw0q3N_P*> dzS1)d𝧳9,_ +z7e/b蜜-q<7sbsBQH70Kt [t" 2j, D1Ƞb1`8 &OD"z׉R4#IERIRT%W&ѨcAwB1d{v6jrE(.˗C"̲Y"ueFN‡f1-Ko9کg~IQ," 2Fѵ!@B#gSh"+~H˵!0IQȨYۤmTP!hRT-F4((v6{1Ch¦c gedziPmCݻb"LbX~NY\T]RHuRȨ>u ndˤ=K_."^]D:1:c/|fz)2.[xA(x"Dd u LP 66If4@+j6(( aD@$MgՀ<0Cb`0dUɳPY]6( l"6e`1+1$b"GGG㱵&D#](ӱʢP6&T(y>85gyFFrAf&IRV$UI,k,k&OYj (21!xֽw! +7qnfrDžz+8 ]!xQ"h@>_)y:^utBt aQY4(4Q,FĈ(ч<YoP&"FP_kDT*:5"*h+QIE RѲnUZ4يgggh I{8X|ժ5\R=}XȦzt1 !Qe50Xnt+Dd7($=#$,ń(FdT,g1f[DPHv`eS,5C5 Pf[ QZ]YclYEi|YNLeomM_,,$2fXQZ9{8륋H:3- z9k"t#GU`1MH"1K6H ]$`t  AϢqo$aŵlrb`zjQhXn a"IYЩd X6Bq˙D0YjbW9$߱*Kx5g'9T@cDt-Py|kl 1<  b)JgXF3ԉmo-+ mu!, : JeL4h5x%uDRD3lktzV.\7t]@VU| nI3?AIv$b5y`[Aʬ d?ѲD,êv-TdYŢqzbY 8̊"U\x#BRmL - l,1RUX0A=ԨϷ(dV˗BRr]f0$QY#>6ׅ v!o!*b)@ I@",|P2*X ZzOD"!أL%lCQ5 nJT*IQneװJ!@gEEyDzqɰ@kYggU!oX:Ț5kr;'4~\fȻB5̱ܜn;X2Gı23s".<4pYK2m/A"qZvxNvBwdx1CC,eڵȭ!˂>ds$MY Js\Kg rjp@gpNa6#A86yfs(F$0cXchlXT`,tZj͚ܼ!>VY#aႺuKp<lj*0nn>-ۃc9ݐ""| RYL#F вD] STjQOᎸ:O $}Y)E)"P>A#߱9BʯY_pEZB(Hx*\vrYGA&DnphUBǻL pO|m $ <ǻ`4ꣴS!xInɲ1B Lm!fЃ쐐YVv^d BD2nƮ _ X4N-Wk yVi8ǚ<[bs>7v>y(,= aoHof[vU9qح2ᨾ'$Rh $֚%X!jdsRLɻ!Ie8Tfw?K)+4/FRSQ@Vcc'dCի뤐t&ܡ!q>x({A&4-gY@}jU ltó#2'B{VnQ&1QL^ʈ$9)v&R>RL=lY$YwR;:R;捦ԱNPpӠJ?V!yj*p1@`ްC5K2tXiP֠>VX'' ժLy%U ()xW\W6)75r~ůnw 4aʼn.o]B1zTR:E8!H ,f@H$j$ReɲT2&閩P*ݫ]No*m &R%-%UB5x )Tr^4B"ԡW@U]])B2 : [m˳~{ mTҲ Y  8ȅܲ Ǝ AsTĵ*>wrJ8n` nN"⢻bpĄ(r =6 OK9o(MtZ)K%w$;R#ebш>%U*NKmmHDj piRAUU-xS 4Iۆq^P[-KPuHjƮR MҴj(pUxE]:GPސm(%hȉ,E7m @[r\@w΍<Š]+aŧ4r;ۭA`wau'w: Νwyw=Rb)x 2q<:;kπ kCT9R(KR.]i8ڤ"Я 4BT͖FebI!Ԏ1c܃몪 >A +.}6ېݞعE;-ܲ=H#nDo甝Jb)v4(4)JX*a n<7;M<~q)57P -dK]ReRRR)qM ḽhiE ՆP^T[hB|GH 1Cբ?+۫Hg<p!}vnY ?apr1n'$rr|\,- ⚸bSDį4*MҤ(w@ nx~'i];E쒝b1{e'ρӥ"rHu̢6=l\onr]J|O:tRiP:"B*Њ ڽ ڐޮҼU֡>B!-j'CkҼй3 i:_ a/\V,@tkimC#-D7J8 v_߂<% P;5q_*ch(/O )6Ŧ*Pv*_*~ŧZڪ4"AƝ|ݼw .r.Iӟ@ h>G4)QFiiN42<nu[nrULJAu(? -䕪Z WWP~y' ,H;Lyxe9@۹|4bH#crevo|\+'x ؔ<ů۪֝;;T<766?7?D KvF\bg1DY ~t- L`w9)#\onnn3r}Ghґӧ:zzAөvT9vj7TP>@G$R~uuu[9Xqx#,\6Y$ z#bC(Ϯ,вaw;os9@N 'ǎrg9n( (t*r<Ŗlr!(Ј%/9 +o+o_mU]mC4ҡVq?GGw~8p0$+X21N +dY]4 u:A==z=`C u(*[ !`1ݞgj6j:BȊPba1O!?v$`LޞL=g<p96h(m)9CC~[-צA*J%/wa\e2zKRWNrNO?8?>*'$~Z]D-ҭ#&]tGɣ/G:x'p d1*|O~{ȓVSh!qM~b1k,2D&!}2_@99I[x2Xș;(e(;j3.@naeeSl@P^5;~ 8| /k5ߺ;Q#g}t?˟?P'@E a1i@8̃0 ϖɳy;y65k\ 1J]3p)?X0G qL|ȁIt!cρ avpl<Ş KUw "]ݻ/^lV҈nYُP#(8O>~r\#zzL\=+Kp@}$OpP|G"OExxP2 O~agŋW,J Cl>f$0'ua>_3i PðgBpGlvlo4ıj|^|UEx\x]Pȗ_~B`L!ܓ+e>RDH"it#jD]=(@NcuwuuuRr c!.Oy=K;E ɻKyo.<a~m?5 xyA:p 3g\"'#pFT9RFUO҈zu [а @> +(vTb9:Lx@!xz-]tRDL߻]Kϛo&Zt)8p+?懳$fTra;#C&5]-_e]?G 9G~I r8xx`+ߓ@!O:>}t-hwG##eeeЁ\1pMWHGGXe< >C^)p,,8Cx궅ox,]hRb1k0cL:|yaxdp9P˔ *qnY@/ 6};>g',DPuW\IO֣H*D~kDl޼9 -u6-Gݧۺ }@9d݇qzy-,e']U/8T_Hs#l\t<9?]2YP2l>DȲ*/7Ss疟;7 >GŻ@'σc,"ُ xS>~`RLWWOO"2a1@ 8 4&z!JtGq 8a"Yղ /DJY@Z1$ `dTg8v}maX#fˣiXM 8G5 )/}4Bcxϣ>G'~ʐSy@<zN0}agW6X# V% Dpx{Gy'?B>E=~+Gw/y^ XO46'_ln~8 HKsKTjk/ =̲ǎ9ڏ A}Y&R* dK8ޅ%n"4z5YkZf~8C_ 8|>|wyA ޏB}|B8{ݾ۷o߹@;_9;_n>|X-_cuR68q1S ]ؖ{X1ht@YԋMjI!inβrJ I ?"48 $a{ql>$M gyVZѫZta3[Ϟ?{, 'ɱ>a%X̰=,>_;w'o>|DT7zBу@vmz:֢Eob{ 0z{X1/gͧ1CĘLŠ؋[HBDt& 6ǜ}н!U"tV]}G8 ^d8~ǟUu?~>_6)<<p~`=LHo[@$/p4746UdCξ` Ӻg%w]ګh`"Q!B1,%bȜ)2O8FF#cѧLERѱh*e`z@]Šk'A,ۚ=]un*rዹwmUO'$ ?;$[.ESEǧL̮@xo5ߺŞn5:| q y4BeNHHSHBB$r BB^˒6޽8:::Hȑ#---GZ9ML X\ٽ@ds6 ,Dn_:F%w h4\o~;#$!&pLY#<#HF!=;Rc벨@T|>5k,_ZEnYm0L&ԩN: T_Q|;40pW^eXs)d`p ii h @D.t@@"׽} rRG7Ҹ~k׮_^v:CttbxW΋<ѓȣGG18MSL%PS k %CyC f6d)! ?`Zn\"$~{.hđ\r}2u},)Hi_e@<tЈ~#S]% ·)>%0Sr;[5$$kr[s[m>?Cu&㓓%T29鯦OM>p̩3g9z8tpC}ҡPtﻯ\ ,"W|y։nHV_V ^ h؍c̴~Ht4H^ۺJr˖-[lR_yykdrH7F-V+[b4 !1DX31(ČX6mVo |2nό5kssR~%IdX=>zdrxOLNONONO_MvԩS|u ft[:$:P'2:pUGrC*9ՙ76A(# ?x/x/8 ]#t|xؾ`__7k[++rAK-J#GNSEJ=GgJbGJ*@9Ola#o|~h=Ƚ;44>aʴՓ{&KD3pAPvwvvxiN.XϡNO@&ҷq{{{; B=- -(+*. |/ݸtח?d ,I͌JK';/ӧe"$970mJ6ɮ#.ܻC~? qp, ==}$kג\*.\cŻ$@&I#Y1W2<P(x E5y60s?yC6nw AWV"Sd|BK9=> *j7Ӡώ\EՍV "|GrAkb8q8 91=rd$ hT( cKƇ7x `x\FydWv NمH듕$(MiU} yx<@AŒBibv@7ɜy~%ǧmFG]PnАb?>㤢@KWO.S2%^D'3쳣MQ/،vuZٵPu~mBRW !Mqr6ц4TY4SUP?x@">nuq.AvN0-[/oNH Bxqny>~8H<~qbGOEqŒ!'"p !GvyoCw s?(/)q))qY'NOMNMNMf?)6+9"uKmm^^NmTkkC^WgyD}td#ym3Y3pTdTI Ǎc7>Ƈ7z{k˺:2>p .G,[1INfv$Jɸ?yɓ Þ}.B8FEp cL G"!kHАߧ`d8_=91~|OIKJ&VwKKK'ǧ~3S}u,ۤeI0Tj|oIjmBRT}p812 1hN@%AȍKw랞΁._"]ٯ<FHd#`1HdÇ>xA&DpFtz2O5ɣHYqL'`[HR˴1Z}>%DBH趠@NVnTW'X=1gb5 sƁ9w6 hy Rog85&GCP$#WGNa>ty1B ?t\qcߍW\|ʖR&u{)|K.A$[aZ[FZ'0(B|{'' Cp89xPݦ۹y2i='V/_2Ğ%7o9j)4ͫiVZ zjM iRB==@* ':1?m#J!>WI!x{F==#'߹\ .V[@NAt k[iD<.NkEH!? I>~ y BqEb}2 xL|Ε+2"qT۴cG%Iu+z"c~( DH?y<Y&`& o)#O$*397a6mv>)4 q=P52S֭WC}^ɡU X4Q\ ucA#YJd/ #fHօ#=## ._"X]a8bI`]o`!zseR$Sp4_ hOFPI=Ǒȟȷ!}+S:jI×IGbXC99=mY()@q`DU5:0Gpu!8 sޕr'XqXN\"4WH"Y]OOu}B$1BP#F/hȽoK3<#O0?eoc 0i8 |nW2K z8pjjL}1m['C=^\ z$+3(Gg_ׇDdug@BQ5q54]b* Á@x^K#M$dYIK/:2UY@1D@$㉇'($T =~B $GI,p r",prr@"v߈ƿ 2RP?wOS>JvB^z7㕐#eBPǾ}=_D A!X8-B,Hp kw]9AvQ+Ve NqC<+Z\:?bYXaML=˜zQgca'? J9j + D"'i^߅vj}/Ddx8t=(/ NiOSc۩[ޒ^:!#ˏ܊SCRh߾{1ĉMBB@FɱJ*-Pg\UW1G E(DP!!2.6N%g?~~Jb 0KI$U,OgʂO|v~nX(qhǿ__L:tz8pjS>V!) + DCоxtROjH0D`&(++Hzlw !e̊ƴunERMQ<i4`] $ Q8jFQ[D 457AGiSZ]7]1 qi5ޘDƹZz߽\yH:S]&⃉fYd'k#ҫqF$*"[' x 4+Rr1%)PH$$0p  k"5~?'iͰ,Cc|=d_'h߫=*b GvbJ)XDhZ4RoٰL"q:<=3i2@h !q&|˒eҬCx%P䓯I LYphADU P.%[ B4B|DVfA(b Awv_vv;0FJ'^sDq@ K",G"L#IDTKB z6&n^]^^ikjLfml\>vUbL|:# -%I2PD$ H4# 8; ?YBD;[`Hc:!$ @."9@L+ {ǁDŽ1qYZc¿Trb?VZ&2<,N$/\@qdz;]qǮ O{pTR!d:٣@JuQ 2o ~kEO,HDktc1mއ4t4S١Ym#0@|pq{?!9E GHVR<~l" K)JyAu'5z?L;~, Q7i4}{}g_0C8!|)¥ǁ0dO(!#EWWLⱜc_uhg"rY  A[uIc6ΐܵ VtD )x+r85K>d0&)(J0tC~`4ؘ4wggΛ7X;Y֬td:ORK~ES)HWŢdȞՇCV\[GU Ǣ",^eKg%Z-hh0s⊛{j-@A;O^"y`"~prFR<ѿFHd+⯨WYg͠f?8H>o*-M ب(YG$!sK+WcNN{2a0$+a@( ydzjI֠h_!! Zyґi S*Wiz+溉 s<k2<,b^>Xz],\cA55AgGX,YF$Ra?Dֹ(<^XQxGt {}}} ,ʸB ɒ%R UY.^>J$2j[R3&Xx++E$٪[V+Hw#,߷@OKk2u,e%=; ?ae KCM ϯ)7F=Y GYD,.N(07LzbRroɽ~=vv%)Y< ʽYf{+Ӑz~`I,DH$!RSbL^pCc-F]] uD8u[ʧYC%љ/ ƸPrG/rMkQgхE5:8nY"tj-;ŽM%pKwpKb֗mGw =n7:WsYo_NtLRJ`aq2I)duX=Z* bGuKODFt{R`]c}=I1ވ,<=Oqاvጢ{yHw!eYWv-',',C!\ 1d\}zm4sz뻇2l4pt7#@!2 ^:Y{NHǐDLJd`E.!$.SLjX$Y(PΈXE2(wDYlz{j Rt94+:CJ@ {|" 汷'l]`Vw+,pC=8AEMӞ!I:Yy'"c_J7q!*'JlTUɆ!Y`=8LCWDp_C[VCDq_IQu!\ҷ FHk'ʊ+(Ve=ϋ %JeY|HY|dr"Y锇-'tHsYr~PAaz&ʩH/yMBGo,>^U^^Wn>{/w #;8b..n1ĭ6lݡwjL=A ji\<\4åOx:8׹NSdqZ|#wuu`.2I6;!#l$b:P+O.NlnB9GjX9H-CE +Kq-6|SM$&M;4LĮ9ໟHNd _^D41HCt_F"Cz%ɂ%CgXJOs޻D4K ]\_,byNNJuqS\5] "(i8 ȭK5el }slE1V3eq%r5q":U{`@j /";[ BA`DRjT;Ϯ+idϞO6*7Qo>/O Y[ߏAhW!ZnȞ^aþ@_N5M؋;v ' MZ^Z0s2R#?8%lr49zc|*tp4:?lCvhNoDί\_OCP+Gu>w/Rm/ڋN1Ws7FQ"9H_֬mlIt0Gਵ7|}qelR2'$ܜoSJmme:Z({îPNZfHo&DbSR4$Ab\LahO 28_2"MrDPG:uF9R^qК(^nӧnjjW,;Zt]pO< u87HbZ⾎F唳\_΍t;˒sY\S$ez{)) uphma]i#KHFufZM] PDzez.DDv\V>)lcOO$u~q9${KO<SA]k ;{zza5(;Ap \`>[+9eMA޻DS OQ d >kVH:K߉>Obc'I 7>+ |]o/A,,Y{W/h=P<[-렐k13#l}!"-$AnSk9qP 0ZKi 8.<Ÿ(0%\Um8m[A"Kl5\7vm||2zcb}W>$X5=ho%vwKψ@B !*Z! `'IVdḉ%h$G5EC&Ug8oTx@`v_3ĭqULo,b,n{n_]W]H7kZ biqn{B ?=BoA鎎^4" /ikp7@x 6nNk R,i}'ҬJx9{zRjZ ! 5lݐ40*4@+ҍ[eI+zu_w˒#MA_@¡_G䍠b[,$SNiZ.;?KgH6e=6B#ră"XL-?bH~0Y::zǶñd۶l<|񻣣Mް#/˫&G 웊VF,t5f"J1;ʛ!V9u+9D7O"/}ѢhjԔF" 7`y)^d!uGˆ|,z,c4Ƅ'PV !0$Kz:)VnF"S'ѿFz Z)ǥt#!*8nWo~Zv.=xpM$O }IoY97z8'xC:CmIMM{ 憎Iho:=|^L=^zWkA iIe)$2ZBb8[~֖V⻵BKDn^P1d* iVE) #VxV FF~F~hBxL D^t $LTj_Z/Fo$_<1ѷ0<[依*}Zs#G!6774w*vlQ$|45)9 VRJI,Z !J sW("X+D1/B7o٩'SOD_L4Y行w#D\ .f>G/tI2>4$Wss9x9UЇYvQYGa~T $YC@)%%$XZ9cďGOO0(TPoh/ QXqcƍgss<(i^ʒZew)"Aaْ&RP,JC4,Aļ900xSOѻh,׿7n%~qdˆ քgbL<239 Pn턇x>!+C*{w)gboArŽN>ؑ"ʊMSk?Eq//5Ľ8NU"Q(5"+d&wK+迡a2((0Fnta<08rG%ꕱ ƄL=`42$bR i!(W}n *WUY=Lx;pk&+6d?"n"+9%ϒY/ӧF2_34;_&8nTC13CxLwHHy!X1>1&+RAm3";̃ < UWeeeU%aKa`$v?t=iGf8ޚƊ~AY( I"+:Uk wQ YVQ .-bI Sgyj_D7oGbFHυ?F 033xt0 !s1P8. 2 A Xއ:-o $$UY#1, ya&8U]?WI$8Z^ɳ%$(buwMD]c Q3f^j5~&2)d :+sXU bM`S[FQvD 2Hx- S/ eHe޻6`w'"aBAhw CBv8dW E.rX5rm1A=eVS#v;R3C"y67s߽pvonF(=mm GLGhkkpЃqLx<*tL{C` *n#fF>vrMѹ#tJL\V?aO X7+7z:G8GwwwWr[>,(i, fq^1"XȈ|q E~GGFF #dfm0`"@Ys-s:bRЃq1Np{Nx& n7cx=.e!&t3!vnEuy]9L_.U^^媪A!&c:쮒A ⣵⪌f&&-C|z(u?BbgN=;uŋ]E8A####h[$"h 4ϵHD1Z'<'^Ւ\vgb'D^o%ߡ+AT3eHT(*]_q (DWCp߇zBbaiHwEދ;j0Ap#5HuXHD'Yza"`Wb2HHidI0;A@ iAZ[͟v>" R'z Nw>^owD(2:=#8ÐrUUU*A1t\ p:{.oWE3oP^Vgt0oNRS\&aG!"C,Ij)azj;쥒7d% ς" "H I^ȤPWg$C>/|~ ZJ 4q G[/ ip@CN_;=tjhh|qb%u;I  g\埕c[O(/ucBLjUV%xDwܫ `Ț!Yʥ|AVef D~,ȅ _~e(24q8F!8 rs$N ?~0CN3`p"2 ax~R_L YI|oáGYM"zevBT,WgH~?)D xV䅓Z/$Ghc~ Gnm斖ܵsgN"8NAh{Z,wE& H]g‚=/CeZD5?w OJDvLsd7F Yk"W_5Eq ^|$_0i!3,X%C@D!ijr"1V)AΝ9w !rj)Bqi!NxpbF]geuSZb?Pb.P'(+4z/`ȞPIDAT>+%-DvRpl>AʦQxv!YGC 0ua!z", 8CZ6[Ih[Hooo/=2p9}4qjq,QDi}FujT]ɸJ0@@L2]>=CSH!+KHq%v2ZbgD.)/N~Nx\ Dl6IAicł`A"-XD3g@OfזČp}VYy]%`|X'B>,F:V(6︇2Tb !*!kz"&r!YjEBolbtX#B d H MM#ƣm@t4 sǹs șӧO:5tǏAHZ&!#|V^nF?i݇iRf|3U2yH]=)Cƾn{!Ҧה4Ar?/kVJշqbq@OӅ`A.~N$1$A͢ xd\;: ׺%LE%3~ه5.]>0S"odל:IŽ%y<%Sd!<3}ToB~LD فazs VFB5*bOC Zt"L'Y@tإbaQL<`}A珵IIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_2e05d39f4cb329be10e8c515494cef76.png000066400000000000000000001064611420147000300346320ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖IDATxܽ{LTWz7?-A'#rʃbRa#"!We<xjoAӨhM{׶o.Xsc4uM&$kxwfMJެ̬=>~.dafϰ>{ֺ,&&l=2n3c6fvgnݺu*pl1[wygŋg͚5kjkkkW3[l%K,d6}E̪ⶂJfos4n_o1ɃYÈ4a@XRvumȲ&%VEa +Vy|#1pL{y;qEb)A !wׯ `DJ*FH!Y@j-Y2@LBE?U <# Y1$c]v;kp0eYdI%#2RQjře[+*42ofX sdWT3,~gXY,cM8@LeqXeObee#5V{}x*vxH) {\X@ 1=f iX! 5?(eȘ)Va9o$fxHi kl?x#C̙#$T )VFtXa@ӊwo82L k? is6@+QP@ \!Tui0aSŃ@sXƼ R(W__A|B>lZq"A!!XS0PL"* Y?A@isJ9|B(XOB@L"@TD!GX !! 05G iEA!+˲λǧGNDDg#N]E0S!U~^OS"ǒt~AUJ6JlD]нj. OPtBfvJt]k*e}*V}>"Ȁ*"7y,^N <rWY._|y-[,YRW5Qüy3o:7ӊ8\]E.AJIIgrhZѯZY d\XгC "&/.j+pG2 Ȱ75lBLСi|is(ߌK0Jl$6Yx; !~@,9yq"!g$Λ(HT$կ1݉LS.)d2~X(,Zp "eAr[bE͚ ÁwY6A`,gc]ș.}1sc5x4J)1 BBru;RƀpQSB y* B筙fC&"`'~KB@,ȽxXHG{^(0x erUd! @BDEۡb,C B)̋+Gi2; ?\Pc^`GdV*L;T,$e\!-;.qU:EXĀ!N׬iT M+rT0 He9"g)3Ag {f- \[[d"4#ClTQ8|a?.5*tYa̓1xʪvsohdDvc\`'sYHC췔 D- 1ȹE!SL Hz3g޼FhҙB|x QYQ)ϋEL 0\B#%z@[zL!ȫaB*O j=UQ)VT. 3D)e3 e@ Ө)) 2}g@/C!<5`Ź"^BJY7o qzs喻 VW`KA=$e. 2J5^]eKHX+(1epcYKT<1,`e|̳%tb2d/rrߜ5~_nbQL4XD&1!%B!ϲAyZzo25pXOpnw3E@1DbJDS(<JD.!x,ºtiui1LHر)7AG 8*V)ob?Sb(sqF6 HH` (@f~uZcݯA"ųq ̒t{ WRybmIyVD$cK̲LPaa:‹ e9)!ԩGMJPP3p8ٝNHC#I}P)_d5 ykt+tMcczcH%% ]2_@ 7;4ǬYeZ`B/[[;(cxҘ˪\R!t1Ӌ[TU5}Ty$a@6ӑGvisK1u.sl';,cOuCm>Dx;`tF&ϔ7s$ik_3oT/f_C=UTiRzQ ۘV\ZZpkW7mpe.[RiN^[oU*\UU$ dŊ( XtlfYw8`#`u2q3.{ !kb5kvuia׺RhV+,XƼ{QQto- !Oq\Q9y8}.[4Tc8BȮTX!v+5Yli ,_=v֪UZWh4x0"x0BI tr5^911{b"l\Ve)k30.F\Vuк‰X-}AQnZtժVlx@$? &61!wńIݒK 7eZL|L 'q]x;a?bl.zf]UHJ(W W>* d֭[+؇cg& 4ٿw1aGB&Q;>cbث_^]6!v^”cV)K(Xû<*me)?yXVksLL&dLL7)DGræ"IxWq_E]f.]ba͏k0YiiiUiikdekCʆȟaBaoc000:d ꕘaݼ֥tҰK Őij X+FV"JVNlkG_/B@}ci8O$E3bb]%t}$9]@9ѨN5k/Yi5 @KvnŰ /BCgM4p +@V: Hd.K!XKt+&&&w‰pL"᜜x$zgpY_\*+ y>0X<֨9.Z+b:}d 0BHzlCCCô7M6@ER*uV\LYp8$"J@3)j $NT]'+`9is⤪J6:l["8H_>@}UL*7g !kUD7= %%Lf[uEk T0^k ~Yּ jkk]|o^ϲA!ݣiwtyΔzp XنXMbڴo|CoзA~3k !.MBXHqPDuБ\(9R1 *}&hP6)$XбNGSAh(+ ]tX:o<FsC.EVUn\ed `ڵ2`YGrY x,k2P {0.ԐT@[J8]dmhEaX9-(c,ӾECzk};—ms jsSD*H9!6|tJH-^ OGa3. =mxLmc\^)>wl9e3a !d֬Y/Ai $WWWE_2_;׮ڵ"}vvjV/_@\ AeoH^Tc CgJ+& W\@*Z"HZ@#5`D4CҿbkBYÀS P]]gϞ-dWapec11g0#@w5ꨱqwmKUSYE?R*^4 |Zމxbm.~5¯zu "eٲA` TaKL6lcpΝ!Wِ7mM4)˴! ;mқoc *D'ByUj,OMM96$KVJAjk=”E_*Y], 4hdz9Hlγ_I 5lS~欈}%*4ۏg>$C~w^oZ,+L _- 0x<ke(ȳwrbtX9v0x䪭[b޾69|Ȩv],ء7 !&SțoBX 0I ã=fBbꈈ8!8'', X]gg9H+:< `ٳ_/k$cƚFo۶!~ݖ-m^Me?4_k/Z+݋Y` 2l_MM^˖-r%2>(Ftk! uV``AqCݍ{ۋ<4oNb 4)J$c()~.Wqq|q##>&L22RTIrsˤUgVGÑ(`Ԍ'H|f7xɓgn7yꚫR}ccMMM.d[}.c˺}%%Uwه:tx=k.6W?|W_/zMV7 ݻwSK*ybeoӋVmݺu뙶U6l0>i=}usO?~ʡUo5.%eRPCܤIoű02iҤ$d$"c-P\9eђP!"YYF[(3%ÔaLMMezlɲB'K/?~fȮ޼իWnUSf[Ͷmɖm[۲qcuu}*mbvC Y?3 kv7}uSSS'e'ͅ)ӫ-RVZbȧs7mP7wܹoߞxgƥ2!}?!%Ezf,DD2Qc@S3rY;ٓ><7PO>b]GV]THW^^'X:Ǐo>`VsfΣ6Űlܸq㾍۴&f}g}fek_op4mb@dDNZ,<>kZܹuSNP $"?$>&϶t{Z~6'Щ|*JU[Q rBd2ܬ|KOcE tOW׋/^<⅝)f͗/K>_5~^e8oM~Uf`{Ený~W,02e@u/7{\1s}fz]ԺɌrUXMso" [Fh6#Kt%&&1"L";854FOw!],MHH "]]]/^<~ j^L c_re Ei[.nqƣ=M~0fz0R0`Yˀcg|W?|h&h0\b+ЧC`vaԉ "HkfXJE~Wb QÁ<CIN~"4)!/-$$Mz nx%$!b Wb%1ߕ+y8n:F,3SH }__K~,?yʓUJ!ȆA9[ Nx{ry#LBDf*$ H%gfIHHK϶j7H^Xee.dg?&IRAb={bWor1k7^ο)"퉉I&QԱӵ0DݻwχGsM3r̟}G?| Fz(s9͕bO)sY-e͝+VgfǎA#%2BC PE#ķcʔ)SI@ҲsMQ 9+KbYn%"D'$&&''[\Vwٿg^ʽ[ %<7+/ qrFw}"`o.BP QeQ_v`jlX~ n$!%=|##UEXXFVkSokHzu1@l.t:]]~\ "ԧ;(豙o]VdSL>#X+W?bY"n]@|L׎ÀxX#;_%Gc*(`sDcrrHMe@ĩ^>0jaVɖćcII5?JOGcEУHm`}"^uǯ?/ `O~E _?x8`9=1"}H+*\UUUozV΋b{fFyƨWx5oF>1Zzcri|$^lzv: \: KHH`=|L HLN[V$LC:}2apիWkubS=UG_|Q\pAx=H *A=ST!;x3,ݰb2|Ѝ '{ 6W.6ARW׃b{v)}H+;_ @p?.(`,fّe1_x?sa `օ D;>n#ǎ1dkU%WUV"d[6BB6u&/bH88ަceSqeRf?*<}td ]K%L*E =AtiBqYn~*^|@ȉ~K!|_\pP ?S a>ݺu+ƕUF{k[Z<8>qc _c@4ᾪz3J"(rE 6/DL!@GPH@D *``E/ٓG﷿My^ˣ{$ <7+dX|E s}H;sfiF{kibY i+P_az׿_^}Q^|:2/ `:R)UtD\B`Ԍ,CJ??%zHr,KSvL =if$GoĘI/%"LR_ 1D7ܺ"RZ#Sȅp ~ `C>9w+}[d!ز)GPHЋ3fl !x:/ B%P uRmBpYd82oOg@|}رcOx4)*`oG zwAEɭY1w`lj'xϟ`< ,^NNÊ+Çp;̙*/MZ<+#)1cƌ>KY+odg "(rS|LL l92GjFFVvW~^~S{_?a ioOHjoOJJf( f&$&Y6,8;v<ݱcǎ-{Gޗ/_ 'L"?~]/?|?|}; # smEKΜ)---jkmimRn\eU貊&WU>%Z)$r+&88޸H*XOKOg{w?? ӟ"SE5 Mٱc%$'%%%&'&&F1l!BA/a-d@ -jx;D@?xG@Iyhdy瑝;O;}3mgJK̭;w΄X >b4XNKOO>}- zfiHOfc,xܻ\b dGDEy^e։źOWݏ?7S*&B.yرnGK] aQ"ƕS nfw)b+1} brxރ;tGbcNz<޿V%Pcw-yH@ڥK;w<}smm[&ns4IEԉFTO1^a6k4 a iiIbD2C/DS!B@vL # :L^ˤ]H 'N pֹB:; 8Āy^( -u-B <8:1WSY;.(HH^B}&b!Vq w?}b,&%&.?y=ejKoȑ}/_, 3/VaY270yS<SW9ټ&zZZ6l`;2u"b@ċx! 9Jh[[u$K~; ק~2hILJL,N9+w~Z{|緾+e' k&-(-FG7/Z1;9E:7ՙ }erKD􃨧CތbAOu#Y,(`PG.+3@)'%ډPיXb($~+\& 'n Xzb8)Xz<^q`oH!bK p%<=n$x,_t{D^OHeEd w{fD8/[*W+9XlE3'w$333) aܲ(- qFcsyqdٹӲ$4yZ2փZ^^]8q2WHu)}K-zĶ%@2Z FYVfrf&R23-1I,t}[ LcNq\<Z|:y]֧,w{Fdư&ϲ,sE|pĩ(@RS) QU:RssDU ݓd'[c/m'ub7Szh:#B$BMNNDJ>q}OKR nة~HҥK<^YmoGܶEb) ZX8ulpPDsR)*耤\0H"dJ7VJh?.3"Dswbr2R(fY*!X- Z݊_ t @Fx" E!v (}eHʈ@"W 9>"ڑ+!df'*CKFzrf=yh$ILT=1+I{A7DLuC瘧{|(C`eHӝ;7Ȗ! C0$hn!Q@7(TzqFԌ\SV%$QK~vA؋ur( ؞BMzzzzBBBCoib"3-tw!r2h<-](8s%:  ;Xs7Fv/Jp־yOwjR6̝h=a !#H`*0 $5W|V'PLF=&zbRS2msj(tw{X12Zaм~&#`@ 8TxwD':"''nYmxխ`{r bPGti䵷Hҭޏ[3'nS?#!nkss/ppD8uRh;w"$c c`@s 5$,N?f(QEDWJ=E( G!oeQD3r0(ǀ3Ѝwرj {yIރ OAKE zəTQD(! GIHX2 Vj&w֫W׮t/?}~}ljcs?nۏNn7w>g(L@ -4xL{FAf7n:N~:;`/>xÇ7HҥSXI}ɧO+Z8r"SN-40a`kH{t+iF蒎 2Y"OtFB &??E?0"SvPT$'%HM2&TR]W4"fL끥{F"wݒ+Wt{ʕ+>IT2\S׏"qUAdw?. t Ժ=oy 3,ڑ^$= ,ASk2abC { H +4VBÀydRƂ"IVԬa TAgg@(^T˜:3"ЃHOHbHCh'T0&/we(FW!O/f.ݳgTȕ>+yW{յW׮ʧ`w+"ߍ3;,c(8`@Xᝍ-z, n߾۽|q|s ).a 9$.h٬! =4z`N])oM|Ck b\U>qb9pN%BP0x#b a_gβ?-=!=)11sJ{o⎧??}O_׽;~ܽ_X'vc=)==E@ `vvvM{~vM/nIڳ=x壏>Wj\|˽ێ{uwīzkr,5*=`Vwvvn߽?M_~7G9rȑ;w3 OWt龶 6ݩQw{"]X^8l'h-ĉ'NȤ0sT ;egnv~6),9euHB,33sʎ;x;v  /BWqXf$"_ܞ]]]]]/wï)G͛lrw޵{טD^]vy_8nxY%wwvܽ{'|ɗ_~7_8ȱcv;}>l8XwNݝ;wL4Q^ί*,/XοNN,:5dj>F[#d|ˑ|#7ec[ eo?$|]x_u2wo߽}l#_1cƺ-m>4'أamŝ;.||;5o|DBH c&X2\&obQ+0$\"М $#=/] g©lG$0~ƍc-; }|8vsN;}m%(cn)ǝ;!' 0*L?ƾ)) a,?ѓ Ab7Wiy"iiyi!Myi@^ 86lf8._|޽l<>q?: '_~nNȑSG3O>ynkkkвN qg'?,C;83~d&r]`1Gx3=C )\Ƒ&r 0qddOrs>y1eŋ/z&˛k}&G=zhH r`l%:@ȩS2qp;vʏ76q=;Bjdžd2S&*olK÷ `a!"U螼DŽ/@'CG4^V\|fj!ea&ꋫ HxȖ[5cӆqG Ҵ&';.7p>wRjhie9krv\M`#vP9L|B8Lv1{+ H՘0˻.0&ɡ~d#M0"EZ@B+lf O:rdD/fΣb߮m.oaL.nE覍>P7m  7(#K cqMMM  "RQRzq ͗&L0n K6B+ <*١)z7,@})=].5$S!&& C 4$+\4 hV~#KZLH}q<{ڦU 0uy-[F mlCC0"B;w40_;8Lۛ>i|rr/|l6p9sm+QRʑ80a\C]JlpZxƇaErpgғ&DCa fW15dSDxu)FG"Бڑp<즸QWkr` ٶ岱SEc㟣G7m:Z8z'@V6yp c]تޓN2"57JJ[@Z[϶ihhp4ĥyR&Dh U'==A݄tB`離PVxSҝ.U'RB1 :OLuBD%sBM%:蠪J=1BJtUe-۶lBHOU}6߾}JMCn{@f<6gYq{6mhe{zO.joA&{mgJ{U}^-vUːW5q54iocSRVލe{!%nlÄ )AMӼCF*чTq5@RLұ`WNTw$I>~'axd1)Pt5ʕH@ёp(Ǒ@Agt]555*(*o׮m[>ECX=~??1T2Vq:1)ۛO Yƕy0j8eCn'66!%.n![ )RF\A q02Aڷ/nyy/OH//!)yI :'&$hi3>%ɾ99)QjH>SY&#3R9:+ޑp2 b=W՛_~Eի5]j(!\!j(zElԏ%Z4AP ?R.8ݝG޾ynauSo e@|RF˛5\s_֭mAj+0WBX 6 v45ŭx(e$$uhle4)e V -nBJJdŐ<}bi#tcSPNHR=)$)i)Rғ$&'%&()]'q4"zR7ғB.U!tIfeQ0+ͥ:2R:.s89:⻘Keߗa,{@)|]555 V.sKKJ#X4"$xX~Xnш b۽xa{mje'{N<`s*ϝ+z̙Ja =[Bw74k0)ߍKIC0a))CH{;*C IC@8]5iFJw/+퉉 jOڃJRQo:s]v!B, 4A 8ʰp(PсQpf۶a$eƍ**U P W8cwvnȀx8B_+(tɓ'Ozfa/d*WjjEkV.IEBR8 M` Р`<8qeC"#1'ePooi=bc5x1f8;pī8Qp1sY93xf*HFzͶ]\!eٸo_ +J> / y /{{nسi> a1+#V֦VUml7aRތ`҄U)$E ))S&LX!+S"V#nk t^ycc5"+#]s"ڝ.C! @y%E1}%9$cTҋ99*/VpNCGGL|l C)I5۪Rc(d#SȺ-of@c C)d>6ע/8/~F \ w/@v/lg  f -9SអHn )mm1W^a,dڤ8$5n(dS)#țo8(x~OO@]㻻۱Ă{Ӎ\eQDZQ )Ϟ= `Q4"ՃkP_hdS!JSRi>RG{?1P…ݻ/@ڦXf +1oƀ0rm3ǚ4-eR4 `q5aJƍ`̜4hY)))#6Rf8xݏXF56֋廆B4 wcc1@+!jRb )! %iiiuKH aN08B ptpCJdzH7͛kvYG˗}-B`㺍@\!n >1dqX!/~,#'MM,ݻ^f3T6{̙>$ieVm kk4).7V:n%ƭ7_C' ^wldM.f,Xְ́4,e|DQnc{hp)A %֥gE@DIa*L|&S/k׉m}0*3qc5wY%eXP7ӯ/ANS! EH˪A AwSHf/ 2UyA/ҪUgϲ,i+X;i]-.bb`- Ҭ᳽|>䞻'S`C콋qlݻ-6[vic$3 fdOP|fŘ6tYőa*sс3<rU(E*nL[62۷+̀SO?1CZZZXPo=+gX C#m%Sȸ!Y XSg}ZĨWpck&ŷLZjh6qX*qCHbGZ<׺ diRb` ׽% Xz BHw/LpB(\VTfa2Gqa&g+ DrfUuݻcGfڽbu8W飼?OVxWxɝn۷t}{-_wޘYٵ'''LfM՚79wܱcǎ܉?SWzٺu>Knos^H7,޾}!cQCc9F1]="?8W`^FZLݻ" 21MR5vlRBycO|'W/Z,}dW\\,nHڵh"OhCؔkR׬ABmVBVBBgEy6E?n=})i8V%&flR@!%GpSx/ƋH%OO<>'[}{˗>r8uիWv8@,wA6E8HNUιs))D#yb~~b~S(HOHOH,+,Bm4vz޺ݮ;DHgNH^n}_w\pA݅ nmHزۏݲe FߑzPܷpcNN+h,$=V?v&Eqp%00p4⺁#.pSb24܌ɩ"dzFF)4Ĭ T`n#[>gU|NgnFfaV7eg_pKsq[ 8A!9; ǏСQPP`N@+) | KKKK#nPWM=" rVԘJp>NgW_|4 ZWWp` "l=ݷH}#f ԄξpV7-;ٸ<!;|FV=)D8FFF!(H%E W>MGqL# NHH`QG7D$ iD pLL/I^쥳eeg_ADʀIhYe(j4֮PN0 AN0@AP C_G}/0$H-v1clw>S_'}O8/}v}7p?jZ^jQ֮Ю|˛wbbor);Փ9К;wB3zA4JX Ekֶ:鹎PQOCٓPY)zA@}MF"\ TO 1 UBPO}OaPՂ TN4.ZY=ST vKY||v[nΝR(E">U2V]zhkn" *B3)ìRA UL [ T?d g'tC'{bj`9|s_m=]<^ LMl=wy{p~܅5ɇpԍAc@P1o;OgǏ; tP G++ q. !yR+\Qx/D TxkD *IfY`YucȑK vX5Z̿SO?={{Y70Nrs0݇0.XXVx^.FaL&k^aNA Ko>xi]sh!,O0(Bbz{ g`p pLӿ06ȥ9@}ڞ8$&- H!ic+ ! LĐGch7܌1܃￿(cGH= H;㱲l/hײFcP l`1TF83k^gc򩧞3't3gؿrRn.Rᛠ MgJ@\e:u\S#SV.0 jНWTΈ \!8սgPS  *`ar<,\I2O"^@uu]je^偕idͪ aDUfzB!4#W@'u $q3 ݽ{Bv;슊jr^d Ʀw^F6.\~ꄪ={ &o1{jϞ}QI##Fغ 04(xЏVr.a6LC t0v68Ɯq; U=ںq[#FA L[x&=NX2mw9n D T NGn3P,&0{ ŘJ#G;~i Eʲ/`n6Yld .Q6 ZWA 3j s.  z]6HL^lX!L&QZp| 4=y!&@U t5ܩSH.T}C.Іf,NzX'nƀӭɫ5Ja t>rȑ>/$#~64jWM,EӀ&dl]Eң[CRKgu2ZgPʻҎ[.dGEmz^CjL61_H.x ׮/E ٙ0G W e/ tIs7i3kje ߪY&ti~jʢW>588$R$ID[D YǃPO5e[ᡪ.*sL$&dW&=5LIchQQ.KK'#t!"ZO J CtSߜԞʚp%r/eI/ +/mbR_fÕ;My Z/J$2 ůE<@h.zZcx-Uރ8a˜cƜ93ؽ0UM Ą5b# *=T28^T" ``7|ͩo*å_K^!T^@R ;VRAԇVvj|_҂ E x\tuv)o\C{C 2&ިbUW߸4r0Z1cN#@^%^RAO4EE}ii"cS|MJ AR֒ xHՄE[VH 1˭-DH dwQI;wd W=@1G\ꨕծE qxWzVH+!nRZZz:ѷBh A! TeeG}h@UET!j߫F OH&C}@mN?B;G"y E6\eER "#'$E.-po1BE"zR5L,j@tJۻ~9rl!_vB@v`"'\ᙱc/SK/]Wa/4zq)yx4+cҸs~+--@NW0CfV`%68аZMfqDž `bcBV-4D! Q`6P@/0H- kJ @nq4q#G3iȱbk7yPq]WT= fekJ;w@NyzDt2ݓ M+Jt2cOee='qQ _@R~*Đv@="% 1HT-ͽM% 567u#BVk< ~_BЮ;l=uA$ ci`f}MzS/T!.`\.r$ .!ݯCX'rI, 2z%_ ݍp! qr !K6tpD1ˢMvR oihn]]CS%`S<˲ 4qH]|d\f DόL$'"c##2NiVhwwa7Amyohz )DcûH!SBд0CἜῐW {*=Ǔ6/ PƴG3/&!ɸ |&"Ҫ Mþ0l'(+kkr+WTN2e`hhW(Ym/> *6Q!$>pKwVEZjeRd\Ch*j A( wvZ:譬 .Oڀ bګSm;-IKv[nn2^C ˆh^@ѥy”u:9QΕp:Up.{*~ ͲB:p騏k\[8p @= Yݜ eUC+ N#S.myxIɀ~#9߿$jPoVԱ xz %S\<7r]es;22iKqڋf<"{ẒҎ!ryrEl&׵kD!sڃCRR6#];AHe7En\EP'pwxb&2 I=̎H/{;vۑ+W ,W_RUR'PH+y8HÇE&EFF.IJZ$YWuG-t״k4WlPl&^ŕEAQpu@ \tm+(흺o'̋ ƞMgA(h ލ꼋|]Tyx4q* pĵ,żW!_{p*\&(Zuںf3ˋÇ >600PZY\bKu-6gPګw I0"ȋR{v IUb[笤Ep4Sc(8"tİ>CxilhI>F-YJd";*A<{`x[ګՊ81"a٨k`%d;$Bya@ "nSJLO.~r(vb)7v'&(9*oxY9 rK-}ˢx@kooyxP$-8`(Ohb-CV+ CfqGSX(Shky.- mO.~IB,R -vnwK 42|_ʂT Qiij~ڛ Sӗq(+)$W$Ϲˆ[HV.]O #]`xͣH@HftdsY;,ELHlxyNQQ#(H@VI`AH(8,ygBU Rx6Xdbws'{"yF;F+>-^kmlߩGh B$%ٽ)>5)oHh6***ū*e9r[eAY'$P0 TF>$$$`ąyoj4ԐI?_T"y٠ܶUK{Tx_ҊY)' }{gѪe|ѷԢl&j|~t׷ʈECV.vC)J$m{ Jm!MZm W(!Y]P P# c60=K9S/ˌ7efjeY\NJ|_,kmllhVU Yʶa$S(dBL~$eJ`3ײZC%s=;vlDD1m1zvOZBzE EEEEYyT%}-G^qVUubE^qˠ<P"E!#+4=p H u,JZZV|񭸒H,uV+^l]}Ӈ 8\ A).:n]hLJT5&SEx;wl籝}-/΢n,}.Wn4Ҟ!!!A2!% He?,[$ξlV,RY%:VkZ[Z2|U?W:L*+DvxnV"7iY?thFIUιDv\eV2ڗcY:.L')",pxG+8D-OS9VCqE|Fc\ɿÀ ,k66HԢp(,4]K+*>ܺzD4!"Cٸظ\N&r~9\x4+na!Ybt'-ʢD6-28SbE @/fr[)nHp(#Gq\hst6'ﬗSU. vB1f؅ !jHE(!ǚUU!ȹs;wGDKN7hNcw%gUf8M-*URhQ(/^-!*ƭ?|OqziŢؒho^ř| =1K!"@@֮]H E[@qU*6ZsYSU"9w"+ pD^И.(+o"EJpE:D3s#m ÇIPHFU F+/-[%&'GbnijlH3vÇ dڅ .ܷw)*O.\F$h!G׬!8yʝ+hfe2ϲ>۶)DO:ujt$FBjILp ԊD+o}v\\&24k[%),Dd^ҶX[Qbqvvp5kH5UAFIɹy48" 7?pVR۬m1MhcT#FB3.jA^{x2_Wᙇ>@.ܠO7,&ȲWz.V씾Wx׮]Dlɵkx֋8T9**AX:oFttu D$=#=}̝m& z׋Q"|}gxG2ʆ3&ǬXlي1'|dC@"ywE{qzk=%" IDAT  zEb!~_&^Cf9&]LaJ

    mGd7)SfOٰ=c;}ER1Zā.NCn?KSH%D .ćQO?(udF.񵐵XyKl!DRHMM:~C,͒ND521qժUq5飏<ޞ{キa61{b1K! ej2L7/fd!6|I]. 唤?)~C21e-Q89 QH܅1Q䭷0^@1kxiGuu3=7i69c{H c K#R\^)>m"C|7,+IaϞ,wX,ӐE]XB$r"<$"> S_}5uzj*[%o x'N.!LV%ܢB&4is=BfϞa9,ގAZxmS8JAq H#PFPF[ѿ> a%@$?;\r[_@D䐕%$rIR'!% ꫚Lxb:GxH oo / }v_?'L@Ʊj+zlݺnLc$F8$"Yx1] Ux|c:ퟀ+!iI?7Iyu'cKDV9"C@,ĈCQo (d! &M|w\*[nu̙&M${!"3{b$ 7F} )_p20dJݏ?\2s#1c=|(_}*M;kYT"K]H"2B̏3+&7c_DWOGGEBx`"|87Y;l}gwfP}sRĚMhL6mѣÆL-^J1`".10GY1s_tMW] [+%X6bIX /ȋx $}`X!H sWUV[gl9cscXQ)ixxQS*1y1oY tCR-{z/J<..9bAnC}f$d.HrsW*c- ! Ay_|!I(_@^G8羛y睭[g:s֙f"x- DAcǴ0D?|)oQCC"& '??m2\^"zkQ{kL2BV/3b!$+.1 d1o/H$AP5+`шk䃹s}wW"2cH &Q<ޖ#2FO ix# ]>~Qq@ rH_Y!k'P| uĹX H̐ܤ#(cZ؀a=&C4Х{|`_qE,C Y, ~7/)=4j?|XFYH&677_!җ҈Gd{y D}Dd1CX^<" 6mHK'q@DKB">LXL EdADݷV^ZJ# B0cMVD>_se@fAH k@cH>BVXty)?Or{i IG*D!<> xMT!@f =ER@@g}28pNj?r',IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_300x100_fill_nearestneighbor_topleft_3.png000066400000000000000000000237421420147000300374020ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDR,d PLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖$IDATx̜ PWAeTX(8'D4j4'Pb Gpd  AcDAŀeh$z&1nn뽮Wk;AUq3_=1zcv۹sy[:oŋ/XĎ;֯_~+,XbٲW_}u׬YjժUϟ+,_|۶۶nݸuưaaW^ks^3kάYf[eݖ-[6mڴy͛Wl^bŊٳg0rl3رc `#RX*>9"-[ `QV cm֭[7n: X6gΜYfZn" ٳg = PXNDJBZBWW'Z EX- DQQV#Grz`=IXLX;֯_~%Z&eTXj Pa%taX9,!y4ea\Rue fƍ$ y,kg; jBvdz;VXTXsPYhn KJgѕJkwKQ+TYZXƥPv,LMeNX,މ4ޢ^Q֫c aQ,dc,j'Pޭn(eN;,ςFk\Fjԉ'NHyaJЖbZA9u%Zei% bP,u X@5e΄՝zOKH)A>HF[(R7yܰ")-)U.V]YDW eƮ]1X'N,e4*K =fcKXcK+uO!j,qnF{\pAfHk#F*ac?L @k3v y\DVd%HGw)"92xgGA0L@!LBHqS{e(7s_OF]Tj@PfR5qb'ݓ;;.XNGPL\\ iMAZr¥,YWOk\^j*  N·ɋ^ve@f L.vR,znĈt=%,wtX NlNs9*4-VUͻ:o{"EG hfG:hdΜ9F-_۶ۺOY%hjmXP[JHK[]VVԷX*'{xpX^^^^ӦyyywEXW^a]Gu*"<><>UԎQ+W\-JOO_,3π:չ^9<ڶm+:o *e}~O>v΄5.]XX<<ӊɺDqX[ZWb,z޽S#);GV T9֪U;y}mݺq߁a PXF#EF98:;OGphـ5*+i3ut4k: =}}ӧ: #&&&f<Ix̚5:AWΝ;ڷo}展 %G!> -I&NN0$aMx]Xi<&Oft(ʋrc!`&q aaV@ 0**"qZ9\9 `p[H?Ђp 8.a$76|t|7JkF)Zdao2ӽH bW]Y 9%%%H*+̙[g:tBTϝ?|BBBZyay4- 0$`,;BɎeԑ1M.NN ӽ-@b7!AXM!3?4wz׮zcwyLy^BIܹs_;}--䡰R4L4'y胸f';1k Iqٻ(ɓ=&)`N43xhp0NmmmM Q^Uxsյk]-f󁼼>7777Z ˗]v#Gyysdagr꽽.-ְ${2ZBZD?e,TTnnu߳gϞ=VАl$!eKX -s^9s: +$DHo8ٱDԅ5 EM7w@y7TJPV\mhʮ] ?9qs؞Np:pi)sgt+111fnnnX}G;nnOgOŞkHՀIASXv_>{rYݗŻh֭Viii ֣i"i1Xf\B? ,mAx ʪȯ(>-`5@64G?2~/u_̦Ԃ9 +,u5 B\`w!(((HҒР3b\rE%X.|F1Y (bHRCX 23.AggL&!ICEYDZ`>vvĵ`a[ 0݉xX}n}c+۷5a_`\\j?Z2k4(+hXTZrp,Ev'X;9 +`Yu ŋٲR^8\U\\ŠŠ GC |B5oI^>MLL7a!`AZ AuQufiiYin T\O>9zy’I'& D/N"do$Jd!`A4)˰4Z LhROu~`Z$Llr]t7co?_W\a&*+פPzXTT4P\2XǏkaiUZZQvev䡥 3838,?nZ %0dX^bDaXhe5"7;Efw)F [L&K 3;a='`Ρ vF6..Vu4!C7ZXUX7KKy~i+bX,ҌP>O75oXNB7w- , djÇ)DYEw$X CݑYv4+QW"-k&VAa}]&*S$ a1` +/驁err`yzzjahmcAQP*]ǫ$FbXwSMu>,>7%kGYi}3 &ɴTXJVUB/NnЭjY,۰pZi`s]jYa)AYIU]]@vqOTXO 뮟nݞsPmZ.DZzI9RR{' -@__Z K՗ KV,yk2kf|YqD{'i/?X 577Ixx tU]]m2]LQn.?X8S+x""imB-lp^/BZCYMMz0)+B"CTX tPdau# <@VBYR)ƃ\\\\LXљ+;9wZ/!xyHՈXTTWmeW{\L5F>e>FPPZV`,  ʃmb,pxO+Wۯ,s c4!)׮] RV !f>@?y|͛|}[#~Tda@@d $H?PQH eHug7.Gpl(1wk׮ݳgT v t444T_?0D)rKJ49<]6N&.`}2;2ɔdVFb@Rm 7W}B}BC}|Dvnʂjl!MpBTDW !q^X/TҿWOooOO`:\w]jkwtP\ UؘҔoЉ{1[Z[VW6 TXE! P΋&ӕv(̡3aC*+^CW,ƾ^==: kWM ª)X>77~4&yC)JhijYdgL1͘惰Br4ΕCT8PpX*&1+HŁI亍D_/Zծ]VMyM9;ݐ[SSRt2H„ ˜b6 bKfA&::ͲÛn=xS9WSCaCF%%`YzCZZ,sKl2LŖ*D[[a[aO]!%  zɟ|QRBgGRDPM* dGHkޮ)*arsK(uX- +d2L'# @UXXhWX[hgllgL##JAVhY$ IfqIwgjcz vrզ].'+{ZQ~^ZyuگU>*;SV:^!a={j/DW- (+38)+^;nܔq%Y1bpeĈL6uP99:w3/ϷeO=KH˛g",z*FHBZ60ˊفVF)PZ'O,+;^!Y@\ԮVĎH²"WLPrɛы/ȗO2]HLXҥ'))NT7AWW{IbJ¢ & NUXbW0VΚ++$ǚ"_G'b6.)w)0%%" ),ZքCEh4EFZv)*̙2/HG`+j.=q MUO?~՗9t JǦu&K{{{{e|1LHHhIhibn`Ro񁥽=HqP |ʇF}D`k'{0Z}ٝ'N:qp`sdURR"jwٞTVVMVÄnXf9ۜmFTwb\$#n|+b/cR". ֘.TZT[dއ;\WQQnGǧׯ!pԉޯx4 #'ckk̙ )&$tbnivRvvҍ_~x}Bqf|$ˋ}GG }$ZiW_}_ϤuWLV`6qZ/N ~"Ɔ \>J9rd' n=͸KILq}P~đQDzTҏ5/MJbF ⫻d.Zl;TWWWQ[@n \8a„7^'~sS̡KSPX&K$jf mm5FBZfs n$UfQV|B%t۪YQɋǎ8".#ӒaIȞM UWQhV<ěG8OFvtU#@j5p0#` < Wv;T:;v㈘TFZ*,J3hfzFp_?aC(j›ouklhhIB%T lwwqT7޹bfHtP1iل}ZHʫU1+ڰaC5D6zܰ?rf^|%~..cpBgWf#z҂d4+( Kr1*в/yh֨QN] :?"fjj„ o{ɪ@EAo[# @ w7~uTG-+)8,:b6׿6luWxC fd/M`gϡ *?/TQͿ9a!o~K9i^"ɇ^|%b].tnܸudEzD&$2̊!dԸ^;￿4"*$3Wa}4G ,+[G}՘}eZ #@qV .o0Ra0 0aŸɵ#AC(qɹd%⇹)A8;{P\@K zߏwfh(ƌ??|a͜mrhfCj…&~57uojlc̙3~حP\ .ۅ 7D+;$q'}t+j1@Е0u0ΕHK5:~6IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_300x200_fill_gaussian_smart1_3.png000066400000000000000000000502621420147000300355650ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDR,e,gPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖MmIDATx{X43[& 2DaKpᦣܭ4)KLSG `"n,Aq(B$8Gܠ2 | peymgm}s}ymny^z_@x3?| ϟ?D#1Ǝ;vܹsN2ZIc d֜s̚|(w-ք5qX.ֿ$VI) ?*< Dz, ^  a \X5\XDaM6l?Z3SXVLXcM),s)+Y89Uh, ߵw*,e)k,$bLY\X] a=wgra)BOܱ3ϒJX[)%Bò%.FkTn¢"R=c}`] Y8ޡxY\zI Gb!k]>NU2a=OddE4ѱ :U|VH3XR]AY< Lg0Cӟ+XщraYw,+C ]c,hƲsXEX=?ipO?B+upZ'O 5֌ӟez3 akMX Y,b?Gi~CCaxK{~,eb,ɲKњmk3pZgB#BXXw]7( 03^X,K!HBdS詖C|XbԲ dLtuFa)f:]}3"b GW_ſ0^zAD}Ьz2ӡwShy.wy5GX˂|ಆ@g }*'OYtjÅTX1mسz7|Jteuڲ tK:cSg:jS`Y &1zohm[~[bֻb3ƶ.lᩰo,dN{-޶Afbb^>Z0&®aYCE!/5\ yʉz[XWUt/H>AV$`J,%67.iɾ#Qoӗ O whdZ7>KX2X/‹)ڒJRdIџ-^ջ-t>u#G`u TosR{Naћ겨# U/P'-'ӺNe9ә%RY!)I46z߾qL]^Z*G˘єktJJ{FRj]+)L`YNX_Ѫ6ti"߲ zfv޽{{K5 RleoN? rR췕X])K}cҨ4Z F1V4RѢB2 ի7fѫQ??%Jnʻ)̱)WIhm+'ݭtt,KV{xWh |yy\RQ9P|r^}>koQiꏣ ~ڵ\nFW-5L)Y3uÔ)CmRBzѨѶUoPʕ[ڊ4kRNZGNy4&af>[&nZ8qĕW_9$֎]Ko)t|9Btt1 %U-T^[GE#JfSeiQ8y2%4@W k jge/[7NY ?Y];6rl|/ָÎ?pVi AX+ڑkդI |iV=:BZ+fX!w6eɪw6*{tBŧ0R1. N8JYHTZ'NHgxٟ-[l˖-xΟpʅ+'\rڵc##'EOϟMpr+] wwJ8o_N yEu߱w߾NO;zzzHi68Aia;}ھk]۽{ݳeֲχ… +WR#׮]6r-y(,B 3V7rVOEY-.da.(^Ilً~0[+vSLYN\N"k۷rZ ( W",*,AXOϛL1hQ k#w,,LX.KKe:Dz'D(qbQ">QVTW )dx.J$w4洞+Vame jnXi+^ɻU~eJKƥwwo߾})tMN`"ܝܝdṒ8TV^REP-^pB#G+75///o2Gu;vb3kƍld. 4{Bc?{FMw Ex&VmBbjl4,qpwv)+ܹΝwn_wFER.4qZӴi R W.\?zx{[Ehl3n&yy$mzh74gZ֔`."5घ9b;V7{s (. 67· z}{xxK wg;K*JUFա% {Qo4jF;55-5b*ia…++89v H@1XH쨹V_"s8}ubښY  qA0\^NN -VwEJ1&&%:C6vspssncGrh誒UHߎFmJKKMKk2jTSi oO!֨gZ~żTXeGM[vQXDXKVBXnٙ@h.>IjtWW'QY /^顡%0V 17--7IMieOUTYeyejXgkoCT֕]Iɱ Ж(:iFMPz89ɔ N4dPKNKmv$UtttS儃ҼҼ2aq8TVơIJ*Ujrt`(- V[SӤJV^EeB Ն*J EXXMLTWmњKJKKJ kZi?VS‡l= ykk ҲZ - 6FW=<ܻ Ɗ֊;Kp;)+94 44}UzXj4XSX.&SKKˬ؀i0 m(_ra4JMSaPuIg0BMnnf\\\N4vZ Py8{u7jd?60z$& ,fZnvvviѱmfR #0 `PwჇ.U+DB@Ehޮ'5z,aY m^W@@@@zrzIzcrQY32bQWM2R&}ViYFiMVCn,S֫V+n\MSQTפ2%0 +-Nmmm{9@нr. 9 9`Gær9vMlc^6[WZ:X^CV[]:x%MDrV\\={ST죬IYM:Q 킝2X3232amb^+(-HVci:vv֊kbM.99 "*VR CwmSc?7FJm'wwwwg;]6 :`0$eorD.H3ַ @ ,}Nj;db74tR%*B RW%|}*K&5 ,evA*4+;3)+YuI(V۳&)m31b374 d:֟8PWPXXfU4Ąo ߴi覥V\Y.cʣ p;˪'z{lTX ʐ%A` 2T2jXΜ(M5~1MrЁ{89ɕe>Kw6ԉef3Ltϐ,]*!![oT`l'ܐ& Hmd.$$^HL^ Nz+֖-[6mڴi0%%%,w.gYE"&]?,˄"Q``,8oN% &vpj֜Xz`{b:[?*F?EZ(-իѫF2ɲ\6/YDX:/SH \YVs Pm@ ~V޺ĕWzm;aY @ M%}]ر2d1[TO5JKxKBwggo!]˗OAR `;8DN,5t~S@iO<+v+GeF:9PYV0P;cco߲iSm^E,/8urQh!7x57Ofnnure1ae,3am=*l=k;LHC6tG-"TVBzU_Rey;ۛ2STh]BSstwwtt!N J\hGV:7vNmhM吅Z ĀZ/d!!q4fF@+bc l%Ԕ e2eU G140v 2 , = NYUBBwE`ՆvLG)LPV8X-醝;cVwiI :(IK,: ]wԩ:qnX1(tbz}Ci,رRevmU+7I- SF6+TkM&:MZKXV7%*48Yx[? KYTX٢kZ"ztRvm7g.>^T")j')Je /*wwgG*^X=|ixmg rUn&VBIxkVS]˄6h >]w J74uЯ`R/ RWW''w;{GRKuntձIZWв#+lJe54ܛ-ZE=++垟e, wtQUSR)I"}?C%-M}# k+ˡjY ,c?~44$ BT*?WVV{QTv9=iD9iGB喅*5nvg";ٸYo`DeQj@ζ I?WVֆa]`v7DQaT`a;kj(a0TIGY9؋ /JQga^V}3YYNlk!HSX  '#%t0B tMʽ a9tu`i3`%!(ٹPct!L`,<^\\k0 l!%@qad8+Ǻ:[P (9;9W`n lCvvvIӊKRn8em`QxWUZE\X9-3L}!mHpwes 2[AYZ cB Aڴ X]XvvpY8t:M{ ^C!L+(C5cTYgnPM ,cwURWF!ao%&…cg;{{G(׷Z,hM&Yx*d΁lXswrwww*->և:;8yف؎{^!`5dg-Yv`Ⱦ@=H XYaj5Z|qK"w åV׮r^9?Uk5*г0݂._N05WcFckE}SIh#! y]&~(Zm988.wrXXT Cڽ >Tߔ 9HhʓL7V4ڷeAZ Wt΄umfsc.H3iMG.Ezz}w9`LիDH}3\,,pe'dnjnjnn2N="rtwwt[dnjln4u!+')KJJBC3 0$NKOKN3$ ii\Vyyiog~ :{b"=(.?v1 IEG/3f(*YtLPD$GEA:< :us 3꠺ 7"rsWϾ+Yݶ$#!CCWhF! 9ِlH7r "36`?QUVb¸ 64m!+8FQqQ#EEEEЬNIW\ȋ` 8-Wv$V`y퉳SVx6CSSShIhWh@(ŕ @[*Õ61 BB$ZEG* fJ/G%r+q,'w,IZ+˗O2e؋r;OqC{\3HHtnXVnnn9^ Vcvu…NhY X\X\\|^(`xd姲^lg3CGRZ4(+]E1TVU:QQ VkU:iXI,`E`aѴMKP ,d XG@!"@`DrWUHF@[ [oDَ[A!b\\QZrPVJ_P-JKMMK%r3EPea ZOZNJm# ,,x*:R3 i!+,?x` a܂ܤe~R"*< Dyh. #lˉ'JN;ĢՋ-JMKMKMMT 򌌌Ldl۶g^(,V Uq``#XQ "&&&8&&>Ŵ$ km.--ȭ΍A;gr4܉] ĉ}]jHZII|߶X`mO*LZGZQbՖ-"#""/5*WjȎҢI;pAw: wtar~Ā4 PX*7)bUmVPDEX#qQqU@eS| 5k99眕HK G(pV-(P$'VOڷnًfi&pkrtF4嵍 V33d;qqQqq1qU"""`$NH؉:9zЃb z% sӓ}2Z'sV۽zݻbDdXmWXXXVX~_ڎqݩ"X!M6]Y`).3gEF @Irs ),;h):;'V^{;, -^8i1bO?ZߦvFvtj/_E~+5*bԨQk֬[NeEL'!q4 5\n_VJ i;o>E`!9Z^IHgO Y>k}{^hmeJI_bq+·2""Fn: ]ɝJ\XJZtci*E{puW)SL9y* Uxeݶv[6jǎSmzl%z}G(YSq+6j&Qk֭X6F|n,%,SP8JPVv# = ͎BrJHCDm[dX$8̎Ns4zmܸ1.pM0֭((w%!lb={.+.,wɱ8)0b@ XBz7zJ~:r[d؎c .\@VCI gə8Viq\|A?]Π{{pLpp0C {~ ;\&q,YOž'[}[Ϟ} [EhA ncӜ;JC;1/'8qCBqi]`H|799QZ-X*&GY;Й̬Em1\\'>>jO֭~fFtF,F <40&Q )XXj n9zŧzoƍ7n޼udp8.qgA+} ^yu` *)_G^QULΨ2T/`.RXjL]U2~?"V9:"-2l9WrJޛPuyĈ4F4ѻܶ'8=3dI"*> r⎐}~G-Yt'HTT X(U#VWܸ$e)A-NCp2psQzzzr2f Wʷg6So{2c;V |E 1>:Bos<5+Es ,U7ay՚왶ب %爮 { XYV*`Suo2%Td3V!GHPx+>NŅ|AɊ_~i F3kɔk2t.`.ɯdU(J6;jVB",_jOuʭ_&=YhV {P\bU1n:RUU*20v 2LJ\0cwK: BkHH6$GkOeR\Pvlt/x6`On]U3M$"⊏9R\tFEE< EQ DUUn\+f*h*sgyDϞ#F4{!.;k}"AVeէ5zɺGݶEEQQ$I {:~ݫ!" ׯ.2~_lNwX΅ $dUóϐ2KW~"Z äH5(zG!wkj>~,Xªy0>tt,2U"{2sU .zxx`X T#|s9Wig HuubL!}H>ErR~aj.g:̝f`^Dpn-7o(s2uUM T' d6.TAxe}P*1(8xUZu d(; eoW!}҇s/Tu(ܔQi9.X>ꫯ=OInVܬ31WkjngEerBqVBoLЧYyo%7^,_ZFtҕ gd)89Hg<{G2$ |&BZc xdߧu'+΢E$X{4l`c Xmգ uuOgu5;;%$ @aX>>xVh4DX+9s묐yc z♊'/3Z}tSIbO{K`UU{I h4 !c l4^M"upN^؉%x Cŕ%!9S`ć'֐v,H13d!=Tar>B|0 9ZY[]KJwķLYɲhPXD5@}сEƽ{r`U(ԏw w'gPEYe5*zq_(kPK,Et#*u>pC_X0|<=a5m=`=lcʒbf[煇ɠ^VlN `mʕi{s*˗(k+_AYcz00zUKC TY!B=X]Yjb[:YU#p`::=:ܓ2'չs"&XU52b *,>1YQ]r*(gPW @m^װOv>z4Pk{ƲY[ xUyP{;a͖yRX*Vg2BX8RgKX$ EXTY=\ mxQV:̏:>zuΪF;4}!:ȘHPyzHPPyTΏW}ɯW)ʺ$(ܳ Xo@@uI>VzU-V;::+,s;5BaSH݋ HNNK`j1j`G~XOY,) RYwѱ4xH@kȖߥK`QUyϵ/,Æ0NYGPr_2i$eLO`Y;lK[P{-Ҷ2ٽ`WusI jMѐ4 B~EqKX݈W{[R[*KpPMLޛ7q>=f'/w q߼zy/[L Ή?O߭;~j~du#ym;qI{F>,zpZrZ^ĝ[~_-3)1 g M=^a.ɉEN@+K).*oC!-7kdG*I٘%9J[Lʢ"ܚLE^t7)&!+ga9<޻cGi>7(x;!Q4`?N.ol\Gun޸A{1t64GdVsˊKa%!-(GgwȦ[%AḘQZ J wpYEu/N &gsx3d䨾 ,i?J]۸dw]ݒVZ@P 7#;###w]ںU|֫ife J/(--m%$rQ@%e`| =.W'ksrrΓ޿ƚuBV_HF0ëeYeYfUVk r)[ߝŏʊ/P//-XJ",1Q YIih~}x?<?HkX?0^Ww٢o S*'~׭êlyGnV7nѴ2 AXr&ʈ sq+Cu,r7낢xb^*-^ee!exs{0#aK:1?{7_{j'-_{fu(K'jIYn]Dʕ_=n*^yyey*ޠ;@n!GVeHzX㷆\s1o{桺}!߬!zJX )눷0~m~뾛E堰,iw@+[WrGE"2,^ la[6  VyG-;ZVXVXXH) ,_\vq$p-[ˀ]kFk:thޡyvNlJ"YuHꭷ񪯯V| %kЀ`0)-kѢriJWd. gEa²ALoeYXًAy xYdyyBZrMRYSM͛790&BV!RHぬV;[/RaIm6LJkjJ`]5TUyUu.Hz| f!VTe^ƮEFGGoF\9)2??a c*,DZfč+6+[զK uB\ݼy3?@PѣuSt4*!+VM,+\:KRbڌz^{=$X2GXprM rX(,ZVt,oz^."'O? i v`c /g/H7r *cO*uK-L_K^[%Fd%t4[T* Of*[pk~nn)b: ,:.{"2ߊOYE%@YsBLh݇¯ܼdɒ%ykK0|jR .f+*KzⓎ*+ 4]R֢݋v̶xʅ nǮ&ϝ;w*К7pظq?p9J|8}JCETdKHז&P"ޔ`]UYvZ/(,-V^: ]+Rn#^ȽHI\AY/_8gN⨐֔)S>xR*~}DZKxX"#f M*7WUFsUjA6 uq%LwKY8[|i-(%!e?Q͙ϐ)@khСt?CD 5 o a0[vFhWvFoyC\U:HK,,ON1m4r1paEa͟;7̲QFk xM_-UpL LCz 7_@ P(+ xH;دcy' /@V XÇ<š4px΁X>k֬3tdPBkJ&,P֒3'@,czS`DIO Tk~njVMYlHʪ @Z< {'>_l>XNrᐆTYc4;WR(, k @5}<Ѳ̙L0aȄ!/ 1!VH NF6ѰSXt:,%e$,1gN@^C& xAUVn\Jo UwӉ(+!ΠVX}e0 )-AY6%!sYf(+JP!VAAHO5*dG jYd"֯dauxQ>q\b%`r]u-2{'5}:RP8S qYb"2$CNIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_300x200_fit_linear_3.png000066400000000000000000000422471420147000300335760ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDR,SEPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖AbIDATxԽT=so(E)`K :Ʈ@bDR 4J (QQQtOfH(HļkS~73ֺyXw>Q}٧C:bذaÆ 2dʔ)͛p̙3gN>}̘1cF9b{QF6mÇ>uI&M7n'|ɇ~G}ԧO޽{=z'N?~ &L믿*¢d(+EYYQXXS qև>Y%` iqV eBV9iz߈$X p3XC_.,ﵜLXև-X%5 k X fIHY} 9S'M5X}DaMr2aJܱޗ9G\X2e$to_XraMiYXOzWdY$a X<rV#d$Ƅ%[ZfW\X-X3Fk5T˰n-ڻ X/HPeKHBFXPh ,j P ,T ^0b+9VK5:&:@ X+1bdN_֧u0-/ֻxBi,42+֓Kns,i()s,x6JXS[BO-/@XLW1P_XSIQ>ȇB%˰>36ԛ-f ,KX3X/a_%*kPYhXc f ƅel =BLÿ2,CIX03a#ˠ7Ӓ ~V)XCX8+43wMWaiߖw KC?{4+000pB B",W 俹ow}?VC%w'ftZ_XtF74_qh*V`I) [WKdi5>}g V[M՜"BPM&n܈Gqo_-p4igN[[Ke;;3tН!lpfF) ЂXBݼi`4a /_mZ$jgդƇj(CDP4tgJJ.4Ҿ nPVGx|R&jөMX-k eRU*4?ꦝzСRVkZ-ƀBF_a'9`ȆF, ^FDVN-2YYhzڡ;|T4,RV*oTK6$.8l!8OnI԰l0pVs<J߸*0mNmP[m/+bmTԚʾ˪)-Q֭Kn..PVհ#kyCґKG\:UW^ĨQӲd~ç:iѤIX bJVo4hձm[NKK`Qa)@VCmZJrtb-Bn.\1a?:~"hܒ%,dAA -*iJ<ӝ7[YuZA&XlmUK4:3MnݺrZƊ([[[( 2;vvv$Z|/Ib/ Q !89#Zd {ogFx0OOOCfV cGK(Z%m , 5I˴+LjJG'n](M*T:vt(ݮ] nݙ篊fϞ<{r\x@~j{ kYY׎d9q( ~A&9Vg?OOOWOggs3338ŋ/^L $ZCZRtHԡmnM̱-- +ԭ[.4U*_eu X99I1v3@UUe!>Ξ4~6[n:{ZlUQ_&yZh4.j8`aC30_*96,FFY[rXFoHBxk'[;XCXX[8cgɑh bg5w6B)TaICrzYvիW8(4 I(d%[n: C]Oa\~=~_A@YaoZ&VrqqvjΕ_j@FVKx9Et]:8X[[XX@ RۅJYsXZYZŋts a.ڿHnvܹK\n {ɸ 6h%]|}=ؓ]]] :[6Q-1a- BuXDZN˱H%VxɩgvlJ*=2_Ӑ.eݺhHLCXG!K9z໷7lXF @X'5:^iKEu^׮aj:rtl5+=z+j_p݊ؠ Kx@{1RR֥DiZ zjJĬ\re>sz3V2e,^dϯ 43#jcrZRFSjTGCjMz899:PI BG;d^ϩ-m jeh`eCbJttttjODY.%\݊tae9=*"-\KD}XB߀֣]9"/STjS=pC6UWkGV,]EZw 1 ))ѩѩKЕe5Hѣ&K8cMc2U1+V|9sza!+:4_qEZgQTv.lnffE=^%ﯰ~2)Ȼ't1T=xQmвԘzw:,X-D%s҂R4$Fճ/׳QG/%$$<oO~OUx,|di,Txүm&y0hD1a9٭Iʺ3I򶳳nʞRe[Qݾ{w{(4VnbI )ѩ=y^b_ф e'ۃEEܼ2a!aa>,4_ U]r tsBKC!`uÎ{F=lm߽{w{S&Xxڷ k6+VRR ~aBBQӐ<;uDŅ3' Ӈm`֧OX6un5VWXN:urxOaP4aȈe4iSYS5|i1LO {]* u8j4{ p ZX[[ޫu`)[m =li3Y 4=Z/???MYY}}51WO u *W hU IrjMI3~JšKr (zEV)uc5yVYZmX[WXhgLKg{[XC v#;{w?cwLwHKo{Mޝjwkwk33d66FC*LRSQXi,Oܭ=ɓ&=}":pwOWtWWJ{QWbNz+\]my%e.cQeiƹap`De<,Q]ĭ Lދ/&k: ĂTDE"-5m}Zھ4eYw^߮]Bw =ES'OQWa>>>Q…0 E/X2X$X(-B+/Fލydg퉬0;s̙3gC%%''k%Z)zDFը֕4:7VձS aj4 q*X.3>lީif,093|Hk0U8==z8C,'C޽b$x *: iiۗ_F466UBn(aX;vɓʈP(+CmlmPrrx:D%iaYpZ$*DVtcQ ?w:s̙g +V${̤Ă䕒Ɣ5Ov.Xpj0T䎨(+uP!C%g//r4a/, A8qV+ge`$"yW\z*Zb6DLLLILIIIMNH޺uk-7R^Ba-X` cQQQ  9velLb]cbP27r\dkN{;9Y֥EjZ^*5; #111hKI^iihPX Z1"c͛7m c̝3B2#//g/r6sP%cDvѺh.-2V=JQuCTřy .\p_^ս+ET'OLa%&&KLYBZ[/_dGC!֢+"*&*js*< [@X7n4h3`^^De ,%R<1"V - m=栝Hp<`v.\@XW~ Vs&$,* Pov}* kѢETjf\ey[z# ffVfVHy6gEPI+{;VK9#$+[[[;/pK@w6 ) //lZ՟*k͚i\]j]ϲK #*BzpZ)S -@++@d+ɋʊ6߀k'Bch*'rH@Vܹs'{gOKQ-rR`oMkOrmX- mn7V+B+0pc`U`G5{$q2;7 ξ+: 3{nUZZѣ$dq)ars<* Xa9@E6wÊ"[ M'R{2"aIņ>S".Ya/PX+ަw* `0,$% #GVrTľ:-m*diiK"\V+=+܁jE= @ZROuVʒPudH8$5BKQʨP_ ^*2iI սW$ ¤D`_6$B]Iı Ҩ8/"3E R.~䰍+^ XK.N[[R#{W^17G3s֑rBـEֹGI‘0tA(I(ܼ惓h21#S adc%;-?"< |jȍ 0)$V`}gϞ=+`ֱ uPaA9\cBȬp\rp4 ;q".<#:thFfftIؤGYLWG9.NˤB՝}di`<*˗T ?$Y0e$Ĉ$ZmZ;w߽fX݌ko>Vl_:!8./R]PINt]]=FL=@ATb\\ZLZ-‚{hjKZm,g`U3f !uh5kb|{նsg [o qE:EVq :_J'|<3Q׈Y}ڤbWgԺlȅ옴FaA} nãAk/D'3q~ٲϵv R"~_>%d[AΝ;"O6F`?yɓ'B6*zaQQykt8!Ao ܂f5!f-[\IdqEp;@VetOdd)hV̭TXiQz]U3'3\(wF/^AM] /]u4Ngº݂\~sdf7v&ؙF'$8#?JtF+My]VFTeFVk4 SHSs ߞ7 &C)pd{zqA}yDVڵV  6H6_~, L())-ܙr/haGNwk8Y9q"ooPRU|oZZ/R(ōȪ߇r[;ȫW/Ii,+0M.o;f}!,pH+_(_/ªB]Bչ{Zֽ@tm{Bi}u2_F?$+W2/<=8dDZæ϶pXDY>|FGh5"HZr4tHDZgpZPozty e%5>knNkcϥBX3ЖWzW'_Xd74\JkV kՔ-R(Dp?0G%S *; jaZcLFOC0b9,ubEXiHahn ۖ|Md!*KKɯ"gb۷J?sڵ;0Ȯ/Mmaeee-N4ϞADB>U<: XYY.)I#ORTkdk k~EX1u5o2QΝ;7ַY_&uc Եf9v[d a!vQSÇgy!VܬIDۛX[ReAUcYX=KJCܳг?DX<Κu*GFw*&rXP2m %S'{/9;S ÿd$xĤ"+\{7BT, ?CVߚA&>5n[no,,),YFf<2eE4T)BH@IZxd-!W9L!Ji$|Na(ç0/aY2oo*kI A=ӐdUѐV`Y˕SNT0z؈e)e´,../_!`J_%?Y NCxt)}>VQ瞵-F,^:t?y6y~LyULMe B ѳ!:a4n U'I6\M2x:wCIX#,IY2V2"ʢ,w}Z˔+HmY{;dҜ8pqC̰=3xk~lk?ce=kޛZCe?ORZp)ݨuׯe9յ5׮mǷ؋B6 g N .F' R;%=FANjkQlOJSڂy%[KoYR.[bn}'7$cǺ)kjJ-_kkG¥_YIJOOGG2=A2ŕ߬`)gߘ٧~Fv)#pVVfFw+nn+}XE63u3+ȩ&g_>VFQO[OS,A`]:w OS6^towzzxC 9nsx\x/y0 ={߿ʇf's!#{T3WőUXEw)kw^,̊m/)k2`5\̓ RSݼE9i #\t)4!tW(V1xT'zhT\J2"6;ț +ub,?z?LjH*"b1e8* /}Ztpɒ%1^>+&zX=~5"˜^)f&iBent7m+],0 gPhgQyo+g iZAKb%fq@5*kZִ>V{/>lXZcDeъp\jA"(\DC= ++/W): KVkWQ_3XnXŲalvv-ZGx{"Fe}Msػ.Zr]uV{ΜޣG{L8qǯ8ïc.%6 Q_0mW:Naij ?nbQYAAa͖ ooZQӦ!+zǧh*iYQ>ᛈz7hVs=ۼ&%9>H冬,jY Ϸnd S`UE(ݛ y$ ktQ܀~ZWỳgޝMZ4_7ц>Z٧OiEٗ| n賒;{oԈ@beQzӍg|L5OsҴ! ^eEll,\31cFtҁժ{oԨQӦMV3aSN]4iҢqֆ7wg+š8aˆ#ۺE>eJEHgC`QS(tnݿ@$ TYֱVdCVDXƌ7roc$^k[dPS&=YqcX8sӧO3<=+E]PT5iѤqT~Y-jĈݥWN %*_z6Š;vb/0au!ƌ#ⴌ E8ކIXpwoΦsqTK/^O^яn%ޗL>߉=rV"ys'/;3p Z:rHzZaEEY}dDX$ '%}yv ~V+4d{;FcQJ`QVڠd@E,XsgPW%%)k*8+,DVIzЦ_~FgjK| tfu9QIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_3980c5868e0b6f20ec95424dfdcb1d67.png000066400000000000000000000575461420147000300346470ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖\!IDATxp[ו&c*Le򗥡! ^1!HyڎX)*:)nW t+[[1K-̒Ewۗ],녒Fɨ /ɨI ,8-w{5H*Q;CA~wιJv*e AW~Fiz+?Ϣ4^x 탟?)z_+䂮ʺ򢢼 )CC 郃C%?@l|S1&h  c<~/(*Ae]EePQZWuMQ늺Z].i  ~vNIzӇ8>?8|00 `8qQ ! 4MW5M#b`jպoZozɑx8~BN1$ϧXÙ×.,* n# N_jJ`hX~ # 3a<22Kb1s`.  DSEWuu]H 7pmkcgzF1Cc dRT2E `RiuEӀ `?7^f;{~k!"Lf<3Wr h+TCS5 f/I_o@4jpLB߿+pBd pIyAy(A b#Hu:rTcr1˽` !08鱑@I(A׊:" ݈ >e8`  1dd.u+w{5C^芊]!4ā2?p8AӜ!cLB0;(n)"ń ZT A~]a`4PDaCtzd,=62pA`%A +Tȕ<"5$bE~o .%},JuѨ r=l0X@ ,'/GxL` |]1 fHʯ c!y,y!a.7X({X1!qRN: /ñm9DجaWLQkDtcyIȱaQXրIH ,^9D z?3 BX BBTx"Izs [7m 4sN@vK8U ,N/Z } p˲'nN_)46ۋ󊎳&&.7(_J/bZl6&ofp$E˫q҄nAGdȫ3,KD9Yx,R٢aWFT6}oE9cp<() V뽎.5 #cl%$#$zNj`갔b{HAR_ VϗHD7Ac(_ JJaK8 #+B|^a $ RxsLki!0(O)CD>1ynp 9u)"E44QʏqdKH>jJD)xNnfSr4e5hV殩6H_p[Wg+SpX$oHڭXBB/ybe Ԑ`׉?TYdW_aH~붬҄ye !i!%X, HnMpཷu"hP(䙻 CX !̕r3ZK+ʊbBop7y^\`ݿRHY,L^w@`$pi+D<`: er[M4=Z*T[d~wB+ &(%X FP)&NKAą) ; /)EE"Ь"+nMyH( %f^V Л%+wWLoDW5# d:pnBLqa*a=o@3YRyS3Đab4C%) Rp,i /4!HmKVi@L`U$n*TH68D EZU)DE:d vvtɊp(RR*!Ɨ`)f/|&1FKK!!"s~f|^;*;<(D("bC4V#,Uu}2 G֠!&[XِFح %RlԠeC*hq$8ij )^y)QxF뫩C#d;f>L&9 ).F!?;Xd6vd讵"RiXMI=XO=`pƽ"\NrK∀MAxd?}>??o;Τf`bVx[ϟ):m 8Cl>,UJЁ UqaI AU@nX=V(BqMtHv j$$ Cdf91bTjh$8 J=0+Zf!8LBVCHCE0._*Cҋxm TjPC[ѹ ,`<$nF %QH"%x2[[%Yr\dHk$G V1ŽڒT7GmiYZT*K`pBL.̣9̡p³fY-GK t,W("r 5 xPu H=O0|B3Ռ!#vJ4c#m,TA(?el[bH<ADz5JQ3+!ĀW0M0`͝VKi%t-hØ^x2^fu^e0X:.:QQBav&t8=dͼ7BSh,$ZWd –TKkb GdDd["-&@2A ͎YdBC(ȳy|ϝi>ۥÊ:"~<9ԁAw( d+ 0<(F%х$-P%XkU2Yh,/ ˲# $3 aX2 v6 gc$*L~+báTLցl2MԹ?,n[&t")ze8@ Cr\vzkXH4Ejn;Ւ:jiA -^xEd9q2188vNYtm¢=,o|u$1㼧xd))  <}@uA;;$DI>oTKEã+V+D2q  ,Đ&d!+lG$5 {3*bVe^d2RzZ:۶) Ih|C`\طĐF%%uuKF+`$-& vKKk+CC8x_'DD?uN;BoQv-Aܠ3] E5C0!`tiDU! U6G'Y$lbHӖ!紒jG$afZSc%Xk+adQN e2LF"p~se1˵#l'-R0>A܀Bs]v3FBxRop$-REٵVc_iƣ2$px}_?7I#t>9!湷ңM<_`Ib}|(+/*N,}( ّ L{ Rs~ DzY"'b ߉YAӌ1xDh R,#Q':)z_w.>]1MB*G$YI`U,*YޒdV @pN'&OmMȐkyC,ָ FH6/὿ /OFſxD‘HC|hhR5wN>}M0Y湙 2/lɲ,kAv=X^Fm%j!lꪪhڧ$e &E̘uDUi(":S-e@۷o_h $Yo ,D56Dѭ0v%$"h4*JkO>-3gҧFN,(eYV;YG²糳'_}ut2g٤Đb 8N=y1<%E*bJ ۃ`<O"*2ao!J$&г$ ԡΜސݙSSN:55U bY0&U܉kyA<Qr v sIJNF?ۓI&EH9a Bvܹ{A4[+NŐ+V;m!_Ƣh- ->3ߝJO=5ujYÞ-kڲ,)" @>f>#}guN;@Yy04f +I ,Yˀ(A [sN]wbH&kE02&h"%,t.!{O`3;3.Z Y>ْ`cg]l4D`]=5-Ù,Y"dEw޹cA|E_h)_"HhVbDv%v!8 vr̍`))0XSS"CV0 ?V2 o+ }g<ͣA5y8e~WDrb")r2[aHUJb{ 1*v %hLfI\|vc׮hb׮] u̍Qgf)7!¯,,qvV͜/7088],;Z?y4ML'53 ZP K;w;C|{W&s<|2 x8 O%DJFkZZB4{#ȮX"k.C1scfԼ, Y&}WK;vv- %ؐ<LMMYH޲\bk;{߽C|=kg=lR:+,Ěf6kc@TK Y,)6* ٽ{wWXʀ%9E&}{WI" ~>Om.BZEejpcY+uh bqb$5Hwv_n耮k*F[,]C"%cMT^0q8%mN$%lt5CZھ} CȀObe/#Q,b1>}5`%c,#Pg+k_ylnt- %lzD@nn 8D #MDavmپ}{Lk(X L¤]Z*"Wl:s㜔C<7V dv#-Bcײ^0MCKןڑD 1,=em\0Bu‘,>&܉ }漐hdȟ/StW=۩izh.BdY4޳H@~Q`:@:DAv]^,N8ub~:T o.ͽQN#*<.TCz,u!5f :E@&Y+?+տD}ҤP2(D]s C0Y kzz:jRIܓM^x17\\:{QGRZ!y-kjiI! c ڌ# &XμLd/+L {W˗ag` ybM[S?zOM&2[4of>7;Gn./ҶA:}\,I>s^ݪɲqimq (eT" X<*H!~Ou ο(\|Z~Ww&kdzzڲ^' ! rđyeb½0qG.ܻGȆ'YW/5*T 8oI`h-PRdAK2J \ BO"!^':SB fe]d$'iC}#^rۯ8Pěܻ}sO_[>K%K "μU+m|Hةq m%F-G4;.*6v <"K4}*Aډhv\9<k91=m R1HU۬YPC֛}({zne! |d8ϑ6 xH@" !qNHwԾTY,ՠ##bK$ Jx ٨#!ta5 0pJF&kο/\;},U@]w˖=ušeKȸ/1a;;WW+YG/ґ=ul{@N" h`K6_׹=vmY-lIR@d"!woo߽s'n5]]:5;&h"#P0G,/xdԙL8J\.>}p63scfj_ubl u}!80#2"4&\}GC|fn.Զ$0i:z?ߌ!b7>;u[8C0"۷ܽ{NX A:x,qb2O0s`# 4a Tbk#ΤpΤ\q\svx`S'Ʀ2VL[4q 'g] kvdvvu'7'rTe粹w?3m٧2dqQD6*rhpZK`3D};dWw{۷oxt.DC 0I`Y91Lw)R8fL<qN8DNdҙH98fN;ϝ>7Ccjlj؉؉eefi'$ x#= 2`8~ܑܑlkٹܶmee'GH,TL[IO ︡p! <ڷc`OAMB􈋀`P[Z5o a;s;εw(͠+95zjjtl ړ!d2'!W2I;={6}uɾfs,B#-h2<|X"HB9Hњj8`BCb"$w"4c8F%!~/Rx ;Iv&+=9gڹgf&=3ѩ ֳo5,1\RṊŶkE^Ϟf_ffYDb8vj0oRWC j60;ŊbE9p!pxD<4j o#nǝx܎vldYV333i؀0:zjtl$5Xu/\i|$ógy'=uOn/2\~u_ۗ;r ZkzNߦc<0 xb1UM~,`PKTTR`W Gg"0$BY'>2jm2Qi L9s9VLܙhzvBlij= {zP) lzgCD𠀈Ql9 Yb/ mݡ8"Y?'-y-+D,Y='2ko*/z/*{C!}o(X|kESĽ P+MTHd~r} #O@QD|9nryyy!L[׉2D Q5h0WRa.3qS^[}k0z ĒEeH. X:sDDC& !(2\ـ/˫D;eQeE|!Ε$n&p{I%lV k?K"c HuDD.V]" gI0&=|7n\""//c}EY]l]! "r9ɔlΏƓ6ۙ Q#S#IШDx-.6n 2YbѰ [<^o ,uox(w #o ƃ Gf yV 1_XHUvaQzʖ3,)]3U~8J/7w`ہ;68ˈWw YVpCv`H9ߌ!|3eU8#& S), [-1 ;Εs} ywHhzdzWb VE=eukɬkIqIS)3{g^rN'hɻ$rt&slId"ͼ_!~l!/k,?VY*+FI'$Svx\}I\8iX8hrT8)Pey7< ;g]=r!'¡0LOgPH*+ &w|ǜN" wӶ޾}ny# f% JSP[G؉`8 X<1*nAoB9^$y9RC p;rlwu]uKy)w8$GG|pj4Ȏs߈u@h]VpwVݾ';\3D2O9",2DPMjvN$r i@:sjT4P8UBp?Yp;p֣[z-d/ҏox9^pz84@{L4`Bf]] d$M,VCݷ[pA`t["Z)%ߪE :杧Rt „#QP u]3SijރLn딊laHrd|^uݓ..f.C $=OK&MUVKvO7r$[ʽR,5FXv$6" SǑ GBD I7N؜|3͌P|OP!ԷFA,ȸ}!jdI2םE*B{ZT4$pu8mJfgw“6nj"3?eJXXjȾTnۑ^qUyOd~?9BGo)$$BrF|-{|#C.)[]#at3 G4!G$#Abޛ{!3p8 @$B&`&_~VnlV# kx?^7 0a[wmr> O-# ~q~=ZAK< W"v 5}!yuU>oK]ɗ!$$i@ dyr39x.0gHN$x,Bl8γ4}{D 1Kh\d O51J2 V o.h=F4kHXի3\fDł\.Q@zd?Ҡbl[aQvEY2&!^ydA 1 D^ϋvv:«8yB7}B!=t aYVIMaQNUEDEp^/LQ2y:fu(?_d)刍)9ӪKa"H,]~f(4}Ԥ8R *.'w։G8E*M0Zx+ޖ29dB!Ľ-ȇPs*>2۬3 < H/4E(ySMܥ[ G{Yh ]5J9X~56U1e EzhڍzNa u L ]F<.$Mj6kYxËׯcb )Jd3{Z" W!Ua^! "7S:i4lj! >!d, FGar~dLLr`- BvN"U̎?&ɜ_\~1y&TZdOC9GOK;uy& $JFV41u@}>Uǀ%>'t,UlC&+9by7*6 YHٌ!. ic!Z4筋_(fIPjďnrzwì5 X+l!m\C\ Q/ [(-F"򗒆@%<Ţc/ %E)Ez$ZDD xwT*aɼas*ز&}2H_ u\F•F@BhJKkl:DTE91 ujIz۶"Hx!I" al 5Fo!SIqb(_f$v<)sU~( eLAʤkBm G`YJ_R"Y$ē@7"4op4A W`H"B+^1$]dd<;SY!kjhuYMV-.ia%;, !x QhHHieruAu! *z]9eeLr:rH`]5dGPJZ)j7TUI!x';~#vST)G hAӣ+W.7juj~jCX "i\ɚ𻽘!3Z,ϗ|\6e& މ?U!!!C0}Vv[>ۄԠ_9oΗ/R\R!*@@xW -!/Ï5d Q#u!ɤskáy7a[Θ`&~סEXKۊ6eٜ!+䷥5B9[r|&uY*MH1_g'[?C[p _{kUB|yP[vWJ={`>9O^ϻXk[ G P6e?noL^@0<)Nz&x`H3YK6T4!1cEԐdg̀)ˏ߹wC^mܔUqYnu<XH&uc#Z(`xYH=!~ \ѐ&n_!|%rfayy_ܐ\9PEr$XO%t{edfQ4i 4WURUg9T,Fݟ\J^Re}Ѧ*"2YɉdJO[9>ռ<젺x#ChotK)r!fq{n"zVP`\2TB ^=FHwbvb 4E!ڸr3Ǘ'b!w`Gy!sebv琖K9UM9p]`u #EˏWˌ OWXӥP]0, >QGnUX ^u2'F{2Qw"5ٿ?A2O&zS1_[X!, .]VR7!xܰgPtE,Ƣ!`$"^m֚ф!ź})1ȜeshgpuĬ;e@A!e?^5+ {z=H hJSp>5%7aeyw+~Kfrr>db)\)bIقqKl:yb$O9gI/Ppg'd Uf?̏Of4:1~t&oN9NL]ۑ ]cIϥJbCaox-%1L!EQB(C%^WrbC S+IIcT#ĉ\)8r4k$*U,Z 4u_K=n6 w/L|pܹ ssU|'Pok0CłJpmk_P<4,7ȗ?@r>L-/߻x]n.޼[^0-7ɈL:HF.l@-Ӗb tJNzIn ^ ܅ͽfKʼnꡩ}TImin.Dp R侌Kbσ,>"{pU Nu)*[~8>$"B~h3 w W$M V5==mhW,*E6[[eZ1w.\p' #pxꛛH+k]/kAܶkjgC˿_}A7>Mj?Eװ7vg7oۋUm ј 6Ⱥsq9לJqq⛙Q2#1nZ!8^8r# s}ssL vKm`US9$ӎ-vs`rBxnk'klwy7Żw?/<++Ǘ62篆?W!;r!4t/ZePH .1o4;\{$/R6==sGut?DqO5#*0)Z}Aџ 8 c0پ ܾ[~W'wo]ݽ] CHNر!w*厎4=m++LQ(Z'ZUV rc} ]9gM\nC~6Im>Ŵ!НLWOeq2Ze2N 9lC6f}p0w5m鬦{ yPR;K{_9O.V@L%_npRWl [ Q;Z/N)G̑kp,szy':@险'qK`e^&H#듮!< @.gmpnܶOgUU 9[|I -2j`2>I]q%DJ8~PPt:٬b!{ŃZ ;89g3[$|fj'~8WxdC~7ܾܾC`v`8۲۲۶%lA]s7);C a^8hd{{VU"C '0@7*B>匦Ͻunw ?_2H:z2p T-u\ؾCgsk{v-8gνuWi&_O!8 ʐd2Y aq~gu/& g"JM/_vwaHiSVz}Ss(ΤggΝ7hTAM D=, i}%ѓcǼAl=!Dғ)TUKpÇCtC`6&P|vk4kL/m[>)zGvnN#G3o]篾zWo٩)~[fb|\p~"9)HWN}_#N@x{}&7044 a-:? Zӵ$@%'::s 6B S[mĐnVm#{E^fn!S4s>t}4}̙w~Oޚ!IgM3)}қUfƟS?}{m8t!nJNan$;;t]aFjˋI.wOAIGpv4=!9sB6zfţgGNBq[ fCސ20CCQ6=֩9U;IO4{VS36F5Fa߸'e t#U0$A^pJaZ>sx;Fc ;!>r #,Xİ70xH@W@<8ES5 ж<ȾmdfynR4Ƃl$yYZv  $Aptp$dZﳎMo87*y?y{CyU4U$urO-!" `Ժ9 4#ZzkfAoLI]!|"."Q!'8(]<1%K1]B >B( cOyCP=ep5]N$|4uc{vႵfezdF|`<Dž;woG<2r$;@bI~B;Eސ)7XBCkJ]kQ5?CҐeܤ([3(~z^L1Rx'bjdPHNx tZ2ZErr 莳Da. Pt>h:F 9-Až1!b 3X@m&1`Ty;!vI[p4H,)FH.#T>g|qY8Cࠢ):>]QWEIx3Lpp X") zFX{ݷoJVY"Evg9±"">C@ ;**⩑/z/aО APT0Zkl~sf&L+<~HpmMJ!dwTWwK@B5T},-=ņT= Iu}#>sRţiЩ?&, C)J$ەݷn]%&K ^$F$%dd,-e}\\0ėB(9 T\iVhT7[5P\2,.FqAUBMɾcDɢ`Itv=92&?t* z3$PW )ʠ2<+ET;^ M'Il]oB-BȐr6Ӑna&OkU?6w~|g˺4Dv!lN)2KB[(%HEc[OJ=᭾7rKP%fUO4޺+ۖe!/jأ,t #01E3'zq%O9( mJЬ@Bq=^0hsl HYӉ!dmBQ,[߹ߡH=3$$‘H$ORQK?2 @DX%qI8/N~+S%MD[uel;6Og7k{V[5ҼJjc uV;:q b GI?>]`` ! F8L +H<akp8~^ָ{2vW< [$Jd i˗x!]DӸ},"B!4Xe,4{IQU!pY,")D-=֡aVX=MXZshIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_398ca764abfff83bb15318068105dcb9.png000066400000000000000000000636171420147000300346340ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖dJIDATx#-yFr=Jz 3LޔiA@yQF`0bD0|[]RT*F߈Rz>G?珷sht+9{gKs7?Nut>;N['>ϖ-+>E碋.{/2.f_+Kc^J5/\ss.k.kX\Ze?8=&g=9-%G_{}FI^_4)G|ӐȟBΡ#.Xs,k5,a)KX9<;a khֲ?% !M]ᅳAgO-YDrZ4h*yiOME2k M29ǠKqmwšKn RB07ɵ)Zr_ɟ>Nx$"MCT曇<%|zJs$#YX 8#u ݹMWLFAb?'/iO$o_>a^ 8z4s6}I$5={Ϣ$A?H]byԐYJ*s_BFKXe aIXҡ2ߙ=x#$vJ%DrMADM+w$ 'BV?țs;&fڿ&r-9Y;uL]I dy0[mN!'LWN q|;|HӋاw@2ɪaoB|KXjnGs+\rjhK/HV֕WRq=дCW3O;HA\"! ݽ"PFs!<\"9bM+}jNjCBZXGYfq(9`D4|} n_7&8=NrԼ;k)ǖXMhg=ᬃq8|I"هHRMi!1gҋ#3Zܻ9jϕO@5 kD~!iЅ~?uX~^+%h7E }94]EGf@*",Fxac5z2XjX /bԇh$Ielzw) ㈰\3ZgSGz$'I8Qg7 Rqon;Ũ͏\Zb繙 E"%G9iNߖ5Rr$qOl%{=5'²b=q}jEJ_<eAE2 BaJz,a)9\k!v}R37&SSKѵ+// qǓD틧!awPޟ{M2^5UPD{dNlVd"KU\xn igi+BI|KE4(r(d!yF_Ҁ?qDra:>F,! ِl IJ(?gƊ{uĨHhk% ]lj\3L!8 j uH |k/\/=g CE1j{evPNE ~ mv+$ 9bI ]t b={N| ZzrIY6a|Z}V?$Q 9?g!qQ 䔀@ wm a|ؤ\^D2 b׏س8z&0|psX)hMv?>[d:^ @ُH #BXHɌ%yIHGe1.uMrUp@L|GTAm4/f{X[NC2QF?㢔Jb]H"xC )4XTy#qQT/F^e݉A]A&首E![ݶr6RA*4;ɤ:~H BXaHzM"'mt!6RP/)+V]=;J'yt4JR0$>א8qFz*8 #4YG“ǠO` }8| `4CoӣOX퇞QCAC@j'@a .Q"M hm|IJ!nދQqwcW $!ђ;kK3t.#Mr8gXQ:YzMzIJ!A.% Xrj3օ\kq]C4=g;C"; uk<8iÆv'ZBXWm1ϐ8u7lW{rѻr;!{ $:i`*tc#On~4sXkǽ,=j;L}HẮh^|eۀ2EOƇr֑peTkEQHRM^MU %ʲ*BniJ2  emlF K\zLeTw/!LD:ࣟ`2|>V|ط JW _n]6[E*!EtKȃ0%j.Bա#%VEVlRKΡK[n&|1)(@bJQtguHXeCr&/Am\1ʐ1i+!~2D~ M򞨵AIEyE>KE$2Rz?V/L] ҂_MjUQνWkL$ڬm/^h^MWZ+\lJPA;_*+/ff% iң.OC,l`H|x7NDG~hY|Bsj\.51D@R14UGjg\+RJ]8BSjGu@ "yb%$nIZcCy׌Pߛ%|m lݹbyJ`\P9G-&#i{0M߯>ұK&sgw'{D׾$A+٤}SBIvS9'La+gj+ɟT=y$dNqpHKe:O֘ۇ%`G..." ϔz ^:H̞%_419?4,|H4d3gs' ԫ?QR.b@'Zlo"L;5d{2DTV"҃"h⋂<)Itz' (zoae[v dW6-$& r=vwjxw߸3ҩt"aܿpZRPoi=JNV-LEd>i#󥕈 $>jX<tyf)Inሗx< +ϭp8zx0 #ŝhG![i3qqh,D ׄ&r6B]A+yHCL>SϿO8MIzu\w2 lmͩ {_7Ÿ}l8[Im6hީxU|Yld]Yޜy%!ԅFPg@r7XiK}OstD( @VXJppDഭi>L;6-D >^wj}Ratl"^3#ĽęP%,/c^٧ Bo0L\5j~z륒cImOF85m5UHD=H 5 C2L,n 7ar_R1M~MS_~u6 0%4tf~k t;z9~9 nj)X&ȸ FmFҫ1D0Ey=4kty\ ?/ $ JSx|i' NiN5qu]swH"/kgm*ri;5vӝه eA vCeC@q6;a a_&QQwi^]?"o,P)#[>Q+{Ph>YF}zɝI؛8<+^iV9zq{П㬄޹ޡ^ nvLGk*(+ Ym[S9ͻgJv;ת[7/'"B\g5!et^ }d.Ɛnc2QDZ<^ Öd1fӍ>*IRP>ikr kKrXsD ?I5Lsw1D~(Lelt\;u!5i:2Qhk? '!qNӱGc"ҏepb5ql/6s"NnB6Jh|4HGq7h>K$2k4 7FC.ЙW}{rzY⒉8f‡m/g@PzK SujUt ޼ȉڮ8K'h!/LY%orB\HGMƇ {=w/&KӽMAܦXRO MdR AYU?V" 3(V9I'6ڢ?1 5d-wR~6z"fH>[ `XYM eU4Z^:+Ķ9P齄K̀y ,UP:x)roIWo4ޏ>CKǐ{+ȿ!C@Ri5ٓ6w"1h_钅m>FPTge 0gqyZZf&S _IѴ+Iac w0T${rI'Ʃ;=^5Y ~HBhH6(["oӰ0yB뻆͸L}t{+3?lpH+tƷL~FL\&M#'N8Onπez@*6P蘬"qfPzXN܃ 3%p6XD(ƽ2@ @^re [M: nCJs|E1`P|CL"QoLyPn`T5Y\5>d5O|ȁ$bQaԤ2DB2ƑJ~tH= /C\$ܬ!i;L<}n5*0]/6@}p Anf@b?c` sQ쀇cQ9u!Eya5sFG#u2Y7n~ZL̈́[ʔoE4[:~Ddw+ Ei0YaP,Z! <}tiezxi~CMݼj{M~kpa\ry5fQP{>%WD)YF8s0eIj41uv75QQ/#ȃ-S|ҞolE}Zi|,ΤHT\\Eo*[HIJ &pe_S)9-4\flqq6,e+&+7Fm׉2Am%]jy x<>vO_ -oC"HAGԉ$ܓI#Jp܆twf'9#!ˋCU `LqDw{pa/ΰ#{= >,o߃DN 36 αio9S5UOFYJ|Iǚi=%a`;Hʌ qf WbϿ}nqHIϽ`lʭvAujnz Ri b_+5pQ;kϵ|x[j.ʄſIwh2mB59ql={h x~ ?tgkhK^d#Ժ|i6Ju!>db~NX-A wiɉg_einL4 ]fhm2yhxs "P$"/k)+/~_3uY_c U(yΥ4M==sC\<&f( G;y<2*~a.Xy\|Ӑ0XLRX=ŝ _ K.1lqkO{J{z9em =d2-:O3^FP򡍖 ASDK8y{YmuNy)0P3qMY|.]",WX݅:V_ dd)(k[HYhx)]%r_3>!"^˻0R@cѬaJ$)$ZQo-Ou+kI!$Ͻz }e'SY7xSHoqyq:=(6 bxZbf@bE\!VͬQ_J)Vڏ&7B{E?^v^WF7ؼ5{9:~w]75dݹ f9Q/h;=vrn_u ?<,xBU(;xjS@"jhI,T?b'W5]!?~{yx] I$"` ) }]A5a(f&y յ.X-L"B BW7hj $ uYƒTq׃a]Fxr~0$eeסu+=HQTw?-׺RZ!N`rr yO`\wv^\6aϳ`o7"Sΐ `[>AP"Yxwhy/T~]V9t ',Ôd{^'RteEm;Fn~(,K]Y@6K L}-GΩqǥZ&ޒ% / ZdCFd ۩Q*did)W#{]hTd}'` .t: s(aBB&~7w4C5bgǹ;W&.UlL2(:Zib, Bx xzӻVȤCWsm~gj)zdF(XPf|/ ȳS.Kݯ?*:˼K J0ϼIɚ|Jd}Ȓ~H4ϧ."^K:5jb̽j|"ELCbdu3ao~I'нʺb =:$YU$_T9vZXV3-l lд]B% Ya&sBb9=ؗAMDtF>Ӌ1S,|H޽1U>CPz(ۤ,v+Wp#wDN' i_jB!5T,ϻ <+ܤLjKJ֌QOWa}ְC-XW.B :5Ϛ M ta-uϚ 09s:v ^5Zd|r,&""E&MFʶIVSr0M:J!YyJ*d- !7Z Z4CdDKC8\<Aޣ<| J/Na,aEP˂g}(4jKABF(kz%FӣrtBns`OI: +"qr x|pl\܄r[f<\e0 p U^'|ODN]4x\IT7S˳)iȦK~9t.]׼u1ˊ$):6 r,rE(dwayP|-|My9lY{.bᐇ ܂iVJogNQqGFͥO!k)Grj"olh` 6q)ߩceDt";ΆRqH[I$6aN9$tEj`*cI+d"!sXᄾlb: >>e2> U]Z r;A 9XE7D#Jr̚/8KL[gK0h0*Zw:kWNda1[2 3؍p/C٫wן :K(9dqc*`:hY nMSt3dRQKK_n3bNC.U ˙)~Ȉq..) ɰ~t\*" #Y)JfuIG_c&x˱ M:ҒӵqC&|#3R*h*EH!ף$!V+rN)%T@(іha$9o~-J6ֱ<" ޜ"Q˼)֚R ++ϔg<$Y&(GArI(4JHD׮z$r5 _l^ب[UI "SVmŠy7'CԄ/OO1^ؒcT0Ֆ1kfæKI+Kg+/uuureS e(;eLe)+%OiϖhYd.cLH0(5 :H` +UHQ=9d\YqwPI6mYAp,~L#r$&,:^"闎3Ee%gNb~A"D[&ŕ.(RpRS lz$Ke4`'T?6grM&ZIE\~d?xR$b*x\8٭&.HӍIo"5d%lFf MET]`PٯS[2TEG6z h-}{-Y2{(9fv|ꙉ(|%DAlV,z|Y[vyꄡ#ѬG Q2HGZ31S'$_(RH}}>nj^-i,׽A {HxpS6˒KSwR-+퐑xieom2m&hȹԾ0[Zx)i6!L(pj`bD2Ct}$El8X_eX1Z| ou ɮ(w[_{78 8套dt'J',RtEE޲rϺO'"; Q,tpAp8t4AݪK1ѤljoYcq lc.bd`gG:Sg҆ړ pv1ߵdonVθ3de5X1LZë($_wt|/\ 쵗*Ew1.Q'_p܅R"~w"5c}[z*ne]׿ieI,Yv83")LkɺA3A_V;+H[bP \=jwY Y*S Wĉ{ H`Dΰxm:xD  W5\F,DCFWz{U1g%zw##SC7{|L. %9ꂦb"lv;l m=3ʜ݆^ k W(c"t?&h@l+YTF"u ەSht_>I A'D_0x6,UZϰX8%Dqf!$#2E+JFyp堵eu^q(m;@P ly-"2峊[lKX)Yُ?;o :߇{$Y9ޥhjBbq Y]/|U[b&ψŵ|i=k)Y_ G9tY'k91cEd:⠴Oҹ9b&lhp^LP{ 8=`K"XU{j_P3]4bV i]xítl-~#b/eBMGᖗUH$oNjP 3!ڑ&df! 9_9caWkGљrιhw9Ȋ C&KȴxAX.$t0}&Z{Pl)~Q:RRR{DWI{޹aQfR45_(ɽvd4Ws/b;WHuwsF([{%Uiʊ̣cAY{.8kP޷8Xk)sKZ m4""^_ՒC/Ҧxkb?d-uF\KfTª]M8\"1;b}(KReG?gpN;mC1rPԨŇ֫fjS,G*"0MQ#Ϸ7o(=jmđ ᚦj]qK)S< f u>GU<HAhFi܊(>^$f>i$;SgjnkΈ8+=I0gǁu52LgႣg|YnIJo^ty/raϑ)/{! c*Ս 8Ӹ 7xyijU1(k<߿ŵ7wj\9u6̇e{XeBur]_ٹ;MӍzbEj:gRr(^vv'/[q(ȎΙx36i@!ESkm/`,iMaZ|yh0T^DeR&S4=W]> z//5[$-8,%hݦ/.xH|E7я_p$qn!FSkd\Kp_$*?n%}FΞ[8Z^W>L`d썖w 3P[겥yRpG7\=J*NSTJk\iE60' Ga"y$L?y4LgѲWk[s!bìxk]rao2o,j< "^# 6 Ix&N79ud!~JY}믿QM R#=tWs!]tE`,œ)쁦 w3OK ǛRdHW<:=& x^f_, ѥtp#1xv>Ͽ~֝q>jZ7MW~ަte[[4( T8LCXP\%N=g &8ˏL6gnt! Cj|ig l%*<0x.{ 2VeP|v;?. +:g 9k'܄uWo4_ jG֐x\hjHXc䁵Y׉ze䎍5o0hxRwyJ iKv2cWB^fT)K?qZT:8s{;5d硊4 /&"=D3u(?OvsBxbS_2;_[RaXS6=8YB1,OM-c$ ~5!ҼI+y "iM;sAFjHچsG_g '’2m6T+~ܷ6yib *c RYsȏ ݠ7^#t.rC"`E! SƕX&wpiP:Vr!tR֌ 8!7Ѡ{2nm]tnfCM"> IYv +*4\i[ֹP[,Ґݘi=9hp"cr;D*%\8|X(MNfyR3E=dƉrO~Uulr.LZc|gWZ =H;] -gN8DYVWՅTiB<:!J'+㾨#ԟ\]tR" .)Z3n(kgW~'<=( _ZcB'PJGBWМQ6;?ګ:{7Y+*I皹'.חl &b^&2o6sNSqd=ʒzFYn]rӹypb,^,Iz%3_7pH j0TZU_&=yu_x9Ʋ3ܐ\ sk z71:䥕2gU0$^]3,i53B66!m9-FuJB-A;>c@1u-hR([lRD>R1F{LZ4f](^cY"ᷰwEL(f]q 0c灁jwo{,²gR#vdڧ!lΣDwqD~jb` 6Bl2Ɂ'/q~İD r{͇kB[Alݕ4Vjg9xsϿ~2zB kI#2z9ӛ>ySi*4>B\4j´H .>NϜ14$ 䂔RsEH+ jp[_<=.'E_,Wk O+r!w1`>Np^ zL=Hxﰴ餓RjE׉ N:߈MiDۮ5彪B@*sazQzX8 aV}FP.#uҸ 18!>(<'4i:7?\uir2),7t]}QQH~VYUE<4* IjrtuJq6\8ˢVR B+sjb62aع>īc>ťM[v"I_lh4Dc[ԩ}s{ezw,拉̟( r qrw7ﳏ2ģkknΛ/ ;0-O)ȝc,3OsOwU TC_/J3 yT i2GP:  5.hH1hVUJW{=~ 3Y·4 g92Ro2wb/IfYCAt{mww5N(zjN bi{cL V,~?۵,v}c!rW,ؑn iu-~ Vp0(sK1tS|R [ڒe`mKiɗ۾?/!:TC.Ws9 Q+ 8j2Y(  qwZ{bUoG) BFYwuX@@؝5 bǼ<~/3c[Ey$VR rx);́ȪkJ*8j=j@yP4G&cYr@AEQU +||P\j'!ϴ>E0N?sNPt:1P ñ" 9u|Al1둥*NŠq$CB)yrKy!; wIT[H .aPkEfray>cbRMMFAňj\ uI&Jx`?¦<;{&KeX: :u?' Um̹ОhxH:%ܾ,̨k4LZ.-󟅛م\.ʲoO%kսoe+Y9HjJh> K!P2H1P/ b^Zc22 vxj4>E+vUu!)CW*YF Z:̧uU?-[ RsV2"H+™l+ݕTP"dpG\ G=j\f9!<ںlP;;Жik..lo1*'۲W?1 H>^AT5a!YgT:|bdM+e˷_i'Qks*SjoxV3r99NՍi/'dy%cE`]c,j;:nhN_7srO_ >G=„@AA^J$DX['\p2N{Y?AO:/tV2hx5d}t=*ļ6`}G.LN簨&9`m|.b&XɍE?JBˍJyWًZet5 gD`i9/o) N0ˊne#OJwo}Ÿf)Y9؉ЈIK&jVjluԨQSVAP+0OlkaXrcU:-ՂβKIX8PIE3yk謠hr𲖊0\xvuq3#O }XVK__FywѕW1'dMz36Od>Pv*?eߎ#yi*U/!=6Ռgīzdͮ*fmQ饘eQA2h3D3BoJ|YaCR*|,Y A6<򨻏͔sE6(i=OX`s~h , J-I.v2 6 ;CǍ ^mmAMG &fw(˜e-!;b!7 ,WM (^ҷ+ZɥrT(y]yWXMXLɻ·.z8buwȐĩ7 R@V][sEְr܅*AIEuQb2쨯"CQt*Eɠ;dR><*u6IU۠/D4:_S\\'-nw E6ao`8#WZMZ,^A+o t鶕v5[X)mgg.pEK[,Ҧ4t%= IA@.m]o=у-YiΜPyalo׉Ùm.*̆F&ZH.^PBא,yFqprɦ;k*zm-KI<1BȪD'wB*H]^)CtiL7ґg/#J^iI*nr3{QR h/X|LEHYJe$64kiy@9/uN7>m,tA@%6Sv!2e{Jڮ&j5Cwk2`f ?źLŬC} 7 (|LdI;TܵFK&:QY^]sn~f1[zZ؊IȄpxRvҾ\k9+u] %oMCΙ,2!FQ)9}Ȱh=dk2%th &kr1%GŻ)j?AQni޷ʰ|6V֦jm- Y"Yu-&IcX,׀xLr=IKjyp`ȅHZwiCŤ6mrQlZV"SaVON(E$. *&W4bA6BhQWFom%R.sVSAd2,4ݔFU ,4Dxs:@6Zɮ!哅BAbX$|e.y?5J1?2K q^k*\z?ѥ ~ P<,Fe.$C"D`=2t~47<zK^,=h^#7~lVG1vVGY;.I{sWhQhe~ی< g 531iQ]]@;8sb/e?\Rp]$C)_CB+S {\)ޮfVI|Ȯ4kHMȪ- 2^,D["$h:nv洰FjYMOɁ-ˆCCo @ }x**.f\GLu {;i兦Cš|HD^3&Y^6VK^QXH5Zf;(Q?_㴞Y7ef$[3eC-[K#iʺoI ixMrdt,fY\2JT(ݣeaܹh^.rtyqL=X^iЗ#m_oW28lݔ.lc0QAONN dĀgNp-PyIxM S h %.F~lB@!~~)ґT" AK nc=9q#SS??%3䙇پ-m}7*GY7ZwD#@a-g n!ol8K|*,č"|͇*ЮCp 2b-Uohe_\ DW=wW]$[JpW_E:^)+sQZآ*-%8P~&CiNDen+6!a7R:xZ)v*,0_Pr!-WE'qwЌ02e:&ϙi{IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_3ed273f49d1dc83891f5736e21fc5f44.png000066400000000000000000001005071420147000300345600ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖~IDATxyXSgc>L"{Q2.E" *D}\EDTQAGMA/Z+ Pi3C$Im)Be~}gI;G{,1}V5=0t c铦O6}iӖN[:mMn۴mۦU0V1o1rsߙܹ'ϝ?ŋ!h֬qkzՠH(kH( L<.ݴtm6 `[#;CfL 3ԐEf = x CVtD $_"W)e_ޤsI}dl]Yq/^xq…)tt_У* ܩ~` 8~)9\S-Ky -A?e{Bߝzwd9q/ ^8eQʢY_U?`y>$dС=@Y^w3CVKyCZx yC޲h'$-24d p% H ~Enm&& NBOᦆ C᫹pzi'2@Ȣ@ `襆-W"` B4t)f_CX_C[H"ԡ`Z});Κ",Y0!Ґe6k<^Cǁ QRX^8Ѥ.0wo1w„ Oxwpx>+x/5}&6d(ԗz.܍#h(%%6vVl,t @<_8ENh8xWLOp` WOX=lm$(3_ 6vY ץH+ 1]NzBN"ncۺ۸0%%eQ, !ǽ gM~! p׵ϻAkV;99 `dT`&l;0)TI;V3&{Gq%]J'(;rr˸g3q0XC'&L 1!xCԐ|CBYAIIO~(B M@)+3f YF6]sCr Ze2+ Ib;=A^ȯ…RVkhfCc;1LW8C@V`p2~`Cr]^b‹9C4^e\Oȭ78..Nߧ@ v͍>}/!͜!'W!!õ Y$V0 ! -Z@$Lvo{7,!4 6d,8+N?>>c,Xqr0\n%V^&ོI'vTb/Nf7777'0VVV(`@f%ɭ@ꓛuu7 nq{dD.\)rMW+d%=bSvNV[1SykϞ9iaias*T,g+Ȁf~ K/>5lP]ϑ7ɛȹ7/>>vWw c0 3R VuKXV&}ŗ_'h'R'4~ܧH77p2 I~RWW8 nN9l @Z~+5 Dbļ'l[s9TդIpƇp&d%ۗ,ر`;/MzjNpNx}p&y,Y>Hkooojj;0&g 9 W_'''lx"\}K 60ɓ& Óy!I$]I])t7Ay&Ȧ!+VX"b sΝSbbފykϞ=ais8C*ީ෻8cƇ3>9Cd v5n4CZ0$.N@ bKlWؗ2ʐ4C53@ w:B?;Aj I"C.t0$ Z@=qmWlf5,4BVXZzw&_|eg|8cGf!k6!Y9qqMry5mo~5& A_ Şx!ZsbC1q"dۂs94!Kh0xCP Yc{В{ҍ1dkVDX;!`M?TSwp@˜Ѳ>Z, h NM ҧ髫r9kH8 }!~!|>7 ̊:ZbIj<#f{h'r[xH///?? YII$>SIچ߻)%=vtcddU8"D#V_~ 0:u9*xc+W*&uU[֦jk;vCP&=...55585:$:Z7P`Q(Flkll_gWEٿ Aj06 Vj-)GmDJph07??/~@= Jr}HWi7I76;o8Xh#mEF"R]S[!M\uT)a;;;;Ua0NՕ 1+1tTݪnmѽ}ǎ~wzr èɑ>#llFĺƺ}(uwW lBЗ2YAj2hj≶` _("HZug!K"C!6;PhWi]Ul0D5$윭 c 2s*LLBCzf b̞nxyRkxjHpj0?F}"Y@Hw9ΪuAlƮW7,ӤeXj-VWy7ė1P$8ˆ,7/@ye!2 OgjkjΜ?#nǺHސlxN]XGCETaQιs1bM2CPdF̙`H[ BVwwO;{#7?3ICx&،`>c_9gtGCԾ$d!iAB `HN+CC?!|xѪk=< fqK&j7݄u! eZH1#x&6dC:Q)N`,WUT\R17tƬn =Yގ[1!?!ˢla<\Ar \fAqy81]3&fŏrr[Gw PhI !HGzyy06E"E"F* ѮJ%&&&JE"-|ݪ5lZ0.uK.,J~+7_3W5m6vC5007~₂₂㒓SSsrrCpqqqMMimnm"29y-VV.]v vNiD.e)Y`8;rpio"O]+PaY)bDHhQT*1!&Q)ծί)b.5~CݡX߿_~}YldWnܸr&fț9 Y! W " Sɩ99z^N[YY$cH"EQ D\Q@x3lDYe) gg5rHN˕Rna!-9Xr0f[1S3u+rꍫ7:v,2Ƈh4]9-IDݻw􁻫'COM8&HL.kѴhZ Yh-v1b`ww[cўx:>d?-[ڷ@N '铦'O⃽J!F(7lW'0wJuA)X%8뉮掮'Op9ƍWo5iW.ZdVe%ݻHPP2,̒M [񕃳6 f6Z]`-j'{h L,M=z-t oSa] $$$$9 !,29Jd2JeRHgG0<;wzKXZN}{WEggOg!zq?nͨS'5>my0 V)L IO81pFӪ!OSFU./\/ϵ% d.٥8=4A@À,OQ2JC^,Op;;B"!c2o%K!<!gK^NU'kLvcW?vxd*JO?6݇wΉZHtrI}zުnc_+!45{{{w[[[wRbjTY@LXCH:VEYR#DC\`)#e`H#x;wJ,bHْCM ܳNrsCDUO?JĨwgM 25$*5,#UѰ'_L>b>\S)Allmݡ;4!4fLL rU[>_GjF*'qfDRH˿<"D,!NiTʣpߺ[[!UZjngow:UrWoc! SsCUƌ݇̧DA13d>X?1pDYbuCK23 1!6@CTCOƓYW}QhgD.ly|%#e"L )Ŗ|*1!n}v[IDr$ BvUJeiAdC$d搨TEjt!Պ` rgC aO`ܥZ Y0Iҩu:ubt ge9fe9::f9I]i[۝ەrvCS2CJ{>dX BVC:Ag7~~Yfuحcs3=*ci!ACH[Es;C`bRG >VMg:^bokkj@J8wyxÂ9=**9:(e݊:Đ}b noco 6CYNnX PjA+b'2Z!JPDHuH`H8`)d),&.Act C'5C&O :*حҫIfDť1dsH>X9Df%kh4-_D_ε@Ȳfkȑ~jٴi#:ZnF@qld1iHùz G:%.s4;<%B!bqĐCi]MMM4^ARG" qJъp]Mզ~z~+ 8ŭoᶷ䐨TEtt*^pXX#j= Y28k%psrs7D"F8C͈Jurpv弎1(|~:qX-Sft:ѣF)7uJulR P#>" cHG* s1UKӦ2//ѧgoJ 'bl3&GEEG<0$h4--2v}XnC\!!jZ/3}H1g S9cDTYj켎Iߕ&dxUk2zQJQ;Gfeot rP]AuYBȬdQCUW7UK3V2TmO//a iXt+lacnXA>0D^-'VFnk $u!`iȢvn E~碌1[QCG9rfEJF7t@C=zC x*Kˈf[?|J I1GӐIDG!6G5c+D, .Zۺ!dDu}kM ~IC8 -Fkd0Ӑ+Q w񆈄"0K`Hx7DEt 2jJQ d!FP`R˅vt9j!75!Ǫ))XMxxez[YCp} rH6\UEc"mm$I`Rq## ,7?/??|='[⒟,0y\.ش.0Dꀨ)#@r!O,b._OKp\R;t!xXltg׆ie%JզRM=ulkkWzzz:غ5$$$$*:5:Ua@Er>XXϝ E)))6Xer<@#qOt+Lm($iX:NÉ^GG,;ӲW@D팣А-eRydK00uܡmbeya Qq+- B&PKll$l_41 yC<0`Cp|, lY"M>!d!,Ƒvaa.C.0^ReshEH*Bʨ|2X'K[ =khh2[9DOM$$d)+b gIR! r,4ā5⩠+fgn~!1N` YJ3#!De22sK sΝ;4!lbU*@@'M2Hu0$$*$U>PBYD/Vm%44ОĽ&6E egmaȵTPH%SFsFrP:م jnHR!؇@!8:NU2"%Hx,<<92vvv@S+IZJ*픉,%L$TCNp2)CݡSw@ 0:@Q *wש Dz{{GK֭2HJn}Qsq !hBт#YL(81pDuFs]SblNV+@Dlcccor#L,2zQ팖Nm5:TT<y8:8fe)aMbZF`goD<<=9A"FH7؅{z&fe)=@tU$c`Jr 3wԀ!<{5s{CFgGgXaxQXUeQU@(Ҧ2u5== !qE``^((((S-mmm-m) xx!d ~^^B г9]\A7a iBnVBg ]%DvDA"KuhH˝" i&!+@00qgX !! BbHhڌnVVx"F},}>PVyw^ D.O ֧--X۬L"#q1!nfmdT;u>1ZVDdyfa"e$! ?J"F"33QihRk!gSJa: Yu'wE#N%ArHOw56c A٪6kFӗOOTУ }pp0v(%Ќ(֚k}]cbS(Ł1 ]7 Qt@sU*TYGnogQY?<ΓG;ʂԒ_X#|Ć 5᧒֭8)1)q]qQŗN\|Dɉ%KJKJclqtF"vJߟ " N5:T1I*.C._|;%J)8=x9 W"/\A'?>ck1$pK!QQd(ʢ\. QFHH$G2F2H8fL|nru}!Ap#1hpƆ?GgOGp;G;䁓a 5{&DSt'.CC䟄RpclG i"ailWk YQ C7A } &ȣ,jL8!>.."+>E2E"3-6@Qcg qp01ӎ7 {@jb/H©S @,%??GٳT6du;vP::ِhi\AG h?!EDQ#!>.$8$ @n `$d'ڀ$frra%QF$A2pB4~upAmhhh8pLҙ3@z_YYTTTt sDI~8 8/8$oϘ1ydHalxqE3IIW$ Onn`` Fl/K$M"R=sՕ4Oq! שd)pO?>+g>~~~uuמO:tLRҙu֭;.r]亢Ȣ _Rx 8vu""$db Q\ܼf2=33=3#30G$5'5;I!Dsy6H9K||$p\Iσ0!Qfb',߃cR[GԞGE4  "BCCbƠ!GϦ!_heT-,0d3U$3bŌ̌ A=R #,מaHx"G>>>.G+B!ā2y(!Σ;q? k@@pyZ! 1bVqbd!g+vur3 zf̞ !<2/gVf.de!l )cC,!QS"7qyC8IgѣcCL! FHΐ !!IBC6CCƠG=zhZފXCe==hf֐i$9$de$B!E&cr*I (VMc;;r X8ngO })oa ndqeS[fͺϟ?Ϝ? ıqcƍ7/Z~qwܿsgLΘ={bbJK۵w]{+nWTT*G a};ر}{;v|/3/}x7^ÖC.I ;62hĈ2lFp'#F~݀<'AO WA v3KX (7 Foos*xԱ83g"#)8֯߸~k_p<stYiڻgNw *UO}}}O!o޾yNex D&@GjpJprp )))#bmb?F"~D <@dLÓ5ߎ%@pPCI`m#LxpP ܄3!g"9CGA$Đ;讴cފ]=z:{ 9N5dE@I 9n$ $('?քB@jKĐ(GCLJ!p&S!$d@Αt7r,V31k5ט3&ٕ+(UR*cУ"۷O1$ !+$!l̊E #HEGxA8C/Y&93| CiD~r#-r[F#nNnl d4 YEDr+?CbM;+ "֮]=C#Xc I<1BBbV&)4 1 $BրPY 3apmAŭHU;;NCVVV#AORBgbp œN;:pUPGn~y`3rME#!XZ"$>dǎ:~<8$u)w0%r8''5'`J'+6XpBSAlH(C0] 2@٦! [K2RC1 Rp 9|H:~+c=aĐ8pIK^X,c;CVvF,!elZwu%~ Y\ȒA| Cr r3w[E"f 1v7!ܼ"i 1(B!b5H! sDh>i4]"5E!d Ԑd6d@ClcT: Y6ejy6:]//%| +'@MզdDWt63(#Fp II8za ~DvƝ_(L< 8I#oOOOL}oP[/:7︸0[cvcjӍע]v)*:::wƕ*r\$W`N0>è(.>.:2XP X:^k`x\M%&@nₑ# F՞=ߐǩSI).{)g/E)`A)1iGӎ@n{+X B6o;2/ffܝAl͸Ԙژ}:tkٸ':**, ss1 KQ6>'###ܮˀ h,jHMuYd xd RAjY0H/kҀ?'psi{ 7+Ӊ |gC){qd$`H:<Аөײ~Ų(Cbkkkjhnbȕ 1Qe!e.!_^jG!Đ!~[[Z^b^E&5TA~~u~0/ɻ!>CꫯX{Gv5=z,8>t+/VV*&Ɓ[aTWWUm\y+3HOhhl\v0^k׮M]\\8%H}ii?ɤI &M _ fv3 cÇ_0;nfD6{>bu~61!18Tq~o^o^/y|d#q҃P&Gx~#%vkO_;}ZtHԵ1Q!yԅ/E_TD>4i$Ch! 7_$@9.Aܲd= yX3krpe]rey-B7 r8ԩ @r%< W_Տ&=x"gw}++++/)( 01^Α  Tn"UE,q4flmX۸4k5^v::*$:HZEZŤIL$ԀB@ek¸e-<7g"jjkk d%/>כw OC[Zz uqC*3+/V)$ 1L,* xUp}>]e:"HM %p#OȐ#GS77xcʕo\9uSB:r}ʃ]zJJ7ưaH~Ǜ\'L`?ҸOO5!!xNH`HHH[:m4HH*aZp8paRow~r+@`96x^ 5; @=8MKCjkjHbbbޥA 2V+/Mr!:wЏΞ]Ν&<:9:*Y*oxD[Ɋ(RK*?PؘajF? _zڵk!p] E "KM6m  5L :iΝw z$Vw~DLGx}eC(6ސ)u$!dVWmMM1Dd y|K,v< 92sv:\ܮhHԺø G'+I6KWnMoCN76_{-z#dk^r'H`T`H`T=K-7 UT*2y#PCv;?f!BA!=|r>? k霂@f!g?C@ZojHR :7xc*cg~#\/|SbX,N?y20im stZZw_s_#>׾ro߾qvhOBTN~o$o;P2 LNNͶ!j_ncyWOϳgV>}#t&~ ݅((ߵ|O>}_x`Gb'ţ&?̧u#?|7+A;oH}&Ux%}} @ |) $9'?Np-%b{$G<ԚDn_}J( H$2o1E MM4 iQa@޽뇮{<CTO>x)#h|b0|{=zBbBbMrC% oPCVRCV Ă;;KĹbɰaao.uX!@t ?D'T| Dpڵ{;OnL%li,mYCKt9yt?CCq!΁}omm^ ߷Yp}o1+?_a1䱹!lBCkXyQX_Uh#Hr ,$}mڵPFY2DfiO uL!O!b0Nt4jO~EC!]]]5g`## YC=4,1D߷ 71!5 J%!Sν0d4A 9/EB }}qX_@o)QŊ@4e!U7޿v9AԷZT[A40}'K?C ݮwu֋[/ǎ;)?^=}ŀ9p߷|} nrd(Iu=jk6oOȃq/r@xE o#+920h=9l4[_qm!j4y:1烓|pOYx&?O?D4oߗĝa4KRy\,|EMU@ o j-tK-hvK +x^#@>}1)O<#w???'`cMZ^5'IEx$ׄ'lؐw!Oy#G`rԕxOMOmr_;2ȑg$ DE 7ė:],vK'O~Fy @^i ׻[4m&L& }ȗ_rnNH,5& c.N: U@j_ >؝ҐyW/^xR⇱cvC8 N}z񃻜 wLbl1Zm;'+GBGB`H$d"Ԑ߰9o+yC7Y[1RzUij2 Bx륓hdԍ7~;uwwu69gZ f5;pM Qk`E C+Y/$E  A<f 4s!HBMBB~B^Y_1g?!XC[[kk@W]7]qCwrɓ4~'0 ,tMC־/[C C,Z! 5nxq3!"w>}z Ykrpp‹DL ؤ_@ YIL:U.e|oq2 x#!ooP@N !P:9}ɭN^?ViZYlӧמ^r-b^17rhuhha;Ct}ܠq!I}OU^` |V 7_c4BC ¹~R=%Jvgr b#^ ("ɾ}Nx|sbCАPe}B Ǜ,#I}$KBʺi r3$d0i1H@Zk!԰WtAacSSç^yt o|0OG>*|B!S>z3d;qvpƛpp !zzVYS!@>%!\ dJG YlQnԫ8E{/;sPdCp CM YK OBAJ85~"Y_DeEx<~prً*CCԐ=z^yАO"CHˆ,>\olyc4~ v1QY/ &c(J1lLǽ!O ʨOT`Ey6 ʋU˛BVj:b0rǛ,y.AB;NaU^;Zsι7à?nj-&;_?sr˂HgP Y?>u{9!Z̬ŒNNNAe`hw+* z6;26;o`qx=ޯᇣC-"uX*Pځ.CJ=! Ӭ>N Ê SL!T Ɇ uAYAu#nP ~z:qڿ|@&x:ig-(b4ꌺA:Ťkpqrrz6}h\/=} ^]z،u Zv⏫T@P*eW@9:1'UNba CkjkeYξxP'=a.d+H1E2I?HƠYT#.'!ge%›4Q$De &A'H`Nl 3FfG@ :g nniZěGl%X֭ڹZ,e%$$! nrQ,$Y ,e-'eA^uՠ^J64oOABPRgg"?Ee!!+9!Ba@v\}BfG>Ϛ_'Dg$BzG^r]d+JeyV-,JJaLM* PAŐ`Z!Ͳ&$ h,x۽숄V[B<jBU;!ݤorA <1N +YCJByj8!Nޢ@HTc!N`Y̲V*Du ,e9SaX aiBc6CmӆiADeIA&Ŵꐕx 1DzeD&YkP_cYX;1 3:N Bd2m`YꫵvZ<-0t un['\C0cyޗTfYimiY,6ɝ C,rP`C^zo A]$-q=,Aـ['6i$\t31(HH?>5β۠Aɘ0j&H`dwʈ Py?U\1dl$~:Dd/ ^Lcbmօ !PtK*!=gA}3 H C1ep`J=xZU%_L2iIdld q8љf3:(>txwCF"Iq$ j1Uޢ:dN4PDpߓV e J,_ e4Pp1 C^!`aTND$'Īas ,ˌ[##Ɵ{C>3A3R#ˢ?xey_Ŋ[eeN ˲Kn{z0u d^,h'TWWTZ;$FEV'^e'R,f@;PVEipbȌed{bc^R,m ֶܖVNXVf&m.vW9"֓ NI!G#\L I K 8"!V$ՖYK5ꁄ̒ ,K'O? cKH]BptCR\kڐ=Ax jsUgUUm})Zɲ~n!dX,& ÏX‚oEа= +!Yܲ\]!rqb%V$hY(b~J? k!eNWYٝ K{WcNJRu!tvNtmnO񻽫L&A_NG/v8jhZ./R-[в22twװ/TA'tsߧpー6e{¡lZ]Z¯:;:e9Hc셎Af0ȦpBO~j֛z٫W\\^ Tׯjkkj{:{:u}S}}S&H-4?++ݽwQYaX)oݛdX[nɤrUUUGw~wzZ?=GA֍n/^%ef@:p+Oq!P2= hZ"!O6<1ܮjugkT)A]e^Ne$]4!*+1ZXh#B2HͭADtb]UESt[ރNܚ.[3q7 8tI>/[;xՅ "X,  ??_țʾaT!lBTfvnvֲ Ҧ ˚Imn_T~Sy- B $CZcE=@jSit4F@Ǔ2L,A(Ww(μBBܲj@ aY}Ax Z3ӧf:555!P @Bު;P Ye iC7i3ݿEpdc2xÆ`DyAY4{n8F3mO f2H![FE7e䨐wn]^;5E`nZL 2Xo< ?S嗕w3޻Wr9d9`W}=@LP*J^Pӭ>;|pHMpZPcwAgWIi{*8xCpAHpϢmc("G2ye?2|kEN_cu t!sihiE!X*Xб+޽w!{x!)k 牏MMM7Xz0=|q >rB;gθmAe`6k=F9 ⽈1$:r[ |?11aABڢUdYP 9Sy̗_Vb{dI_<EE0uMaiUg4dc w',GLkkH9q[kbk"T%26f3c v ۹obbb-ceeT*xyNם+7^d'==|<|釖O_/|AVG}QpDamQR^o I 4o> [/,<8} v]Ӡќ ?~ _ٻgo @zm6G~mayE ^ӡLA=rTIL;8Ɲw>dgrz7O-AzAuGa֧@zo/.H*/)(/᳹!s8re~Y>60pP!M&=SVF]F]W b5:M0BFlF~[P! s`XB Y|FBBrT9yTׯ_3 \rcO{{:@ci=,4 i/\caWuR=~ OXYl Ѡ9Ԡ!AWFQnAhCeaŦ$6"B_FF\W,%hB + u*ոS%1Bpl;7>fN F>Z>S̙^9V;EBW#dzz̲ΣdY H )rlC9$^`Y'5>q>>:S*;jh=t|Cffu>jkB]A1!`Z2"!de֖{b!$UXhYXs=W뙀bBz H |1$dcVR^R޾$r |]ὒ={>Feyn\ּ8+77V#ZBg޺a/*[T_T檖aq \wdܡ8fFSSlqaH|< )`4q8O~r:IY#eE#He7g^)( ۉo'ܼ{{b7xB1$B8V^R^56E:΀vF_qsZ&,˜͛7sss/666656Wc{ccȱc:ݫAb=_wxgKKϖ<{vٓ'<pi"hwG-(0Ph›S3f8v&JqWt؍y.21DkL!r5kV@PV"!yH(r'qBp7.\1gO[[>|x7szriᄀ"H 4/(Ⓡ MgO(gQ :NFR}47ߖW\2Ŏt4tĩڝw-{v-AM|;!*9dEZ5w=B‘FB3~O !-''ۖЗ&D͋gƴW`z0BxֻFXXMADbY*ۂ#[_\E,ssOe}h&uEHiCH1X]`Y ݢԜe8$gD!$qlX[O>@\,:N)!V-{qd=A0f,%Vl.4,gb^#qS+9bLOJJ8i}ү9l.$^ppz7/9R ll @A fY-"lQ!$4O $uS S4- LDB9KϺ\)" q|=B@/$PB+B$NDDەn(WYnG=/@)FtA,=js#!J*[R"4]Nl;DÁamݺḳ +X{ڻ'k==^XSa;o'索aE9;h3~ޢ(H%HNnёXud3 L}|Hl@ng%H.!fYkUO<ᮥ,&@TG9/`z|zz|b|r]8J`qbo=u)̰5BBCBCbCcC[bcc[ڳsǷ(Q)sN1 JTLLtTtTttJtttJJXJXcJ3h! o!ob@2B+yT_"%'bUW@yޖAPw^C KO>xǃÁSHs4qAĆfړ7k=Ǐ[n;?scgTADDa)rbAGrF|vpAMড়m:&dË/л$t&f Z_rX& *~4X[A,,BdۉH፧Ȳ [YVH7=Ƿ[0@("$ -9l:NuAv%_B묋/8[%!^ ǐXRBLKX^EBt՝=z:."DY!!ւ$'nKL܅uF,"YVe1BBCCcCc!{0!;eFRwB !H)y8H@ so_!Ψ3꼼C^^A^A z,S"k)v+v=J=S%Q / 3^$>>`]vmۅWŷA B!$"CCCCbcccCwvX;`aPOK K ÀXrXPJ;:BIo-_).W"n?+dXdYYȎH"hy 桇eYX Q* MO? YVb|6T$؈zly A,ػ7  L LC*HtXXXAt,@F[9!hb',+ŐXѲl/!kF Yw9 .rIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_400x200_fill_box_bottomleft_3.png000066400000000000000000000632511420147000300355160ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖cdIDATxܝy\U)O]BID! ZPxAEAeBB4E!GLP@/9t͊3Z)uֳ }"!ƀl4-Y2ٳgOF^A6nܸqB6qĉ&L0rȑ"{ ̙3gNColذaÆ l*w6`O?ul: ၈@DyL88 <͜9m&;Ǜ"! Ȕǻcsg$d@(%s̙3yy <@F)͎Bxp *( X cI!@+/SƏ?~Y&W y7BD4uLcy |( #BƎ`"YtA<Do<֐aÚB<ఐ_"D1cTC c=.+#ʐ.xK-Oe9)'ә db͡@& kS!X@:Lk2yVG`$Fs^ѱ@fDgSW.y,A!9/:%?)cP1 s%K@E"X9/D!*dRk<4ZP5LV 5! 鏋 :OFw(=֜% kqb! U*iJHk1 tN Hzt@T&o(yPBx>OP39T!XΫ^@UBUM" (d!S+)XJ&2 Dc5b?Tx 2( e](T Dy D"^ɀb#B>#ta]A  y  Se]'uXF |H1BE B>ǀÒyYۊj)@8ׄs@TAB-ߘVs^&1|M( dC5lQ_w;,./vMDwڊBw§X\}Św2t@ڊʐNx+弝Y!D^)dBBސEW50eJ$뚼WlQ'"!]!&jExծ R05LuC O`[yeaQ8ABdR:WC:<? 1'Ah+1U+40k2MB2imP̚0}pdlA//L$R2 *Cѫh.T28k",TraJbɪtV/*Df pXrȱ>? VWn%LV )>LUHϱ]ןdODmK.ye`D6b ],ʔt40+[ r*Ŭ ͱ2()SOR>Q+G%&*ʵ' ?0y">S ʅٟϚLy)wu48ܦM=%Z<:Oc eNr^:(|C2~lZa T7SDOn䱨@G'XH6\$;=>؟<ɳҟpC%ŒM-uW);@" dGD@!S @/.zIJc8~^'k>|ޓW1!S;ĮJ1iThdSB'8 ʧ7|5I)A4_R, FT6vtTx&Ea$FyB"|ƋQ.39pBQ,+#>Hs,bI0*Ca!@$5:E(qP/o $8ã!]}քڊ[H?:<maSSB{'Og UI8^68|{/7|1cSB:[)^VYB]9_-w[5íV322*{04˓tCI'|`*"c!=^M{/0b"ymaS"qkD4SSSVHCz D A!ɳ5 ^"Yc2>F(n= ,(TR++ ǚNyʦ 5M:p<L&l--^^/Upǖb拙eypCA^6bu4=0ER,2#ɘDzehVy,@7y GWӥFFz7/$"QɶTqP}0RSv/x/ljjBff X!# 3ĕ[[],uMT܂B@)n1n1u|B^C{uQSsDHKט2ĄkX32?R4\rMz#Q xdtXܮ%bhG r H?~[LLd;4tMLҥS {<ѳ罛2.)hyۅOTM/ӧg&=XLlnj@DN8=vcFWYUJp6|#&N$[@i@/u '"V-rqpV"-V$m򦄑B$ g{zx` 58pW(i<(`O!E KjꂈMIp=o/>?O+9Nj4IB:ɓ33O#"G>=4Ϙ1}d9 e?_Gze\qcǏ7k>Q #_}J^+9dfȴi!HB$d1{:???Gj7KKS^zQ$pxD$ ð<@"cdKa?})>} p$9`?qLXdHzrGE5.*v\O*.F?D$ xWŎ;k߬}&8qb F,j%GIHINA@!11oڜѣ[ }>H@$}#OV(: *ʙ>} \V߁: ty}ril~۶1 ͙7oyfM džq a(P{lfIHHBf`!1X!Uwjjy Q!<0yP0戰'!}!2o?~~@$ EEE#@>JB00yK*uu̳$Hll,m,-'LY7@ co?&VfI&@ De]/Cѷr'''[[[''''.V7+˫urKkK[Kd?*۝KUzN?n+ǷW}EoSVղw05akiO!@o߾~uvԂLƵej H: bd;VC[Zl8`&}-^P.43$Deee%N_tz쬬,/^o9oF??U~V _vGÅNV^@(*.>S|26"y rJΏ^WuDHq-CW>⶞ȳKCH{{{JɖI"^'/]20$\Vvhe+tfggegJcB^WHQ3gщ_?&5oy+MV qLwo~|ggGG~=l$!n׽P!ΎȬ=;WCh@"*@Plkt%U4#kNNB }-铹}[O @#!!?X/HW9,1?@mꌢAB"B{@;EH߾E W/^ܿxs)irB{d&W U2G )D'! [+4Y׶E$@v$$A;~J|+N$ QH]!yc֭ @ sE@&[ tw5٢8ܑ: A_s2 ]IIu/xQdƎ(̻{ٳwāO;s *)75&8ă,;R\A"Ύy*/-N,lJ /^|I1y zKMWPė7ANvvfI;))=)="Km ;0 ;ڸZ5,3Ĥw>+t]x[7$4$T |{C!Ng<vqY@_g> G[2,e~ t D#h} a2?R7$º*Pҕ A%V+\+&Ih) Wғ*+V7ȁ>v#F}9,=(ن2o+d3/@"R:\6RC]?H-I"?"B گB1|˰ Wz%Eg\dڤcVOn wrz|={h= 63bKDTq0Dz37+N: D&ܜtϹΗx@Z,s+P_| U9җ ۭTHd5!cjC4=zWb@DR0hBd.+]>sXesۋ-U9 \n>:BD !po8D8J NO^& DH{U]mBd),L7noNLWB.NȓzbxEZKl: Y_ZϲytT 6ъ)88>>>#+xtB!H-)X!X""A6N ,n* &Btfx^X)?uj1zuHH  c11kw“ӭfNj;c]^)r\iSppprrr򺘘ۇI(^vE:Zn^eHOcYX񽓛_3=&{:1Mi/^f$ژ[ !]BCQ vT Wq <Ή͛q#R羰ONNhuFU푑H_B$^՘;=Pͦ y q23ÂQF!(Jo*LkanηuD!\_"ɭ| e9mjCKlްwnurOA!H"Kud/҇Yh0 |'ZGD.DAmz>{2(YOAMI2tL"H-uB11ߞV1%.X7^~)o.F3utHQCȁ7t(ɲ0=NWuR0{>.56 ftAh4]g c[R ?5 TWycSQsZ.s 1>QɳRFe)aO;x/ "ɬ}k%2'!DeI+BtmIL :!temްylg7a |kШp"7t*kBlT<[ i"@ͭ:KI+HB@cB 12bݻ(:6_Fr6($ x|&,> \VaK"r>K{(S]@z c}Ev;70L?‚N$[$_[8TtVlS'>6&Y2kDR!|Q-*.Ẫ2uvvX!=eStޝ,,ZCDrYVǀ~ױ_KbEYVڊ+/+$gyG[= `DD+  tٝlAp5P78;Quڑ!6@0&fV:v Um0`#s(+A9TWUxA1>{8xt5X CnwGqvҎGz2DD) 2 BsrE>,Z=W愈,+0Jdndd%!v!@V9sGq_)dsi{j'"|]KL{TjުDz!DH  B/>UdT5ՙ ̂Z] [;;ǀBP7HJJJbmEEŞ=V9.ɀD9{M=E=QͥeP-M 7K,#ё+>Ú.᪬p+/^JZMZQIR\PK&Ẃ daf鉀슊lDdV)kFyYgsCnН\X#C僆eXDGxuݙ$AZrV-ģBk*4 (wxŋ[[2RkU+W(<_72Ժy+6dh-+3O~dbD.nNԲ;z;,٣GREx l.--PiP}iqY ^S^pwnoo\]=\]==\7WWZD_yX3QG. @WLZy]9uj=6gEPر3Aۤ> ;͝vNNfvvv`II[dgggWWlɮή޳4rŶֶf7B!±!<`vѣG۽eҗn^ H}vȑi9wd&R~ ZY0,G3L~:v;}?3)$%3A9DYȩSn/ra ƮQ@/,'a05R5;'O['OPO@@ G L"2^G$;CPX,Y,D88HN.DBB_w__h+vttst.emm8P*qu!5J#Sq?)ƣ 2Z;'`bGeFtcANKL- ]l"{E,cF}AU rHQݹS_WC@ GPiСC*=pR!2D×D 6eσ$p<'s|H7 tS-5M*zSdDbBp v('esfgeeg{#\ܱ};vܹ "\3K'/tii"[:r8|˗A8za@/)ő1qd8Q} 9#*Jz^/ #HژOb4z8ۂ$p<ѷ?@"9yC'{0 тDiQ&vZ7aDb<>X9PYbb.YsƍFv$MS #&wYAWvX@ =@8׭[.9aFj##SQ`=fS@Q]qs)` ot $$F\shmq@~_81@*A!cGVV={6wo+a`%#P..1P\\b\\1>>H^BabC@R}XJP<J ,zC/d@(l) zt$v|ͧ4[)W`299dBrR,X51跑E\2j_Z'mf\`!!!pƁDGD07rtΏNM8tÇ/Yb ,BģSQ&i@ @>ߎKXdAbn%1]ADbP,Rff< 8Nǔ} 3A<撓d͛42o=*H,(deʕTq߼D!!pO0Dȸ{J| H>R,pH*փy3,I9S fvfL gVRgp/=i⅞/d쓙 G]~rmsQ~yY)Z>\ʕ+f\sLݽScU&q "7yb 1)#- $::5 $ 2 06 #"y3|#8d̎?̸Μ[찒x,[%\e ݕrJ> DN0hŬy (8 UFC*)$lFFƁ?Ȏ(1E 8|QH1|:/t)CuDbÇ@:`_2 '.ɂဋI 9|`A!(۶G]HG+rg]]Kq6h珞 qX rYk9x'x1/ѱ 0 Qf½]|yf[A'z˲9ʼanz>^mP 8˨XB2@2g=p9#$K|RYD1n%b04i/FTV(c,2RVHᚨ%%U~$5@HK욤@6N;'" D$ňpmNcy+FeDSB@z*0kT`anQQV_XmL# |!+@5SK&&Bp b1c:uX &%S2@B$G8pď4Dd)a$$,읰NJzcbbPʋ]VģWiz8V(U@$dn^QǣWW׷%< bL#! Nj2"ҒP A` yx. <p`&twBxP)))Jh+ױ"'+pz!U  2 Ĉ65W3*l$"vC ` #i :,NGYYY\FxxH!Q0D6mHKK[ A$^>Œ7>VdKRikM.\!8)zJPW;HقF슶`HT*`+uKTbEaoMz80 HWԈĸmI>@&L2H'-b1O:5līRɋJB\D!Bji!$ ytuxΚ$$Y* KY %㡈H7I@Xgnna.['Y%Uf̓'@>9IXAg=x`#[CxO*+A[ŋn}y/Av}*v;\BAǒ)Hƅzp𡴴4!`A!!l^[9#tM Gm>Nc5_bXguH!-Ǟ:xgUt0j}b+(.&? KҤ.uYF‘FH<غGLj}ɼb~\T8pttL, d%K d16OR Iywb ؕgE#G>:w/$xaz1.>.>8888x<-( 4-1رcX_udeckDNĸ"I!mɪT}-0RkW=ܗvsq 12h9WA vE7f{""o20"6" Fxk5 j^Q]&uIV$ 7̨l6ǖ- xս{w>ۉ@`z;`Ep m͔"M> :J$q₿`b?HRtRNk- 83!R;EBV$ h45 /WGPt'|wbVWV} v"ݯa|՗V#"; W/9+3r:v%@zwL&l<.McO=#3$13M4bvOS̓JDԁPz[*uVr"dL=qHOߵo QH(AHvAD9+'1$Z_߸Cd |`:('ݙrd4=/J#=c^xQ"v{^h55Wo<1ƍҀb9p\VpTEs;C\sq$KAKY!zSI!aHܑ/X(Wl=,yKFy & S=p{h;DD۲U";')WU߁1C?"|ʡv^B|?#⾠@x -;z|!| tRSSqaJK$XZ:RswРA۠2_PiBV }߸Prc!\m,/\ >FHn#+pW.[u5;=3'r՟q]@p[lF|2Ɓ?qU2յ+u\{-+e<8~aIL~$(8>wTDM7:XTDHf/q4$ A߯X~EBrp\nP2}F ~tؑZŏs BD~-?PDLl٠x_٣ZG@zw5Ɵ<#1xQ0Ç-FqG#y܃,"zK(^[ bI5> r}޽>|/,\-0 /B*[lۖ5Z{9oooͨQH ݿtj8a&#WO =Mz׮x:_'9r#G>U`2 :]J|^^4^\Ro" ׉ǖY3eÅuÿݻ;σ*iUc"yDR]a'HmQAtdrtg $շ=?'-776GR۵%hVPX"aa|y\4&^7U5^b_EH"EL"=沀A:ݝSAp_7s=x4&YȜ- D@w!.H;=eNJk._}ٳg FEQѣHvջwȦ#Ȧ/yԪnʞ \!-vW[tɱD:2{t{Rx+F◐d;e0d(u R g?g-980޵kWr"M駟~zS篤GT+ýR뗌8oSᢃD9ZsyiqdB7H_R{u]9ߋwMECyteYC'y{߿i6!y9)7 #.fgi7}zO?k o-:Z+Z[{ ;ɯZңt|;M0"4 r^icH˪헆1^]VdoaWGNNNL |GHQ>,R\_?<6)Y$H5"Ugr ?or6ՂBhGo rċ~R?cBPȂҀc!ͼ~RC>%EP~ɩ3x k˺Fy!>D!1\s "e B 4M !Q3tLH}x饭 „%X!)5*qd$Z^ʀh4w }Å+^޽U.H!/'Ad A1DoH!fQK!ӢWDVoȑ/ޟgN3@9QȱH!ީEU!,(h$0r T{V(} )"@, $~X vojv(Bֽ x dźL!Ww?|!}tXz bH#sw@PQxE:*HYvNNNH:XA!˒+d1d"BB ަHguJ\&Ⲑ"Sj1aS 9깅uvtĕZ 1沤E,%1d <xL8^3S wCPW!#=cea4t%?=x;V&.c)Yk$5^91ͅZ*fYdmoeюx4ыg@PPithhpK5H7.jA ]Wo$4<p/%"D"hD ej:YP'QgC:eڲڲZ'/uk!>Sʊ!S!RtYa밆vz$+XҀ¶2%=֮]ϝ3Cts"1deQHVpPg1D"Hy;NGR-!8\Nt- /)˄dvD,U\H\4 ._D!Ii2ԝZ,; dIݻV T!4V J+u޽$1LVVB ,-й 0ԝ;vYx5(l`k/-VZp߯Qˤi9Zp+)=} L!?w?J]:A@ %t,R+1u^!?РkŠu!b%!R 1O0,]IE.QS~/_~oTC9"@RS$dw5뤯b^!Vh)y.KeGQ" WC,"X%: xjB,0$ % "H+R| CCYhx}}_P]_qƥo ۠~Rˬ~eby%D\c.KB C貤0/ORsn/2eO <ùPuѐB:,\hB}DžԌ-* T) ՆEn|ǿ>$@h譑\w}}EyJ@p+ϲ@!@_J]-BXޕvS{P|ʒ4b#k\&/@&^7uJ |ށcޯ6!%zT_43cѠ.ϲTXίyooexE,T4u??#ϲ׳B{zi ^\bdEC@>{( XunBb9A!,_BkҊ!!>\rA>I޵؋i޸\o2Y gYqY&r"~ K{;hш|^ Ǎ(Yd@xJ@A]|BXaXHc"7wZȝzjTiH|w{?CH̠m|ċAW 14{1_އo77HAĥlLmBxE3U!)DCN!Ce^~zCi{(~NtN^e=ӈ۽:?.dC>V Fo"DZh略Er U&92.PXu e ẽ.,!lȡF C첸 C~мwh-zIP]ȯb1 g=bd>/_\W ksēya@T𖶚o엺FDSB~^$PeS'UW q(d8E!&P{*R- ݗG&Pǧ1?a:#n[ KB(/6̪KMM-MM7p|ч !Wk\\45sߩo҉MUm ,|+(d k. sYY D`.rtLc'ᎋΨѣ Oso~Gv .̮rCom1'xrpdpTY}WE׽Ek͇ i6e\`|* W/+?A-~:ӕY [ܒ^]4ؽEC|QRf/ E۹$!lڴ ZK!g`Tߩ t>7շ+32`a?vٛ\λ+ ĈlUiw8Ɇ%@䠴]Kf [h_1;*D߰#<͂Sh4b-Ȟ]{v?uhݏ%m?[{(xzX@WJ#F">C#8*ۡnYOGJ9:o >an2jj/52;cvxV3Z؍!Ļ ̓vG=P^!Gh$l8lfϮoo&1Ըxo=@ƁKఙ$ (CQƊhqO>[/M?YX?!V@Ѿ=1z䨒|@>U5.[X_jp(z,蝪H"{v_{Խ5pf jew +ː=zѣן*?AiSb yL7EuSO*h ׽8{|EpNDkVr@H1lRQxuu2cј_'T!$3y.l޳碄(>Ȧή\y䗑q$;sƋC#&~S\ܦMHpw}p YD"Qdqc4(բEnj1/*Q:9+BzB:@raWϱrūW/>CY/rY>Bknἲ݈E7ćEq|+9^8Ĉ [almd|\ܦMqt :D%jHhR[ x7,ڽA9̌;7R<鎁 %\nР x5pH, 55(4RfeB/np˯˵k>B %1 q8~@ځ48z[]p@`r4+=V压pX.N8:;''3ewX898ѹN ^&455 W_qژv`~T KV I/u xqnIuECr_srVH.d_yIK[ͣǝx9fA3pb< ]_\" z+vpsaPt{˝d)d@ .k455W߸aln:h "|Ho2wtK=wo߾}/ρJ\\(鐓_srrVV^X…șph"p7fѷdr>oa2![[?p$!ݏXItp'Y􌫍 飳 .k>/f\!p$,\NnI߳}#7[ƅ('`8qD?v bʁXO< \4+8NAD_… Ϝ9~Y E Fp粣 p7w/"^KB H@Tku" 9 KHtǎ^8ۿ(Yv梥R RP hxkgtd5_+cR +V̝bnvV6>T|{w<8w oVܙ>|9Ɓg3KӖn^Z+`r"9,Q±.y]J R/KC|KHy$33bCb!SIQjVqފ[PP}Ҧk45O.[ʘd&ߔ\\_[Iq[4ାիw.߹|9>rVTt8~=-rLoL!8\A/MN!WF"Z_w- ! ւ8AԘhKQtqlر ~s>XM1xڵ4N͗*YYc)=dڳq㞍T" !+P"%HҠCr%&oq-l7zyVBFϷV*z7t7e79~!gJr#*$ 7k?*?f 8A@*D X!ESX$Wھ3 ~r#6vXD¾ GQQqљ3gJ,-YZ4n@(-ŧ%bfnz[ /$Qk1E`wGXA 2ERpw"kN,hhz<==YλLF|#$at5Xz|Ma}؊M<)9TB/ b结#-SpIaS5nё Ϸo%9DmXB+P^~)xp@4Q}gݠ 5e@@@MlEzzk=!pFRT;S|.4Bv((7w~"x8%bD[#S)~WTɯ!Pz+ 5錪 (k>N$#{z7!} r7yz!\"aA/D$ BoN2,w%l腯?!xnaS)ezG! [hh$53UO`ƀn"XD![koBgQH}&M(Y4))F)t>ٽawEpLsmmL r? WRnx:@/㶮CpY$er WAgMnJ' naFƎpC@&N"#G"Uůq䒻1"ފ2,%p A<ܦ"LA)ei*d6r\"/64y+:IȈ?! #bF=W״!Q e9䱦 w J@^7.v|l,db^jůFR 6,eȐ!SDO2%::w5B EaH#]8(8 S)G$FUȏRk0j J$yzna,(Brj8idqGj,$&L0rȑHk%,V2S& _^[G01i$~݀zw=ȓ%,sU̞\' K!R`@nHI M, ㆏4[\PII e[k%__7QQʸqQbgx 8Jf,2ޫ y "6,?i>&6+wS 0L4}ꩧx`T͢RNr`I·A(. cb\B6B ̛ Hy9W^5nܸǏGE1a䄑e93d洐i!M#ys͚5o[Æ 2:$]@yp[OʙK9~cyH@ jxX?q*ρ+^VH B؂$"8 "2od?7@8^ $ƏG1}֬}ca`@d̐i!H;o5k~#bd汦 _^CM_E,?8&wK/:rHu*G;[X . @pmmsM.% @fϞ7y ` dx@ L {'읰~s͛kz cؐa(Tc !z@Pӡ]CS*@LzJ .rGH~*=_di [P,{@@e˲-@kV/I+@YHy pL{'wn@e;K ]aD\lvzAպjUR H!@y+}N! Hbb``*l]U~w؉<<|\$qz TY ZV ާrB9[SoVrxt:hCb!$,=R$ &A$!kT ,XOý!9I$cszA$Xbgve$\/rSY@)^Ŀ; k<̱wAASc 0!` #lȾ$R(Hs "?9R@ >cPx4N51q=\8-u%|-V1D"YTiC쭨X$ V_7XH9ٓ~|HP#Z'={bg0Vpܮ-%n6Y *2j}/lȍ|ջGedOEQ7DVz& NG% RXq]n_ނ^t%Ws=d_!PmӅ!a^kHCѥ!$ȸ&ȑXHLjgoXl^n_F:?OfIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_400x200_fill_box_center_3.png000066400000000000000000000632511420147000300346170ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖cdIDATxܝy\U)O]BID! ZPxAEAeBB4E!GLP@/9t͊3Z)uֳ }"!ƀl4-Y2ٳgOF^A6nܸqB6qĉ&L0rȑ"{ ̙3gNColذaÆ l*w6`O?ul: ၈@DyL88 <͜9m&;Ǜ"! Ȕǻcsg$d@(%s̙3yy <@F)͎Bxp *( X cI!@+/SƏ?~Y&W y7BD4uLcy |( #BƎ`"YtA<Do<֐aÚB<ఐ_"D1cTC c=.+#ʐ.xK-Oe9)'ә db͡@& kS!X@:Lk2yVG`$Fs^ѱ@fDgSW.y,A!9/:%?)cP1 s%K@E"X9/D!*dRk<4ZP5LV 5! 鏋 :OFw(=֜% kqb! U*iJHk1 tN Hzt@T&o(yPBx>OP39T!XΫ^@UBUM" (d!S+)XJ&2 Dc5b?Tx 2( e](T Dy D"^ɀb#B>#ta]A  y  Se]'uXF |H1BE B>ǀÒyYۊj)@8ׄs@TAB-ߘVs^&1|M( dC5lQ_w;,./vMDwڊBw§X\}Św2t@ڊʐNx+弝Y!D^)dBBސEW50eJ$뚼WlQ'"!]!&jExծ R05LuC O`[yeaQ8ABdR:WC:<? 1'Ah+1U+40k2MB2imP̚0}pdlA//L$R2 *Cѫh.T28k",TraJbɪtV/*Df pXrȱ>? VWn%LV )>LUHϱ]ןdODmK.ye`D6b ],ʔt40+[ r*Ŭ ͱ2()SOR>Q+G%&*ʵ' ?0y">S ʅٟϚLy)wu48ܦM=%Z<:Oc eNr^:(|C2~lZa T7SDOn䱨@G'XH6\$;=>؟<ɳҟpC%ŒM-uW);@" dGD@!S @/.zIJc8~^'k>|ޓW1!S;ĮJ1iThdSB'8 ʧ7|5I)A4_R, FT6vtTx&Ea$FyB"|ƋQ.39pBQ,+#>Hs,bI0*Ca!@$5:E(qP/o $8ã!]}քڊ[H?:<maSSB{'Og UI8^68|{/7|1cSB:[)^VYB]9_-w[5íV322*{04˓tCI'|`*"c!=^M{/0b"ymaS"qkD4SSSVHCz D A!ɳ5 ^"Yc2>F(n= ,(TR++ ǚNyʦ 5M:p<L&l--^^/Upǖb拙eypCA^6bu4=0ER,2#ɘDzehVy,@7y GWӥFFz7/$"QɶTqP}0RSv/x/ljjBff X!# 3ĕ[[],uMT܂B@)n1n1u|B^C{uQSsDHKט2ĄkX32?R4\rMz#Q xdtXܮ%bhG r H?~[LLd;4tMLҥS {<ѳ罛2.)hyۅOTM/ӧg&=XLlnj@DN8=vcFWYUJp6|#&N$[@i@/u '"V-rqpV"-V$m򦄑B$ g{zx` 58pW(i<(`O!E KjꂈMIp=o/>?O+9Nj4IB:ɓ33O#"G>=4Ϙ1}d9 e?_Gze\qcǏ7k>Q #_}J^+9dfȴi!HB$d1{:???Gj7KKS^zQ$pxD$ ð<@"cdKa?})>} p$9`?qLXdHzrGE5.*v\O*.F?D$ xWŎ;k߬}&8qb F,j%GIHINA@!11oڜѣ[ }>H@$}#OV(: *ʙ>} \V߁: ty}ril~۶1 ͙7oyfM džq a(P{lfIHHBf`!1X!Uwjjy Q!<0yP0戰'!}!2o?~~@$ EEE#@>JB00yK*uu̳$Hll,m,-'LY7@ co?&VfI&@ De]/Cѷr'''[[[''''.V7+˫urKkK[Kd?*۝KUzN?n+ǷW}EoSVղw05akiO!@o߾~uvԂLƵej H: bd;VC[Zl8`&}-^P.43$Deee%N_tz쬬,/^o9oF??U~V _vGÅNV^@(*.>S|26"y rJΏ^WuDHq-CW>⶞ȳKCH{{{JɖI"^'/]20$\Vvhe+tfggegJcB^WHQ3gщ_?&5oy+MV qLwo~|ggGG~=l$!n׽P!ΎȬ=;WCh@"*@Plkt%U4#kNNB }-铹}[O @#!!?X/HW9,1?@mꌢAB"B{@;EH߾E W/^ܿxs)irB{d&W U2G )D'! [+4Y׶E$@v$$A;~J|+N$ QH]!yc֭ @ sE@&[ tw5٢8ܑ: A_s2 ]IIu/xQdƎ(̻{ٳwāO;s *)75&8ă,;R\A"Ύy*/-N,lJ /^|I1y zKMWPė7ANvvfI;))=)="Km ;0 ;ڸZ5,3Ĥw>+t]x[7$4$T |{C!Ng<vqY@_g> G[2,e~ t D#h} a2?R7$º*Pҕ A%V+\+&Ih) Wғ*+V7ȁ>v#F}9,=(ن2o+d3/@"R:\6RC]?H-I"?"B گB1|˰ Wz%Eg\dڤcVOn wrz|={h= 63bKDTq0Dz37+N: D&ܜtϹΗx@Z,s+P_| U9җ ۭTHd5!cjC4=zWb@DR0hBd.+]>sXesۋ-U9 \n>:BD !po8D8J NO^& DH{U]mBd),L7noNLWB.NȓzbxEZKl: Y_ZϲytT 6ъ)88>>>#+xtB!H-)X!X""A6N ,n* &Btfx^X)?uj1zuHH  c11kw“ӭfNj;c]^)r\iSppprrr򺘘ۇI(^vE:Zn^eHOcYX񽓛_3=&{:1Mi/^f$ژ[ !]BCQ vT Wq <Ή͛q#R羰ONNhuFU푑H_B$^՘;=Pͦ y q23ÂQF!(Jo*LkanηuD!\_"ɭ| e9mjCKlްwnurOA!H"Kud/҇Yh0 |'ZGD.DAmz>{2(YOAMI2tL"H-uB11ߞV1%.X7^~)o.F3utHQCȁ7t(ɲ0=NWuR0{>.56 ftAh4]g c[R ?5 TWycSQsZ.s 1>QɳRFe)aO;x/ "ɬ}k%2'!DeI+BtmIL :!temްylg7a |kШp"7t*kBlT<[ i"@ͭ:KI+HB@cB 12bݻ(:6_Fr6($ x|&,> \VaK"r>K{(S]@z c}Ev;70L?‚N$[$_[8TtVlS'>6&Y2kDR!|Q-*.Ẫ2uvvX!=eStޝ,,ZCDrYVǀ~ױ_KbEYVڊ+/+$gyG[= `DD+  tٝlAp5P78;Quڑ!6@0&fV:v Um0`#s(+A9TWUxA1>{8xt5X CnwGqvҎGz2DD) 2 BsrE>,Z=W愈,+0Jdndd%!v!@V9sGq_)dsi{j'"|]KL{TjުDz!DH  B/>UdT5ՙ ̂Z] [;;ǀBP7HJJJbmEEŞ=V9.ɀD9{M=E=QͥeP-M 7K,#ё+>Ú.᪬p+/^JZMZQIR\PK&Ẃ daf鉀슊lDdV)kFyYgsCnН\X#C僆eXDGxuݙ$AZrV-ģBk*4 (wxŋ[[2RkU+W(<_72Ժy+6dh-+3O~dbD.nNԲ;z;,٣GREx l.--PiP}iqY ^S^pwnoo\]=\]==\7WWZD_yX3QG. @WLZy]9uj=6gEPر3Aۤ> ;͝vNNfvvv`II[dgggWWlɮή޳4rŶֶf7B!±!<`vѣG۽eҗn^ H}vȑi9wd&R~ ZY0,G3L~:v;}?3)$%3A9DYȩSn/ra ƮQ@/,'a05R5;'O['OPO@@ G L"2^G$;CPX,Y,D88HN.DBB_w__h+vttst.emm8P*qu!5J#Sq?)ƣ 2Z;'`bGeFtcANKL- ]l"{E,cF}AU rHQݹS_WC@ GPiСC*=pR!2D×D 6eσ$p<'s|H7 tS-5M*zSdDbBp v('esfgeeg{#\ܱ};vܹ "\3K'/tii"[:r8|˗A8za@/)ő1qd8Q} 9#*Jz^/ #HژOb4z8ۂ$p<ѷ?@"9yC'{0 тDiQ&vZ7aDb<>X9PYbb.YsƍFv$MS #&wYAWvX@ =@8׭[.9aFj##SQ`=fS@Q]qs)` ot $$F\shmq@~_81@*A!cGVV={6wo+a`%#P..1P\\b\\1>>H^BabC@R}XJP<J ,zC/d@(l) zt$v|ͧ4[)W`299dBrR,X51跑E\2j_Z'mf\`!!!pƁDGD07rtΏNM8tÇ/Yb ,BģSQ&i@ @>ߎKXdAbn%1]ADbP,Rff< 8Nǔ} 3A<撓d͛42o=*H,(deʕTq߼D!!pO0Dȸ{J| H>R,pH*փy3,I9S fvfL gVRgp/=i⅞/d쓙 G]~rmsQ~yY)Z>\ʕ+f\sLݽScU&q "7yb 1)#- $::5 $ 2 06 #"y3|#8d̎?̸Μ[찒x,[%\e ݕrJ> DN0hŬy (8 UFC*)$lFFƁ?Ȏ(1E 8|QH1|:/t)CuDbÇ@:`_2 '.ɂဋI 9|`A!(۶G]HG+rg]]Kq6h珞 qX rYk9x'x1/ѱ 0 Qf½]|yf[A'z˲9ʼanz>^mP 8˨XB2@2g=p9#$K|RYD1n%b04i/FTV(c,2RVHᚨ%%U~$5@HK욤@6N;'" D$ňpmNcy+FeDSB@z*0kT`anQQV_XmL# |!+@5SK&&Bp b1c:uX &%S2@B$G8pď4Dd)a$$,읰NJzcbbPʋ]VģWiz8V(U@$dn^QǣWW׷%< bL#! Nj2"ҒP A` yx. <p`&twBxP)))Jh+ױ"'+pz!U  2 Ĉ65W3*l$"vC ` #i :,NGYYY\FxxH!Q0D6mHKK[ A$^>Œ7>VdKRikM.\!8)zJPW;HقF슶`HT*`+uKTbEaoMz80 HWԈĸmI>@&L2H'-b1O:5līRɋJB\D!Bji!$ ytuxΚ$$Y* KY %㡈H7I@Xgnna.['Y%Uf̓'@>9IXAg=x`#[CxO*+A[ŋn}y/Av}*v;\BAǒ)Hƅzp𡴴4!`A!!l^[9#tM Gm>Nc5_bXguH!-Ǟ:xgUt0j}b+(.&? KҤ.uYF‘FH<غGLj}ɼb~\T8pttL, d%K d16OR Iywb ؕgE#G>:w/$xaz1.>.>8888x<-( 4-1رcX_udeckDNĸ"I!mɪT}-0RkW=ܗvsq 12h9WA vE7f{""o20"6" Fxk5 j^Q]&uIV$ 7̨l6ǖ- xս{w>ۉ@`z;`Ep m͔"M> :J$q₿`b?HRtRNk- 83!R;EBV$ h45 /WGPt'|wbVWV} v"ݯa|՗V#"; W/9+3r:v%@zwL&l<.McO=#3$13M4bvOS̓JDԁPz[*uVr"dL=qHOߵo QH(AHvAD9+'1$Z_߸Cd |`:('ݙrd4=/J#=c^xQ"v{^h55Wo<1ƍҀb9p\VpTEs;C\sq$KAKY!zSI!aHܑ/X(Wl=,yKFy & S=p{h;DD۲U";')WU߁1C?"|ʡv^B|?#⾠@x -;z|!| tRSSqaJK$XZ:RswРA۠2_PiBV }߸Prc!\m,/\ >FHn#+pW.[u5;=3'r՟q]@p[lF|2Ɓ?qU2յ+u\{-+e<8~aIL~$(8>wTDM7:XTDHf/q4$ A߯X~EBrp\nP2}F ~tؑZŏs BD~-?PDLl٠x_٣ZG@zw5Ɵ<#1xQ0Ç-FqG#y܃,"zK(^[ bI5> r}޽>|/,\-0 /B*[lۖ5Z{9oooͨQH ݿtj8a&#WO =Mz׮x:_'9r#G>U`2 :]J|^^4^\Ro" ׉ǖY3eÅuÿݻ;σ*iUc"yDR]a'HmQAtdrtg $շ=?'-776GR۵%hVPX"aa|y\4&^7U5^b_EH"EL"=沀A:ݝSAp_7s=x4&YȜ- D@w!.H;=eNJk._}ٳg FEQѣHvջwȦ#Ȧ/yԪnʞ \!-vW[tɱD:2{t{Rx+F◐d;e0d(u R g?g-980޵kWr"M駟~zS篤GT+ýR뗌8oSᢃD9ZsyiqdB7H_R{u]9ߋwMECyteYC'y{߿i6!y9)7 #.fgi7}zO?k o-:Z+Z[{ ;ɯZңt|;M0"4 r^icH˪헆1^]VdoaWGNNNL |GHQ>,R\_?<6)Y$H5"Ugr ?or6ՂBhGo rċ~R?cBPȂҀc!ͼ~RC>%EP~ɩ3x k˺Fy!>D!1\s "e B 4M !Q3tLH}x饭 „%X!)5*qd$Z^ʀh4w }Å+^޽U.H!/'Ad A1DoH!fQK!ӢWDVoȑ/ޟgN3@9QȱH!ީEU!,(h$0r T{V(} )"@, $~X vojv(Bֽ x dźL!Ww?|!}tXz bH#sw@PQxE:*HYvNNNH:XA!˒+d1d"BB ަHguJ\&Ⲑ"Sj1aS 9깅uvtĕZ 1沤E,%1d <xL8^3S wCPW!#=cea4t%?=x;V&.c)Yk$5^91ͅZ*fYdmoeюx4ыg@PPithhpK5H7.jA ]Wo$4<p/%"D"hD ej:YP'QgC:eڲڲZ'/uk!>Sʊ!S!RtYa밆vz$+XҀ¶2%=֮]ϝ3Cts"1deQHVpPg1D"Hy;NGR-!8\Nt- /)˄dvD,U\H\4 ._D!Ii2ԝZ,; dIݻV T!4V J+u޽$1LVVB ,-й 0ԝ;vYx5(l`k/-VZp߯Qˤi9Zp+)=} L!?w?J]:A@ %t,R+1u^!?РkŠu!b%!R 1O0,]IE.QS~/_~oTC9"@RS$dw5뤯b^!Vh)y.KeGQ" WC,"X%: xjB,0$ % "H+R| CCYhx}}_P]_qƥo ۠~Rˬ~eby%D\c.KB C貤0/ORsn/2eO <ùPuѐB:,\hB}DžԌ-* T) ՆEn|ǿ>$@h譑\w}}EyJ@p+ϲ@!@_J]-BXޕvS{P|ʒ4b#k\&/@&^7uJ |ށcޯ6!%zT_43cѠ.ϲTXίyooexE,T4u??#ϲ׳B{zi ^\bdEC@>{( XunBb9A!,_BkҊ!!>\rA>I޵؋i޸\o2Y gYqY&r"~ K{;hш|^ Ǎ(Yd@xJ@A]|BXaXHc"7wZȝzjTiH|w{?CH̠m|ċAW 14{1_އo77HAĥlLmBxE3U!)DCN!Ce^~zCi{(~NtN^e=ӈ۽:?.dC>V Fo"DZh略Er U&92.PXu e ẽ.,!lȡF C첸 C~мwh-zIP]ȯb1 g=bd>/_\W ksēya@T𖶚o엺FDSB~^$PeS'UW q(d8E!&P{*R- ݗG&Pǧ1?a:#n[ KB(/6̪KMM-MM7p|ч !Wk\\45sߩo҉MUm ,|+(d k. sYY D`.rtLc'ᎋΨѣ Oso~Gv .̮rCom1'xrpdpTY}WE׽Ek͇ i6e\`|* W/+?A-~:ӕY [ܒ^]4ؽEC|QRf/ E۹$!lڴ ZK!g`Tߩ t>7շ+32`a?vٛ\λ+ ĈlUiw8Ɇ%@䠴]Kf [h_1;*D߰#<͂Sh4b-Ȟ]{v?uhݏ%m?[{(xzX@WJ#F">C#8*ۡnYOGJ9:o >an2jj/52;cvxV3Z؍!Ļ ̓vG=P^!Gh$l8lfϮoo&1Ըxo=@ƁKఙ$ (CQƊhqO>[/M?YX?!V@Ѿ=1z䨒|@>U5.[X_jp(z,蝪H"{v_{Խ5pf jew +ː=zѣן*?AiSb yL7EuSO*h ׽8{|EpNDkVr@H1lRQxuu2cј_'T!$3y.l޳碄(>Ȧή\y䗑q$;sƋC#&~S\ܦMHpw}p YD"Qdqc4(բEnj1/*Q:9+BzB:@raWϱrūW/>CY/rY>Bknἲ݈E7ćEq|+9^8Ĉ [almd|\ܦMqt :D%jHhR[ x7,ڽA9̌;7R<鎁 %\nР x5pH, 55(4RfeB/np˯˵k>B %1 q8~@ځ48z[]p@`r4+=V压pX.N8:;''3ewX898ѹN ^&455 W_qژv`~T KV I/u xqnIuECr_srVH.d_yIK[ͣǝx9fA3pb< ]_\" z+vpsaPt{˝d)d@ .k455W߸aln:h "|Ho2wtK=wo߾}/ρJ\\(鐓_srrVV^X…șph"p7fѷdr>oa2![[?p$!ݏXItp'Y􌫍 飳 .k>/f\!p$,\NnI߳}#7[ƅ('`8qD?v bʁXO< \4+8NAD_… Ϝ9~Y E Fp粣 p7w/"^KB H@Tku" 9 KHtǎ^8ۿ(Yv梥R RP hxkgtd5_+cR +V̝bnvV6>T|{w<8w oVܙ>|9Ɓg3KӖn^Z+`r"9,Q±.y]J R/KC|KHy$33bCb!SIQjVqފ[PP}Ҧk45O.[ʘd&ߔ\\_[Iq[4ାիw.߹|9>rVTt8~=-rLoL!8\A/MN!WF"Z_w- ! ւ8AԘhKQtqlر ~s>XM1xڵ4N͗*YYc)=dڳq㞍T" !+P"%HҠCr%&oq-l7zyVBFϷV*z7t7e79~!gJr#*$ 7k?*?f 8A@*D X!ESX$Wھ3 ~r#6vXD¾ GQQqљ3gJ,-YZ4n@(-ŧ%bfnz[ /$Qk1E`wGXA 2ERpw"kN,hhz<==YλLF|#$at5Xz|Ma}؊M<)9TB/ b结#-SpIaS5nё Ϸo%9DmXB+P^~)xp@4Q}gݠ 5e@@@MlEzzk=!pFRT;S|.4Bv((7w~"x8%bD[#S)~WTɯ!Pz+ 5錪 (k>N$#{z7!} r7yz!\"aA/D$ BoN2,w%l腯?!xnaS)ezG! [hh$53UO`ƀn"XD![koBgQH}&M(Y4))F)t>ٽawEpLsmmL r? WRnx:@/㶮CpY$er WAgMnJ' naFƎpC@&N"#G"Uůq䒻1"ފ2,%p A<ܦ"LA)ei*d6r\"/64y+:IȈ?! #bF=W״!Q e9䱦 w J@^7.v|l,db^jůFR 6,eȐ!SDO2%::w5B EaH#]8(8 S)G$FUȏRk0j J$yzna,(Brj8idqGj,$&L0rȑHk%,V2S& _^[G01i$~݀zw=ȓ%,sU̞\' K!R`@nHI M, ㆏4[\PII e[k%__7QQʸqQbgx 8Jf,2ޫ y "6,?i>&6+wS 0L4}ꩧx`T͢RNr`I·A(. cb\B6B ̛ Hy9W^5nܸǏGE1a䄑e93d洐i!M#ys͚5o[Æ 2:$]@yp[OʙK9~cyH@ jxX?q*ρ+^VH B؂$"8 "2od?7@8^ $ƏG1}֬}ca`@d̐i!H;o5k~#bd汦 _^CM_E,?8&wK/:rHu*G;[X . @pmmsM.% @fϞ7y ` dx@ L {'읰~s͛kz cؐa(Tc !z@Pӡ]CS*@LzJ .rGH~*=_di [P,{@@e˲-@kV/I+@YHy pL{'wn@e;K ]aD\lvzAպjUR H!@y+}N! Hbb``*l]U~w؉<<|\$qz TY ZV ާrB9[SoVrxt:hCb!$,=R$ &A$!kT ,XOý!9I$cszA$Xbgve$\/rSY@)^Ŀ; k<̱wAASc 0!` #lȾ$R(Hs "?9R@ >cPx4N51q=\8-u%|-V1D"YTiC쭨X$ V_7XH9ٓ~|HP#Z'={bg0Vpܮ-%n6Y *2j}/lȍ|ջGedOEQ7DVz& NG% RXq]n_ނ^t%Ws=d_!PmӅ!a^kHCѥ!$ȸ&ȑXHLjgoXl^n_F:?OfIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_428e769d14483c2fcdd6f5c5138e2066.png000066400000000000000000000564671420147000300345130ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖YIDATxԽn$ɒZmV?Havk%(@)H`چBy q.,ffd,u>%s{YS+N3iN!e^ꏞCB[ [E_*Nq5ٽ՜0'9tJd>z'úղ|<ܵǯoH$Q(1CKf"п@* 2caFmo4ԼJZ{~yN,9{牊jV^ԤI 4ln^E@XCtFIe'?R^ 7~KR5T;̍@EfVѐL*5an d2i RFz#@Ȥ|醞&#v& wDd8B%C[ӊNȤq^տ - (F' ҍfJ]ܤ?SN}gX[CmP|X')r0 n?LV}sE87Ď zH2a2;׷! rYc)9ī|<G{b VV# i$3Z΁G%A* ;Cb4wOLP_E$,C]HH$vw#?)M@͇ଟĽ&{7CW29"N=@0ɃC' >J5lU#^'v^>DCNC?^=傖X>D\,$Udaysh:+r"uI.[ރ핎Rry/v\n>DiL0 ,J " duxIKB,- QseMi~#,΅R]/>?3pbTA/!iw8|>%[ -[FN)zn2gʻFYr/,~aL Pq9#ޕ݉EPL~d˔xD'ܻ;g6/b乂[ߕ{T AAav6 px{R^;{5=XAFHIܹwGFR8vt+1+.ɆuܝR\Z(/&q{T$ut#)r$E9Y'LW .5Dkn4j3_{eoLR0cϽp" jl=֫Y,VGRݸH/78!jχGUٙ,u ~m/ iz='ɲFnV(d.@dZ ɉ]UR[O@Koŗ?dbQ]+ޤ2ezDD!{|p6r{W6˵2qS'˓OӸ?/9^A~W SYų8,]KE)x7X٥?B{qpu]סdv&/;sǽ{'>|X_×>eBJ>ƊV7oU$QxF-HpDi:1X繈2wezRڃ&xLyS{^w{򋧛 -2[5'62giV$1=AƉru4y-̺N?uϴS2FV DSuv鈭V(HNaͩk;$݇9W/A~a!ؓ;^A4c?<\7gآ5ܬk%scf&t8,BUF[?.06u&uӮZO_δޗ?S:G8f&e!hII~4 :$xW3{r;~K^"^}G{wG8ufb[nC{ԇbCZ}G\돖Bn 9*s: Ұc,y6u2,ðɅ.T\MIXC9'&_ Sn IٓGL zYy sYwA ځ^iK.Rr6?<_OGF'HӍQ^#6pYgA;gy. k3YKU̝;_ƥ5PHx~BF]re;7ȭAHvYK|i߅eύM߬D,՚(3A5d ;R8X dzҫua̡֥<S]LCy!Bt _6 Y|۹T4 }z%?S_Gv):1N48];^.rК0r)$J~Haϳ9qH(: VZ@!r ?rlФC a֑}3O´: nH'+3'IߓO4՛]@ Fvh"=Vl*3' df0Ia^zX|RÒj,ek-+M)d,R~EO?k/-IlD&gGa'7%)qB+-H5y̟&Υ7%6[SrXG9~&r&]-y/&bQh!,B %3)ɢlodNRgũ"Xsj$K0B܇I[Eo٩2\΅rh_j]HeׇGr(LAWsCst'!KY!"Ӫ>T=ʬ2ͮT$S() ½uK!Xs0퇛"zyȦw!c66oH|AUQ$~48+73 }-Zp%h2gKoXkZ(38@[5j ۮ2%u;l @ߝrhh/|e+(i,1fr.vj%>&"~6\F2M{;560Ҥ=$RNhē }.$k{`&Z(`dFfKF>\(+7(JHaoⳔ<45}N5R@vK |d'`%yi!X:U|Ƴt<_2k_'~2¦ [B㨌i[3h֌ħ@tVaF ۴xH&a:: M_k٫ + ,1!ď7%= (>+ݿpxòX&L>\cA#WVLߤBBBza\L4U:{E$~bmn%N2)3jk S YGk)U,LCTA)+ թ)ͮĈypzR4&wW7gB; ̵DՌLMںK%n^CK/9^E 4d'9v^EOY<6C^ȝMGK2kgot0S^K!#D{5/. rmjf= ttER_= C? A&7iER?Z,%B;0+Ƀc߷C!O"UB\_#།] (⩂]Y  (< 8`B fI|$6EH{ lm,Pg"$2¥4X29}+i0yt9hbJq ;陂J%2*}ei[E4tmphCwwKuJ"3琦E*$=xh/؉$0ZX;Iyֱ:OG=*G>YWeSW`y=B}O6e-&i8aOwSb4:8^vNb=HgCcWYa1jWCo& [EI ) Vq,wa]XG-[9q,:ҡOPoQ7BvG8))E vlgb='sU2 .4HT3&@,hiNmg2!BZrNE՚}GI:<;|ju!E ͵.N?( ~#w[BX`=ROdŀr_knNEsxɹԨ0 1kiğk R¿'q rxT8hwKJj|=~K @$Ҫn\|bQqpPʠŽZCF>&SrTZT՚7r [E%U#:!%L\!YK9شRv݇]X2ۍo&4dgMC֔4+:5O1k\S2|5;QۤqH֝ǂY\{|r΄LfHXN~)q [;62#H6mNre4O9 sŝ<'˄}E~_\uw&m$5)r*y 5y!VI²0ex1-W20';dZ#&o~C3:W)d/mBX6$w6hX`x$#vD۬}{fB0g,CR3#roL)Os Y+95rau*sOdoWKْ+\: ul Wt<{Ӛ* qt疼[ s^\T+&P,01: W ty\^OM},1FJJ.y0[L|ޔOʱ!NMC / e}$0}rԐ^oO]̻j=q7/}&>:c,ifjdro?)5͛k㪫4DYD۷G@ѥjUMC͹'x@} y52 4Idg}/?]LNzc`'`f"oBED:I8KLDtIsjx1$5֐f؂ SN} i!WVTCtV secޱs$tG.06 *LE&Δ4 | Wo3.S榎d3a9dSh:qRTAs?-x+dN,',K=wRY($s}YH d^}{e:8"}1+ <] DAd+0ʝ|X(?|ap9,n{CʾmQ.#ea"ڱCr#8sB±법R.mj7oݒH|ȿqMY~i{hjb .&m((P'&KPE',׶4)Ba~df!~0#rdBZڴ2+zra8MvN=B!*L&̸f>Q`L4 jK*OD,C=.`:Oll7S,'EgdI&׏8p]qD^MGҚ$ i稸@ 5|5 ɛXq0 6$Œ)c9Ӓ~!n-6b9;G5d)N͉\Ɂl֐b#nUGڌj4r+\i 4+ߜ- Rc4d&B"R'zr\4{]Lś.0fG*e[4]wPb02p۞CۯiHp5t /H u|p&G&:^L L/CKûm$Zmk e:S:\8c\Ly4J"*_DLK4Sv&k' Zg=Rջ &YEhyN`6kFC윺`YBw= :}On1ߖRZ&,bm[fFn!ZIne[w[ WKCA4m&{A3." -#jEAp %+ 2Eދ]!qU48e !q' ]7Xj}OLDk&OBԱɭsy ZDb@6-GMr*eH%vH&ws726W7ʅ!fC~v9.[K>`AZ-) cY*RWBn  E^\DZ(__}\YdS^q4|=d#G\G DȠx&RrzI\nLRK9*c7C>xѦ#E1KC#=:dim O @k1a SCNsNqZ|ҎY?iޏ7v9a*NqJ϶:Ur]s։TPuJjʙٔvzH\T`˔|y;' g?L-@h'-m˒ ,7.?ZD `M:%BJDE1KJgKeylwYI7-$4+qә B_"r@CJ{%_^ A`XCԸS9pY۶?#8uelg8SAЙYhx򜨣cn^_r \It Rb[ Hpu*3dF\mז $Ɋ[if!xƘ]nOawniFCoDx?9U/C@|gg¹7"1J鶪sucz)޷q .@6r7 fƐ=4tm:w#s2NpDԺ f T䲽_8-W>p>}ݸY([mwip0<,xGv-;HV-9dd.`ѥotvmqZ?vK5,2$uҋ%RU-ԞrƬP@Pb#=c7gtW "{Vg!x9 %kJMbg_wikR. ]O伕?0q*c&VaYe5Q6'b1=VsԸUh9ؒi3?}±V>jYڏ* lYX)dC΃cȒ%0mKf?-Qv<4Ӎ}-nZY/\{k Kte&3dP(kpYEW65q|hҖ>$lD喝Iwػ0˪Jphzpx1ԳX2JE)t_&W* 1]V>&>Y͋M[v}Bn t3PDAWB=>٭vUx+OY >ͽ/ƻڨ!M!,L4hu'!]yfFLYzjTͶWM}ȠA?t b,4ęIHj}̩ n‡$NgD^4߅4nXb)[f#3TZL09IN.Ћm}FѨ2㿘uZ]);A|Dm<ʼnu8.|V"v% R!_>9^X0$o|j_OMlaQ&=Y,52Be}ӒjonP Z| E4_yRzR@MIYdt;cj WjJ X'Q,5f:q"Q/I.s7yϭ%3r wdC 2߼hV𵳐r )ęhL쑣^aXR兵D7ۑ#8zo56 "(ŤIad)F!۔&KV4!MfGY դ<[f!T5-;IHIɛ+5sN<ɨΉUX>ț5i6ck_*GAȭZ>w\hLj#UL[F1HIijdVFPMpнlp/,'e/_NoQj3 8+3N-3lș1[]}tG?Qhh"cf#_G9ì~u5D;PzQ-TϯgF_JD6Ic^HFk tη)Te&24tudbDDΞh _rA7k5rd-0&`qwY=Iɥh 8tz( DI e,*+DW%e+SV#I5_d[BHzR6R$l^?$ !e-NCfUUY,t2٫usD[2ٕ\Dwv, +Mq3/@2]U ,(,9(W /l֛ AT^g/r"56;fGDiQ|\/R]Ӱ.E'eu|/Z1q)8ꪴmIBy/Cą&Ef%:|maYf_wE$G㉚t|qhq1=X[!ejc )$hFL,2xA$TªޕhHJ 0TCGI axGM*a@EDGg{&ߡ! :>)zZe1Hfg]ު<(M*Ӛlh=zK'AxI:ک -u{sq\J߾1q{g9ZfT*ΕghH7|7}~$1̊BBE%5j:Ki- VR6A?<_:"ILmF`kү{2vO} j ۚzL)@e XQNu wUStVR )*0Ep\QZ3Zo\]l=#iҔ(z*ߛ8,V J6HU`1M<j4G^ynOZ'wƉ/~r|JI @p_z~_h%0#z$U9kjKQu[d϶jB.~S^EXB.LՄª>ij؂cL#QC#>l]S<,-Ixq^G0LCD}[5z!" % $krVKl-bZKu%q1dcI̥Lx)D9|f[Dx7oHk\6Q My=Vt4fON Z{"FO)]׮&xJyI($S$!3.[VDhfgt#"%B nF꧜Eʴ}rǛxBgR(Y⛊&ShJrGtd {^LG}=Fޑ.U-P7nR&ۃ3o--suqG;:xIķyLiS^.XM 8- >,+E`"MW.$ϰ1DqJA۱7Y^ *L$iю& =άzRkFW9},: ,[kkz,5VV$d;bCyE>GsqʎhV2gwϾIDcqAǂmQUWtޒ.Z݉Ιnm +7+s2Jew,]cy,U\j``%FZaͣN8kgj(Yޝ#\i2OEu% d}W=fij\|ys9Tb ./tu ~Z3><) (eB,y֒&uZdvJ!JLpH/N(u#%>uhCd<)&_w 7k083?f4QxL8Խ`΀R۬D SDR}^7!X0Rs?qԤBtJ"]G_VWn6Wj(?(@maNY$+NAO.-94!ƤHĩO TM7RO8V8kOi6v7n`\G$z'XS,gTFB/^nQNrR`rcb8Q"tA7nQ(":ƾFK#mAȘEV_;f6ߌG&@~ VO)r* oҦ5m*;g,MZtt_V+3t+R.fR vM <Zvq$BΡ$ ȋF[$$;-V ) 50.ҙN elj.KZRX_\7M;ZmucҔYerc 3Ϥ!yZI0-KThQK wDDͳ/q2f4YMPϓ'uFat'aBdN I B 4a޲؁(L1.2BaHzCtQ3',/( $h-2Yu+x& 7!ҡqy+ŵJ_1-"*$I"ެR\15OU7ƍd [A ֪UAGq\2MAE4.e؂Q-j˽!u9` I0Qrk^Bn$Ĝ]VI"|o9*u<4Y~d̄W˕\]w>eJўUY̬W]ʱ!l4&U%އ䖶<vvKu̱T'cma_Po"GD29X>TQG rCa-cr.Md#$Qtrt@EYY?U |v2 rE1\|yVxPW͐$oN61Y.BgUN# EB:/Ĕf=J'ջYe1O2 B@g7΍*&fY6|r¹J2LibTI>̏pbȲv%5`43j$?JwO^C]ȒT@*ee,佴Ԝ{ѧm0r" ub)dbtDQC(e : 94CLm/1*;AOH2m;Bʍ50ڪ9!DQhd*4V5qv#rKQ&eb^Y'B\&llu s]̇hQʷ R"@B~ eZN7Q{BEMk3aj9$Yov!-1s2ͯJwANN9;C2!ҟ fy-("3+,΁G`WIǞ=3u 8ȍHPUE?ߡMR+H9"sr XheNpmZSv*!,eK]4*ڼn%[$f-&\K%/I#q'`Kƙfˣi?&>YP72r$t*O]SHєe< :>)2 b!>O"y "Hbce5ڱ$ee7cs]xGE<$ Q-:`Wпc*eC<4%%OwtPN?M'h <$ FWolQe400,|p$٬wr'؋[U 5R(-,|7F {rǎje>dpqم{NWǥXe)FՌrjk!*1S41skX8e ! AfgeWzzsm%r|8R5T PSu64: eK:,y O2,BL.C./sXs"#Y)f)#QVA׮IڴfMNSޠsL=-g8E|)g]Jf;iXޙQJxݘ!Ɯ:9jiVW[z~C)Sf)Ƈ@?#C/ʪ˳ =TG^ eKLIgELCTCƈlDoT$ee6-?avlˡV<$IR>2XZ&kdsĪɇ&lRN{v~l?a1q. O#RX5QM6CB_/CXsn` ΋UHAf 1vdylh[OqΙNZdyM][P4ˏJ5":vUzQoJf 4 B1'QM}.4đL&>ؼd(j~*!9?`]jnHfgK5EYR1'b%v*yreCs"·Dƈlذ4.ma)RW F93Kw#e1q\42TΗKtH(=J!nW=ƲSl3P 5rY|7D3&%z,KAdz^?SE 'Ȏ@+Gi@V³Y͵i⦜{QGKQtȿ)E=d&wmZE?i␡v&ZZNrEzZZo0wфlR[$DЬy|[Kjr sV]߽ ^ڀ$Oo>$;ؖ"%U ^mXՙGn%)!wTP 6NCrJ4^oEGʡ䂭!1idx~#Xu`4lS2+? +F7Н,/'.kC۬æ`PM洉gu:ګY; #kzd;@By8i(gan;gshzR"V'gt6%VڕMe%6wl# .P*C&+Ew)#w9Vʺ\_Y57|IT)`_'J׉eYzC(e"Yg*z{I>䮈I.T֚eAӖt7$ ZiApgߞ9d|$rVŭrbo1Et](5KZ@,|,CYG2Qƅ ux8"YYTk S 'tHRraY 4 `'C6[s$!kɹlR]i6%0,VnCn¢aq Y (1 7آpW8ބd&5~ݏq? 阑UL`1ACQ;2ZLWjrä?,<GvkE02n XHqlnq2l(QQV_dm=yQAzjWAtXb=Ve %HE$jCjI☖DCxA?8Bm.E1h%˽ z%}ܜe"2іESa1Ϯ*HnKbă,oV=nqMpW+d@F'o :L=H.V7U]~Bt}45匓 W|O֐W;&\}P4@PĮbͮtCϠH6$ p4N6wSOm:lmͭBV1cǡ\L2ry>\Q;E-gw ]R& ah~'D$Yӱ:pZn MK5P,S57 Oa-E Usu0+Yu'?&kA{_e)zL>u]$X,c=: qWܣƞ6;s/\j r?"TֶnnOj |!R7tr![tR}Xgx0r5kue b4'QMXH@(4IF-H_=SJߺ/oPfg2?.^x+<E6{Y@q\ PF9 ѕ}L&|6y/:;^!QsLY>SGϑmi {å&-;$dJ(RCD %!q*&=!C5l贶KxJ%"S#ٖ CPsb佣0nggNp\ nŐ]"W?@3.&pS&y5-WDVQ /Yk}f: ! ;;) ڔXmp|ؔ)qak_Rs-XFAEd{Gu/gV\ Lo%MGpoovPWr.Du~*${gMX]~ǫх:u6Jf5_޹΀/Pog9Y>MN.YԹSh9or CD*DY &҄@JbѩKOb*OuKs6"&&PT >XHŶ*z?yT;ZVí_Jx 1k9SdiMujrʢVYrMV{ʮ62ZZW|#Ս0,S& R0Μ2+%EFZ~MK.VSaФv;ShQO0bEj]ԟIuDG" p+z=U[d|EH1K7.,v볂 k6>s_J|z UYt.bʲ:ɨRۘEyk OSu)mLě3We:b~["+x-Dѷდ]k٘ ]X`^& |S1MrE;T׻䗎㝱^9ԁʣtL0lj0#_#W0T`V(04>Ey{>76aldQ4/ kpTX$nة[\$&l.dǢs!.7` <4&1\uו:2\:ʸdlM;^lul;3s.K )Ux-n)[fR\|1?{ʅC.Z cPhZ`(W]IL,ܖbh͋V&4HW^r' _igTg%GusFK%ܺ|5zD򸘚,Tb-BþA0WY¿-FEEe&..d@B&ddkaݾ)?DYysxh@?jq*wu)KB(ո;դSG|Wi.om$8& _o +/pw.+%H-i`fbqQ;;!~Ґwk0We Sf ITHNHwSa{rzg 7ebޤS5$͸@6v{07@*U{U,޲4EW),lȗVH}"^<[u4Y4DEWawvrk}E^ j ZWှhnڟ>V)voC}DY@L]Ig5-}}$SpljW$!ka0~ɡSqtJqUj,oH|Y[U+e EBs/qb¥N. >. ݷ0Аya[*$L YYHV!:ˠqS H>C0YNAn~,,"+g۫d&TSVu9Z.`2^Q[y)mTam!IEtli8ȚV D73=aOY.5 > dƔC Uʶsh&ۤHO jG;9V %{ šq¾!x[o_W'lIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_600x0_resize_box_3.png000066400000000000000000001346041420147000300334730ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRX,(=PLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖IDATx PW16P|ЀP(F L8^Z(BTDlBGوa^Gm tTv])\Fwt׿ڏ~Tw@|]߽k;Y6lذ_Xb6,xcHqƍ+H,_| /x,ӘOI|.HIbO0>c$>$I1Ki,Y#o[Ӆ ƋObaqjAkEc`Eڸnuަ`͂`ͥ`>%d}dKz z5<W|{Wyu<+Dk)<VK|"p3xXre $X+W:WWXL`K ּ7RjI$Z0sj)jE/>k! k% Xs,JkI9Yj"jWLHX,W\bJJL <(!LRŹR2d-Xb%dB`}")bz=A(XL$Z*e/>,= )lKL(Y,W,WM}h_;sTH8,Y$ s_0M,˹/#*XaMW"1̣kaEȸڸNXŒYTLj(V+B`}(OZ\!V̺r9X&'hޟg`K uW3!AK2X\VXdMRld.%X++uIheʄV"K^XCg`a 3԰fkeER%X,K¹R62i5(:,eIk R&\":w ,aÆٯ %feWZ,ͺLSTz%F'`-PaQ˜ `SGÒRׄo(eÒK+a (ZoXƢWuܗKB g`作Z"VؒpYfj+VvJ iQaI`k `].b Xpe$dP.59+֭ք.!sX] ?ȲevjJ&"b 1$Rv %Lp XRk#~P,&4G_ZV֐zmaa7G,B~^͵𩾛T.F]Kj[KheB +#|  Pі֠5R,JX,AwX`/Zm;BճT80am,5X\/c,407bv[nI(ZiϪz zqtJ`)QaƲGgj Xj k0=VЇ+!&g`IԈe$\gYw1t8wD<,RmrXˮZ)XB]k7s5!,"X Tu2;r K֫!@2z'[u2W`y,a9,e5HD(mL5XUw/^R49.YdGF.5=z؈R,`zPyG,6HH"XRߨZku 羔'B !>^=K]Ìވ%WGR }YuX,!JPXeayyR3XzY>ˠXŢߐ[$Ql/aQKhZ0YwU7ⰴYv<:,K]'tXo/\(&|]uXz]ux92}Xe2(a+։nrHURw$.LȱZloݕgstɠvs^>Ě39n0oV0!UOa#_jg(mB.X L R3>0%•+msĢ:Q,ٺ][3RЗ$X箞1Z,Zlx֐ݜJKkBrXzGtk/#w*cv yG3]%3ƦO͙-V0+Y ˸Mr4SڊМ `ٟ1%˼8來g`52Z6:"JuXg.7|2%҈%k0RU;_j3+ycSZbF K&4am?{:?CV3_oi~Zx3g kFapv6Ԉ5⨱6j%yBڑ`G?k +azPòXsTbE."|[\J} J;kI4A,b`if2 1>k!,͹ϴ;C 5ZQ6Pk KBO+5s%%XF`Yze,u;gAW _:<|Bm]. }7G5܈5O8wYC_hЮ8*?u"+K=c8ņg}h1̲Xf5۸&2/ְLuտf>K8PU8hDՆ^CM hcY~!~y?{zfѧτzlmԣu+Bc,biZc2rޛ÷4};Gl05kgka%n?+Pwkt4Zh9jBք!U_fbfcքNLWz+W%YjVl\|Jum#_mmmgeP?U 5Lbp#Gu@,ϧԈ/c-@mcE3_*fX9R ,|yD*ք+q\usCqǪm&d(hGg~<+^R{=~^aְ^SybUw*X~1͑$hGjO ֓KP 3m̔5dk ِ]BLbbɇTF,+mߏnݟeJ|Sga05b gYzŌ yzG:# `{[i 3/'Xo/hh X* +в+mBaٝ͑ YXڑ$NXE-?."XDD^,?\X;Gۂu_ga-\ $֧j]D#c{ W/XzuTTpIQGɢ`K'jƌ3Lt= YF dZX8j_ gl2dBE Pg } TVD-2-P$#Zm9"f^ pRLMKKgپm@n;s?w9 734 W.'rd99*5j` ajMFK̆/ ,S >4KK_JLVTr4Z]CgBÌd'g3!z_ ʊʊt9p_ba,X??,֒ )$5la^)%4lٳW,]&}XX jrBwi' Ŧ%NQp\X`Q?~[g%w$;oR>*[B:$d=)[0F)&MT6le앀VcnRUZݭj,%!=nju~%$^uX k|[ӧE?X6z%|gE]6'hSP5 ٣Qʔ4h*+}X.!.7N{O{ݠW|<twsPi2aKlzk܋?!`HJ XV.z:D]W{lZV:4J!X҇~ح$122"Ve˄}@L Tx o1 Ē;LP:Q{ "XEQA;Sl5>9#c.sFe镌բ.élÊaݭG,m.+++T\͜=޸rX,/3nrepYQ_LHK \U__G599ԏSS Pq"[2{zCsoq]}}}hOרd$kxK{d)M]O•mJ=cd׀ 2Eb2qX.@une@ֺV@+h"LX'Lv杁^(W.NML!\qGC}||h2 v~$Akh ,^=i"=;((hY ZzcWAMu>$$$d}BBBhr@Ķ߭[unݻ׺X`k-IWII˗',_0V:&B*11qwzg'8Y'pMx@3Nzu&LjH4.Nsa||T恺8ȅ1>> GhOr"I::":,.,lL]h(w///Q,+F;H hy$1`KmU5V%H;h+#Xr<% uEU JHk-֮MZdZѠ`1}^ T}pA> ZT}Hh݁, iDPY07i֐beJq?yzݾۯ`Ģ.wuM @%+Hl,Hm@ŕ ᔭp}U`v K\*V7Tصk+VTX$X)\T۷s>KP08~YǏU[zKH䥽5,WD "d -&`A>8%A ,5*4`M఺FL%QPG],.Y:Z_>\[=,2pҭՕ{IM bUs务jU,j`PUTTXTaaVbzb6`zO__O_GvNՖ[NA'X&|W9YWΜ9sQgGggg_ggǿx+ 5i$ShE#Z _s"""ƌ 4ˋר?y```?N6-{& M+XT&?rZ{|Iz-r8\ 2%' g!pQq=~(WƲŚNcm>篁f]v^#gŪUVUS%=L(ZH};]. >}swn'7NgzubXrʙw:]NlokS`,j:m ::..lLݘP̅L^ ot:iN۟BdKʇC/U EZo͈VXSE[M \M+V|oo@dcm|f$<%kDK殭.&&2l*ωNY}ױoKs8nErʙg츏yM nӱ60ca9Q¢0)j]D\P,//6×%e#Sؔ>]&kB?888?@t=\$v.cx%L*dʔT0{7oFbY7õ.CҤ҄lUnTCsj@-Bq` {4or$6BQ ɖςdXdń Z>1^1ÛG?'S/呬ǃ%5K4\`  )5KD+(/pdU@A t5yxٵD-zѓPZP^a$&j5\ X7 P+Wޜr 8k)Y6uڂ+^PYuaL\K<|wƒHqR/5a51X Jd6KHE6_~]#(R+z=| >gnlT X#rJK)SWى yw+HՕ+Zv\Gn_ \Qk(B222X&:̅$AJc7%5aB(tLTgNɚ j \9pU"rEː 2||}u5>,mgee#WzRVٹٹ۔q`]9~GNO\aMgIkYQ`l+0mNח~;X3) e$ l,ɓGt bkp„ɬU@AX636Fbk+ݍX]i軈d]<~iJՕ+ekgZ>j[޶<}kpQ+>y,_WdZcZ  8cjPFH.sy0ކ2Xb.Dbd~8w0M*c_3 Ⱥ+Vc'fh\eNtE+bfZi^~>Ek XۤKzX=#+WTX`ՍmPRW$k`DR;}&ZЂ0pf1 e S8. XWzvOwOONXk ֬Ydm&`u6 lهD}I\T]:[ J=V/d 05&lL cX?D,`Ic ݝۃ `\Hs!kpM-!X0jkׂ֡:縎;x}VÇɥ`s' J}䲵3m ikc&ݨXX,@+f̘-/l岞_ޝ =Oot7L40%Cb5!*`J@@xx|=be-5 КC&:qV-EXU{qazqg2y4A2ܖ 3a5%yߖ+.X+BVؘiw VsSGNX4`M19ucL}ǟUZ]=Z-@="WZƽ -@KMsù\l늦RE*X%WTMoۖXjѫ…L,=#*##> i6&m_}!1prXdM8EoGq#D7اt:Zz#Y'`±B g{FnuaǃQмUXt zEpσ\+jܧh&H.dd='X'%ςu749z7LܰaDwSG_֢SY.䡾!/<<<۔ .us5T"\2(x,'> xJɕ'wzrPW^]=m5PȊCJA+jKJ\eK^kb {?n)!S ^mؑvM{(XCO,׸ݟM\T(QD}v>jqœ%K,@Pjh4xzgg~~WiR^\ЬXaDl30;`Jm1^^fdhK…Gԃ/ p0$dJ@}g`/,j`9oo//蹭!#^` MXUn P-U έέGϳիW^}gwȺda\Mg/\X_LZj4 ށb bah*DsȈ^1 'rxf':,X; }S^Ibjvt\W)<W?7*- 5łTX]}ʭ]Ӭ~4_:y"VI^tB;Ͻ9?'?'*Z+B q+2ѫmm7yR}DzFlɓ'/X M.y99X{-VTT &tQA,kiD,i8`T, rۛw5at/Rk Rb9 ؁ru> X>R[AwEG*XGD ,݅p/BHLV/eR0x,.ЧF2оCcbb XH+ 0Ȏ9.xMV`5 c``cJ7o݄PeٳݻS9 ֹs_E:k#su;]9Y{[ oRGAkmw',4G,rh0$NkXeGg`[zcCtӮ" vQh*$rѣ~Λխ7 杹+ ?:Jg.Xb.tB9%Ko`. dmdE;zy*'>FFY_~]C&VYwQt}Bu,5xԁVm'dkmRX]~~~CXqgϞ/THJe)#wP;^;6.PB/ Vtj.,,4YԺ39bahD_w_p1$ML+U*dҼiuuX=ؑ򙟦XFvv\A9(֞=ϩ^R&>52]]B/;+dKq VP!)鿝a`a*.y.>)>V_bcBCuruՋ#E.rU@AЮc"X;=@fA!;HVCs\f!Z qUX!Yz"ʐ }'^r}?\68;KՁ(XVaeER #mjdz˯ub1oX$ɮJY%Z,P@uC[wxFe#0K~ePv5 * uLO.ֿkûouX :N?y}I ^&=Xgw0,ŲcE,/־f<6% ͩ0VO6>޿'있XdVkZ ,{,gφ5 P,5a0jX*b`X]=wN#?KGǣb,*)VB"ֽG=y,4Q_R11t]U W8gB{'+6`-*f`ѷ_c\j9d~J*1Tد뾛G0ڦB}s]_baPԀ8{0'%'0'Cj5*@sŲ/70O9"}a,X#=B&j>B$ :9Zo9Y*X=QkOs<]Ubʴ*r0%%0'"V9 +ڦP(+X'"Bjlkbz8bF}HVEKa!NO0rv_ϊ fPMW{`s̠X DVћUGvr>`E0HR^UxA6BJxFcEFFKߒb` ۅXPw=s ޾r8}+isSGףb U"YK{ljR! ֒qH/b*˰W8K]SR+XEEm[;Qqws`EKQ,3V]l#` 'FOR큁gշ:XۊĽvp<؀I,}/?KhxVb.j otMh7sd uK$2*)/4UͬwOuAD+0e/;Lg$dhXrr~50)k4O*v}*vET,ֿqnV!(X{xfIzرmO? >_}tw5L$ѿ8Xr*/_Il6 ;uC\XX==t)"|nU(dHG[k@ w m=Al:#˷po_ _;N1A=)p=$R~SAtv &knpa4tC*,\Zz1q_u_P,Ы;v:H&g0r6%KպkT,[F̧[gFX~~֮v%X=lzqkPkA_PR~`Rzg+kݍg>쨖%Muϵ9 |~,H E@ ߂?GSbXo`gdQm8l*[4ci.W֚䱺y``b-4ec}NB[|?Un8Xi{޷s X)Q7#.w6=Xk'ÅsqC:@鮑qtq 2 )X\ 0xZ=G(Y{Qқm)*Gw=2ˣz>Xp@ow seHuъd=I;dHML!KF5c%d)L=ѭr=D6 #e>RyWK{RXǎ]u^Wr.?2a)Ր:_Cq.+V crE nW,cMƫS y {-q_UGƦǗ {YsMLYv=z %b8c\= \1Ր`K X%G81$22A÷? DaX? 6܉r屃[(߻W`=/Djr6! sƾE~_(//4ؿμ$lHiHi(4w0F YUJV`re"W윎vLk`ԍXcbO3xK,,Yt,Kk>Ŋ.7X@zښ7c]=oqšXnvݕn7eݘ6V*Sy{GX/ܕF rU[zr>~e*XATx~9:[;n V\555ݷ-byH(|^<GTWGxx%2V|;<L*B%dBr#Q,?tHַ~jcvϢ=iWE޽e[+kZtZoV!Ih< nl"rUFݍ4:/kjߑhIf߁,Dꁎ[]}Ν;+\΄uCr8\;w*:,df 8v%!ѫ~h3b COGDT˯,X 5RO6]==퀎x wi7Y|!+`kwwww}?3XnvJOZ*-  ʩ7oVw}=8 4QI@GHos(Ʀ&+V.߬ԳbLlz/ [Y0...."/hh#H2!&"&2LjhwYZ DGZ`I녹ɏKIŠ\6b)Ʌ ׷Cf F}սOxuG k=8# qT17o>͛6<f)|SYYYFUy]/c:vB}& »#Hn,rcT]6wXѬ MΞpGN r%cQ4090Y0:.."sa0`"." g$#111al 9ww`Z]4ZzJX1h`Q:T<ۑPk]$+sgd~uĕ* Ba`\U``EMx5&ܟujVH֭F6*-n ~@jⱎb:w9~@PxMXM,6]h:tٳwߝT,*V\\\=naK + בB+aIkBN M ʭ[,_VɲoQ^I3.3ϊTO$oAHbq~5Wk܇ָrrBpW6bܪinCu5Q+@K΅']*buK;DMMVm:t g)Vu.OP5S+̂U\X\,rR<}AE7of|q"QyFjuJMG,a,x@USYQvu0`9† jGDZv8Xaqaaau Tx"lL yb[גXжɺ^d`J@e7l?_;.}3/ԮtpKj<@, 7puBu : 1VW tV.D"YܹG0+$kSӦMM#S:]$ DXa;PXœa||] Fu"P!dah"N^ bi\=,)+Zd.JJchIYʂKtBՔJQ&\B3_{/*Wh66j< dUcM߆xaqt ؔZ9I Z@X"6Г*Dq=<)E g#Wx]v0u0"Y[m=Tu*V,! *mll< -$pۘsjjl9r薣;=]lbXlDˢ ].xrH%(VT˄qqPPՇօ' rS@3\1B9{3t0ػ-Db9)j(0JfAJXZz@Ҝ[~@/@'gWO0`ZۥK.8ҵ׈l]֭m% ؊XBUXZ .pi)EZK:/w'k *֎ rE O"XQvfCSXUo8*U_ '(Q>b ^OX̘1a1 T^ 9M)Xf#t2h{Ub\R+;.Md1.k+$UAVi#UZz ^jv5!7H#-GT蠏4AEj|W9d6daQabO"^e SB WrC7aɇ)2VVLDMQHPvJ׫-¥y\q0mr$ץɗ&_tVxXѨXŰq:đ-5{["k}-U[hu*׮]T+ VVᗕOoë>O}O1" /xK1|nƄa.R`BcA^DU)R2<"iicN¶Φ*A+E•CK^ZZ.dmFȊ][[jH&"`9d\xbЗ:?T^sE`U_ ߕKg-)ɜ,2/b䨘Ô \y_ĔHux.*t>]1 =o+X/:TF  MrIk<'d\TsRMM5x]VS*666vViEiåه!r Y`۲o *֎&©Xj(g BTxb!X͢j/E"dǧا؋Q#Pd>^1ma֊T<[^t(TH aiJN-ؗ3NWZZ&XqkV UUUDZkI +V+H}clC(V5ͪAZdQb+bcVSZY٥V&f'&nߗ/ [v̩¾G]BNVZxզզQdᕗ+ 5םXe)ULo "-/rJ!X:,*p, ;`u_򵞙,+k-Hʄ2Ь|ТUC2*KbYE@ &&deL(KNЫ#[ݱ觏%i4|4eˌ*Qb%,,X(Y a}vW8ps' p]kS0-U̓XEE<❗Lx*;69y$X1c5xahʣb`Z\<\\M0V]!0%e,^ =<`q,bJgUR*!Vz:ӫ!vrŢNbWgsJ ʓ$K4UV9*U\ 8eRGU,Η ge$RrRy\ِ9wYtɓMeQ*!.gXYVP^UsWªJsX$( MJx&DJ\Yhۖ-+V6*Y2:$X d*yؑ11L`I-ΔGpdz^ ˎF0 zOjhm?ˉ+%G~Zee\.].`PfKrk%E%+ʄtK(Yw.s'\1ŢzU WSJ,dJVye X=-W/:4dT dY%I+eԬIGM` 䪦.ѫXЫ*12MZh@$ \%uQ^|o"K: ,iG\/)NG> OJo 5Y2YII*n($XIְ|9dB,LOxfYg1ES-[nqCc1`\ߏrUR^R:M`}X6XR"ܻwfeEeY*g;@kHHn,J%. eiKGĊζ჊/$p~&D.%Lp}G϶R!NJ-SeUV V^Ajfp+Nk bq"z$DMXkHUjXZpݷm#قLXEXzLM W\)^]4T,pPRAn#:&a-p /Uw+RJYeVejUهȱkomEVJX. fY@Sᖝ[nز: X, ~(^"zuZ,ؠEEjXL}QYYQQtYX[zE!As;\ Y6p Z+_jRG- ?S(U# AdV!bFKU"VhK2P[QްUF._%-D`Uo BuvK\xQR,HDX%3B![,+a^XžLٚpNjiPKl/,ݾKRY&6d(Z_p- ^th vej+$3Y;v&ٔ`1$k[78pQdIj=ѬB[CUtWX{9WE{AB֓bc2,@ (a //阅EC$',>hΎvr\r0КvVօEF/ znZ*ZUUn祆bQAX-E9$rUR;3BUtS¬BpiJa wQVQbxG/kY}RjoBdmbr`4@ժ4WXvh,Bȃ尨uϷ-,ST9uܽ3&'±l ZNJ &].x;lr?V4:;n,oavCl65Z͆eB2va4+YDFUQJT Jwsxa-aX7P.b* S!ak&1~JfӃY2b xJ9rTe c^Xj`r ?4U-HJ*h%)Y%%xbȕ=x O{QZUI"se*\*=TJ*JlkډϤuE+.YαXib!Vyې9%Nk*,̊ǣHaq}}1#899*4rXZq!4ik,X>Y!qg/ 2[jj]vj֪*+DL=`EOqJj(W\Y޽DLaBVXyyؒLGsIU^U|!@Cux6]i{e$s W*PE1%K3ȫxa^Q=DQƻ=p/ \dEw`l*٤jXզXl|T,] ٥ ٥x~6ae2}[ wWš%K-5S@`1bGs霜|*W9d^< x*%%),o~E-8:e) (/dUb V{|;;yt~F–FmԦ?+A eiKLVZ5667}~70{7yTB߾oߖ-ҰChX0 ))9U%|j<`6(Vt!IIIٛX۬x2۝U\\b6AbUX]tJO߾LN-UD-Ya` lwh{i ~2NJuR%6` <Ԫ\a|X~ UeJ$=iKjTB774ZU^"+V-I%06?EʷJ)L)H_@G@biO(WI\ ۬ڝ]b㊤ۏ拾lMd C2KŜNxњ -5j֭$tWP׿¯k[tja6O"3%UA-[B qququqq 96fҒZs@bTJI=&_@~h f U1f"Es'&.OZ7̙37mLJHܙf2$tF!m[-eA8Yju+Xo~\¯dO@"U!p <2t\Î-^]ܔ_XGbd7j"~| Ȧ2/UVKf?6ZXWo~EesCC+q=VuǷ'$l@b6&8fɖFX{5|x8MZd6cmrK X]/5V6~o~__~/^~Po IY˜5>bWU1111ļ_,,B>RGBRv\o~A4]*1lR8oT,Qq'o\{ dk݊$,;cEK+Zt}xMO&/*hꅟ /l|9UXe&& C! ev<ڜ8+1pRRֳʱANHfT姁:+قX!7Q=S٢h ~+tj+:e;nĄP'd%o?aEgC[mmm6/T5% P4k:w-A- T.鵟}bU_$\L^~cB^Mגa@w*EBՎWA*Q.Vam@^SK:%(+FX B+_7-Q-&Zc քwٯMOL$X [s:j'kndr??__/L:?,%,6 \M^1ܕW~d#_gJkZٹ"V #@8 L{|<j+^-L61jԄU{Du6T)ծ,,T6+Շ c'3 +-iq7,$k]RBx,Pep/ //G/}͢eYA+>7B~_?oK9AjbqE:® \:+F?~ӑLZ 9ɍ즯Zvo Sv$?/|,"Z˰1cԍ{2TUXtHo0f PWk;"hR&eIq#J:p)Otҍqδdƒpv;~Zc,\XEd, ,A*ƫ|_\D|0^4V?ph0O'O>|,qWVblʝ+W\":#U6ޜ+ -Zi)Vxj.=.\ȔodwkA- >=щa gp `E!. MLN roEhsZ~gꏩg*+nZbW-Yzu,g`k\D?~^ q?￿|\H/䎯vP ^UpE]P5T~^v)!)mATvJv6ɢQ!>AMT}-3CC-kv,k1⋣MRj^,I\um'[mW囟͇{ _7mtk/W4Bȿ@ Z?F$.,`< WGa,h[iPt4JZ-2$hO>E ~pMY4'4>ĩe^tx:v~ZDmz ^)Y*U\MrA}i*0׷%Dʋb!>00E;2,K;w\s4:e1 K%ET1\➫gyF-ZUCBE_v;E5g'7,ÓeÉwC\O3;WEK|4_R>XNc{զ]~f+?I!HB:}Ow'haAT W<=u/hJc|F*WtKo*W*ZATQHw\W֍_7ZL!~ 1>b GD`p6^XU{ܱc;nYvVj -_ZWG|pTX0ʋBӧo?رcǧ;[e;WVpXP#/odRtf'ՓJ/0ӺU\C|%dFku\IDZiA&fp>Ӄh5N'"Wګ*7sCrb9UWz//&jyiXyњ,$֝Z5+w$] BV!@DЛ5tQ2u))VM'"QK/= yia`cE˕uEKQ՚08<,q*&Yf(e V ݲj]G}DPI<A-͉ʉ:ve >Hh7g VJZ$j~Ow2I:855##H+,KO*`+oӹ>Q-`.xMjVP/PJ1p%v&Qݴ|nB+43xZYsC#KQ`XrLVX"Aڹ&?g*DX9Ey,:SnݺrXݛ.}:e>1HolQ[+ s:'m=Aʙ^VqQWn`/9X`Oty\[Df=Xngt +2a゘2.%rȒ%ʈՍ.&W9k5x9(>t"W(VvZ7[]y\D"K8wVխ/^m;:a[+В*7ԫRb#/>+S\YаɓTl~txyU?4WP,:c#`6O-``B7ʤi 9x S$>"Aj,/`&Z/>f,AR{wDˎvxdU>}h5eSwD!oTVU~U Z _I᳼=ެ4b<įf3(cK,a'xHYJ! *<ݛuua̷I^ѫTʯُ ( \E'%cE2+S Q|8=yKix[d+NH;d,RҌPFk$R tZXǠYb95,wle"/=g$Һ"S,,,&+W(ԆlwMħ]-ުUv㚐['z5|y O0q>W< +c+tCŒ,V1dl,*J{W"+vMHƪ:Ktz,A ytmX~~!Ւ;fHW%_ETOXT롘m 9 YX!%BXRd(ݤM͒]6n{†vX:qqRX'f%+Z]WC>v`K*Y}T}9. 7}da/X!23E[^,c:Xs+4,V-QnPԱ$ŪO,t\t+%kr~wԯ3\4T" z'W{thwtq8"iR%z sQ hBbF+˯7)W@P, BK`)ˢ+b}mx2ҥƚg13X gVhK^U/Y^1+al#UjU*گN"5)W^AoUV^T~ }IM՗^d %o%;˴n5+||Qq u V(Zf1sBio U ŪU/be }[!`.v0O~)dB|2N 9XmRg%SU68/P["_~/YҩK'A$EwX'EY5 חu72Y܍lXڒb#VrЎ,XY#Y]*%2XfYxȘ XFRokqihT./D^z%T,KcIXТ7$(+[SOe,1o{R9KXBU+ņFv [gԌyb-6WfXo,(tVȖkK+ @Dhte~,,rXO}X E?byxR2 jCR(5`\lYޠj˻ l[!r5*s o^xOK]Q`G/4(V\69g@^ˌqTD 3RK SģHu,N|Ս !/id@%s$d Ѻ)U, {(`+G~ۓv߭e-Ά>2>z a` 'hz3X֊%w*BXf`=GBT ƒb=PlWlr63IDAT=JBb)J]pfĎ]`,MV!˝bY VlZ_Q?r'l)I}#AF(Qu,_@eXRcjVHp#(719Iq! uDĢͣtR\5ǒ2w7B6VHg"cu,P#Z "{q]}iƪFXʬ&S/k>!k",Blz,mn۶m۝'Qo2w.s0[-t}l7]qX?[ awiVDf!Xܚn7&;*Unԋ= `uXo5Yx%v nlLKmp)T:qV~GEbǗovr}JIAdy;ciGzFBLK 3Dk8 [>[gJƺQÙqӏɒQRfRƲ~,U~3dŚ-wJѧVZն{X'oȯJAjOǺ?>XxyTjm $c^X~;=λ+̅C_](F)- ֊ rˆB3XAf٥vLYJZ]/ >2ĕҾ|  pDE/ 8#D՚bYtIš oǩRGVUsP,uIG֙ f ū!^xMnOS;|$BVj^OvUl|0cNNt85MF}^픞^HΛ!|ᇒbit,z썗% k,5Y)X6<.ut~/Ygw)cqi bעbvT$ X웄,_XDbh\ztH|>'JuH`y+`gὀrmzT$$57>|7"e5y:!Sb-"cv|,477͍ WTb\)s$•^c9ΝpR'8Y!ޏbڽAj˲bX+ S~߿ M`z$YJ$D鲋Jh>- NLI!>yLQ~ShXrt)[ػmg K#q_[k+o2.kVUmWj_Sj ,gcF:(GiLl-J] ƌv7_~ Rqm3H˪Rsѣ=ʯ>DQGTs<SB5#j*9 g\kT3֣]j0 ]gmjkhra&h…ױeʕm `OU•Pzi+N(֦c-qVy4X^Vw;o6/(Ox*>|!)]neRt;?6AyF5}zva 5<<{3 fw,֫J-:?X -AJ.HXۯX'΂/ e(*Y9Y~,Rzq缇x%`OogӦD6R&c*~Td5fL Bjo6K+r9R6\^5Œg. 0q;o?[Ž0 -3~g WUO 5S,Weu5T5.пt`qKX$dnڵu]>yu2Wj?cь*oΓRЫ=AA c;nXeL\ŰΓg)X>H>Yi#W0444wbrUת˖X?PlΆ\+g`VxlƓLXfeVrB/Ąڼy6(ʉhooVd9j+x‚liȷ2o yr/M~HyҊln&-  ?82fapXrt-~BEZ.h`]MN-0..'*V{:Yd_Ŭ0D{yDW$o8,W؏?.) 䌑eq LjR\rtfArX16OuK+u"2_fw\2}Eh jں^)Vg&K= ,b-+ddmݵk﮽?"7c Hjc] {K @z;طy~$5SS65*xqw/r`d!Zvm@dY~U +,޴xz8Rq3!ҙFe:B/ OM1UO=ã6pZ~X?"W=U"+*..'J֭[7mJ4k^ }[Zm~!^~ЏKa}m:J޼;B7 cTdy?Fߡ; ʐ ?q… 5?1,<|~'5q&kaɽLc#ZZvիOLL^ݩMZ _y )Zm'M-%E”w/ƞVKev܋BnV teXVrڼ KhUu tQ)HTvLLvAvAL/ 1SrWyy/y!C̞}!]ALtsJX&&sA7ݻyoKn,BGqKsZ[s@n%`{6hb*+rK;]J 2 YcW {#0МUPF*;& ;&& nbp\q8\E iRb 5cg/ /kqո]Y([udQ1xTUUUUQpgEtA 4'g)9nݽw^$sO?$!޷%DDA"%jʕ@J`,F h5۳k׮Vr\TdǤ@ b22`Iq^Qj]fe=Pǎ='<>$t5( 1k0; %=Vh!6T[[CCCkkkM m mUQ{lA+!) ֽ{)X?|%A[LTm>\ dXWbwU쐊wCqU))+pE:pNY*!HG3-9,4|챯R?|]%`7Wc.\X'ZMz PoZ|}}}UbG>6acZ[]WX=0@-8Z n. -⍆HbncX-[rΕLGA?[t-OOkULLy 3c\eK r|HQJx5m[t Շy}EsBK|fBk#/4XhdS-0UWrCC|݅gӆRW],r_ݮF?:kRT,Y?ݾws'jDBWDltu l|jf  mMp:P悫RpdĤ`he͒R5YzhO`XC+41>懯!^>~CXK8W`;IeIEh!$\| 6 ъh[~UǺ&ƕyEHeZ#nn[?o߽?_H% lec}Ν ,GAu(jֆ}6DϹ"PniDRbRRScRS x(BI񆂩YfOQӷy2bCT0c%|uEa|TzKFA1ѓhC$Z]6X̰^FB,YX1Ky/H۷P-/v4\sʕ+<(ao*d U1tg35% Qd V0 3 VhѢj:V|pX x$HuZ}v+>XTl,81<\Yc>̣{_ƝbҋXl,Yu9㊎{޾}ۿ +=ȆTU\ 2N),:ݰ@+w͎퓰Z¨B%0DY+(SC!>%]?1@*X!a)\= X@Sm0;侫C]eCG̢Ky$+y? %J*d83V)CEt%vWgd c^%h=U-Zpd >>>fw:'8:0)0r._NR^FDn prBjعsٲJ)nذ?ԳV=A4UJ*1 : _<ٳg>sbX}AM(VTL $^'rf/V?DJJ+E,~Zo6_mAz+ @<'Ś5o֭[4A`|uqhl*v\d\r2J C"Z -i:Ԕ"]`ZO]OzUNx '_\u@V-"}E\}!%U&h :gWGS[\TzrZl&Ctl߻kKd`-ߺ|Pu hEkލ)V۷o_ӈV ޴A+l6Zh?}v,۱ JBE,YWŋoXR U{2O/ Sׯ_OXdpr:,hņV/ \LRyUCُpQh|bSzqߡ+; d1 rY.jFXdmjm+`َvZ; [+EhѣET@PoXw: UFb?%-%%-%5M*D2V93 , '~x@ p|4p $_8Xeق>g#dm[_!=)VW`s:ZŒoF+ KV :={ HXBbłg-@Le5_F U8X g??:"Wy}aoc--y_$hQ{2V޳g/Z)sbu Yk --aKD@VdRP\1(U, Iyb5Pժހy2V'f++qeRh XUdTzڒ^,bXL,X m.'+k $ ZMWp$g&/[ Z)"UE *yUs87wiTVH׫2GV%[yyA=`d2ĭ}R5PϫrŸz"\TTWaO(X OJ(*0@EիW-|p(Vŧ+%UQ VIEEiIEiEt* 4ё`"m= V+g3~h2F'NJHJHcz%yy>y>C\gaVUo uQMRp*RU}!e{bi>h+=&Gٜ_Σ.Y[7n 'lQ pdq@U5hl%%%%Pf1sQs8XWdjDJHʃUc7o <~orHG2[Z;Wة0uaOϞ=q8 :fiX@WC7^M4 +`P)XSޤXQQ DF/.f+ U&珞J Xh[j {?=OC6LtK-˳eE.TX9WXm*X! XU3dkA;lzRZ)XM/O=zV-%k޻[\ WZ +B<+&X ,WS8V%%%%V4<\rUik1aV9"s~L$FZ1lİ Pށ'iP5#i `k̈ȗ#""OI%T]ug6(] Nb ?znP,GnX X WfW9P( L fHkAxDָq㒩bXD8Z0d6~|%o/}J+} KF ֈG F;$k3f13 Zl TEOoLZq%IW[Ko; X+c nwbm Նt<|/@K%UT RZaQɄIIT97%B_<`K^W&5eʔ#F2bĈ6mڴiABbF\13/ww#Q\eU*\L~E߼Os{%pΕI>l6jCz::aT\NP%]R ջ2Vbsb`Q) }9!5oU `h͒s5e)kit1ba^A+i3ǧ1#Bկ_Se"\u+mAV*/([Ty`^ЉY!^ E,`+'N QȵqQqKs",y`[ ƒÃCjhGJg\q&!Y@ާY ,pBoN^{JgSd#\Œp2Պ)(V#FI"W4;I3gZ3%͊޽{S`2[Vo ԌՠVB1/i nΔfΈ@"P͌DEDz-S2e ۠U[w+&MXIR﵊4M|mpB,YI! TH,yjNX-FhD52ljb`MBŚ>Kvz J{Y(Wo-y{ɒ5o`M/"51`q#9s&hVjO(~(:POV[ /V?fiJ1<3#f1aBĄݻGt?;O[N;Fjp :׭/~Qo]\IE:. ӣf-ZTy|W,W Ã:}:B'N'~ȑ#!ccܨq0)WpJ $aNHpXYoz- -k'OvZ4BÈj%EPM}x w޽% u?t+j!]ES+V}1΁%f@jP,.X(~\$X~)Y ƒCbN Nd cٝHI2T+ϹB*}=+ X[胓N f, yRSˣ!Vw嗐jHCܮ{$ Iy PQ9KsS"jpADЉO8q"!,Ċ(Ez_N*XbQ#$}@A胓AWDiX`b\uL MnZU7Z+)0͛w+ |K5$b/{/ꂎo]g # 9 W99"bɽJZ | U,Fk"X4bD(Ypz{ z[oc0OZ!r5LIHF _\sLj޻sX˴ ck:d'`>C+%aI {"XӃ!ON8 =q% dSMŒ;Am:Pz 2e2KJ6izՕUB2M[2/E~c:x dlꂎY|uw~6SW-W=XЫf->)\Xk@/3'xQ4aMG% ,ZrX$, oςɓ0%5a?pkbN ~2 :f/e 7l0n}(IIX\'EED K fE,5b1B` WDɂ,f\`I k"X-bEd=5WRxoUզvvj,_[gU5$ \/I?hrC:,rWTXtgjf'RŢXT8Qk zeRb uNHaE<٭`kHB& ޟAew芿;~-Rv7+;t,N'jG/ `9G2:F2V sYŢ;p51a`aȚ8rDE4bKի7WڜP! o"5Y:WӴ (5̜@p8fwnVcHR=UOX x ,B_Lh:K)X^sJ~ V:**Y8< bAN +Qnjf' [2Pj}p+2"VF2oW:鿅*uVHad=fv_ej ,ߺ)ARڄNx\MʙgX'Ts`P'%%7.%s5 5,5Aa`Hx*)=IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_73c19c5f80881858a85aa23cd0ca400d.png000066400000000000000000000473471420147000300345440ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖KIDATxԽrJ5ʗho`[8L8etsQ0@Zy)ϜGTKj"Jme4My?|nx[9vRAfȿn}I/u[Ço~v;DL:'QGZxs碑?I%J!i?ޏ[ڗqM&yo&3~qÅV RsU7jCI& 0w/%n_}]Q)<ۺyHv~R/RԒ ,BI5Ś ݄-L(U>vK/ [N]ھ6PC ߸]v!xQCyҐ]ޅut݀tSq](*A.^?8PˆaPa"&.y)i^;ь Bҡi_viEdzE 7WAQ;DRI碮!c3}U+eM[`5 g{5%E_ub riD$ p!1s7¬C:s-'[ ϶6+kiL8N۫-Y$LsmxXCb_oȷh̉B*:-o8TvӥB[ ^{qH-:|ǡRfzE(*Q*GT}TڟC~c;պIG*V3(p "bwQޅ_g&Qxpy)w V2ٺ0*ܺ|8z/ÁS@*+sD wS"5޽9E=Bxt ι`YaUdmv.2҂%D[uFM yO,ْy; ^NNq 5)!x(YfňWRDX=__,ԉN<[2. ψ?x xUԐp&%/ҐW@wHP#=4dLF F\fƜݩ/ą8L.d">]6AVEYE-,E&Cxnhį[k_}-b VuR4z!h{fyuo혯T}YCMGc 6Eg"p))حk/*+΋ɚz۞~9%E""Es568!S73uv_op; p:d+Z+AJZSOD ݅GpNhKKWSI}![f+,& rxק賋xwCYmaQ΍x}/jůI|?ߺ!zg\-$oVIWьKsx!e!$!W"-u.sAWz_|_~o0xtr!řRVBر(5)mo@۫1 =onkQ]LWG6֋e~o<#S4{*VK!DlVrq3RL߾ gA49Xb5fqd )ֆP$݂VԯWY>ʦd}[N +f§Xi_͕ƫ cm0U,:x7ZaYKXDBi1{O?DKKr@vlrdե̟aKNwZ=poa %3u%*%{>FwooMcf֟3),IhDتHs~"ػdw/w]W/߮a}t]0.:TE,%P*hBTQzO\zN$y_ڮ^U;\:7"M&\ZA],s$ҭا2E;zwIVnwkTB~rԧR&_흵Ǐbꚫ%'D7A4s>9px_.BWk-ļ~ aҡȮE+"_NOmYtk@^P/,/[X,DWb!BI ۃXWX Y$*\~n;(w7oH˩/M!NE\0FT W͊wl>LN^[EIzR.db>De5J$648Qz̛(r"B*nUt\υ?`(ȷ NjY5trnQ=IvurvNAɺF|eA$uRYlcHnEad 8U*%ӻW?tiM!k_ؾZr7 .d4#g~# qS"%҇<+,6C ;wBӘErw? lCsEB:Mmt)=^,SlD3ˎz9t`,z$-Z6z<[ H58RQTM!yN;gڃM &d R:QD(e (v G )ᾊX)nWڭw!4F<4*f}*?+HԼ`SsԂ^Ȕ㋤Q ;Pvi׈X}VDѨ =2pN$L6ͽ$6/^r)h4}n;xRmL"C#뛼D\_JTRPZ_\d|O{<<ϯHUfE bỴ{#B?!b)~xQA(`2Zu4=) Id0KK^OV!6ij흽.ܛ8|=uq IA, j299*iD DG/=,$"7Sꇿ#_Plא*B'B7 ~MY/+W7>aD~`mG8~:3-w>6,B= WSa"69iZOM:SÒ8 ,8Q09 ^CS,X+ QEiIcE>)*e`s+d;%a da+"TL\` MIg_c(b5$u|zH>"c<$‰<} >/(FqYg8+eV (Itޢ%t!3eHEoߜh5BqZ8̉\&sz7P JuR(WŘJ2tvپ=$uM!,KE]9EަN8tH43[zQp$g*+B mu#!9^ӭV׏ %.ɦ ]3D̿ƳNSy15J$v` .wo/#t2䜩ʟl>'o&5C~ś {Nŧv-O.9La}f%ߺw"#QMZ35ԇPkYѻ+'x]"rK>4:uK''׶%_ &>DabRGr_WWo1̺p!'\:4|9|{@to0YQCpIJaD!+3Ya:!B(A;nz I[2Qs4 ?6w }^%G w~U_unc#1G`ҐrYImW7TXw\4G,3drEl.sU"L?5ĺ1-sJ!x땊)˼.唔o3+{c*2-kͅLXCy${Q&IUdJkȬҪ" e7W]S%$_ݲ ߽4]d*:;!rb1k֥ S63.ڶMxV0.:k:JV&ADQ\8" P v򰾓[ ku6/-˧YW?)J\S|^|QgdMg ]ڹ²䄗\Tb.R S_Wh\.d(1Nh4NaTSoYr|8I<>99Y/OV% tYC\N"q2չ5O5j|C!҂rQ X N]n0Sݸmq%~"%s@+|{_M4\ ǒhPW18+~+H*::<9I^d} }:+YG9 [|:GrPLJ3%OAGYAӀ4S8HnE]?% ^r3=?k)GF= @w!* ^ȣw}YZ"Ao[4zs/f'F'9Mc{>9Kw EܫbZc?a%fA7[/O ~2LM 䨊$^W ʗM&vxxWo%1h <PD69{ڸ1EPAakvɅ1Р(z%}E ZMڇ07Dr|t'=>uw,\Hrؽ FY_ppfNE xѷǛ?ΠQg/q]> =]㏦ӽts ,ҚO_P6*~w0,:H)|- J Go=Ƽ5sͲo}LAj!2zCg?YQ}-։|F lM=Q qLZr$,YM^.:0Y:2!Xcg[^?D}%!EoQZ[7YuY48(ou. O9]huĭ8@tkYMWDqGrA1v  h+%U EqTHWvo 3'׼pLz6}Alڄ˓ wG+B@PdϙX[lpItYlӺß "z4P7'#3"ff'dJ̝1MG%B9~Mg/3`y׌?!y&;{*$ϠmUlWVoh9"YmvNYkڤ.>H9m@Q"?loM57W;}%MA %K#Hu}ۜ"/*W7Y vlmՏ.N:3Ӷw@ܦ Z,ud-ZʼnEu?0퍆X)0rκH\ҕ3s}}MJ>[vumX!GKP&#Sް1o_oڌA.f7n=(уp-DI?q!k V4sU[T(#̨!&&h-F/tM$?lI~ߛ A=G@UhL|?Cf|jTmY-$~)<7"qB9.%zU%يz(Z. SG=<ʱB/:>:у. /f8'@ v2m*l4`n3]n{bM}Kf4:5#{@8f8G|}?,Ѻ"V^P l Jrcp ODE9 ꉒ%ŋՋR1~oICfYOSPo@xdxY[wz'I^fw%I=T*'DC?vTdMbI~c"ģӐd¨\+d)U^&@BB\! 22 Xp蝗rY)&,nP$S|<`W],#,87:+5U`6:R R0Mĸibea޶>m!bVC/ ^=UKGiG74>U ^C,6Q.D9ra? X斑VeUjGfi8"kB?9=B%MڠiJ"b}9)vxo):> tv޵{)~u 1[&fd̶-+..ӫ6j3'ؒBHD0@1[ nѷtzt,{ xJ~7y|45ZMڊHYiۺj++BHQuhU?ʇm|v&JiGq\c%E]y lTݼ@5IV#~b%h5:;FGRUxS  ?yWx@+ZiH ]޲E+&4ϙ4NdBI!MBNnUh|&/,H8" -{5wgVdEI*6 Z$6V.qpc!P}1Dk+Nj#"68dj*d"uos/;l-FeYlT | '~Q ńI x LIBfS:~KXnTeMh:6ՙ.u j`W}K![S_FkT 5rذz(l$v=Q{v{ՕA_IRs!"0b=jRŠ|a +Y&.5UD EDM:֧"Y̹*jخUMO}lHѳw|*\dw}͂ĝ U7Gſao0;6«9ymZ2tᛜO\V± !Z)wPɶ0:d <j}H?] ʯ4g&{lBXlEtW'VP41mYLJ.db0xd."y7YK!Џ^aH5F'Cs7|X򠆬}hItb|Ɩ^R}uoXG"%[֤VT8VYN5!؎Bn\:m @M,MF28kGf{;ڹeAŇ WƼ+טW$=l%J\YŰwn$$-lVw0 q!4!`M]eHB8=]?ZGVra Ӻ?+H*%kՀ)y2#0KY/cT֭X/xKmT]Ih2d4>U\,8Z'"YMzXv{|("0aEwqB`KﳹL|y];uaDSә?DUDhHiW%wj%I )JݪFRJRY{OԺHԉA s H += c4ŷ1P+X V%p9wvTb_I\uZ#G!b}7IN(k~ ;ސtbZ7/iB 4cf2ؐ$zܨֵʭ}Zɢ/kE`PBm?+\jHzXVJk +L];^CWk y3շ&[d% J"? =r$[nE>5M3vYaZI/dƝսLt!I_ҝvy9׾*RKR:rFЏcYat zRfwnGa!w0Ы~Ft$ \6^Y\++XG]*ElUZEӮ' =s!XĿܧwƈ~]I,)a*bz[?ql rαee = wa]g_Œ-_2WrD꾾̖",b6B~GÍeOyw5$pDxs b+ȅP:.APd"ҷU/. [Xg2,pay]8ߔ>7񚪉媲Y<n:l]9Oo IzRޟ!K L)vu%|yㄘu%*<k3gέlV< t29^ɥ7k߅Z\k'U 6KQjZήfVsȾ'4Xң3Ix.6Bz/{#\.[ɽRLW/>|1\pE6;a(>3!lU z Z"GOT^QfE2 9;Etmk28dt{)ƼӍ֪ރQ≯ST [@nx^L@.$n#PzIhrlKw$kjX> ]l::܃"ͤ.^J*bzfx轥I:VRc7&Y5~iU$l磛Aꇿ8^c ̥W9T`X 夊ovȈ{RN ZxFcGGg8 qc|&:۽1()ʩpۑyh{ Yæn6;p=>k)\Nk+9L2mKXjHv+m$x9(Rnk؟ם_ 8σ U)m9S g]# 4JU]mKh-Uo^z$\r095lOӧm05b]Nrk њfkpcxR &" "I:> u D)=XÓWyc$7-8fDټifl0`#-$;{0Y7viD\I[wѹ 0V 8ѢxTIl;fD D+' f.4f8SǓWBBcc%:XMi~Y/??19~:~u3M-VMkQImםEmlBU)+-.NWЋm=rFjeQ mlBƌEvy/vK ZRjA1A6]wLt&kǜpyR1(oPH4+>a&:S ŌH>؁. :īܺb5M֊G)u>lr1KQ dUIS`-vCH&kOD\]sA&|&}ϒ|l¬ aPYlUS*{`ŘG#\ݘl G\d 8ɶKzwDHYC$V ӟ CّKxmhEY:aD¸7uF)nCeVU]BuEp#i=^izVq L yUI;N=۝ DxGY^;Df4n.6iʑXGgc}nHٕ{] 8xЅRR5,Ry͞ڎ痼 mWO6u@<~Ne9Mv3d2k2*${UtvfzXc1Mo.dv ،:J%͓!pL\yrB v<7DŹy1]qvVF =d [NNThj(׭=IA>]EyX隣R#sT. zVvnOD. F!j(?cZlV\g[͵Ç`ը iC|l_H6S]m*)޼CG)THPh&6{aף,-j)+وh`EJOv50t9Pם2Ԫ9|OԀbVSڒbxhG{SL$@#{ѿ#ffWs C.;#Nd] σ2zDD!}@7#_ #ՆhUS@&VՉRht39bShL-&wAaMn k<nEב[d:jCQiA--;_c6K+-7AAp={C2,-$:q’PIjҲdžժfwIz_͇z%\I۬ԥ o\[c!79'mF)fi?cE =J` Gy`j4HH*[7'_-`p9 IxEtM2jyHHtgY3WPSZFCdYsRebcaE5Vks~ }htwl@iIh&k)?LsOd6~b馥q@ԡ\~!!m~ۧ,sሉ4RE;_k@Z ' ŭ+Jqs+Hk%4h]#A>'VES6L'C;ڪkgxK"W2ZC7伈ʲ(жoB5aUI9_| J׸MK(m(Gu.MW4%Oq/5d)|1J+ɹndGEL%diЂޮ; ^?F2N)/ $t TgsVeS%QdpX+ԏ'b!viXئ#(T3˓ԙ9%ND>dZknfy!4ȷkH k>uck.i?-4f7'msP1ƬjaZ3Act+:Myvy\ V; 1xCEH|"|h`72FkzG5ɔ^N0]xzأ$e\]\EUQ8ZnYa -2c3LyU;ID}\F)hٸNG <8)/i5{'MVyB?xS[a_s]HDE6kIn"WR ,FkQo(e/vA i"/Ɩ"%YQCf$ ƞ|Xhw JAȁ$k}Oc#րzmY5'!0LG0ܼU֞Ovz%\k7%{_оZA qL׺.deb11*xG{ծ-rQۅЖ,nV:*'zBй#Q҅<,.WN( !Y(oC-G 0ܽ)-md]jfZ.8Y|(,R:`OXJɂyp~#wEfд.qYإ;fIEՁzFY"ΒT#'IZqOX) >hV.$#=׭pd 0fXxNGEoc9&U[h'?)]Dix͊[U, 8h;t58|Ga$iU,`0?;%YVWĒԡ,K4d%=-u`>~@;|mġ3mqdjpS-' F+PEdz Lm=+BTE ׺{E>kA2 w+q;],N SdZP$6]{dmn#iвxuRE bv2d& 3Gt-䬖a:#[d!xϵEATfXZ3D_t BTTNJˆ%1k!i)}BZ7%IחB2_Xw.%wtb׌őUT*_bOr+0͠SƊ&_#TmjKQpI<7#C^8۴uMM0kb́O'F d7[f[s+Gaڒ,2 )󷲳e~N63ͅJ:ȖJ8{><7 ,V K".,/.c:'!a8o7xL!kg3[9{l!hNC^UM{qQWuR&d%9gpLQ'tm`|+rKfV6k\pZx~Cʵֹ#\ /Y¦R 9a_b\̽v%iu OZFNan?jt5k#$VRV?%(PdsVNQ>sUSp r.㕥vұ$I뭜'}42П 7f[[ھtY [uD6I<O}tslKqdSdzv/jQxܿl+&b\`'uqd)hr؍iC .KFWMӍH0XPL~def2@2Ϛȳ-캉75W_OT$ۘ:Ump{Y<+e UN<٪w~ .kAC2wڲ|TM@@hChE$K(@>-Re+x{=|wY3 FXNpRj8K< OelV8`K!a>jnm_A8yQzdSr.J1Jß`a]$*}ۺC.`˓!=]ͳ{f+ Y^@oYyX a _w;GMWgea*2ɑ;εtZ %?XJ(Ԥ)r#A`Z`G.ݴ-ѫ{>܂DlՖв˅g*[Uªatvt%"]Խ_Z(PW~anְ#(Maeи^$xf}r(^;5H.a ![.$"cbʂЩFwsh+!%f)LL"#0I7BΊ 'a_m-FvJT H >$M&ܸIJ' [,_H&Q5|BI+dw*RVl]w2-XD˟,Hp$q#]{k6>\U:k]d=n#$@/t![ n"tۋ. 7cZ(â|e7F sJ3 G2 |UцaRoUxy;콵V|n{KsfWl޽[>̦K uvcNELS%׫&ͩFU F[Vae)$O4R*dL@?\xE^QK7H5Getċ -_^jş4F'6;z$L##o Bc{fhqMahsp罚`U ]t+tL~UUuhֳ@_\vo}vni!UQU, mRd0慊KZH7N 17{JL4i#HUU#'@[ u{co+G el89kH.qv6PIzƑ$1YEV$pqs~( <7s!%F{acatpl)Jl~*⛴r(3a +NڭL Ji`g\fJk7hHָs+><լU5nEj nޡ#K\6q&:zS17Z"2مѾ[Rt Xbg\Y-W&[]GAnDRkM \HAAzMi uE`b%AkkV,uɧ]$ܓQԋ/QC(WgfP!l}dh@%y.fwJpF$ZZ۴!xGچiZuSc͋qVE:3-UrӓcU}6)r֛RB]B-+q'/V;>Ɯ6yFvPL@ ҟոթV#w& (zxj"F*Ś\*\ٰ7X3Q$-DYqӦ{K!_¹[n {P2| ~,iR]'Ec"jHlҖY"bQ?,q=L]ZG冈"(OkXB2׍vY{6wlh^YI1qdBHw#VNEq1~9߁ds!HpNEWdm ?0$0O7ȥ(}g^8t9NNsh:;p5 dܲݱ[(l!RbIFs#`8W Ϛ ָn\+첒B#MT|+T~T{eq_r1?`GO`rwNA+(!_dS۳fq]NӞ JP]h-o (Fj(s!w#rC<[k"{V{ ',VnP BXz4RmP3ee7]\ C-RRns|RՉca +*jv _+["Y )ޙ tBI$ "oI{ż]YS!|rh%("-/RѵQJ/r׋^e9pԡC9|R9P 8Qԋ+O@ sdߵՆJoœv +x"nۮ}Ҵc͵grxוkn-\"j7 }@ks*2yCjyh] Ʈ^&K7mEB9LMK0 y/We!+:"&I]YH X3!i&DOm/s\+2ܐ- Q(qmXWD5b*bkʊ2e敖c{ț i-. H'1jl$yz рU }b-S`6нbc|ݡW'#o(]}>xMU!ʊ u5ٗP {ww0!,!+OX8W(hWv1#s:p~ZvȉּPr,6Bv Y"L=(ij5?. NA(b75p4sgSutxo/>^ޘ, oVG( n-6zuoI`-:-hVqwxcV'1:Յ\mp}&[;6zu&\ޘwg}$e?J#v˹Z>YΧkEհl.\.1,ZB;<9Mw&jz.A^\ū t ԐWBȽ! Z*iN11T,:קS^wHz!#I IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_871826faffc414ca3746f65fc9910eed.png000066400000000000000000000520601420147000300347170ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖PIDATxܽAl$Kr%%dAHRFr0t6N3tA@t1 :|vӻ0X IGIbffYj"d2L2ųgfnn~K<Xe/TnzB=WjTRR-wjvK[.uws>zIQdlT,!@  `czrYTK Ťy!5ZCS= xi2DG^ l"_kI7Kbh_RxTO!!RcL<ך_ b9-wj\* nodd?qp]5L.!,c4YpSD zjC}I-P[]3iSn R;lB ՜~o:u1AHP' 8F$Hy8D6Eؽ48CX#},RVՑ!K>Ct r[:FĞ?1Ut ӒuVhHR]2k w22\n/dBxok+'zᆊ}r9,H@HB00D8VV-[B,*zYdݚ(#nb(†}QB{"udJ~ J_a2+UK˧N JGY22 :E!XhLgE q$HP̘3Uս\,u1/t5^]" D跈OCԁoUj#<,lNd;'k8 rA1L1:$tqdBFNקdؑ4YLe1_"A.A Y, 6HC̱Ќ!8. 1"y #5o>4((}W-j Led1@;Y: ԉ|7Y@yGMb T0(pEk A a!F}uL bM5) < p^ݣp0CaH̊8"7_Bn!eM\iثLӏ u7TPyd}v l= -֊+ |"O6 L%2(GQ`;5 ӼAC©VLو' T.%X '٠S2NCEG6$ddN_T*nFFxj -0!5 ɒi|jn0RG=TH潬!=V2g4Tc?JE70E ȸc!u_E'JYe%s%A]K'bލ"!~<UvHEX٢U%DW8+{oҸЄ6hW#|A%ⓏiJS??֫y1#HHJ+֚6:0̃))cQqǸ+q$<%sz+o\Dy 'ȼrx3!M.p6ɑbߟ?p{r%ߟ#!bB4WGcJ)ڻR헚&Zl6X~$T,3"#ѡw 1k^1Q.[rYXSqukX +<6ZMԛ)h(R2`wLHzNV ȿwpzLO(!snuq P#&)cr /¿IjOI'Ȥ/gG2%* bBW h,r)_u'Fx 2yDWH8>y8`)ȇ K[kiV}G+>rwPCXHhuZk?D>%%`p~pr$wȅ!a'eQP8<}zޱ/mK\rqr72&ͧwr溼,R{8~].xEp{xwa'6>=> ȫfABLęBP],K]@[= kз2fyI p,\:kћJY#+ẬAcTܽ<:~OT87f4)"O7%R˝e>/(Ӌy,F_^2D<&S*=M~Dy]y{G 9l9pl+bh!!*H҅M&ڔKo!X3i_pkGMk9˲,c,ց'܉gyuy^]'>2a)l!,&Be@[L@b,& '^?'pxk{w1 Wjn!`R@G^ :$f$a5VP_?0-fMv zU6P@^4,2n򱏖O:b4<&^-gY^| w+2DQUƅV󼰨@}1 ɒdfw>R>I>I((|T똺w}4o005$+\y4˚%eM<6X8R#)MD q.hxVU!@G𰈌 9?%s8#"8G/\aZfudIH,&:ML*4ŔJ^!PjɇÒ"rU Rdu(mVopc{6:L;K\.;Ͳp k@LRLuȥL*!8! ?ɂC,5ЋL ᄝr isպ]AM@TX>;'ďF룖xNNWrd)Rp~ ̐.ְ &kiRsHs[+ R')A&#!6Ԟ@8kv838vKGʟfK(B,ˍq ȅ6rrdO<ֽM4+&'a0X:<˅(b~qG 8 ht\~!6ܿRQ~^"_k媲jVK$C}e*+O-ZYn&.~ acXD2>}mu|]7xŁxAVX@΅pBEFpcֺ!!Hz$E@S7ևhTbuYVguB`EYI"?*2Yq&Kq<-S*[]k2Vx#OmaIb9P$&;kmVRk]G"i9~ɖҏͻ\X&GG ! bGx(LѽbW^gviN+^$0eV:nb}^hS?ed~ɘ$EI%ky)#.9aгlH;"RD=7dA 1DxUˀ^Ql,C*^]tDdO[1S>:1~,&FwO z?j"Yo?RUO/݋Us{CNF Iƍ.-V}gpH?ղX% `MV@p+b/,ޗYciH ~ZĐclcV 3nR^oѬ(̤QOh :B]N̉|b_sA[z_C2򫾅WCx C{T|UЩU0I~G.pjq2Ұ&#R'08  7y)&#~@2@jZ!E{$cZܳXƇ" E__wa".3e0uAtŖ OZ0dmY: x 6CG*X 3(s&10L7FjH8r䊼t¾O_#w/RI|a"uyY%S ֥Oߺ'6<ą_pmxZ8^b%>BnRh\{^;$ n=S׃b.E^+_;9K| 9JŶPf i;u_-US)Uo1Y' O^Vdʔe{!=zI.2/eEɧ_G^ߍ!9([[nwKZN* 3-Bb,ʽւ!XT s%d\7Pm^6>c5\N;ը;a"Ÿѭ0DGZVY~Δ>U|r/q>Fꐲ7ܴ/Gsj. gG#;QNѪb[l߰'vV@ niz&>G/Mh3$IRL}ra빡C QR>̏S6H q ƻ>tuݨ;%L;KbG\rd74KӾkR*Fg4,#̲' W ^V}det!F3kȋ˺M5XSw70fJ60Ύ! mz$h8ڜsdžSfn|0R G8e|Ջb5JV(aFYBB,EQSeZ$Ej?)Cd h͖ ̘6==Lѐ`z_fbH>C٩w!X8T3Dmk`;ڲC) ń3[sn}mKhFDibpJlEI_2e Ot(DbI7Pv11Ce/.C)i:QGT]PRl_V"VzhFW SO:&+ʖ`g˴g@KG/m/$,gXU[4T*3)zmcM*b2)\dY?us׮o_ld):$xxE1e 9j`ir<'Z&eۅYoD,!MgL:;K(YND_2ǒXvptRno?Ue cS՗!wup )[@:0r%jUC>'pG3Xc4j ; _Sյ*#0f܋qJQ^,sIbl0HVriNE#uUgJX.)RH#&=PUb`@1'~A%r-R^W DgCzUgQT,KR[̛$&B+"$=K rkE`ʀn( V̈U\`h Qw5&&-$^^`l(r@HΊa !`HM]3<\~ex~WQ3$Z<%cVi9f15YRЕVia։ZC~]b& C:VFЫLy9Fɟfd _m&UQ_|ɧ9Br`C _vu4~[4 UT)[VLLc8&D%ՔN0yVzl5:8\H5~MwQHǬcQLwWo,ؔF\*v/Q9/gkb-Io۶ݽ{byK+" /EZl֛Mz6[:(Xj?9qW^K4fh͒-Dt y[^by ca^D_h`\M0P"9%xX?ipFK5xbBv{]^ gHY;+I-U۶]ke {8DRIR2n@VJ_k K,%ՇBnE 'e!_P%$K }e5NU,Evgm۪,&W)&lҤ0gfw cf6\,J=d!t ƹXi+SCtb@a:6S1=ȳ,%l[c]kw_׼\YU- FL6kl:>8;K'ZJIő͏<ӥ*O)n6cPh!->'H±hbRI19x?^ M|,ǔyS'2_Q FNCm쾅?" D*"'%#9cUFUfkYl@86))5p#O zrD4nC>kz͉eerXTG;ww Ly| Zb #5:Nǎ&mDH|h& b}?;5M}}|r{9j n9eHSņ |-Q9T+V-Ab h0[m&fk 6U)2S_߄r5]<9$ dJD {g餎)K88[VeZw5 hvծ2("[S#9USruorPA?4Y)l=Y/b>)#=MU?ԗaW+U꺾z5 Ш]譙 k w6 _MkEOzz jCf Zlx겸bXB۶#ށTH38bM'X*eD;s\Af|j͔697tctӗA]ϖPMI!u;x1DlWwame-`&Ka2E.S.X]D<`'ϭޚ1 46e))o4#Zh&V8XLx{ ɲYCcŎޕWj@&*2/A0YHEd nXl8ràc}otv$aD&NA;7ݛt_3Nd|PXp,?C)# m]`%t۷w[Q͸9h]*̍-=#P- xD~i7]^wݼw]t9; QH P#$t<Ű& ZD Ap`7<+]T!^A־&ټZh X}@5C삵!;\$q;Vj1 ּɂ27.pHY̊Evkx0Le=hA'bieywfɴGaX'Vs~ [mona%4}V Ls詎/k P ğpUl܅>  3{&6jd \#iA(vz/5Twdҟe %V7&IԤ3*J\~\^(IگW~4"'b!Nwϔbn~$ʕ`gIjPB @צPaO"**`Z֦H ׉+ծ_4v+XŒ6M)ܮmmegC`"N0z=<<H2/^BjEE16Χyr3S10k546 `|5Z;E&U͘;8L/q LЌ}Hӗ2yoD V?eq4قEmvJ$^]*vdZm͹@| <7NĘJ!Povfx!Vf)φΣCh(% h>F Ix5/cHP졾gwUO`.}bqNX[4%">~Y}~xʜ׿ߧ[B)/ql6N&H |gF}ͣ8?CrYub 8>UI`uC4TXoxt?+ޭw-~MZ PkAP9+b,[~KίsYr_׳YB!`({BZ+G8?$y|nн*N5|PN-v?z4TÁ1$.į1iѨA[m/}Mp|NGW5%9|Pnލcb{? b_=8@8C'd|H niUpn:\rN_"Gm+ocTd@٦@t׎u B4I,Dp>4-BLNBxJ+~beW~͈#Y][$GTW<.^@:|y<_VKOK·F5u(eԼVj96,mz6 ]o5·,˱w#7O"޾./۷ F]7f,n [n5qwkyp2okk ȟF=6vR5d|-޵+^_o6ND'RGz2 9Kϴ4bs:=dU bǖ"v۟"꯿yX3|#?0P~]uYDiFFcF#CJH q1⟼kV' fp 1!Do``oT_o篗kye㰃|o5%eF{:9*@+DZy6hMԬ, (nbIuFg%RAap !.>=)t' 924|r< !#D)ޭѭY\^X<_%9c_}[^O^Z6|jd%#sⴉcT0͍?U2Qw3V?~t GV66>~˙})hv&h6g$rydADOXƗ^ޏyBx\yv ~[ZWrR-%﮻򩄷rN"NCAn@CUu?N.=/Pr j`źH!8d^ܥ{Kd:KBM'FETԃ̅,ւWIw ,ú! Oߞ?GM5k}YLP"2,C[7e= ,ͥP~vS&-Q=@ ĿOgu8t͹ŹO5r+Aܓ·/4؋:Z}۟o8JHE , "ר0uz1A\g>2kKwʤg]G 1T@ӋBC zޒυSFJ:Iν;@(T8"7ҡM5U'uwfF˗˗/_N[y9% aBV+s qqHnאwuqD}BxYVA ]b>|ϗN*1xY7MJ^V]w37,7!7^Խu# ҧ;uKZEIb hkr E=hƐ:Ib9/0cxB.R9m=B ǝ4 8LT KJa ͉Df#6짬 5}7D %{onfH+A0$kE^C0G/t28d R7"J `=KⰣ'L@ز,t:qn/DdLo1jSVw>Cr*ru3"O[$&m#եǑz&P2zVE̝d~Bu{ ,hj]4f)1d2( .ٌKoGA%3z$Z챉 zNc?)/Wˮ^P=c }~d%H])"&M\&84W &YZE%\8ID5> fͮF_׳ F|Xй] W7(K!4,Rߤy8R7!R'~/=!'yss%C: Ph^}MB}aCƱӐ~RCcz'''oc]9"bv.e@( ᅋdrY/ofVP 7,ybw-d~XJ(&xYaN w7AU)\Ԑa5ap&kS'k:.嫁_e8,3Y2/+WVR'm;~廬qq=ªLPS%Chưf-weĐƉƐiOd{hd3 %yҳߦgP{!B?{cMh_m_ۿh[ i/:ͺ = ABbP$yEDVn(='CV 9/iА9g%Y^4I-WE"|*`.XJR)ڹoޕ~ފ w!ڄGP_^.Ku]"O_ gO__F'lWo,"`iq6 HJ(2V̂5HIN:"8H_Y,.5Dqo7.X? :{c|}=uuse% lۨZ u>&[cSdkmb"*ڵӜUQ]]EBZb4V \ ]2" 񧲚[U!qcBCbˏ:W[PvXGB|~kwzdbc^f34{&s[t7rwZu/]~J*˳| N_5~qQeR)6uPi?Bˮvkm˝b?X=nr敼 :qT3+ˤWoMXi&?-֧<$vFc]w<9~Eyѹ#s`.]$RƊ9`MM8R)ٿ|H)tn7vҡ 4hJCk04MI5-{5Bs.o!A3Y=sgrQ tz6zx9Xw XsXGn9R .*w?'zMpiR`19nWtC.MY A{ngϵKnU1I@B 6Ya(<z4z{4ZRK3ѫ;.J,/V/TjC ju'!Ie금ø^s/*FhbF_s-'-|kL+R$0t_&Ѩ# oL uĹяZ{ﶿ6p%u 0P'׏76[CQ^U/ƽ U6OChN:T4PZ\E~UсC҃# r{c-QF`e1{UU]HCC |fONkfhs՚2qsz=A[, ǢtK*TFeQp2ɐhG>ƃV BІF2qXhsLfJq#%nCI|%nhwSd{텺(2 @t\p^\,v2 p:d& ͭ7NBv^+7*B8:>hظ^VZ@ 72^Oi5 =r5nyqqqam8 d0A`{e#C'#K0YFѕ֩%7搆 =*{A&?!_t`BֳhH?<:bcXF|&6ٰ*bX`i+T@dYT* L0*"y]X01qd`*L-\wfMvqQNɚ5l?=X$zq1:|!*$"HF{LYLK%AYvU1Ž%b@k.u7_.1M P)GVEɓIOӟQ{*RY'CzOAxivuhʊ1O%_YzZYL`']>7haѦwspZ"'2Fp-i#YL´$DٵVm_4-fKі+Ҿc{~MCB+4Xso8 _hPw~~9? 0~M0[ ϫUweGD6d$y‘ )cH=8;Β&d V R-J/Ee>Pkso $q'gˣF=8Pcn a埲gExg8BX n/B2t]|-G"  xU$_rRm}Xj] 3%ZZWʆ^&,@4[BtaUΣB!S8^3`Miv DNoO$RN>@ATk͔wzVҕkPu ?ᢡwń0 6\8K>kbM}V %'b,/u*Syqu/%^+_BXI_ZeN,3׋A5vo/ r{M:ejܻe .^*"Ma!K\JHP]~T\0+)냥!sUY DdtJR&wpOqF3`1`Q֢*Dq q}/:Gb W+Y}&Asaa4>!*$He{ R& D %z`*]8S6eI<)O?_G~IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_a0505112c99af88626ac9b9a16a27acb.png000066400000000000000000001027511420147000300346110ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖IDATxolg.Ũ(ɴu0܃Y\em(IHqGݖ( bӴ` CZJhq2jA$)e#:-YcVQjsVt7*(Jy9y:#*G­\i*T҇oR +jե_#J[vܒ*wyt~^UIWޥwN_ZVfفjlu1C [_=rByB_y 22>kҥK(V1}k)rGǴٸ5,h*PzE~Bwz`r: ffg+Օؑ UODzzrjb"IE"Hd1r}d? uh3kiBLh4ysX5*.ؑ^q^gniuAϑ"G/YLuMĿXM Dz-Sʺmv[qc !夋?CA !Nwu=l`-Z `3P9HBDT: XW\;_GdB^O8|)օX**7!?|wILD61ƪlz4K%XX4պ[ɲ@-K-Usb`Ur<7TdE됨,}4R7rP}* H[`"Vʝ7'(;vե ńpvvcf h鐄@rC1&Q,+Nv^N+&z8~~X LG~ i9XhǼ.IL[/1q:u:{֌5S XwG7V{io+z}z?ߢ ɟvBI)G,]qy(`5Wܼ*\WCQD1/+28z%']n+rGTN`YoUL(y?WO{Te!DF"#C}}#(6\b҉N#!71qhF>o1}! JhH@Pq]ALc\e `2tF@(AALFRBy15 mCE:IK 첢jwcGϿi+0:ltuz`v`:`Ug{0X>ZwֆtOOO? z1{c^*\kLB!TV8t2~uCR7p#J b^AE![@ꮮTV U9jN`&z.)<&}C> YΟb__/ hx ^pSEEXvW%wEk\%WA6y)zljy9C.>X3܀(Yn*򲬰 !J="`o:Gשfi4U)12 K 9$uq!/a9e^ȕk,6weg@8}ꟛW'+Li(fhzgg'YIYqдPt.p,O\05:4w(Mhd6pGkae^ESTSvd߽IB9Dd( %8:wpzd׈d:>z ԍí W5GwmhŢbݝ%nf'^]i&VfgiJ/TI8v3t&iޟro Fiv$(Y:ܘ e^9 Ǯ }jod8X󲢐zŲBrX.v+;Yzk,vc V!l d 4&)DC(XA Id,K.:,HBj˛xLj&<k8Hc'B*%6t+vQuy~n@KX 8PXEcu '""! G0t@r|MѩUݰ}!nsJ%\̚My3B!L3:Xo^ Tf{qhjnX$B,8op0$k(Iv&;;ddrRӮx5a."6;>G=|_|͞c $[GI*9,cb 6,4<@Cf,..eԻ!-@ŢnšrȒd4ZL֎)Oo=t0MĔБ1C軅epԏrܨ\Bv^_b1Et,>j-gUET{gp,&Hp߃SXbc EQ(F8>} e^!-tF3,"Wld[sP!@cb* LI_꿓r҇d!"8500k͎V{Y{uu& ,ޭuUi8B[] 5/s0׍`!/D1 ѡ :Qbp|&_GkSGǏL`BUW4;3GfP28[ fcfFhѯ^t.,7r]*nwE\(G&{EeRU yk -P]^auj7ka#!8iCCߌ E!EG@x{#嶫B 'avls%,qz |8rJ$}H&Wa}X겺QgϮ k230P]vWoUs4!e4հd(9gF-u65GF~}d57g9D2rgw*Vi㡪E%[ CvU\8\B0(R%Uw oc(quXﲆ֨5zֺkeTG'@ܭŹE~Ьȅr CH KOb%vLBiȷ[jv45!G&:H\L]ZKY(Iv*Cܼ%SNus$(@6 $]@'UQ݈ *)H.|]>:j wn_zg{{gYkloJ 0ӽX^~w?=/DZtb"#724A?N =1uuFoVz{VfTb_MW~Dß["`y`I`J! E@ZCO0%kjp70"7҉.q[R@UeY$oq/Ȩ!v-*EiiiiQWߒTYVUUFR0* ,HV%ED 2#;WGۣmkZVzYkzo>Rr[ b<^tw?ODY+_ a9,KK^_;mN;mHV%l9s^;b(d.UݲE>'Q-Ύˈz ,-I%;,yZWĒȲjURs$nT[V֖~C=h?[{Fd _0 W.T, C>[ƫjT2T?]N/#Q]nH2 \ޘ(Wd([z|v_+rJϷ-3H$u%uzzhI]J X%PVqEQ ! 7Cjv`l*mEB$ydYe!fjp7 0t%jz.Pϭkk8 -j/MO0Z]Rruyf߃ FܟNOhTyBC#Ca= p\co`0B!_Ȼ4u>|`*3_Bf6 '%2tݛ*ې'O"3D$Ka+,"x]YV8p/*h Yɐ6ݪdbDCet%okZ ,,v]sʕݙ+ Յ=8k <)T*LDi! Z& ZNAA6@'P(H;b-,,Ko},#DlHLxHTRx(<8$"*nd۩ /z쮬\]X~YhR_``yzF#L&QH|KKK^xaxٷ>Y%A<܎ vb.f)"'%`z2r 2-j Q}9FPL W$)[3ƚMTDd4ĪAv?XfZAA1Gҩ|,54He>L" !uy(Ҿ4Rgs3J {: *E~8!#H=E8"vmWls5n(B a#jJ 0rlGL`G_[KYنP2W>ϲ vʫrUKi`yh=eW!RSGE8OlGE},\QP%@vl>=٬6>J-LUYMz$~oJ@&ȺNR Ll!暞0ֶPqz<. VJ ˃~d2 BJZeÑw[d+"C^Y߄`+R~gQ@ x`*6(`BN@8A] @%[56^-'J6҅Q[gHn-///XdZ9 >X#}a$cH2"XU0c }[K>~dR{{;Ulje@ԵLq<f6QJFQ%U䖢DIT+9}Mhx}PJfE1Mgj>ZCkGfLؔep?,g?X]0X5=Uz0?8?Xb}hpKd !!-%x(P(Tͬ`z׏>psۂ*17e:ff[ͯx<J/C(YPL9`b$zxহY (f>c l>  Y@L <(.1ml_9HAj# m!\3Ĉ25&UAw*x9=GN߹[H !^4uCH0/T(*;΢8g.' fL:xY%K !b:Ty`y3o!E?ߩe53wA_zkھXlpp0 EL&C1HkQ0S1;+%oD(0BbxnGwwb[,bAMG@x!$6S(uc@M^+$dK@"CeZZͯdkfb-ڋL&<)Afw9x,g᡺4lkx>˱hpd#ڙ$͊6sv6. Qo;H봐ţup Xw<>B9']VgϽYŊŀ'a+%`bLs\kf>[S/L>/ PYw1 >-6K fpKCO8A@A(4=`KFRGg4d!l7y<3{Nd")S(!#l :H2uAr@- ڹnzD09t'4Oh}H]#UϖPz4,v*E[xĿnJ9錐 ᕬ2d벩p WWꋒ530f8~"8܃l&_,gvI dkD}+10-8 XwgAoGC`8%,;6Ca8º*y%iA圝"gPyZ Aî6W=|Q(oARL!_ͯ*D> 053k!/;51z~*6 cAFǬrS3^  ?jnkCh,d3!V{͒mB9k_~%dk;B 8N¬jNyysf#z>dv;Jd,g ^?b(A_̛ h = 76@W} 1q" '8\ŽNJ0mB(ROQP$9rvLV2j0S$E#YN\DE_ # k FAP{0dlQ*< z*XTL Œ7$XN{A`6yEKKKLLa&Yj5dA"a2X}bMH#";y6CV%fsmj٧nɨ `H>ͰQ,^(2y3H_0! y`cjS@-sJ(W$YG3@5МZb^f,ۙ&bx`'5hP'J-P8-O]ſa3dF[K^aDN_cg=ࠒ!8ƖƄ"KxSV!L2fce799eRiƆQ}>!rRG '.B!G:N.\/9Mj,8u4(qjaM( SDxUS,=4|#AFlh1YAjND`J0&޾Hw͢(9|ſZC muB`WJNrQ2㠼}~;ABV(:wdJ9R}( O| <30* =dylyV8煟&e D bm8?P-ـ8Qa#"%Apl <$ȷ \0V]Y l=I%ǚ9TJr^RaX֪x%Q<)S(}1g<66-1.99R0mjj ,~F9VDu;밳~‡4Ç$TB3B^r }yly?v>RS@5ǭJ6,jE?] YC0Sos4MMf BG* Lq7_ 0#){O{bwN4e`O)+&W?;zS N>cf{ 11d±8@]o5XƋ >¿S>llŢ N euhؐ8 6өBVLCT4:DM^"tmoWhW}-Q7UA_9kdl8g<(㭔ǖxz?F9ߞ5$q,[Bh`wQ_"Zdz;jh c5KT;eBr*mnI²Bzq u7U3ik-#ozpj1uU6eSQ`XZ-Î/!3p3IATfxPٱ<_ՖcUBTHѓZ(qK| P3,EنnDX_M]Lj$63lr0Œ_j$L76$髼xdp6𰉄JP-܊ RX&Q[[ŭs"<`!"ȼYϯN4C gpvx5d2OޱeCۏ%${:znt0vo7|ϝtߚ:̣a)0ja^`bJp$SZ 8sUGٔIKV!BcɅ _y0U"{t`!*ȏ=2Woo,\jɛy %3;lf7dުe-kqMkyMmhd2;uGj,cicpkTV`i!cs;ه%,+;̡ M6۔)4L<^ao'l}Wm7>> 3ЁW0t[ p]4TU nn2v$xa 1L~7)>fp6w T_CY4+д)#;0%L2CI!6BB V w)z< *P5p^)D)a43̵յg`8`-g2~vP; U"ؘ+1L汘6M^X2FcSñyA| K^MÆze]r3e]A " ȎX-"&Y F5j3SsU5] 6ݦuڪyX$ln>[O/)'C VMPdj^Mi91.UIv}aɋs^|%rKEw=*?TxZXW(48/i/ڂ' #o纀.)l%Y5kf~-oa3V"p"Alvyϩ]MhikSSڼQs|HjI0IX$}PCH ۾ԎpLPјAĞ)BSJfB!1~khP]o\f.h\KXk֚5l&px2b[PWs]|1#Jk<˱X9A w# NH o&&>AZ~TR,1`XE$PDȞhG]HVVrXPM7q%=Dr}}'_Nb:bJo N@`j>5Kb`p`2~xG̛|I;[:mi7<7*Yd1bbm@+^ WJ8;%8C/lV?oq*:9[%_r9h:'.4wE{Dd/c>jrzp #Ik'cɤ7Dv$n|YVP+qȋO81]`$ÐhCxx8E^H!Hyakx};ܛpd3ď]+LļjC,eIb!\k&6"!A  XMGq\·aB}}`'΢MbF(qY\_(mloo?ܦK|@p6^覩\l:bj]zn3MXѤBY XՂ鑓jɟpv [֝^+{epd2|Əj<R'[+p>1$ d3Lb5191 uɡ~mjWK6Klm!|%%|>m'TD< ^H䈨Nr/Y:mQ/2Drx$et%ӯr\Ւ_G÷o,d!r<kx;4|* !&Yeхom奔ňQW-~عlȉ6Cþ`p<*^Y"+rc=]0s`[ZtrEvI书+?xO~b_:{غbe58Aql$5? IATmh!,q><yM7pD(-:=:3fk<_3z{goclq( @8jy^rGr ]$%S5]|ͬ<]?aph8|v7 AZH pGߧ H L@V9+7 II*:|tU#!8v9:!@?`}̿f8٘lo?x:ɖRG+-7]N>$EV+ԭUF]UaKNGzBﲀ akԺc] bA6],g qJ!),ӑtzE +D_Oƒ1$/MH.^^ըUWIh e&&nBvfGJ2cMOIl|ͤ`cբ*rcw5RG\J*niI!)t011D _ _ٽ~yr6Ak?I(V` L%J^ֱZ}M6v6_R^VYtVP~$7E{O|]#ی2_ moguF^|;Pq 8"%Q稩**.Mo"'9%&Qu;l]sN&.f:eAXB:TzBKͧS|p>HN a Vy;::E:"X8di}s/`R'I{k4r5>Bvl'?_ BPP-i_n+ 2AW3X2' &9S2slFA>'N`5j^ ` ;v\qxܟj􄿬ҩ6818B3A-;pX= B| #`WÒV-ڗH[?ow Z6Gg:|ǵt-wG\toc$8$q9 zEeP$٥ҪbJ;1ѵOњ> L%+<Xw»,+\^خ6ƚMtK'SA'/#T5Kn7ࡨ_@k{㊧$lt%RtDtզ>]5Wwaν{d`sF@$55JŴGLM'I(mYAZل } (ێD`Hv^ׯ'Kbg06Ɩcx:ǒ{U+kZڟ‘4.5N/p QCơ݊8xk`9QN?_UOx =*}KZ YO:p|-! k%88,bE-g} lUen{v͵Ry=',' +a%;b,Hlސ7pūXݪ6?|j^ 8STg{#ԦH,}[y_X4=rh%裥y=GZ"Cl>Om%b-{/Z<Ӹ`@i;`Gg``)fpKv+mG9r7L;}˯p_B` >&O Al궽UUE]1U||@~I\]Qg\B'k *аT< X$kMR1mYӨy|Z+kӰC)G&>#cpoGp >V*9wV7ց}Ϳ?ş664|], ^NQ ;ZMUyc"F =a#AaVAy~ڮ6FX7V(p2:rABI9O!WU?KK.-Ɩص8E Óߞɓ'?/t!K ՔmLb 0UGDV2{x1" {;; `5aT `w9cpxOzCd2-kq,-iU4B6_u?S_P,2yFt:+WU"mfrQO,;T k 1hoO>>7_:z#b!r\G [j8IЮU2rf08qAB̼_Kaps+ fӃITSH4H"ރ18x@DI4x[`̀ъ$KrLos#,V6A!oX0s=F?xPGc- $,mEEsIn d Bb&y+aFp6tDz#&g# $8#DODZ= <[_,V K:4B[G8 I$IL=\WRLMHhs9 H{ɆXKy(k[:HZZ)8;jeqBܻg&0Ma6gұ$FdO:u̙3ZWشd2FphN@B>x୯nEܲтtӇ퇖p- 8zᨘB.|v.Z^KB0E\N[]tIX=_.Ctu$]L_V !Dv +`8~Lc%;DASy|vx@`:¾-Z )^!*6IHl+G]I5bC>?ƛ5ǿ}!&l!wߦ"~zXXk7gغ PdhA) Ar@H~$뽜/([ɉm+0pJzTLIrKGi>$YHbEs~O1b`O67Ox XӍ?O7x}mo?W* 97yrX4&la;q{Lڙgy9 BʜϞb_8|qRI𡐉Y=YW[[\mOضe/ro/ȇ<- 4`q}}TZg?q^Z/6n+pgv^Ch-zOH>.b>.Wq+rgNPgH4%Z]W_lӆuGVy?jF  㭊ua㬭{EO??nwy1'~/ۊ2o㋇<no?P$+`1t2%(x Q|$3 f^է&ș/ ̡3 dbAuq Cӿ"kDfN6[I湚/_(1s?zQc] 6Ep> 'v$ՀjG(޽w'N<>Aٰ%bJ5+Zd3f\،23|I<a7"<4 ~u ~.m__QlDz2\ȑ4S]Z[ dO$EVT@\y<=Z f>_6ksj t}߽e2[Li2-ʝ_&)Z$YLj4] ؈ 1QlC9ȗtxHQ&I@cj?65eӒ0BkwL%cGepHR,\[B9Ҧ[XzWmI:j3OFi4}8N0_yUn?ty[Ŕ!B2HG@֜$D;+Œ^)t CS:ә3x)&~[O >^{n<-t)\`ʼX9f㪆fp,"GT.d"MtCN>l f(c'sP(lmnl?qbSra|Щ|mH و˧Gd< R0Cޖ,,$ L&NQj~jɿG,Q.H2MMA(=~FLݿ>gSBr"-ҬĻG)HU:%U[Ddq=,%p!m{'Oج=|*l{ cڋ{\ߤx_p{GN6Ε[XwP {6LZ2ng$2` )?v(B(Qd|&dlOˠX`!g ~C& c/ 5_SSSၭ| 2[տ MoW!G7%v5Tc}A %R#%D,d!^~7Ȇ<{Nq}^:I cn^^+x8ht\ (r}Mq@@>ģ'S(~C߃xd4maF!P.qC|uu&7 zn09C.=r]Gnh,$mkGT޳Xp*a.:?֬qɺw}fmO?b *>0|`*Θg[cBb (5OkN!T=_I6ʧ(X-:P;Nw n38/'(?_ӃէC=rEPL/ʾ.3[77Vrc#rqtvZYiT\t)ukK#mw$6AQ,*KSAnDD#ƀE |`1 |*Gk~ s 4IFۏ]ώ2 VgTW5^gC]˗O٘Tﯬ-`RE^N_/ƥf юFp6ajl,tңPC2{8 Iov[N( ='BQGUG< }n",}`[Æw>a4:)2SBg)k+AC}"OȯJ<9gyS~ѫ|fݦxßvBPDȶ5[2UHiyقRLCx4$J}K4kѣG!2hb*PSaB!n&|}Y*uRo.ZHرuh!뮁E@TI'ybjȿ=sf fhtI)?b#&nn7 ‹m|KHdL~^}Mv   H6۽ Ãr,`i7o+j(5)r#5!kt`U꬯UB9CQ(, C -_ s?48F>yNtQӬC,eY|^n9$"yyɡ/D$2ln3I1`sv,ԏjc" cZ78es X7i yOʬ0ĐhrbU )d r&l [\vuihJO!Jz`>D5P.1#defEԉ"ၷ*2{!&_`4ep-"Uv4 UT|>&WYgYd(-XR^FigiBa!]iM]K˛q^ౣ !3W8Ihn3|Xq 3'QD!A7a!˲t3uJffvI9fh/CLJβ.lYo5>w>dX5'Tl?u2{\MYl!E1,ƈyaY[ҥςrQs6 - ?) q>dc3-^uXjg!D˂ךiHe4fg dM:!xMACH2ZL[TΘ YdIDa9 uJm.BDy/k' :U.iQXByp!iW%ta_3o*:}󸆐Y# 9g#\]!4J5vqhi1 ;iTK1w Wq6lϲhBRAk(%iٞ ÊyKgھ%"P>la){asw9Zj.#z%3ϵ4Er*B-|7@ahv4UTQ|ɰ6IumjZ!4Q:;6l 8_ceie'";;X9bhmVX$;{ԵkuGOw7r6N.(е(- !Is!f v "&"̉U4M 1 - eP/K-6Ұ5N樻e_jj,v{ u?\.(P`Z'>sVe6?GDV^h5ņwg )pvCZs3$G=]t<Z{+ Iŕ^UNrޙ !n`IJXʩzM9(w izYĐGFsr41Dۥ_Jf#bSKSH#bsÇ5JtQG@9IL=]>S}-jImrZSIԳ2 LAߤPآkҢ|y-h09':#YѾU={Yᒦ0dYy:>{htt/jo7+J^zN)?L$)LC8?mi Fk!F9ݟY",U@Yo; ]^ Gl*$ ɩYZMr9gsǭڵlEP8+ ߂tQ!6:(.<)S7A%|c'@ 2b58ʭD=3gְ"hUv,S3gaxtbƲ-{VA ^4;\8:Z2M$:)T2 fýJ^^bK.A{2vq&B] :ݝ:2rT+|s/&;kIY3gIW!Ң̋w+3gi1aG 57lm@-l߶7o}eA#eƫhg!jt Ix,˞,ӢsY\CQ:?ggccc:[[n # 657AT|(Fآ  ( N_ԆgϾK 0USf~j(Ysgξ+\OؕfJY^Gjy6n7X }s-Ղ{]k$ׅ.^ׁ?*!,҅)H7G6 5cAa[PQ~NbTG%: &|98T;7R嚳D@Q;F,mdx* _wm2˜zuF&ۇY(dWt2gD~M]%͌@"@ơ*H3%i1z?! t.;"7lQ,?K >/xOH!UWB݃N֜;W p|.̧>i ?j0D <.O2DͨXr_!D ǒ,; opDl;4Lx&; \UԿki)Zʔ~hNJ ` _Dž}ryvw0VO9 nrP#EPԒx?(xpEuu*g_-IAo}\^^^FnF);J4TMG *e'EZU@Ž.$[jgl#{{St0٭ @1UQ-s=M$ Z(ݲza χ[Xn˵g%?WcU+J9VD8Ζ@n W'k}@ >޶bdB!l\//nZ*P\Yߡ׬PefYHMZ!}mFq۳ѱDǣS{ qlbތ{h}Al4&ϝq?=BH5XkB1n(Dt?zpuK}-v7^.+|nhcw>ww_\?oߔnnF3Rd%n啸{*^zL{|oojjt*ݎHL&{S} U4D̹}AR~~iyT' rFKU߄t^W>wg!ȓǹ <nCf돢Ѽx9n_@3q`Fvfᣐ|y .|c5[kV|,goOfpw񽱩{F.Zvb(g~ljQ'+ n2vD ωNKw+A^v ? kAJkkj!Յ* p&{#?>TW0 C֪~ݢf˥l->fL6g*4!gZֈ ҋ5,y]fp@z3XGǽ{{ɱM% &^S;p$خ C%܈$[%X)Z>1dq(v&I[ڱq]3gx}6)m꺪舲P1˒^NZYET`oR .Xe *YoH7/f$$|~=nӔ y:<{<HIISsKSsE'h0B2NRryMꉏ: {@撅4٨-l]0E#o`UV6uÂڿFw_.fŇԵ#̆v!3@VXsWg7sZJKH Jr UOOϘ'`޽Mc&w$QB]Õs<%ç+u ^ 2N -'&1d;{Tka,ڡ76jorZeVAvn[TRP?^m',M`N WWpD ZChu$~9]~\K0YdWvk}+{IO)Y&[$2I3ڵ eז߬, ՐJ5`eXeڤ"\J,ేzz:䎞=OǞgoz8v^rnr0?AE (-w%hwKF Ϩ/]q*$j^L0Np,T# i;ۆiޕ_ϝ>{\k$T~Ti63i[4S_y~۶nc;(5/6۳^ &ՌF5!n/^tOf^i~FzU أm~tx:<鎎dT1D;❽;Ѡ)w1=%PYhT:parT% ħCA{0AXk(} 2R!mڇvaI+YuRU2\.+ENQtsr@-+n|#|#ya&A pF?bǔ8&)BN A$<8r1a3(Q_4s><И`P46=ilR;#=! .; GA+h vZ#꫹}m[1n[euJ ?۷*DDSR'RY*[FTk5n|^"$Kҍifsfsf%d|_xzb3 ٱ71z| Oqq?AASȝn+@)0fc = }B3WL8Ȝ4 :J8H\ε~C7MeA *r:1Y^16_fj^+0/K37.}{1ٳݛ؛NNwb#&S)Zbh'Jx4^ vm17$aIF:a GF5M^wf velY%I|EW;, ۷ώ33*F m%0Z4mGTn<="P$z8)ISnOO:TMxr㪎I|[pf_FT#X>!¼WBCNux=W(K%b29JSA'ޟ菳siiWwWWi04]bѨ˅>Ѩ8T)? W(|5/ WērؙMEuq;[&:WUbqVqms ]𢕭2kQf4k7ִ1 |yƑku;4aܗO+v:I IS~/׻Й]` @Z+@~DP\)@yi||!$n.o|OE2A25" +k*H~Le'tm6YjX V6p:-+ڵ_w'Ob(!" O;~7$.>;AC Z9Jᮮ`W,bHDA# &E0ƍ oib~hp3,[ZRw8 đeVwdK 2$C,!vh-#O-y@0ya@ga@n@S4x<1y:Œ$2DܹJbPD8J>` D+upȦC5rxm鏟hy{N@%2e3r7-Vc8#@B|/#ր0 \ }}r$&Ǽ^L=4cHN-nq8t;];FOvΒf$eF@CNkוyE+LAwU'+B}];8A.4>SD86Nq3W:VHBC HLu޽䴘~L;Sq1.haO>0$R(wvZWZ;['D.:.FBP0aNōHU cB*.6DjLLt'#ɅU4)bk]Eh7cZ\t{ (#>G^LrR)D$;atwݮ{{/wz{7@;#W"Cx"f  7-v0UvlŏzTENqۅf](Bҫ -lZłO3ߌ p? ׄBۀv&' *WMD؁I>t:9Ůx?>Uå 0$ډ!ƋZ&5_/:L藇QUm. c@6PX)"RAㅤ܆+^. !2dH vv bY,ςT $FZ kŸ*z }m{^'{r+zcw:6=-N?~a*#H#NbKOA_텈쌼~JʕHk<=2Nq1֖ٺ3/7rϭNk#z3#V?O2f~ܶQ1帄@ԅu[Ew;Yg sr)[!2Fъʨ"=K ۄ6+&} +z8-ć)1S#w!dŝ#RwK/_t{%0fy3r3tF244tV#tx((hDŽe^4Ԫ:Huj!h5x"MGE!\%BBWo=;V[UE16Pk!1)ኞ6Hy^=8=|bj$5":##N1tC;՜;5XbFA2,hgojV̰TO B ! GڄUMn/==H{1ȲԏEw$3S ;Kp?_g/0$ۉ>o 5d2 N ИtpJvm4>TdJňEMپ3WgY-WX䘟x ;ʢ;IDATӼfT dhjAA@%QCw_BhH{{m]m^bbl:F y(>~t#)0⟅Kp8/Aĺ9A tly%~ʕȟ"Э[uLuW MUV85PZ-,ljYWYYB@2.[^ZAv<BІl6Z̨ r+OA?*x\ڀ ^#AL#A"LHB#133KR v#Rk/քS,OG.?qCI˪J=4YN6JVY6Nx;l:^isba1K(R j!|.ӂ1mV&!.A&'xiK XLBI/ IqRr=> #ar7q9PbϤf}BCH[D:M9 cԌUdmOݢC!C2}f;Eu;(qsZȭwɂC'.#ZG/! Y7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖ZIDATxp[ו'#|hHW 4atkǙ GQjDͨ9dUrb%ZB*C%M*ka*咊/mjyIV^Pr!u}C"!s>{9cOryéTp^z饗_/Ǿb/lk6#Brד B p/ ~c06b招/76kol 7R ňQpG1@y!x éW_IC/㱯`G(b1^D@BRPE[Ah1|rv40 We^z,V~Db?`T&"x@M8!0&]nvT"0$u8 op< Ą$eSl? R,fӃ`lJT>X"rmOCl) ""4[EV9)#HǢ0+X, ȐdHP.Vv0D/m  4۴[u\^A? I[)F2AiA0YLy@H<+JE1mS[$АEC &Qz˱l(:7yЦB %8 6|Z"aI $&Xi˄ VwA,;Smǧ!rLXX6`綈ap~fy[SP ?] ,[dM@Vqݷ9MŢybR n'|t!;dyyZc ~B$& Bb&N'!M'lҝB Yҝ"2@`*sL:Ig>ȐIдYȽ ?(X6҅-[tF5)2VnrS] "ɼl,? j)k2PG%t[ȴZ4 n Q$E ql͏OȐ\LrX~K̚)極&).VLTPT1U (B7:l!K.+I/aXe&eXu˫ͭv8D_O=w1]27q&8mm ҷ<@yE(%&f;SrO+npcE7pY_ݯS.1UJ>.to! #Wn;~@ܺOLG؊,UĐKCsEQRڒQБSb8r>c\AÂZl,+b4yISfs\yߨbep!OƐr|+@>YlY^t'\idȣb۵"҄q2M1?ۏ I-/-ݤ;$˝-EDȮ]vHDhD\,fplp&kA#yJ but1]5~s Z12y H=%/򀌈esd{$M[2 >F&zpxq!,IU//3z"CN;{ GM;4 $R~g<`c:b=jJLkL#i]]UFvi 5yC,lV7*oG=xxqQѯp !L]+}gɚ:4uuBEʐVϼ?qP(}G`HvEģ!nq!倿%R|)~7}ɻFPxēF[q9r*1_Ax8;?ΔȐyyW0Ҩ/o_?h QVfEY *d{㉽ Hm+|p0XjO"]@>ٳC&NM1414<_#uY\"POEtWd[B24mQi(ڳA $ŪDzj/"'Ҳ1XqWXc$D0 <5]ѹ` Hrj //DHU>G}zzZiqYk'a9@ ֶ\ea`m־>5 i3kQ59WUՀޚ~^f(Id<ּPڅZjWDx(.x"&lww,[-$q lb.D/c<E*C,VC 4M#(,&䁺wYF;" = EHapMV[- $ߏc/H XRZXX*&'8EօeZ7(Y~tVXMOOO1 0l6Y]f0=z"#:\̊\RFXYKHr9{/%K3a_ci혬~gFrjN/E/I` ׬K%Āldc]Qu٪!wGk==#D@o` }|ǖH `sGK HKp!~9Fh V?jmjaqaA{fp (AWbH ӂqsieEPFt IAMp=#ph+7>F̐p@wwTmyr,d⧂-Ca+ޕ W&j8 &Ȣ&&&'&ՉYdԂA\P1A dŗ1"AɚL^$ImD۫ujM|p+QbE'و,"dʺ:/u6.<O;q> pLHKK HL KXZ$ZE,/ B"+"RDi!OdJH1JdG>2?;!{" ᙰeUm0[,o `x8fj.rmYpnS0hr9 44;hPM\AA_+ ,yE|%UU+&P ֐oi#v}̌Ʒ=tuE!'0#J2 v?$U9$k8e`.%<{wPL~.ˀ --~!ʉDoڂ&(]痤t,̑ɉa _⮜ ORMu!ŕY>?*dg;|O'#\CjR0 \?!Cxjzfu?T4HqZ QnUb_c2ga_6c| I* AaWdo&|9->hrP=!;ݕ$[*!5Pg4E]z0bPDQ|`PDrqbȤ:o:/(Ԧuz׸TVjbH&+",[x/dm! @h`ELV3Vs}2v (b&Oygo\\\$FKrmWЕ 5k\['ZDzĪ3uR.D$ۭmA \lyS6Y~_XxR$^{ީnzL"[VLш:%kmKbfIQ^*!?E^gH0\a)Ƞ5ǀA)ќm& KJ(-~䏧U"Ӫ>^#_uiS}.Xy&b2 \ ?2N{K9I3 8xA,p<Ϟ?קHrK:]GK2Cp\6^ 0$ yT+'b@ i$lx M]I꤭ ð*{PH"U.ޠT/"`w~LLLNCT1:t)tß44H65 +^Yu9U3 yD]V#X}VaO^DNg ހ!,+/þp𞹳Xt||~5Q͒_W4dOt]d]o_ޥviJO \zz+ĂMB:AK}>4`(LZ mmm, kyG '_\.,ûc ) (& yg=kbP?75Q[ ;;I___#HL]0dz,)mjDBvuʹ&noP{ Hk,Z>9r G }%gȎc;=Vzttzj||\VPN"6`<֧Zū}tth'FKpXg0>_77wwΞ|M-N-NMs&U׬~RѧGi]F#Ӏ1ӥ[L"V{ z_d ._\H f"ܱ(J `G#;2& "C`HGGݻ`֔:~ Y2)vfB [pHM53Ƭ>_ ]?ٳ_?;550pLL-N,.NAkbrud1/&k;OɴE uFjMd<`uuELɨ w(:*!n!0Ą 7rg-B!o2Uٽ --\B2)3g0?i 6`#xzްP 4_45u "54|IU9IW/ ~OE W Ѫvh{Vsσ"====vq,+o^B`HOapωW A5&&t:@+}0?]-\4??ijjnj #8Y3oQ1o_'D3$4 ƨ\;#ȸv}ubsD<ϳ@78I"bI"q`HP4B :@r@8AocE'QP^c |>| ssu0E1Ȫ&ۙ3g'3wxݻ7M*Z(f g֙mfuk3x("C'8lQf J!rD f$I0QYCt!p4-?H?jz9:PȅB0[SoSg>3|z&=,m:@12q x"mn03NiLȳ;w֝:HJcQ`%BXl*! C..:KYMe҃p90ωwGΚ|_n.7W+ /^x0ccoH9NO+yk0ij'zOHG 70Ӻ]״̌hљ'1y" "Fv:G}[K@B/jG%SUPLN~xTÔ\;F24bΪZC?rm1_x Q:?vcƎ1DIjz2AGG ƨ.E c`,뚦A9VFˌGL&1Hx< ]64<۰!Ҿ"$ŒQ%܄Y, 8M>JOp* F4J\PӖ rppPxp1u8u:ѱccCC ϶;M (5 m} 82Z&3Pd("Da׳;F;bJ Wp{:}战I(|r@DxQ(| k$oP.T*5V8z4K !?_pt`m^B%ƕqe c$D"G3 pIp v;nif xfx:CD~%||+\(bh `zPhHn0;w Oi3V|!KRGYNF*:AA!"oH7NkԴojMW$0;$rc8R?zi 7Ģ be@A,"R3N- sCKEa͟ćOرб\:X}/b0fo.~fv\4qZ!" >~Z{M;8)@"c(h(J",ӾD,, >H;C 3%D(fd!F% !QA9 ItIE !|qP 3d` DJ4Y{{$7ܮ60 䇩W nخ(m~"k5gz.w Q];.![8 (F1;\^I|*(!i- GN94#ehB% (pm$u.̚o¦97O&/lkj:601cp"ǎG _`fOX,?VuHeO` q4N5#c h2+$e@Q(EQ_r E۬T@⦫CBBLv8Fc;L8@QU\-Q{IR4л:}k+C1 e`CfA䇥0t q6k*<-b9AH&G|gu,x[]m[L vKU?p@c5!m凾i  &U~Z-bTG0hOrЃ 2^/6R4?v< L1NzUyO#4y$ˋz?t 8`ff ' !p4u!']s`HdAwv  a.(CA(Cp8mELK-7 +^U,t@L=B7C bᛢa<@])_ACVj՟ߺ/ɽTIj-Bx"">N?H$#1H^s^*Boԓ!J% . oCAc00A28*LGq ms)C\Տn=UӋ\h-XM4o@t58\X[3#ŢxUYAս@DЛ6^~02@B$ $juz?)"n AjIne?/=ŗQ2?$q&K[$  $by:9GuR<A>D'\7ߣo#t8`q02gELf` F3m^0/X4`LDHH;C پiHcC]->!>G jk0" ")ʀJP2bۍI@jb!taȺOK֞3w`Dhݏ4 ~\axƏe[Q0XIJ^h&FDBt4Vtt8d P'+fZ!H$24ujlb g Ux CI1F.|<*u bD"=fL@w t;iUc@{MK3㊖< -3H$4xW "G H"FsN)C~.@Ad烓A+Hb _skn+;SW_,\xp (9a'zкZ5aL;ʼ, yq#chq23PI^V~Vbu1[VXT 4ݔ^td}sWsW s󬦁tu?~,r Eb(3-E~s6Naȴd4OgSQInnBw*͢rM0e/WyK>nfQ1;w0wn0 oN]lpMG (,X'`l8q!m\#mi5Zգy:;;= O;qkgt#ׂ"d\^22gPH&%\)$;Fy]=wun~j޵]¥TbXa Ze9ws`E5aZ*mHWG[㧏f ^mF35>ՙSОgvăЗ%?xR#)[;< .Yo%+RXy^_ܹK߻} ߯]w[ΏƎr8lE'բa:~ŏ\a~yDGij]8CD隙x:x< F#VȿWڊ#l(Y; Ji +f_sϰνS"pt_L;>ucGɦp*-`] S;br7KW߫0[ kui{1z JhVRʻk.Xv+[;P\!ɉ0ٛ9Xr)Rլ"LJa$ΦIp&'0ۼ-LM;z$ 衱B)|iGzGIjSDO]?k@fzmx$OFz[göQʅTFvxojj}Ɲ:Y, Gl$}V/+IoiPhQy6}-J0@ Sǎ*Ei:!ub<څB`NςH5^G}DcM@ăL1W.g-2mU$n0:'HIu[ҾvvW*Jeڽ]SmAnAZC }TCvi;A_0HXeAڽ05114t @p ֈŚujۨhoMѵ#2"$FK 1"(9HIDBn+?stly6@M]vV+,%sZ]]m455U*k-LLL qfGaFg@r0 q8ݿpȭ*حHB0&ݕ;E*]2 rULÐL 8FwjZp,0pG~VGze82[`=Ciدɇ*G5WV)W%YRdT*&p~|k.;[^k%J|¯V1Jdqb3J X<#w3^0[pMюr_WDDt9 Gx`+W5Ñ[]nzʖrD¤2,@<g?B죠Fh\UZ83LDZuʴnq}zB/#JJ2겞/9=&C$wx7D@0ZfNK`*ۜa'S%˥J?]yҍ!v=1$VH\{oqbruXfpGzF#"7‘qC`oTĘ+Q/EHTəQIqIADhB/;*Npͯ0-b%Ӻ@xaq II3j\]mQ:`)l2٧,2(ZHI3PCga7{U_y܈/ml<|RaN0UX0ܸٝsZ.zh%hy`VVVVV0$<,YTϨgjH'f@ IBcK#6kj|T*򵚀 rrr9yn9W$9VBֈ]0$T6x_@2wicE5U%xfjl-@'!N5k[l$V@6`NLNNNQUl:FNa‘/ѩx2GVå~#?3Ń.LӿeNn%GKa2LnJjꮈƌyew0/8|PpoE^ d0[S1ET=jI|XqxL[ӺkV,mJ^M I##==#7 Vvܴ,GV.{tʇ`Pwvt[2SpGt7VxG@0H  =Vǹ8N!yWd^vRF,`C{idAidFc)sd|x>s7:t޺BN¦ &`8>~Ȥ߹mO|Jϗ^!Da0 @8pB|e7("*DO5i aWG$xffT̖%TYqcIh FhWjN(k Vr/9HXo$ň)^#l!6\.tڦEhDfﱳ)BM&EL2UebͼzRWndž$Rj|H[wͬwx*@R`~20MVttKa$zzFzFF&re R>V3j<2Lg5A5Mj sodBbHgρIlŷô7[ۀXL8&!ߨE 4fC( !ro*DQ,e2DA̤ rbW CJȮ]l|"&b" =snA5(\AwK&2el@MV_EC\TCjuL4YӂE?JYxj^CcQyo&-:E$gnSUe>!Mfp4`ّW{LƅM󮓑Va0uǀ92~$%k&BbB-%KR/M,&7Ye9f`-L/K:p*~5oUM?#qG ݤ5P4&+`Jwܞ= !`aÇWwTH=8dVCta{$W`b& "xRv-|h_sEY˜UAݙʹd;FS7nC.O $oي!ް?۳ǒ~v.kʑzϛ=D#dEik}oL}T/K2Y,wF! e3>=ME^" kV{0"m$&=J8N؊!YԝsYvICۛ6wt{I`"6xSJ_р1nQˊ^.}!04mYٵ }sdW~zWBVgDkL5lrcIlOCV%7beHRIZE#bI΃Nd@5HC-"rr<.ԭt{Y*]XYOV~V߹nܹl=-R:b CX27GG3ĺ. Ej5"RBޚ\l(R,YC*Dzv 2}f_ ;3  SOY\pK#,'֟$N!Z7ɓZ* @dD T.hI)?7#MIl8 D"r0,ԓ^ػmޟ5N߱xZp`myvaWk+?_raG!ВEl&|@N6"Cjn$t0^r[D}ddzdZݏ"x|V,/Ȋ PC+I)ēqi0) '5QzpG"~{緬*z08!h/BLu{[-aU$[њ#0sY|z\<Bc1 J HU~*~CQq&RKƃjbq~{pXBε%۷O#ND a@ pu0` C C)I̒Q76vG{u uMjLiL$[+@:>1/Q=r_Agwrok:FfIsbonn7ջZm""l(=wܥ?:$T''ӯCK7yg계uh5s&;vuuiZ'*D` [XJ[h$v՝ǚwU0 Tiz;-9{G7vh:g9].O͟z{.Ng"&ҨZ2:x_DoեѴ/tui]: ȄpшD"]}-Ip1Xb$5uK=R;wĤb4ӮY-VCo8W;Wt⥩wǤ:qf*AG`rj`H4GPzh?siZ' ZVK{7^wEܽ|Ih_&V/u[VyZ;f65L aD@TajY=nU񘘄n3""]zjP:z[6)a tP:Fcy#]]Zkgk댇JշR pGwiM%\+1@˩hPJ޿}GbEF%9rgulELtk}/^xƤO_P<~'p"RH3;|IZf]jbo$[}j{xyg/Blb|a,5v[oMͤ[XuƦ.AZa<2KHV1E^G1h\4 u9xb\Ogh"cD3 㳉Db&x<}m6o@k(S:T!qtD*Sa6hAƃ \ -n;mRoWVI3Q&B[/"l[SǦΞ]~ 䖴ARт =.o55#a$ƕ1`T:̭$'x a.N{T\ݝvkao,6R_!*D1(eO* -~ |K0$-,L11& :\E% O^'Q4W[u6~AxFa-#i4<N} `g1yے]v@0H_qp&C !zCy 9 [NMML 4 ̒orhm|_׿6^a[F a#:$Iv%v5+o]ݵ!"GAB.όyiVx#DL mRYnʗ)k-MWhjysFdpJ9c05RLPIzaLTuB?u?m_3i|x +!R6$ldgCCdN*ۻL"\YpV3`rn⪱\H6YY}1Ph;F^s.U#!UM llѡѱ7ƆZ34`uA}~8=~xFB1 q+Fw հ[!@‰RV~)!UʛkOhMƠ8(rL򆺟.TɘBj;B|?J љ&iD %F缋#a2P 0Q2>gW{C!r9+-kUicci㗐Ptqک2r"8&8rj)pBq0J sEE[XB*c88:`44000n%5gAow ? nV at3Wy-ޚ@vs-5@w[4mMcS< lbаS   Fi㤁qaG' N迃ҿ>h(@(WnDQ!攀:/MQpxn;LgWFcQ&"Xnr;4,ͥ `zfL c uPa ,$ ˤmQĚK$p!j 9&J Do/!r! bV &qျ9phN)$x c&I`X!ҿ5!ccVVQ䎺Qic,cBފCJ4r 6뎳~o]X^^=.!B$@FM ,D\USD, !t-DYo 4~k)=p?I}%5 ?SE9PJ6@ я k+8o6MOӨB0^`Yy''bKiNCiEYTD(C(2~!}M0^00+Fn9G5^y%FYc%ኻ\&`V(X8Jq֏. нz\ !.dyP.G\YT ɪl6D(F "VC_@R\ň Ʋhs0bq8rn"[d%[^w PJ5qM%o޻\ Сd2.cH3,?3hn%HA{9d nVEl:9=:!t)HAZ!+痸Ў1.GYYXTi"qa>4%R k:3Y&C63 Ɂp!% b:MNJ~*6X(&! r$VAj啌?[ǁÑ ´hqզIkQB*h kn \CDHz*E%Dv|YWX>҃!!r߄./ LLA 67~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖IDATxܽ{\O3M0`8O 025)xDQ@IÀ AHP"t I{WE{ëewik?׵}Xf=5j ~\׵ֺ[L:W_}uWA @b!6hعsu/B,x%K,YbŊ%; ֬Yfʕ+ϟ?)2۷o b#ĪUV;wj???[،"b99@,ONtL4سx <m_%cŽ+pxGQ ^a+WZb-MS_ ib*d[$:k^ȅ)D2,L.}݃Ma wɓJ:ȄXm8aٿ{'a ^::wj&/]FG dE<}9x:;w5M'A%[c]![ K;(s^rw!A85k(c1<~ES2f,< Ak1 wOkBXKh`+!-MU@+S+`v S5݊ح l&ֆA絘̧ҷ.X'ne _d#7]Nj_ʔXJbAG W ,6cYCNMVKK"nҹ^pk?goX>LH@$wG{v3su@nEݗRK[ d\b΋lyކ-˙5@,;\yxj&':I}hvm f8 \X@GGcM9=X/p_@--[26gl޼eeƚbyg?=s3g΄S\[~3oAam!p1g;!x%}R:s"d͎` xq!t@6+[ddlܜL0X,Tp&?qO!O gG wY0nŕkv@ΔX:UnŹto>4?"ͫC*zdeD*"Qbz"blgXoTğ }X,{!7c-a6cQ]vvX*r3htNu"Hl}68]頰8*y, gL3}XSR3g3sE:"v3^u VlڌH M`!3fTااhfHmeVMphY^9 y:4bg"+p";p`㳈\􄋹shXٕ[AK_B7;Ok=¶jX@j+4{D2 yb'gO  ve'֤:WGW>NGǾ",fKޅ^m;Rp%Ybal@4//ずiq.*ZD̙OZ=% RŞ####GϸŎ4jkւ;ltttuu*>_h#IztN8{$dd%w(;5aB)R+2Z JSܦ̙2}"@Lzj24GbWW$ښ|Bև[GGFFWw:G wt=~qq5tnOY:wj${v3 ^K$gnp<*:rYXYivE[Д9nS@!'(&B\?:G}ĎdڢYvs}]LjsǕ]fqq|bWb%JXы:r){MBaw#9w2_"3SaeEEFeq{bʔOX/3 3QOӕXdh ŔF|RԋmvO5.C=@4 8p9om?ESG߹{dS+KSnEׄD8nTMRdi1mʔ)ek<źG5WZ= $3&O(q<{ 7<]݅5+'p2ض}ۧ ?]m wќ%$K@9"ڋlm~.@6Zv遫@2bF*rΰ@Dܞ"pbWC_=WwpK;4xfs 쏣AU 0s =;^"._^|y۰Bn mQX 0b҂ Kw,Yb;rlҥ痞_vaم/loں5yFt*ґ@V70YK>E?b!svqqsssc@La<# `G]Pԕ0H, ?}hbW!qᇅBS)˨Pw# oq ^\4vGyD aEB҂_H_$kŊg8k1:~g^….Kغ5!fӦD\c&kB $TԒ&!oiq˰v rHMX$,GWWOyXDy WQR!|P  ao__tl;iO?]i⪅Q>"vܝ{]غ$:$<%YKV95g׬Ysfʕg柙~Kc'nMHشĭB\b% #C~ʛӬ3\\llڣ71ybʔ)Á@ GJ.vwuD|f:L@X)(D B!_ ՞@`{,4p쎈;,l]RXRRRRzxxxxR8Ƒ#}Ś(֜qf3+ }@YvŲ [-BpjVlnrPY[ "AqCA@xǰG?9:.C,ziǗ%Wⴞjx_倆쭩iFA񈈊X3"bwċ#) 5gK1;8D@ GD#!q{bbbܕxjڪզRk4ӾjER d B"A ],R[!=" ŞGȌ@Ď6p=O,a[ 0<}}{z{{64444 4YR3Pp 8""#"vF%  /+*-MF'P,c"stZh#~4==Bel^%O8|FCE*d-k!w)O O/DBZȈɣɉax1 ǰY˰PNS獒 |9AcKa|B'c Ř8] 4_R!ɾⵊkzo8f#,V!ڼS̥wPg4;u7n*ɯo4IeŁ~wfRZTK~GJ94=E I ۓ\ :g8Daij PԴV`O>M^L<+m׮]o&Rfl4:ul$YFq!:]tkp%ě>ZXXVnpR\N#HʥWR9⧺K FjL@lpw @Uo D(4 r؛:'6O{|@` 195ڿv*h6:Wk4";x}( Dn.]/"n`\njqqb ,$(4---$4.~LTS@N@-27 )D.9ť@1ʙ@k"4' lmCLz}uŵׯ}O ̈́Vٜ__{~F٧Zc4u(ƻɸ)dx Ê@HXX}# <c@D.~CZV{:2/*g=1ōc"V xsLB<|>!TG,/H,J)ږ1gcDQؤo_s>YDh_kX!koJ3n4tD2%8k}hûBL* DG).prI u"cyJbx…6<2j2zrylmmmyDYGev&^u! l6:Uo77ύFow8@t:]%3| Cnnq!RHP LKKkn Q^%^A-^%,uoSe*j'?>aU-@ nn O~'/V&SlDo+Lj*lI=FgWz?FP_h7盍 oCb?r\e*/wo}s2 fcDH AiQe/ iD!2) 9@&*v}_ĉ({=x(8X Gx6r㲏jueZHZhVjY_F!ʲFP|Ցk %a:999;9秚ImDAfc#RzoK!B7sH!7@jǍp 댕eePnskg-!....C;D/|, }XzmrqV9,սЈX:}֟Ng,|o[[ӷ7Z@Nޜ}č\Aa"&қFL&oCml$3dj8J!ekoUøa|}0ah;v̠b&h!H Jщ$򦶙rLeЈXp%8:fDb+ypZ3t/獿א @= j+7FH1(өL/9 q75~H)ćmXBt2sV9>R=%VYe`"?'$A1PHhّk:"Q^X™$7|ي!a }}қل|VV+bzԏx8Yv-ɉ2ui#/)46͜OdqBO[=*4񒱲e4+ j[dqǴdU~ iQ*RU\ĥikR7)+CxަɆNL<HYN&.=}ya fԮ_BrF~ͯ7*?pwj0DgiEJp;bvj#K-P0Nǝ9d,nm2R7 Mz"@T<cS˱_6~yMO̔CY.cWee%YgMO ZJYW9ګAJrЮaL]XZʜUv^db6FCr%o@4@ozqDyO8Ȉd1aocuc#εCrh4NhJW"a0;j,YZlUrY)K?G\.XL\';:.%4w2?("pc&o O`i y?e"L`mg3ٴ‘хmBlyx<C&''=ڔݏ>N$|>ۚmmUDVp` ^Z}^oqTWֆfl4壅uhubbaM@}{22JxCKq3zcl%hl';% QRʥRJ*@ RSE3BA9(ay<B@\ bsDbc=)q-u 0y ^ %| ! )*˒k8l+NԟQfnӛ 4J4uy8~87Ǎ~_@ i\2 fX#e1e\yD BE*H*RIerTvʤ!WI*-SIe"cᝤn@ɆX"J$D"()V ڢ5( vs 4SWH$=/ *O`$'ՍSfC溛u:?ցB߫40N]+ituX1C!7..7Hܑ#GZѪ  i UIEfH ˤ*HT5ALCѸ⩉ #I'LP" j9rzR696J>ߘl>uTC9dRV]sȝᬇ뒮+>>p%++=ٙݙ},;p !(ZDH2EԬjV5>T"J$§ U*J2"H*Q(RoGr Vbv4 ;9{{S,~o |/g˃<(_=}aOO0eA)mm{kVWUUW}^uSmN;U_{.cVx1gnCW%]e|Θ .tTf#$MlڙZp U"!G%M(CRyyyW,kAS%2N}T1)SB]xzǂH0,ɖ"xЖ ty/!%W;3 9!9q){kRR*RTWUU5F(kkO坪ϩ+KO7>aB3!bt1111 Qdghύ8YS*NXԢliniVZT^^iv9S0PT΀D*oX jё k O!=@@ @DGIěO~" b˧Re+nå 4M98[\USUXS^ޖ3c&SSuh#gw. GLBLL̅ MM#G  efPYPePx /3V Qdd2  RnDBj$-غ=H(=<$t! $T8;>< <^1қ"@q7%D(SjP!"G]ci##4..9x@4FCY.>>&QT^PО}88EqBEf\fff2 U(4s3 RyyD"HC$( xLt~B/۷ |}}m<'{'Nxc? ,@!$- qسOi@OOԤcU{)"UHymyNmNRmN)Ȫͪ-KN6_|P2,xTД]PPy.L-N-..DLLC!B82\쨰[K͆FD%/d4;g;?gDOB$P<|}GIɛaqQqr@+4҅U(vtGPs> jjjRjԠ@ ;ksGmmNNN^N^x^]^8~(99CR<$+[#MMŭŅFe[(3FQQQF*Cam.v..,5)vv BdBƚnŤ'| $+a@닜| yH 87AVbr֝%+.teoP{RDjpK:joDyyXy[u׆H!ɥuF ?uz&ԅħ1qوH!4EZFsƖ"k*BW"b¦i{f1wt+@+$|!9TX!N_[ *x!?+5>VP͂8{+o@P-*""vu>99ᥥYGFr<_21GB|B{BBb{bbD# 5757(,,C8i"EQ$R" o6 d2;/k]>9 T-%CK12٢DUZy;tC,2|&V3]g2JqA@{"PHA)$bRx:}ҬC C$Gu2K2B11 @>ڄ80aSd죀D.D/u;;{BxB{xE[lH 6gdp@'.\6tEջ!,yLbXYB@)PE݃) ;+:|g::wdAi9o!|s^$ U++sGu\~XYY]:G%#!)J (6b tb("1Ƞn3\\h!XD0;_6 I)S&HB8 xo|WNSqqڴiӾ bkkKp.,l xtnef8@RVM~FD7KXG,9,+dH YYY,ϝ;w*teet:|Lyѷ&nL܄B9$*z34E>2"6njH=gP8b 8ځMX={S+WBBF#X&qk+>>3]]}<~k##X{`CYb}IY4,+c%-&]ӲcS)Gj´ԴL}E͈,8DFdq2e HāEktelLm: IJ(ly<\xqdzBt*=5Hfe4gDBWH!qpcK^gyq㤅x+i'MB@ EK  >HWK=p? ~7eޚ}UUDY6v'J$*>^@pqSqjj!ȑ#q8E\&5M윱9 q ʘA5n:\\+o719{Sk+&y*T.kR|Hڑ#G2 D)XEA t5k;/k/L,L!{. A39} z4BL"cz霆)) mm5ջzFyyNy[xNNΜqd/K/J^z䳨ªϊN,2Fw:^JOr7*((ׄҏ9vHjIEܾP!+$MhATEE ;O aMpVd͇d2CfqM iT-]p +SNB[b"owǫjTU>VU{>2Ή--Oʡo^^T^4 q([*UZ[ۏ 5ţ >=}S;RHȍˍ;Vx$K';rVt,/2T2f=᪋1GdRYżZuC#'p5?\چT{3)- x1/'n^UQ%lP>fFjH+O^WZJmm`pJ6/T--v!ees1H!]11㛚ڛ G :ss`/|iPת U 4h4L]$v/=oh¨L*Ra$8PcI%<"3D!ͤx/100pUUo~׈IɆJD++M---udC[W#5M҂pȦWskk9]Yו :;ۛSRn팋+'{3'Q:ɪ$TZlՆT$rgQ8y-mJ*zCF,Drx<ډbKDB Rq<Ľ=CB8qP_cPx](褤d{|[w*C*O+M˪|UWwEp{ IJ~+K~pv[mh;9rxϐHCrR JL8DR쇈E+QC r;Mƍ~b d * ʯ$2G~FtTN[{ꁁǵ ~Ma!^OKuuuuuY#`EԌa8u5; ޭwvXg "O}68dd>t7PU\pto X[ro3׏>3A* XDM o&-P]R2dV~_vR(k۵$^!H"z}nPHJ6|X_[{*Tu f*U͖8$!!-I{NC< Z$zdGGR)UʝEPRTu6Bl֯_ [daި3GJh8c-K L.Kf3\k>= ۢ{\lII[^Oqo7pa-VQ}Ǐ{e|l4ug:BB<ܞ)IsWȑ]%х`"' DSOQ% ry9G]}}r}FvGKJ6)V%fQKh04e/Σ1 \/`f 2Q#zHV4Jso[paLIĆ+ i@8uMi1FNO B' {{zzzN=QQ1Psصgg9D+yu$?e 1L"jm MMTa{ya8١7EH&o f3QVU>;;k;%s  "R rZYgKI߁ (@`k+ |s W(ħ;L9?P1}Hg駟g1gOxv׳|:c}i=D~ x([;1twK/ ⦃ OqJfr3"Q5 (_$<>ϟߺ{?Լyt YɎVq mGFY[Xɽ 2>h 'V.^IPLJFpſ}"|C@+$5}^ ([v՟P"7x)pmOZ =5_cGG"uǿCCCC38f> uk,0JG d=E܈ FԼȼuCyBؽtqdnɆ g_;E[FOPm-˰__H/yTTCP?lblkt`P}?QEHÏi4OS6)Js!;o~ : H Ĥ䩻Uk"?cݻDv3x1=h_DIUvv8gL7 )t[o?VknG=kVww7@+ n\2\(@$<_2%UZ4p+

    #A^yTd] ŖGj /e#>,Xge.ïWC,ljdfY`0t@XKޡ',T3jGY}^ssZS_yeaNL*_|ӮEDQ;F ==‘YtbW^ X DlN*{7lGw[SD nq~n̥[AbHJX ~/K7s 9 ȓ~dы_yrtBEsg]:|o ()ȁ )*Ph D&X EDkBE@Z~)nfPD11&CG}߽w]l;_{Y8 SXO~tEL1 JU~grDWPI8 ڦ{0b=}}"r?gj=VHz]9 YX!rkGv 5!!F@4<@|dQaUz>'|RTqYH!~h+b">޾&:g"@".޺0OI:fӭO^"$Ql PۮmyղUt . :-wZHB,F3X) SW<6qaD >Fm,r+ks >xw'=} !ؾ}Q LH#˟xu'+c2DT#r\._ KW䒚EX"jEi^:"bunDFF.X/A>d_he:d̦OPD)C=L6+U,ˢHB$:θ;:Z1_(+X"~gd2|32YGSHz,&d k[o]uF>, aF@.޺h%#%*7DUEZrը`_$7"w5ϨB5kwd&b !CBa#[BU':Xf-F}GB4B1ߙ{}?u"31D;B4H@tkx(=a Ƿ.NCÌ# "Wi-r|"uW!WB+|rr@x$Y<bjLbFGJƩ+j_"D=c nhCDa"G0T-~Wnh AC{^ fq=DDDFa20Ɲ n|g‰D!S+!]e<1H!lVȗҮ+xꈈ . K#SbZ0!)lyb%TYahB>>}q d!Wp p"m]nVO-L{Y9B`rUSSӫ[sGPIfl\K0}ժ$•H@B/+dMݸK=NÚ=䩥!- >>>>:-k$ҼB wfѵAȳ%d&ep,'\ѣWV=!!.y}?·1uIk@L}ckv˦M&Kvf1s-$ f8eB]Xˇ,5D DX1l%M5%\aG-([)@KY%+Oe×_ۀhB*G 7~utMqnAc\.w[|PM}>gYhW:fdaht{vӟ+}duGr,RH6BF9+a"D,F*bp{]#8BW';I\mˆl㍋>)ydj; O7ȶa uTB>nCnl !MM}? Hei/Z:ӮK^lU(dpH:$&bS"4usQ$!L(fm&bE,"\!(lm Z>>:s0*} 1喈@ B x$6fY k|\f)>]/Ohւ5h5b, ޗ~eDaM:+$|β$b^Ď0̠yo;>}@d*geˌ,lkVAOWj!10r++:đyy /_.qADvK;{Mh~>OLHSOݑ<"xւ n߾}_mLM'FUĎ'P?'@ƫ7hKBQ]OQ>H' 8'p1!鐾ўjZDtFYV#In3%b?Fu>th:_x,7%#G I9,.XbjL|5g@̶B>@@32:u%w:}ljo< 3wg!W: OV_rNS")|H4W1/u] C۟Enc%,l{nA.pLZ9=g gޢ#avv=!2"P T}}@CN$?k`v* a4dgI W_s:#zz)Y1>&|,V}1+) P٘14'H1z?jAkOOG&79|YHYxQݩ>{VA9iHLLtpPGĀPܐP)cpt:ÛP]Y{$޾}J*F{Xbz9ucN2pF]LOMAU-` d&Ǿ Y|֋ CB|(QCRr$A1Q= w]To}G4I,ʣՆc atvCrCrGGG.5U瓪CHy@B!+faB˄ ;c+4!uՆ홙 ,z{.b-@bAѴ穩J /O1u؋A  2cW΋ܜUQ +vuv勖?߾""D_ Wѣ=SVVh,!T#ǎewQGGCGvHt*g|to;Guћe;Ҳ6 $sV}8{}{@w db.`٘u2Gx0Q` (a0e pM'| St2;-uo [y!/H'D{ztqƍ3. T&H,!8XJ< V,oH9IGGy#cj 0ww"qqqK`Q7@Q>\`+ܱ[mؾp%@<ʔam@sD% 389a٪1t!o!xtAass|\{fr[---u? KƀOx8Z/E8G7zoܸq/]Q0EBqh/5W˫˫atG5ґqNq+h:] qF"qςf{wo>т[<.gaP"!+jRcl U'F."5/0'4*( 3:p)&US1HU*Z^-;l2~"ggA[Hpi@O i+kiIi=~xYY뫗RZZ㇕GGwX^ݥwP@ p VΙkrU\w2ZeECeyWQQxMMs c#Kh9I؉bNNԝ.x 7d؜\#ĭ'pp LG~`rx! tp7--RoG"Y`nmBB֞$,H|| ߘ\vxYkKkmmѣGGK(n^8p&v-Zնmm+**+jjJt< D9q?! cYQd@!?\iDJPry"%!0?\/^ݻ 1QӃ@aDe<X`!7ݨ`"{ @!uxWٖ42,x Zy'TYZzTYWu[ ͹pr=]}} gj_ۡd?PCTDHL)&O&ˊc51.{/Grk)R7m`3 pqLYls~;7Տ(dbbFI( YE{nUnU_N/)gϦMk9ؒR tRZ+[-QբxһkGWW뻌<]_YYy Ϲ-( / ?^Y__^ Opޝ$GVHVI 8܈hnT4W2k[̱E1mS@(8bYۈ# H쌁|H.(pIB8`Qg3;MkLK;ߙRvl$NlQoU*KRbA +%Dzۿ?g[N[ee<<7726ĉtX돧/f$'$lŀCX 36`xЧؕ i1JPa 0\?r@) [YYS r++ y[؂B]$!ԝ9WuC&Q~yG̃dj2erݵZ< Vꁇ-a]a]a8fu% \ݟw(gNNmyyy96^^^'_"K?YIfGrdq؉ F9ڐbP q0Ch`uٕZ- DLŨTsiGGE=dtbUU\8X(NJD`TzcJcZZZ]Z>L++oQ*v#"xLTZZ֍y}|{}@DAl˻|9X^E8tYTY <"#ccceGL'Rl/9LiAْxu'wۻA!Ź>Lfҗ9I,dz`un$ޏpO+gRUUUL=#8b6&B礓JeMGw-[@_ooo``oۆncs*+**j*‹6E(GJÃn***jjJ<==A!%XYLqLLLq^Yl/s*ۻx2DF< AX npeD$"C03Vr+A!~SSӣ1A v;X$Rᖑۜ5zgiD!<26ETuxP}hh;mٱ%,,,77/%E<㙃xT{zFzGFFĢ82)D&sػןk/c]e0ޙ Z!ۉx×Q?xil4،ݹ2|Bc)h[2,X]Uu3BV3ͱt=G<Ӑ`UeneM~JM(b)lٲx"蜜y$hp/H#=2=2366_ dk2V؁k1b^bYxzdD3w9N`iredΒ$ L͛+  wi"4##(d2gnU|U<HLJ$)))pZoOܴiShihh Go/ YBڂrr+d+<Ë<)Xb ^s:,tu2*DcY_"L!v6j;$m(BOHȇgf<'@f̸ec?C@"nUUH"\K#3>3-)mWZR~TJTJZH~H_r݈HrSP[vt@"aAA} yG\Nt^Em**m/*B8<="#GL,!{]u U8@_H2x<<:͞|Abz:݋On~usCȣF$^UaUUUFFFFDa!H{gIofR&±kWA$$%$??]ʺݛٴi&?$MH [A+(/!((-../:/://o[^Xӑ>dGLD]֡x)kZ<1](H>RوżƃO_'?\KzKb! YP[ @H )XIiHYnݺ~A@v ;  AA mqq9 9y۶m(ڼk[EfO//O>@ @ `!2${.\+F6 miG9t48g:'o f"7xk?T7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖gPIDATxܽ XMB" eX65$񀨈D堦*dBϹAʳA۬H1 DaG:_zX[3 Hgik-+kCK`c8!8Fc i8fcرc_ o0|7߀Wa/?ep01A8׿9 Dic<^Q 83*/@ۛo&kNjrs <"!8=`,B 1s2" ƃIQ ob[< @V  i%eAO?x<3#[/%,ߞU,_;wˣ^`_=@,Qx!D!#p dƒ@ / r"X \ b ׀<.}b=ȣ=\!o]Z.}X='vY% -zY.} ik<b=x(,L mX jDȃin_΅ԛ5OnKB6BN2VC 2zV<K@: fs}?y`ض֛m$-5DY,EE2,)"&yK +.lnoH}?pdM hx͜yDnڅ2{[75tws/<)L E5~J `qN,jHk02p@ f;W |5˾x{,`m'amU_5 }Z[/ss&KhyŢ3Xܥ} *曪EL y^џ&:) Yˊ?4M !o_]W}=( "_^f|K KޮRޫ^z[?\C`k <:זoakfκmn]:.Q<Ͷo_[b^ukׄCp yۜzA,+AS=̼zؒz//Yw(+\Ы*NhƲk"JR[ )uyRbq0ZߙmШbi1Zq 34XUXtfJyG@l7777/Q C,JyE. y-yAKY5yazMګ[[[WV3VYQ[ B[Q;ĒU3Sq]'< O{ ֆBhk+P #U'R D>S(eU>$k5@Bs,ϫU J)U Ų(_W>LRP@dRDC@&BT! c5uduwu$DW=.@4._!۪D=^dkoխ8nGŏ=^x: [r%_<<nkK1jD>Z!9QFǿ?K !y4/W/h wҫ%Kb)){XB̫X}B" d˓'O DP!#nBD?W굗%olnaAH+3#5WLɫ&e,˓Gx=)}xOlHJiRX ,6h,QibXaH#>2"@ <4F_>8QW %l[%2JW{ u^EYX<Ē,nL"G~9UHI8 aa*iG_Io&`_?pqŔg ʼnT.-Y]_wUk2XG`eheeUr?py呑"yޟpit;B.“<^w+;RM $!h0V._y<2h_ %2]e*~ۗ~u ĭsim&$]yIBb&'2Vƒ)u{;oyo1 @G(+R2QdUtYɵsݻ3$ȑ 6pXYU [2/Mg/>d w9` ;ApИ:s̩ Icb}*#.|z3 I9roVTo<<ks^{U; #<p 7Ξ=̙cߝ$! D!W;`0KNzp(mS:p^Q$Cij[wk^('!?7q4cIcN4vcc0qabbbn!"Q}89?Tۘ(G∔FQF2} ɓNm?h4~KE" UtVw&z{ܥKpVeeheluĐwArLIXf̈́5HY|[8 lڬ#ǁ5cEm^*Y&[8i5IH^+jB>qAܥKQ X]q"A1r_3M ,V^Ȥ {BDBO|ˈ4 ѫ794GP'oHL\UNq͚ HDJ@):RtdIXi%*{0Zԩ+@lBR߭NLfGH:7#`dO79: w miSҲM)++~и9͛6) 4ΩSNݖ'{$33Hɓ_0`ŵMM !q,CxPh2P"* N- ͌Y[U۳?w3f8^ u>pMZ.C$7}Z{nOKJ*K++*8&̈́MEy #@O?-^(A+W>D^l 68|G c߿z":䪤+Wf ΘU,t!CAjLV!ԍBp _lJ]g7w04@o}4LrzqCFj2YʲVb>_+>6/=FVrXY&T%_(d 2V"&!HDaZ]R%|Gb Q"Gm+ؾZ(K`-"FY ":&EoEyD YN+yC! HD!D"r ڍl@;P&BdC6S~ yH;,쭻/p|NJJKmjrΙd&%@Z6:::===}eB[%DaU+"V]Ww%qPͲdTW| `3O3c M88WB3>? >ZVcYIx+'B֯ C$Sx$G'/b2*Z qjH&K* x{Cɵ ۋnʪ2'">L/S: 2M ߍT!}._W٣Z\iT= QDY\!Ʀ4.2)W֥[,? ЭF~b;`v--Z)_B0Q*ץ7*U#q#@.+?&|Lx88Wq5CXP3jCCB0 )۾bH@N%Y"Cd"Oe6K[֢*L "&fdk-ΈXMM-Y>em]d+ {>Li$TЮK_uvqY,]R %\QSmwfX,R+kB ȞTEpȧp4SCŨn[!]qwttvvn|d9{i<͙`w#4g*\V^6?@Tym&Ap$"%stY8w%.AL;Qqś!@0':u{>X8;Yzn#ouq2--M(zيmec6 d֥!  δ^ HBHVҺՅ! jivhl q{Y><^9P"zyG"0ϩc+iCs<!c,DS[o+0ᙂBkV$R)uL!7_#G/X̅h)OTG,jR:^Pe͋gNfHW=z{Ǵ4B(++Yk5WٺuSM֓W11닋?]_\SB{6zmah)5:J=_Qr y)\CQAzy 3VTR|~3A)e:<||||||C|H}HHHkչeee@dNHԔ4~-<&جS[OIM/qBشZ w%kG[vyWHwoI $h*"|G(5h ;14|cs˗i+{ƆFvEʼn۴jI_oiMoMc@`d=uὂB*(OGՔW\y#i-H`d[$5Gokkk% *TKx=m'ޢ& `0՗Axup;z2|W.H;CJcJKCJK}BCCpMI2eʆ)rsss˲6܉9w\ScccS7|pl!D(sgro Yg!:t֚ښֻJ:)hmmERk ܱ!;>b7P@@gj߻Iv1/qP61%AyH AD?.T{}v NnD$DW}H#!1!!SBL2%kJV G2B 5|"d3>ϧd!8#; Yg"8ǡO?=!AG4X8 bD iF"޾ zHopp.R ΃6 >D<%2!!{tI'4&$&&&D6l(PB:vT|0:vmGztzaz4Q8ƒ ܼ : H 伃bEF% ʃH$.A hq٦Ȅn#n@BRF S r$vtnsQ7De˖[P!5&+35bqwYg͚U<+)޿_#ymrtt2HO/[axaxPx8pF..psqq TJ|QTH`P)R~YP"9>J*h}; =9Tb2wnܹs)s';oT) S E_ZգKzzGs' M;7Dm޴}K-[V! "^,4XfGbdcmRRRtRrrrtrz2[8'8 [p0~rxs&GoM  V.t jD>uI.2;_]6h b|/qTG{Q{ϟD&Ο#gtD$fSآU)ɼ-nFU61XH۟'+WL_0''ą qq8z0Q]p>!$TЮv x*_Sr ݑ- l!5Jb!Dn$dty=@L~G3 1qDf58p&cժU[cܶ޶cIb$}σORibzJ䑎ąƣK˻evpDV)><@ R&Ƀx+9I 4(uiXcǎ]f?,_q)s( dMoZH<0XԼԤTl.f)P13IzbΧ2kY׳uDLJɘq"1zԩ9ɚ k.#XȖy[mY6\ ٳp#&,H^!<_|y<)|ɉP7ȢD;quvhR AB%&K'8toܙ3Iu[8Nc۔}0q9Ss&MLZ66X8""%"bID,ںhYI;wׯ)!ٸO޲9cA$B3Û<2ҩSAN]56̲xՇMXػs0"pp>w|!5Ttu]u=׭[ćFe'qrNek?<Z&kѢEܾSRAJܮhG*K,uI&< đ_O 8"q+‰H֌l*'Cs?7GtaBv Lv8+A-2J%C"'ɈptkŜIS܊lUFEO>r whbAfS tT-rHFF 'DH$aU9,`)@k GG9K` p%t/qqA=hikEY7!V~"Z}*;;{὇s޽tEwWÍ,[@Aq:)H:ӥ Ut/Ҏm@d$Ċ'#29b*l^ }5=}DYu iرæS(c>_~B,у @|phɑ,X> YH~@ H$suY(0Xgc+XB2Ȣ[VNJ !rcu=Py\ékm!+P'p"L9Ssr&d,n?v`<X@ՙgpc@~̥/ke Q"B<(;V VKpm槺}4QTM,@O$"Z"8H7 vB,A.:+ػw5dCJYI+I՝UziVHtQ/7URWΊ0K]{gMJ{TTSxם8vL"sGΚIk4,b=_KSJD~aњ?8A~τMHO-rGӃqvy'ߐ`xfs(͙2$a[>\n07 geŚe&GRrjRrRrtttt2;Ow>H(, Q!^;i|'#̜qvIԈ MMYJ$Rd>zqz۶;[8}Z]{_ys1E)%ۏHIIiU[$y,>n0v|Cxa,Vx/f<ؐp "yxKݏ4OPx 0\|1WG6}b'Mɾ}ӧ/y{Onrp"r"?N Ӆ\zz?T9K(B3HF26 < :nݸ_uHzH vWe˼^Q=̐ 79imR\?J( U:.R: Ef@oCq4/HFD1[%)NwKJeunDOGaouyy)YRmNbؙH򋖥@d \=yl]ѱ#ң@$<<`EV~w;4#InJN;jᄙÐǒP>vwoU?DD^{jg%eE;{=ZydemVFGfJ͛Ҝ- \}uё|C!<ʜ;#+M> @P}3w% ]FyOe D',-͒FGKydm~@Og7kc8Yvٙu~0 -K儠#ΣGsg ! %JJr5*FI3}zDϕ 'C6P0"v]|h"65M9QϣWJQFe-_| 3:Nf " Aϛq햭d="Vy )R“q=!:8>W9zTpT6S HԕL{6A⤒ ľC/^5%Aom+}nT#|m熬)YY$EvvCqxo~޲u+Yu$⠷%0 a Nݚۈ嗟$$Wǥ^FwU"i8p`$~UW"R\+cJAFy:8巂0'"J<`ܯqH6!)+ >$;߫LF+frS"y4cB܍P*4i \h+5d6 rm׮]u.>r'Qv/2WT7b+ڷ4E37kڶaaaCA vVȁ؍&j-f Qd0̡w츃,RC}tGj|Xhl}@|V4a'=Bh8HTG ?;Dž,W @`(b Oںgkftx>4Rqyhd~yDsVMo,Շ\x?z:HȅKD8[M7h>d~0~}B6QaGdm.Jdܷ&t"2EB+)vf/ԩS{DE@SAbu1]qQqE/G>:<4%D(ˆ#M_=gJboH'[r,kmf=&0ER(Io^U; *)ˆџLfLBg}#f"NDf ?E% Dv!1%%ŋr<{eeSu3qg:ĄplkLmDY491{sjVt~@W*B,C)S%7]7ɏj)n0҇M=$p"EC$X 9s޽j;B#^ڃ. |||JCbBYAMCQ|%cCDd|C:zP}t'0Bx⃏ ”D!xZ0B_ @t[r]{!{k׿~:#=Rg> AEɣ,|P!Yow>,*yF FY(UG0 t{SCI , &O .Px>sޮ{?`1X{%Fcw@ ,m$Y>>1>1!$Xd)b!T q*BٲJ'ޡ l̫0XG7]I!E~>*|A"(iJt"\d%J*x!Yvn_uoDKw2 wnMS-]4TH|} iF)%=:BI!ȏyj(B4YkE^ѠS^Ozn@}I&Cl*("]Uҋm "Z=&n/"ѩ|̩B&@ ҈C:{ DV!b ><ʒLGS"+S^^_!rw>!rb…~闟~駋tj u"w+,àeDa}Nm۷LP;B@!!d/4JVGyEFLwL+htLrSC=8u4YkW&Xu`@: {=")څDfc* W4ۍQ"B%&mʀSC+Sy w˃e>DCH X"**b,9y>(*՘1>[& 9.Y:*a? P$,Wd" f(lDX۶S?}ڂd>dE}ȧԩ#1bxq\}T"yG&'HC-!$ZM /)$TOO2;׫Mq$~v~J ]ȿQrxKnR}|bKF $Hd zo߮ⷆSg a>* 3.)D!%*N!͒pXQ۶"3ׯ]nÏ-v,B,n ?1}]EJEB,XiYYۨS  ')SWNH(;>8uQ!3kY“u!(KJC$O,c]hiER.]vk.]oo DtI%ݑLѺbW3D8K4\MTjgGСB]~J2uDC,|<ʒ|:uxB,)1 9p"ɿCKQ|qȸ* v2`/~I.3CŒ+Mr>%Fɒ|I!)0x8p`oEc%\jHbb`yY36h(I#1jq]llda:ɴ i.DB^e "ljaa>Ե, 320)#R *+RBbR'%aT36L8j cJLQWysb/X,ԕQfW>;Nr.bqodQ%ԲDE,*U'?>Wqj&B"ֲEK@qO";l.]Ԍ.\:j/P)$YS QΩK3̇,1$*I:"Vuk Enj/y(rYH?> */@uz={([QK. ]S,ƚ* BH@TN]=2nWi a!!@1 HU;|gSg߉"aRL>o^}(q"a,/T*Rl۽]v;_(9mrM34b/,zѶ2I!Rbu":uM &ԲիĢu;:uL֣k4 rK>3aƐa%&JDxPG@^ɤ}A acs5vMp^?-`AbHLP:=wZqw-!dU?h࿧TYaTn ̩C7cԒ@4Ȓ .]X/u]g 5+Pײ%L,NsƐ!SC$@Xգmr_Z yx|hf㏵,ar&.!nt( Nì8_WPWw* 7蓖L7b|څ@_移pI75rcQUqK& ,(KE"ؗu]'{HhUu6Jq[pa-V4.ȏr)7bK: WMAHޗ qԫ6Oɰ. !@lv\ %os YS|:ʢNkʲɒ:\$>d0l%7{Oqu.*$`vZj-BI5giwʙhv.P$-\$WN\l6dkjg!m)CB.cEEz{|ŮZa+S{iOJcl}L$,9߫H@{JJ{{L0K2ZRo<OL۫bcS :]&mڻSe1,Г:h{C kM{ODžЮ,{~s^]JJ=k {Ra~UG2WHs$ozW ,EE]T"M z"Gffmݶ}v ȸo5B 5f_~(;dNG+V\a\xZN+9b'3`(v&'- |>zߐ1cV/Ȯʫ:?  _p@Vrl‰ܶs{lE۸7ܤ#ߎЅpM]6 Ȉ~ĪcR\gyDGr`lb-wz\A5a&ٻax(mnՇաL,M$+F{X-[;ll\2Ny򈉑$ܶjC_Sd޻wVn63z2"V;zLn~ݢFy,2¢I46z{Ȱ,b S$/P2v,м%Ց}իp! zQ/,I1s1Y_v`r&*'Ag#8nC6ǂ޽{Fq";P 6.9)imڤdvX:T%ZHh AP[a#d6ZX,˽`> 8whk@@ . ~pp''@,/\hTwM h/+W;{ӹM-7D`KH$,q̽ :jQ(hzVztaaP4\|π t ojQx3Pa}2f+YZ].Ԅ…W]~҆UpDjԯԳ!:LvI9i7%Wy 5h֭1$g,:dfJM7N8{ P|}@5dy <fNZ<q͎{tGR!%,NOI߹i 7HΏ(;w?rh #G23O(oA <|C2's͒?Og8 ?TtK9t4;Q$nM<| oIE圔{ K׮^j/ Op &+QC2d?Tz/+.0]ؗ ;{vٳg)#G:oA #'Y*^.!`z*ݫ,U±2}eFRHKM? 8{ bBhEA܊lcG嵋6ͺ k~jf/9)LD<[I|0\:4V_~ҥ[m7w9,(*:R>. 9ݝtRW0"66bၕ_ /au ڝj9(-:;A|BFDN2")YQyyɩOMT6vJaB ; !)0>.((pQ*v6t6S'%qO[ d60}hW!~_bX8 iB"t)"MoZLwLޒB]j8owb"8,QTt'O<9ଃ<[rJOff9Я8zEApPyq xv,YVACk츊Ҁ?oP:~1L:M c޹n֐#!) q$"&NMFN8pQ!SQ|wTzR1y zm`|\R"gLSt  ٻfqh\3Q")f i4q,V!a O"-,"T RZŦ-C ^ rB*.Rr94s;xf4s8\7 m|el$a<~;?#!c]VWJ:=GA.MJ)llp4F@H: 5*qή'aX') q] Sml|t~bJR_HG0˯8WbmMyq"gD| |f"K y{^Q9Hvi#c4B? -BʥsW4ψL=U!ꉪR)4[VSvZcn7g)0(Gb ew5dH2A82oD5FEƯ&FB(:]@\#6 d@j6AbXLi#wԞ^B)CϤL']<.q&/w`QA5t- ("ncI< iKR]8*L'DH3 fXD4}O *[vݲI8QQTW* h躮;Гl+}),- ]%}fs!>$/dCPd"6x}QwZ-RhPL'K 1 q! = *<(ZCMإ<8JBI81ޖoHe_\L&k1/WEA^J3nȸH&IOu@! Q&$ìHQ yqJRe5M2]K&Az芣$Ly`KW+qp >#7NfoG  ;_^x?" V,@^z@R]( GL'͂$ dE+V:mvRT@tMQU ǎX5GBOJ2G0 /O]8E= ${!\" R'8IU* %Q"٬%kH @&$!Bd芢(zLѦ6cT%&_AW@c͝;YȊǂ~mAB$1%k2^ CzHjJ.(X T_B"(H#O(Q6 )5b1=Ĕ("iE׃*$rV8Tbj_^3=ܐ}F 27o'ɲ!4{bBKD ix !`U*e bW,)@EcH@lmh'/^2dJpXĭg؇([X"D>VV^!BA Jk?[`X<< B*+DD7i&W_.ukX4YuK:ON i #'':5 b- +U,@CfobP'iU8 iIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_c5140f11378ddb13843432a5b489594a.png000066400000000000000000000640471420147000300343220ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖dIDATxܝy\USj" `*i6hA#xPq@Q&'4DŽ 􂘳AWHAIBZ*Y^Y^k}ソ?ASDLYkis='`#D6$dΝlʔ)SC6^G6jԨQ}lرcnj3fСC@&ɓ'OG;.A z8dƃ}-o {gyu!<8Dd"2k=RM@xG 2~[“yBP1wܩSP"o#"mD P^ Ӛ@N!%}\  x̚*)d x5cQG<~9,țo(;+ z1n8# <3' Y! CBFa"\YAƌUD<+$5 x,a!D#FIzRDWFQ!!]ZH<[oq.M/ .35,1ŚJ'xQL!c i5zEtX<_ sʐ>#5|∎2EE *ta]A cy d]uXE |H2DE B>ՈÒyR,^! p 瀨݅Zj[y@K5(qYפ/D}]jJ]W5J]h+r .K컿_bq}Ib=Wj}wN .;\[Q - SU $ȫ2̝%S۲:5Td]Um- b@$8+XbDH5aQYJܲp Vem+r9LZ- (C,YJtyHg]W"FO5H#mũFڼ}šFfM>Ry@^!GE[4Q6(fM>J//L4R1 )CѫhR2:k",UraJbɪtV/*D& qX谞rȱ>  p++@S )>dUHϱ]f/DmK.yedD6b ],ʔtS7V+G%&*ʵ Or:&Y&&&&Y&c|?`T4D}|A !*?O5#R"|ڴ r:!lB0a@Dk@L8ʪ{?_o/_<-#E9}y mBe7 b@&N6>l$E<[]ِe"XViCe ~)>ɶx"sgEWXY.*y?2RH1nƌ3PHы˱^x{@[gɀde<8P <3.m%"hxq'ǫGʎ)JhSbD7ukaH!0 9ˤ ٵkUUeU-Y?Hs,bIȴ *rE<€HB? V`ڲwW޹{hl~E̡ A@:黿-OQՐ>kHmQ-l$LVVd I]]Vˠaa D!N @_a*X菇w{{硶b*i˒ OLWn{ntj5Qs }Ļs@ 2 ouحB瞿M͛7o$7 נ,%#nb}4 «kKn֠h4zH2$E鰸]s?x@DeA R>cƌpi33 w8[v'31 dŵF @,@*vnWA#//*OSvٳgמ]ϵn籮)NrzG6Gyrѕy qKGڼ3([z9;wS"0y =rISMccc ʲkJML 84MIX(+ʛ"I۳gϞ}DS$1$4@q?q8⁁̔ B^C8 M G^+{ Y+7񘜗f^伏>Xqఐ>|||Zo1Vyo2j")3j%tc={ .o/{þ'Nw{!!!!!~0Dc>lc!9cr@`oMΛ?>B`yw\cdԕZҢ22{Nܡ&4CFrsA #g180YR,Fy{6 #D(:k7SHzt 쬬ͭ<,L43"wW}^o(\[2%F^ @mmћ->Ŧci&NKMlhx=? 틫q~ݻ; @!O07\VQp@p ,n0P}sڞHD~8q[ `nl!>Wᒁ[,idWHD i[ɏUoh4?(Ӈ""೰D? GwG!#)888`ᖅI{^ٶmm[EGG1ڗFy TF&DVĬZdՠ%(SHL! Dzϩ:#yq.7W4TV#+/a r˫H@Ӳ0!^<ړ } K@iw_ڭ-:::گ}H@@!FyhFYdɒAKf <|ܲڽ})TF$d~.]RNvio߽ =7]oH#Zc:)6 xKRR{\hܶm ;'6H<+X f &2F8D'($ Ek DVwƋHC5a9so.=/ %B|G[c X$)iKR&w_}钨h(_HbbbJo[1D!3q! 1%qhzMK:и D\k" ~knZrKE_䎄{YX羼̢-@Lw&Upа%۶#ۣeޝgϞ-|O8pxbb3g^WwSuLQC<.+${[.N.Ңn@o괨‼{LZs3gΩZŬC-<~u(mK G[[ضT[T%ӆfC-}p28 &ܿUWy c͚Wq3fs@"..N.NNNocɥ{O{giH@ΩB@@Ԁȟёj?2jхlڦ]FQQj^!ͻ@ΞMP!$&@6+_[/./Kz]CCu:PyܾFѻw~ l՛N: [ڭ5`s1^4fmSձEV 1˻oرsPѳgo|<6ᾀ_mB@\d͚A3⡋!$ )DS(,klH @C L!(#@N!S_+\+h& WbcVbˁ>#FNrYPW +d/@įt,]<Ĺjr}$N& ?"B}w!(c-|[-+\F6p[mqY]cWի @n.k+$ 9zJ^!A!ׯWx QȚ5kA"8@R(ť{ﭯ>N3_YTH,zȯOh.c Jyԟ3Ϝ>vMW%qrouuXK!X!x{a;Q!_~=G k0ƃ( KeY6!_ @B;syD9M@ Bo0cX NUÅY  hEիGA!WFq\5NX <Mj@8Q`C.Kj뼅ן ݛ,EѨ`ek(:uԜIJZss=gh,s+Q| U9҇#ۭTHd%!cjF4=zGb @D\10Bd.+]+_}gƹ[D˘B8tz_w[!L*|ݩwsA 9| 1"|#rE|tjhD v!p ϯ?D8J [* DH{U]gZADE!meX%7wUS;Μԯb\材b9ߵ?,Sre<@o+dcPPTTT&FV(hB(r}BDD l@9ZPALxR~ ["XSUHXccW^ïV >s_h$!df4#%v_B6;7:9ՠ$5t44C$N@o""6c]|H$o0g},-B11ǎ#1e.׿R~)o.+j=-_5tHo@\c\~PS$Đvr t6b:R Kxeg!@VXeh0 BSݒBLYo:ʕ;En<~K{(-. ]h`Xʮ!,du-hƢjeu5*ߺ1hHr$g[:YO+!ϒYF%cn.n.ji(r''U6NIʪ D$eeWd| ֊w=X+v.\e.ZV^!;p$"Z1(;(NH# %Hb D`^s>vsʪ6X[^ 9 ԋV*BT!Nʴ7Cԉy,BTP@`+ĮϜSEFAIm9n,բ/Pox,<bbElllEAD.5|YdΝ;ϞmFOsQ@qojS~eTjc젍AR"K{t E1BK*+,$8  vvs欮VF[$UsÔ[03@@pEZQQQ"{HW4|/<;M\ذ#)C僆1YDG%H J"-}δ Р(TܩϜ9Wihʼ V}^%d|TRrb+;stmiC}=5/F@<[m ۷6y5#+wYreeeG=)@ٔա%uEnd<dx-Nyu:ͩpqqwqqwrwqB?\\2ZCya8/olD,m?h_0m@YQqԩ9vdڜAaǪ=lӊ"x'\p6wzz::zzzl ؒVT%(-(mȥK+߯d LG=zo@Hi AՑ#G?jl#80[tN: d9ݝ`kWnwk<`Mr^2 JAxH :uB/殭`"gN,O[#twf1## ) ))@‘ v;K \2oӼyGW_AGXpQ"@Yw'w''O=䯻{| !>>X,2)$,z`dKzwKw``Id˖-E 4ءsiϞKضcߓنǎ$_(W&n"v(Hl#7FR}eN9%AN 6L;,XT}T^Aq pB 6,x&ѝLdCRX - @8ҶH.Ҷ헶_"4oG8Ɏ;vT4J|qަy͛?/?tH1*(( Fll7h+vpppp.emm8P*qu!q5J#Sq?)ƣ 2Z[G`bKeF~tcANJL. ^p!8mqڴTcmNU"H Q߾]YyGC@ G`~C?DpR!2DÇD22336e۝$p<'s|H7tSMw2kTdԩ982)J'Q O#  Y 8MKKMMK"lC}v'wDo߱cADf^߫k޼@D$=#9t1222(2***(*. p#pd23331^5RcpP *Iz^# #HژOb4z]'b H1(pL8 HMMݰg0XnczmG3aIH?~9E88g&ԇP;N^;=-b!CC %yP;n:! DI C@XN{ɓ'O)3_/.޺x⭄G괉H*a˷-@HEaߤ^p_E b#cbb"c5kQ~@#4HH9UC jD&y:cil=J  HÂ(UCkOJ!L}Qx+NL0XxlÇ6DQ-Bc@S#&=YTLTT &q%n)f/Ȁ(Pt0Xd Ty+5o\IdJߓ= ئmFyL9sftdvrp.%ce;o o51t8 @DD-Y`Fqt_Y{ MӀ^}-$Dɂ(JbBd.ł9šXLIz2p>I)b+fxL#'ǥL>idrz~~~~PȲ˖]TYĽszRyOZ8,"d=>|p u $D 9l$t̼w`̤H) 3[3&J3s+y؋֋4Pѥk)=SRRR/NTu=ʏ7=Tp K׭lٲ+o)(!mwnWDX8sG,X ›<1xopll >TӇ ldkfKf\ug-vXA DN0h3)8 UFCy2Q:Z+NV' $p:F0$MNN>p?" %}db(ğ>N!:A"Ëtb+ /Q#dA԰ſ$ƃP Lt!<(XPVd֭QD!ъY"EP$M>|AÁ\*| kF8!JKtl;Kǿ(t`^.Y/ȁމ<3 -̍=eu9ʼanz>^mT 8!~!˥$$#$O>z<rGI Y%KD@@w %8,;wر#QV(c,(vFᚨ~X5@HK{욤.~I @c+ &҈N"bDp87%2`}+FpeQou ƫĒ'`pGv&^ sRvRViiuuesEQk@"BWrkL,bDfNBK5`H<8p<<  >XA!$,Y#%(.+AͿc7z8V(U@$dn^TV6WTĊ< H~bL#! 2"ђP S@>-XtQ"y8L By,U:>GXa8|]9] jH( FU4,++ˤQa 1ҷo_#)ANc aA=8m"zNLMJrCBB^C YJ~ @$q}y C˧XB[ ue)Vͱ ߎ !GeAOW j)[Ј]\ IuesP!"u{nJ H^2,i"-cbO}y='Jd}y8D.z8 高ZπB.5FUGL8։hh  f2ם$r"yǁ[Tz8bBw~qEǁ&(Wk;􆅆e#Ȳ^檤&/g:eaGYBUWnydg"W|E3ޔ'OrRx0 H0}JERׁ"]\brqB<>#5MwV ǚ5P.yqytDDpQQRgFhb*L.-^#={rJ(ZL@jJK S-yʻtcYqAXT ( pيQK֬¸8d&d>V* m(Kޝ{EF(oT6780".5c?DSHO~Q\ 2s&tAj片pE:pD'HN>N<A2y(UY$ >>d0,43,y-māa(L@羢F$ &{JMJc-&jL$z5/5[b05tk؀W6@YΕFˈB( B捁ycbB:kM "d'w@L-e ""Q&ϭ\ %eٖTJ T)]SND$kغx1KS l X|99nב&֢Eє8zcmȍ\>Atm\P\PPܚ³@4ݐ!NWX`pL#<=\hk+/I,LK'OQ\ ؒ(^zp .\xPo۰׃u"$b`f=(PbbB0J!&sd~~tYNwۄbܐ`8CtiN΁1yF@L+nU q :dsέ=܅϶۶1"!2uMȸl̎OLXe!#?O>:2€g8brB|Ν5w_l:$G,@LL*cF@B5ra]-Q7!EQ#2*&2*2*(((( WO?&:<Q0h8L;icǎ4/O'~ƒ׈ IeQB$ےU}>z1[`z׮{\8wNLs7o.'HEGq~Ѱ.b$eӃt <ទɎG5 GdPTܧUdN)wF& +Q\G8t";6rԐ(2E4eRZZZ -(21)`{vF!@x?ٷIUD8.^x$!yF8֮"o]x]^qA! \tww d|b>`CH`~CH Lct\dddƨo>e8(ć q$ <+K8fc;xICE "DzDFDxڵƚ&Ju b= ʣxBc.<Я@fvy86 (Cm :H:bHFW >}9??Td, 鳆;xp Dl&FF$"qjZ/AٵƦҬ4&QaFe8lA4HXeHag:i8899.;xo'Vv[*Y&vVr"dL:qHJڵ/ aI(AHoN@; 88cHt>>6AJuP$?}J" R3h89c]SSOSSSJ#>izHN v{^he6[iT1ALj8 O/,F8vz@嬽މ&D;;{% ۥ\!Q(oB (aqY;w 0SJfM .THDraUeeJ4yynYV簻۳[p 8i%8ێ;D,Aў@rHFXnYɐ|*[N..ABςX~ 2%ǎ ;/W'ID~O;sÇݫDJjjkkjjJK@V>o߯_!pap𖀤K^ s[=W-~Njh0Ɓ 4ߊ oRČ #G|yȗJXDSp[ _:'ijuⱹ! ϲ:?Gu \!B軆!|ogܿ31'6R> %"SPX"aa|׺=溦7T5^fl$k&osYQJO &\c2ձ2"H Iǂl$}ADpYD!麳׷v@Ayɮzh @x#_7"r͢z}<$oȃW]od~/7HyXRUwmr#*/CjR2l BG| A D@!zy@ܿs8Bpo߾=9Qigdl/<%W#5/ @^usGrq֓P[1K< Nk 8}{G{q'>* ;ݻ6L EV|/6J<g-Ie!\ ?yٺ QDp$,"/2R/thj}a+oⱃ+Jw!ײ!/Tks#"K0{+rƀO!N!5.()Ὢ*1^Z\kgaWGlL \X֋4JE^^km p`C*@BpEbT#R|%+y: gJ]- ()& HL=; =,0 U8H<!2 .A:(R\aGUYM\uC& $s$\ 7 4ӬQo GMps8!W?? 7PdG Oy>)V +$ NPDoK@gά^DGwrF ]<="S!c 6#tBߟABh%"ztN)Y~%}<,Y_;8J(\zxz U‚ I # @AQQB#٨BU}jvt4zpN!%z<16H @eᤷ bb( O,y Ȳ@"A&@izOfNj"`Ў@ LVr>aG>?*@y*TW_ }cc=nP $!ޝ A*A!m1DtY|D!ye "G?_|DH? @u*>` YzX%Pί_xt;ksFioD,KMbjJzg@"p%CLJ,eQ]MҒm jw<&/!ݻ!+bԑB@2Rɲ0Cړ0 +d#C @}Y%,?L"~'q֓N\eß|JaYٽ{޻w^UV-!Az&cV|#>)Yk$5^91M:wj/fYdmeю|Ge c]՟?D!?.k㺉eg"Y8 &H$iVy.=&!^1JDDaTܯΙ#D=eCha]TfdH yAEƲ,;e+zYWSHW CC⸐^E!*ڰX͛{Dc-aK+6?߬ WeBTpwo0 ZJ= p !%F$V'!!_2'L=o@J[f/5iW]kb (ČX4˳,n-,+iۃsYkq,e4K( xʳu,A]EB:`lZR=\eW>fY=TJw$\ֳոݫs2O1knŐ}!Ro G{Ov"k5ML792(ĤYM$ZUH0SufAx aCZTbŵN wy{IDhڻՅ!H ?51-VDlezӁ.AG<Duoi+kiR/դFDÓBr9^$`eS'TW qreY2,B=O fci(3KП0FS^/ra !_YR)݆YrvnԓZ1ȩiV-QMgUo] * OsYV%š!3l.$ˤ j@-~i ӕY [ܒT]4ةEC; QR&E[$1!lܸZK!W`T'}'l2v B}"oɐs[)|ӧCV̺Y'[)f ".ީ$g%GK gpV.\pW! (Ǐ?~녁tqQ7F"+(d|S4Q9D&pف3g<8b䬩!bYQyu Y&]JG ]tֱh̯͙<nvsIBu}LdSVg-;KKN>Dȝ9C 12rc(>(,#"q ;|1 Bj#FN4F:9+B2g:@rXsAڵgH^1E.KGBzmZW1Fcx@ ;k1~#ñ{( 12(^7A}9QԖ;)6v[#qX'4=:*-JINHXP6--$" EK]o޼B %1 |8~@D8z[p@ r4+=(;$;3N']n-Aqpr Ofz~'wM^Hn94K-sgX&eeUJKMh yW@ >;j[ ri{ m~Jaם$me(ǗGD2q'2pٚ(| feH'ފ]j+T:~FRi@S}/s3YJ3=ZcS^"jryJ8AD/޲e {޶m۶΁J)鐓vܹl'>:ne.^<|I< ~ p~9h&* #f"> +=]ݽ9(NN(rDwO<GDx6Aϸ$m>:+FrpM:%}϶ pnb"^Zgzp< rxbD$[(by.򀛹aqQnnه%,9R 'xAAG7|tr3$ˤZM[a` ZلvY`,ŋL牧B6+?@C LyiM丝Ȣ]x 9~3`"ҡ(Htvt>z =ADܲ}H(I*s]!gs1d.@᳦\T @J /֬Q}2[X(xiC7ٶa'}s]Hx1orǎᣋa 8~83/qަyK|$"!gH8ĭ@epa =o1qCvF,wH,p*)J)T[cbJ m~]U itTXX3A t䲦=H? ǥg?\cюEy.93Րocb}Ae*%۸xrEO(qqa-D.E!dž9 */wՄ2)mÈׯK׵ZmM5Jka XLoJO i{RlذgHtt. $~ \[Oq,hq11t l>>QhD$*&*\ Wvph&]YE:!f_Yf͝'˖,kx%߯k|5v-sYVv\XBLz ?ᇛ(x`"Gň.3g(,8O\T:I'wk#%SzH& Owg[;, [F;G;|g׵2I!i=8%k-ǚYIbBJ=_+p^r[}}䜡DyQQQ11A?"cb[-z$S =iUnn<r&CcK_§d  P}W!iG߯?_wք'H,WH!+h dۖwD3a׭[qDD,h\w9{Lޙyy t#M/v{_:L]C&栈 H+h"^VAh@C4rPkڰT^zc=<laa}H$H0v CiA6a\BL!?#0,A@~_cT<]V,H$## x kdABxLwϔ{UCH#Fo4W2v̘1c:7|3y͟,Xjw%ǸqF$"OrU1[uM+YJ7"?x\&Ukڛv\P [k+%2__>R~~K_}F-h,#or伏ϟW.z-ywc]78,/"-DRQɎCEwq9RQ[? K p 7A!1Gt1O~پ/Pz DžcƧV>#R|lU,eͨ"Bc, "aFnY0$o ~rO,"Di0%DR/M=FGAvvxb)X@4M3nf[Yh񆲱$&, fՔyq,yZ~! I&7/n; ax+Pc!  q! H$xNꤽCѡӑqDy)3֊UoEɗ`  ȝ5 Yrb)fTȯ,qCf$^g kD! qi t P{>8?4u=˜'YHǂ>mCd!ٌ +?/!BHb.,C4XHS? ~xdG/O,05US5ED;Ҁkl%QŲXZ%ӫ @_5L>ye٦!'4p! "}bPA$CH`D LSEJjjC<r* `fg؋>S XDUvە8ǚĚ!B*#%w' )&HGAHbiXl"iToL5WWEǿD>]>~_-zwEML Yٟ!B~N G$zK ؓmr$% Ma37X֓4 =j@*[IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d17d0184674fcf0a4d770c90bed503db.png000066400000000000000000000474531420147000300347000ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖KIDATxԽ]j̲.\g, y4FΦ/>z5uq@EBX` e=R{9{m岔O?yr'|qY>|W9O{GߠM1[g}ȧFϾn_==^*H1ǐɝ>GK $ok'S1v]SLU%.n{n1*⏴ɂb_C1uILE_qտ"/ %[(Di_ew*X'(@nC AO5䧿lQ ׵~9TMD$'A|Q5agsg+~#~*V 9DT$) zDd.׃_e:8+^'o& T$e"P-?= xKHO9q(+L?7Zp4pA됝:[vzׄ1$ibI,)ے^SCN4?_W #UA`<CF yX}ҩJ4 RW!qTgE@Brͷ2gXLBi/Q *V|jzŎ!p{W=|eѕi_9J B &r%~ou{9lpGc{'Kb}#/YTqdDS YN 6~և2";7;ʧ/~,zwJ18R# Vs/ko/wkV?ZFn?}'sH#HDa:ÅR-]pmY+]" TD5lj^Un~.ه;:M&|' }?Aޓ"()}?{s}8X֞Kv}g7徉 sS4RIeS^KQC|_l#1$Bݳ_9QGɼSNAbRl,F |.grҮ9 7WZS}?d^NEgqZMH λs{Qs|V;ʦ˜O^Š 89ܗ &QQ4ȧq;<o 8|%FRƓQt5^$vq<=eRVcKEjݯ~ovSRTh_F$_: E07! g^9>ZNk?VTFN򾝂r bj)&.g#ō:4mN;~sӿx/+# %wep񵌈xevzN9hA^aş/OԢRO,dJ,u\h G$9! *CKPl9ګo~wAe8qV40JмP!a:VOA/ٯq.6ܪU>n/LV'UOҪ䙈P(S'D"AMI~m‰:,q}׽JC`̜/!#u#Ѣz H5:GU/luY'7϶aN7Au9߽_aGmѦ{8Z&?2ԇ9ՑF Hڹ'S7YaCBf,6jɁu1Kz8n,qDuG=^|w =R+yqI}q]d8s\ 1apKy/\&MZ)l0cH>nOX6 %b>vhlKgMրֵ[ׯҖ۫EA9jqY1$8r ԏ7z8w;;&),}`P]w\~-uU#VJBS ǍwvS5[~_)ȉ8Ow}+}ޏ/  UG`2-XgWW(jNTJɹYf.+?~YO~.(WAAOU)#xR95C~֐ ~&P2u}v8>,]p9O_sMsqm|M`Tq{9% KdZ^Y-y07ajiyz_H{COZF3,k׭~B䃎VO^JJB8qmyIHִE )U:Sm|V' yׇ rT^dMv9MVGr^%5.εC!KwXV[b8,ԏ*z] Ckr. z?+aUT杫nHSW1hhd jȈ>cte9 qjqBJrБs;}WS &?s]DZ8%LSU$Q$ThQ]j6&ZR%ɗC8LG 6 ru-xsufaב5vfB5YN@ia /LVnt\xHs =қɪmi7Na#?gÕ7r V4̈́']nai( /P<}w[nQoJ>S9[ !AJv/KI VRJB ^,5LƘ"i+easdғiz׺>%+2e ?Eu4O LΜz׮I5YU?d%M=dEG:㺮ŊXnj}]>B֧NU׋uIJjv_%=8r6ւzv}}߯TQ%Dh30sb-o]DX=r+a*P~Ԋ'Ov%xb~g_DZkb;(ݺ*뵿y|kK$Tx2>  )Pڼ,xDD3#rXɅ`eGvw0YOw1IJH@ %i+KB$xW"7J:=͌{`4!Os$Ih!H)dضxf nLJA<%hӼݱqV[̮ On͢whCr*yM!~_H[n7{̌뚄x8h&ȓIIDHW$YzV ),޲?beo"|}M\}Q74?p?8H?v |/ܲ:LP{YD!Ӓr(9=}6ZKe79@7 C -hB!k4D߮Sޏ̀hH ٛUwِoT??1zUm}Wn%\=vwNq"倫yH$ǫ2D`v8݊qӥ>,MNn bc^p~A]_ĮqH ePF1O. Agn?5Yщ_K"q_0:UTzي2Owrf7Ɵ[56ĵ8̍T%(=j[*p##}1 7LI;Bnb\w,`]2W!Lp6oC =Ck_i®h闺q 0 0wR{^EQ|Y[쁚%1j/H$, u&'}kG..h +zTv;yT.+ijH 80(.d}CGWPGxT`Q:HjYF1Tn7Y_< 0.+{_A"ATY̹.?Lz妯ЋsvuM TAU 7ϥ{j,'҂ b \tI$@׵XCvc.N.GWVgGՐH^ *[\;CINIjd$І\i%P&;hU"!]ayZ}JoV r`́tŸj4Dy}YX. ` f^uY kAAN¾%£8miw0ַBf MAY_ՐSD \~bwh5Ęz-L^oc\ ký2bH Sm0^؍{ 48 !{RނB1MPUS%,DOp,UG{U=n$YWPC~R;\{02"8Ҍ®`9}~L>FrUMrI-\ܘz}eszN/@NIM9lAgnA-egPQC^ ,ɼCx"o2U d+W8R5Yj淎)5 - jkXY(P7_8-} Cut}WN(Q\a,70z5huVQg·!z۵~bH^kv Zɿ #% #q2`,b^` sOH%j~ pR&"{^j!!#,Pd FJ}UM ޏFLRN'mxX`K[C{oo?4ALӪtA;3B.^&ѐ"XvLO0E=TpHr:ی~!_^K]8 o5QyJ][8o\co9Uϒ*r{x=u25>u١ a5hͼYhEj-QC (S?aW!CJҖ1V{ؖ[1Y\6iC-Л<4\>=+ri_hUh]JfgJ^<(}ܯW$V@8LePd;ș:H$Fr8@˘sٵglQkVd&(p\R\v7Yrk q.eZЋ!壶]QL]v;oi Tn bIj|- ZQY>c4s* Ir5YZ[h1 d"5{B}l4]vL K4(Ulwפ"]U Db[{&N{]˛j}THGΣ[򶨆 uG:bb^751q~k@t~GU8&[tW/,]!4 uqQ|.ֽXM/:-ۭhyJ %Ywu+9IB~YƆ0& TO. [$dJ&,J_0m)/u^y)ͨ`_e_eo<˖P%mS1Pi `9ޫ%c\82!|e)A 7e|?(FdfJ(K+!&Jta~83YZ')jRQ>fYyҪBv3H;_)}Ņ$B.Ŧޣx裡pP! !!bp/ɳ-Qm/";TFrNݕŪkȘ!e6$ g5塢!\TB^ >I&J`{J hr0z^v1"o␸!Va\ ljW$lv=1$hٶqj$HF qa>Uýӏ&1Dv'E& T)HvWg,\5=͜ 77ۣ)kJi33>I|̫6/Tł37Z. m;R"|*0Z)3 O#S?C< 7D_0?T4\&lbLA ClHĢ2UVGl/E6$ :DKmG'jZ vGa‚wѲ3@p O:f_o7tlDG&(`@F dcgS7Lp0yKH`aИ,ܲH'#x.ZNNe,5֮B/ ͛D?]\ Z!k]lEH'ͺp63w͈2qe1K $,f% ,ڤh7zyăB%bgLtXwKS39%0?PVVЖ뫛az[-XA$A;%jđr=<<:NI]17B#Z5O#S=CK$MemZ,saCup6,ǡ^ԋ %ԓn6ŬGlr{"5!j$rAMxP20BDrt^}kuC 7AL`$eQ+=m;X ?Q^.Yf·)ɉ=F %[j3S_!|!n}7xKj]`:]M-Nă$:2XܗD ܃q3ʘC(-ןF4 i&I1tڧ~SʖS&Hzpcir0wk7YZE#w LZc0t%k<4>13&Qb<(QDϣպ/3`Wͯ!B36Aň^ۀC w8Z4u0f*|ڛ(eS QO̙j:gCm?tu>OeZQ$+6ͤȝ8*7SͫYY,CSU;/YA8HL]#: qd 步EzIU*,:D|4Qe2./ܐteQ\S2ڛh/X8;xl4DЙ3 VU’՜ɂEOPcH!.>mY8 aMZ ׎!jksgОиyXea~,18X_>Q ܨ{ɛX֖&(PCK 7'MH".+;7 + '  ~YrE&ɏP2 AǖE5rKΩ+kJU-3Ho%Ik`!{e0xQtH !c(dU=v[IȒYU&ZDY-`HIJ$@wྯ?\5擙xqs^gu"+Y|,f,G`HK p1HLJdE~l!w0HhښX1!¨WFBo$zZT M>86M) jm"w%Fgm! mesӮ7d*Lbv,Ӳ V%!IBXE3֣-߃:GH%1>~R\>@y/DP wƿ >>t!`ڹRbYh36O34]FƦ \<+ "17QZƦD\1 mXrI ,%S;~$IYט.Vrgu>yZ 9%ۜ3*QTL⽬C!I&}~o09:ǜ굒/UG-A\A)ej6̖gՌ݊ړ*[qY*pjP*N(H (I`g RB:%pY )~X٦Z7Ş0dې_ӌ]]*Ë]}rZAAJp(KpxfxoN.E @;ۦ,j=xA%)oxzCvV X-q㈔n(㋜n|Ӑ] ݬ׌P.w[Y/o ' pRhju(6Xrm3^Hd)jw|&!;, D$dشH7ԘEDfxUZRQvdXC(4O S4ciP7IdLc]%jU; ݜ NPW7=@LrNStQUTlk?̻W3 g*™V5I4"Cb<|U!$FrZ˄+k[;3\lOsB XnkA/+&>J47n #p.3$N5X&39hJ8K#[a 8\i[ݲ ECe"Uh\7-]˾PeҍNoX =%iXW8ߐl"qzg}~gԘ=|yӕBE*ХWƘm KgGIVgc@!~!ʳ&3Vj b݌E-)$b{%,ߣ#6HAJݮԏ`؏M,f1֣ u>#:PoФr frLT]J e'aMeZ/ M?dU5qZ.1" @rSې6ʉd"\9JF(l™82!̀Y/֐:eWҽ'Ƹ1C2Kx=( -Gě|d X؜l|@Vs/z>RiG|Ei}94A 6 R,X@ RH7kY@$L* :-pFݍ~b;#AD b,t˞EMzT'ҳٰ<}pie5&M~`܀L$c:0dVh/+m:U#sȃ5 '> kNRR4!󓬹OhM:YIR:~:h ÏvI["k*5/k0]4pԴuH5U!HԒAB7ݗ^ ^2-hȐybijSLL4eD= MY&'VA=ňl%:mxGVɓ-%kYDhKrhBw#G1Kk?[ 9!v`-A/t,n 웘ʜpwbb` s4=47+lC]GnI%\1As-$!؄= ?ϓx K%Bm:C_:8znWa,1}a%4)Yߓ݈C|گ}1bfd #SXǾkz/'Z"\hHޟ8O4=vJӧKú1;#gs&\} ixkCXX"ն S6@CZBbٷ1RIl(]{)y V tv/"0fڲ;9ߟ}|)>~Sx-A( ݓ$`:<24$)| 3qz2>ʛǺ6D929 0tIljd &n~47m7ʭd37>>~#MGx<ǿ$E(/=IBӴ6RܢOeXZI,dnuTφ=ԓ}{4LtLDڒd9p~M$x)Fn | wHvm,#!e_9<m5ݟUetUke&I D9rx) =6}wb ;؉_j,&:/L5 h^/ P"yY[Mki.,p2Y1W{kW_c]A-x9XKx0NZF3}+uiƢV,rD]͎| :"{-AۯQy&ڙuHOD.nӾwȯ_4v1=S\¥ X"3O",ZM DaObQHx_k`w>ޟN½Ot\L,4Ұև25 $ӫ>Ȕ͊ZBXE 'Odi:(PSahN[?J[g2g|kbHՐ**&0yǸ.U֌=}||r˜EC41MdECzPbȥ'#|:{Wn8Z4bܓZv:3 .EL.zBxm6:,> :*E1*BYwRHi+zYkw[beR$A#Q&.* RYB.ۨ!~ u9:9ڎrvg_|z=JN!b^T": 9aS}-x5 2I2Wi=& PmH6O Z[T\`׫ # aEBJab,'[ܬMgE%MR:3x L̸gD.Kn.Hj'"!U]1i2CS"kda|lѰ*g! 3 %5 (E&gq\ _Rh 0 [nv.Q9JNi~LcLʍ~qHF"l4I\C9>`YS_&# 6A/9JhԽG׿}_9}cU1a%S'$1ˑ~Ш'љ|_}=j뺿_Q΂V* Z,.NR#"'M$;Ԑ$5ƳCSK!y!ׯ=4ܿ_$X0RǬ@FNFS$ Wq2,Yf%vCuV 97EucG_$dnI ݂_.[Ѽ3fr/\WJѲ(7A !N?cʟ+)eL{zxGLK۪P}| 31l#$'G8~3PQ(8+\OOd|ncWG(!BdH8) ڎ@"=R=bK;==ZJ=LȀ&+Ёs{=p7Yܴ>SY֣,1(6n ]=֐R1#u]|Jz%YeqDoE%3޹~@FB[b>M Z6ߑCZEvWK39߭Ĕޭ1e)DhEl^Atz KuNO*bjne2ۥSB)(R\BxX&HQ:1 v9cCz:5}Tl9uڟlpfTM UzG\.EOP_ ~]/OK,0J]TXvcV<ɟ>e:ƝTH;ډ XvPgJdAgy\Ɋ6Z "-u]btS~Y`uI7[TeJ8DB/wy]^n~j&ۮ=qY|` ѳ_MxDw`H sl5SST9/1h D7Ҋ.m~^Bɵi%QO-N!bn8Nf_fLTsx'*KLӮSoMKDT )A2 U >\o(s4N] ltn'35eYzZG Y*0jKf$`&'h܊S3  ibJ}媫y, ;hDKN\ar j#mjIQa.|p{'%xm߆ڸ%lFMPUN"SKNUCdK q6@&g )ûl+ s,pU)Oޟ"wjB{qwTy Pp n.[Y4`Q {fƒqm֧gicCq(,Ќx̓Y ׾b ڮkZlP$;zGFݰ $*{ R<5|r =&5x%g}riX5 y$lmH3+]4M6>VtҚ-i|+w 4}'РCWɎ_#Yl: EQCJ06oM=-sOt+)c  27\"Rʁڲ4`յ _(a2pݺDH6O*T^ЧVhf8&sλF#B&) x  J uV L z&, <%4uv꺿qhaFoQQ!C%H$HIRe6]h6FuxvHV )ndC+l\  G18XlezXb xi|^{vɩL-PFV{㑱(dgɤZ)5/l] ݝֽ_D0e{`v+%(''^?@w#ߍւTȨj4.C$DrI' uHzfe"::e?Uc/ؖiQsX_ձ<*Ü0 J3EEZ*O8 cbD@( RtYQKvW{*r3eg-ŎGvZU\chlN >B8"klGod zEْL!`-\-`cJ!.I7 $G;Ր$ڡZMGh #.DG=CBF1 ~ϥrOKzeIV>BnFH}Ȁ QgG!IBt ОPS (EH I 57d0Nä8KNLO@5#eÐ4Gk/ess-.Nj"fV鳀)ə;*HcZA ɽw )d[Hxf}VvxcU]S5:N S|nP},׮[ }af,"H_Иu,~w&+4z{rxnn'. D쉋b:dP ͖i֌kErU!jr_λqĖ}~vB005H/VCr&GeG$.daF@ bO+eO odVBCM(rvF1^#܃j_fHL\sc)_iuI+qn\Mת}k,ܖݢIl|0ARQ&q V(CθIfZUmx,FcPCJwޫWrCHs)=lz UxI/*_hgf=2ʹ ϧ^7A1Κ懲1&$V,ѷ!hh/6-|ypʢնz<'WAI#hluB2bA?0Y'2y\,83"1DMc2jSrIW(68dKkLâ)楄ZNxiQc`I.f ahmJystŠ ؜\#CF"C@ $"@B q{RL#ֱ-9p6 }1zv|¶Yr{RX/׊#7GdwL>34dQTcd^OC@]I1.ԸĪ@WE ^ '"A,*QG2F\z94#7(1N ND{,8(''u$TieQƪ,:#gVb{,S0@\^0]&`a'#Q[!Nyax͙* :Bl9*W;ڡ zU9bǬY#Swh+7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖kIDATxԽ}p[ו'[+ A!S 4:RlMOlijF&F%gl'*hb ev u TD&,LLKEI(Q% T[JI_ _~wιk\6oL&S`cֿ֭,?O7~=s7oc='Oɓ?so+E+h ~|0crxd[ab0={٧}Dy3z{3"ʓI5b=y\ UzqT2@PbгCCO =3駟~{ois9I'+яJ(2WCfl/H {~Z>lV&#+l0"1Pl8ŧ4( !142# UC*ܾ?7~"xd֭1 ɳ!#>oӀ~08bf $cB(f*T5`T(b`^xHQ~Pz)qg yX! v0G`Bfs"B_!=5$C( h:d G<>,Aq@5Yf` `BP|eya")Pl!4OLL?,! 6WXC۬χ!>Dd)H#24t<;haG q{EM6TT?!r}~-M"ȽA g L?b:%`@5L Qg)+Jl1Y a&KBC?w,VAXCk$HxM1򂞇V@d[2d۠'Z Qt‐CՍ0E44BoDxf@lQ I0901'}(/% FI/d#CB0Yb9E=^ TG!Z}PTFm\{RŶr I>B$"$`mB1+\^J&!UH85S~.}>!<,)(+bgApQ4(TVAV@!%#R~`iQ%p{&K@"=,)(,hf@ګF&P,dCoGaA^?s~2&<(85D=N5%f6ą$ PB Œ=/2/A(ke|Y-}$zK FA P~OcD 1Q#1}-S=sd4[WH~/Wb1A4A!xfD05G!j0AQ^A>Ct_{@aa@_sc XNAB84K} 31&s-ZIvboL)C /,&q?mH(TB(fȗPcEfcK;݉b2ZUlS E ^':gWG*+i TAK_'Bc -;!W,VZ"_r)H [ =Z,i$NhZ O#Z:Y^3_J!b63DW|MS]g}#w#;$S  a1O"kM0?BDBBŪ|a/^3k{EzAjuHhw˚qjX5c?UK!B>KgՙjTDޚuPՃ[vqI|֮H =^m`h@q\Č 2Kd 92 aD'?T )p1& P@Ay#RV0\:>2Q~y]":f":+"̯H"b4 lSCڻZ[>HDKxAzܐĚ !D? )&$vJ:fs?uIWˉ&18M12 O71GINdKaI\NҼqfC:8HL9YUȽC PH_yYy4XȠ魙$d\3X&D1Z&A?R BuҼ}[Tlj(B3%}V.71]6Or{$TCF1&7uݟdl<(--nӰB+VV)"P.sUs(F|.BMI2T]M]|X%_pc%^[nPD_E7@8}&Xb`(+ȅM0\($y__!r"]:mE®"v\۴wDSOQR(s4#*t[4~B"2a)< 3e$χ@R޲P&-JD:8tK5iR?[Ҽ !R DWxq*Us0_sa0)1RyzQtښ*Y)j#6fM|j/SW MUZK])򏀈&: \GʠDf ϝGOB׬ >VR]1HlDF # j(z߸FBCJTEH̀L҂!!2PD*Q}FIzÅ /H:q80!3b~;&`?|MedH̟%Ƃ38&6lMMX߬pZ?J.*%DiaJb$ BlX,#I] M:ewz5ucqCؚEұ?$lvf>肇!CSM'b(b-Cv*̆ } ۪iMUzC63GI "V^g luhyP A:_vA:60 r,3/2 H<:B+~A{8q+Ǒ;:*U6HlV@.JTFTUB}Iu)<ťj&1Ye/$xQ^H V)5kxPgLMZrmG9vݝ zM_D.$H$@H;s}ʓ9|ppldΝOMHxb? q6iUWF7OxS."$RHj4Y@NH|mniSA]+$@R15 ~lliH0,;+{".сcR‡űX^xY[caKu7:*ܮpאJn7f_vJSr@R%i;Y^oZ+FSDZj_\{̙36uǓ hZH!tOĸAD@/N^3/a@$YcY&b [ӹϐ2SJ--Knѥ !@ՎGCo>@nH)o#xܐWU_? NrZUUMf =~KLi}X/̤7@\8א3K/(UK{kx@u4=6q q F ]:w0$ߝ[?܉czw  ̑Z,*&QUN>y 85id4Rjv9oZv{ɒ9glDQ7Af---?9lHRvXeio7r &#4OoDe22dHnT%.1DM&n.:H}o6M+htb"΁+J"׹80 &xx gn1HhԭVvu,#iLx: g8 2Cw{K{KB"#91&N֫KS?U陨!j `Jŏ ~=ۿ_QBڜV?h}:n5ȩoPVeLmil>_p"k)0lckd9&]tӾ rQB18lq,kT@.;1nwg{{LȲ(#(ߐkaL0aC ތj8V$Ro!˩Sloz0ڛה9zVUb{<{@o* 'lm` auˌ.ϖ- YiZڝnFDgey}Y/76Zrb&\MQkQ"-3Yȹ]&N&U&5U-yg.:QОHJQr9'6א#8'ņPxYV1YS.N$NfS84,S!,Lsy6f*-b,dE֐=.3k0yuէ ^L^%K!"'&+&|;:/kH5 Dsk|6(#xmDҙc뫭kWe'v,^+*!X񷷻 0ё5)4= "FF3s8RRyha#}{{&"}aXmqWϐcH*ep|H b;2FtB 'ݣT#,Z-zGtP_ȹ+Sf V>/ޭz" 2m`$KjNtOdeZDӽf: xx W7y-2Dڷe R^H fPGxV H]h6b.1$#G:7v3Ј:K1YZpN H6I(:D!XU3UgNV@KN?]v| ^CvbEgEHcH7b1?5U\ AQ7ߥ$<,*%|s~WFٗݻ7UdB x &V&(ݲ0HB %]b/, I9 !: Tr)i(=oSo̮@!FFԡё/,jCݥoׯ̚/7GҲ Rq̑@!bW@+h†.cQ/sgX0+Ej^2v8a ѹvr,ݩʺy~(~MF:thtT}Jo~$.DRRSKImh~vP"잽H$I$bsg;nm {Huj/K$sbD`!h!lTf]MrrxP<9=eG^QtuttL|0R(7Qʂb9!Un) o@& )%XEx#c,HDE Qx-' pz}>P8 !ʢ=f pw"PDTgd-W_ex<lhwOG8=pvOGGcQp|0:~Dy0d8R_UGG~k7E}QRQI-Lx]t͋E|jOٯMeH"ѯkgjzք- xm4[ A~ ,E7:WM|>8G J톥 Jl(ӭ ,k!XK*d@"ټq@iNxtyw' Bp1a\p-[c=cc5I C(ꨊ?UɚHbv$Zݥw7Տݷ7۟MD0A)EQjkyVkj $w/i/ __?P D B۰ wԶ dqxE?~=jj{W]..G{{;CA@.,m$qP nOww7=9Y,)' ÓSSSuzkd Bs!BCUwśDB$*%ѻݓofJ?QvOj>lJI)D"$D$(Ěo >_0` $ MĆ1Xbɀ)'.j8?8 -nw{%v`Ip8v;ʏ0|)EWGqPTP*co5vxl᱑G^~dhhdhhجoN<DI&{pC7,8Y*}ٗKi{%&fl(c-Dmq5aY} FLGx}A_gY@+ _Bxb CxY;#] ,q1t18*N7(mx0padjlu@'c?:G@ل~\l ~ kϴRMca5p1n7 |0B<(:( / tx.*#W0So cSO 1JW=!&`7xSW~>]RQJzJ'O~vP;|botCє~MD\E +[ fY 26mm Z7MV9X1gd@ϭ,n#A&P)" s'Ab>BJYKP\:t(>"tQkھڀ֧)z(JD8"DĚhMl6/6mzAok Zޠ5hd ±)eK!W5q0u`H;%0Cu.~ڦ~ȑ#E{0)f±Bl=޹ΑtmPeKTA*N8?Ч Q["P@Nb XgpV8 rCx쪽Er<ȧ" 5i $kҴ+ӕgH6 %ԫL33$ΗF_?G'nޘO&1? I$ ?C !5zk}HA!MA!sTkf֭/҈iNK!b<8(ak%~k7OQttp3Xx!1G~}XM]S/ښ].hW*d l%Y/uzT}鿙GNRݝ$˄("Sڊv ;H(!Z[׭k\gܪp jd(*2-(L>Xw"p&Ku>m;6&H[Rȴ֊R+o;XFEEUUT5kjR}7 fR<= я%e0HO0IXQya1^8t "PP@ !$ Ahui#8֣RP!݉Fh\U_PSwQVݐ3y^:a8V1Af3=C 5KeȽPJ!Cq! pzD&CMCy6$&=j0X{l(&kV5#BVI5 33`@~zb"Ydc1pcHZa]'pXZ.<0 $OB9;Pd3NJǃ :;n @2M@A. Z3O;jR%p;D  (z?"PDb,٫;6>p# ʈp0(FI 1ki65\;7_3oLqrKCh YB(pQޠFcKO U5"(E~4o y}A x2(QLn7hqx( ։ z8"բ<"5,K'"vAtEXXBS~d{!`dܓ(.B􁄄@@BfiBo Q/Kahlmleh..Y-IeHs À8*~,Pvl<˲$KЊ&oW"XiVJPrDX ):DAp [)j4Ԡ'56$8Dh5 U6ܬl/9J-B0D!a#-hyDx֣XBWj/`;"2m8pP,2EٹbĹ+5ܧmNj4;$2+~(TEqH(IJ@Pi˺@1dAhqz>M`.3$'!OcAy.Cԛ-nϢla=Y,LfJ1>.:! I Q1Xp&HWEDf%eGck ^7cDb}ia;$3Ab@GɯK:/ߣ+@nY4n#^#$!{=ȺX2>nYn АVz ) GӧwMm>px.x"SuVDDӴPo -~UB_G}߯Kph)MSDdb<}CçMLNQ8),v !p1qp:ԓu#CFE%!qy[Q.VuHх]N gd>}4vlc3I i1b Ⱜ5,y{p.:מA}Z4hZm6nܘ"!8DkM\8Ê ?uHD !$8R H.]Mv*Wup vUEB],u59YO) 2 _;#|;+Cc:0duqq%qF1|q8?q ^tsv ngqY@` ǭ5xxҺΚŐ$;P?NB;z~<Lp#~*E{mjY|R#X)22 _CİZ%(g^|0N79,LBxZD0'ɩ)JK.5H0(5evQA0=VGֳAlWkccB#J?;YB'K@GԀqE"l*fq<| ߿②xTH'vꭩ'"!ӳxjڐC0$NXsgv >/==6|%IO/>rxv!:-z!jMhz%wPyS! h8C1V`<^6epӥpl01 eI!Y$q(BTkU#?H"k;wq/l]vOhnn^o"=  piZ#=y?m ni7zW{$:pryLUZ!0~vkc*VBgocaHeK&%! '}rZx!̿pk2[pNXUܳhCH$922" *pZ=xAxH$:yRۍJoj/}t}`3F1~2,Q%tpǖ Kvda諮) z0 4s3oH7ϿD<ƚFa;<|>_<{4suck`P"8" J ֊eZ [:YBǷA[+"f f LvRS/ l#.%W[C H--0(-YZ6bޣs~i b~t{ypum>3YJ~52zhСC/aZ-(( I,ބ8Pp|PKqOW"I2E )fS^ &=[jI+`3gni4S plg˟]re6\k]vBCz%=<~w|>;wܶs2$YحӧWGa!0WJH@P4ݲFKJJ/hs Au%檷VbRYm=x0zPBTT充P&%m :ӐK-oan܆ 疗8$%W,/]z-myz3q>%ƪFpy<|4Sm?͋pTl`k3UY<Ś( Ha_7P5$F'&(&iww;&7j2-ݢbr0"S16lysW-ճs=c[.N˂_~ǟ8Kp4L;'13xf:\h#i>ɑBJֽdj.! s+HgR٬MňJ:i%!*s}彆fOO8w>?Lr =uC Lbk\PM`cE, &㺄ǥma Hs dPHNC!xW1O'&_\\py54$X/PCEm'yJcyqdSZl&ӿRGqiכ1E. /zw0AR9EH8"[T6 ض"CbDz"ECx`281O)qzժg(R56FOe0uy\"@UUY-,xhzl6s C !&=CȥOmY)T :5@P1Qaǀ3fw^EK.r$"OP#bpLpo# 9! 6J l]Z3Ŧ+1 d}B{u!rcuTU%ظM69\24!!; F`e"l2MWfCpEdg2D2XKrR!=TˠO`@PA{@UMɪe8.b dKnܘb?DB&$+-7[!7J,ň ڬ`,޽W\V*-^OHt vb}}Zx8ݝT~xA,v 1gDD4zY68d/ YOWHNR;wL,SxNZeGR+"! Ⱦ,beX(K{ m*ڐ@9OAB~qgR9g܍a F,!S"R_,ћ_8dGCV a Y dK?./}cȹx| !Z!fI4H]KD2Od6wU ?kN@U&;~4O\s]MC-j}5YG&gdwˆ44ʕ+Їe!ی& Z5TAiHDC!;8IQ/$a6 )1${Y, 吐C" ejˢ څW/77^hhhPz;qXye%/}im qJ-JaLK͗.}rK\R'k yYJc0őK! !(;[m3cxY,0",9$}LNj,Rqc1ncCG ֙.vÆn9uАN@ YEr|K25<սNH#Dh8^YGUZ-: 12̽,F#!+ر/O"$dzZ60\2EDeACZRa5]%m5ѣG'L/R8YǮNw,Z2C!#gE0C>ifACH䐶qݽ,VAś1;Dprϧh6Y/y7En'MIx(T]>;/{(~bC BEԺI$ /^BO0Cl{J_mܑSfA!B9В0[Q-Vj") Erm֚ S+z=z?u{[=-O/7鯸N., qn!%$^`"9'yYs&V  |8щ)_"-^ղg0uBӢN4dfѣ{OO@U}mtpNyؐNBD]ݍ 2%:$^SJqgLz1 "VII7.a 6€!!L|ვ%eWh.ƅZ ~G?G^Ή;'яm"vyg$1;4oE42 l^C.Pv kpxNH41r%8`;OTC9XͲb{YdI @F J0>QFh .\C(͊swʽ~IC!"%1dn+Xd5lνcLGc&sou %ũCd{\V%m".H.G3U.N:Tϥ(Nn4-e/y쳘!0B0K 充%iXAaV Vom%\`K=5 s߿1_>z9ѣ i!M6}-N^z\ӝ/1"lM}[u wa TXC,bG0@Uj P`0j~'^ZVn͉"DtepH)0(٬ ?㒜#bŽt:}/^`&Υ7.޼>& &5jp㖮tŝ,(8cf{eb˒E

    ^T/^p\AC҉al9K?_O w _8#%v'/WI3qTIr;It.'ֽ)l{f"S)t` h#=R|^ОqH*֧8U6}h`S_g@v'%"CtxNc2?9\vN#b.w zEzWU4 E" h s\͙f Pd~}T$IDlJQgZ0\ N)H>/:9j#.-`s^}qTP|ZEk(e@ZB_מL=w У#DDR$j$u;TUϧ=Ǵ]DbZ\Yl`;4=(1D2>t9,^XdaK\w/_Tz2f,/uNdNh$vzXg&J=@KG~: X85jZZ]oVE;Gf@Bٛ"D"DS,CLwͷD--@f'-m2DG i^'gn{HL%@⃫W/\v!݀mp5 ٖNJw'?Z'ba0\x$i~CbdD5} z^HM"D Yj}Z_Oha4`$"Jdc6+8"t#j}>]o&ŝi, Vџ ZE>Ŧ\W]khOSX,;~Eõ\!r'3#Taj0u,?U\֢H%RWeq4mNZڭZz*Gjg>eU"Y$`-a/?GSd [OI^٢2[@!n\5)$! q[|T2$ctl }KpflQ#GҿNI:V;65;U{\>2hEU򦾗L&ѷl Rz MVe}ZD<E8D?1FlB'%ԹfDm/m򄐒WDS³Mj9 S\ꅫVAQH=]6s~tBOϮrwɢ5r4Lw]ɶBGMa YTd/[O_9C)2!]_h[ٷgoF DFpk;0v$ʰss; (]F'rM6je_)[["n1-JTHp(3buI`K)H#;&CQr3Z,k%TCx;lfuY{'b4ozG$(b}Bkn-Ny)A0}~ɾHVvٮ#nf[nnBbm#XR[t3HL!cʐ Ha*HP!jzOx<#WI!f{.!ЈEgnXTFE-{_򸅕ǧ?\o-}(yL1/&%-{8o]й$΍n\iW jrfGR$Z;^rBd+` _QTR}ծ5@u٧܅}"EXӭ-tOOLL3f+vJyZg eb$SIBNa#u'/HvtH S{nښf]KOjzFc}q]l@ %M ` 9I>Kv*; oWSa{ԩYqlD "Vn97^j"Ic2ɘS?eW1&V^ɨgq):IqIj} yF6NIu+$?#͢J+v_++o~+EP#AJ&W2عr^۵2h1+<ѻ!A+c?( st}cm!$`BC}jQ!|m86Hھf'SS~+&8ٺZY4N ϯ%y4Jceeѐ'XYQfB-h,k72T싄PcbVx<#nvRTIeya>w B}J]v`<k㤳pQ)qK}i!nT[:  x_C0Ah4DqZCAt@8C8l>z TPވ`!w25RtRԑBj"U*.mbmK "E<\qp|?84w C yr%y?wޯ Vq=4b~ ªtl 0dh p*@5=Q瀽-2ˉ hQUGÃC1zMi|8rCb2@G9 xP ֩ p[ZbX9=j*{-%[A3'hQUǖIKp !r_ Znh1ul2)6?{ YZ+ZSlW%8=1OJDAd `"I̸B  ~%'a=Yu }8AH?V s+IE1`?y2:ԡZ PH3A('HrU8NK\/\{{|Xp@$*CVW!N azYbIw]tKX.,RDg,x !-AgA~A y bU4`q"i%cA XJvC>5Ht+BQ\w_?[}-9s;5)$0I,KaxKRJ^^!@!PH~WN<24}01 " \"W4BL j !nP9vx0v|wp+J{/zuu7%׹?:$+K;Uf1/+ņxSanhK`2 0B jxҊFAP |(~~>5I< A=~:=$~"tsˑ`)\Sw]+~骂0DDZrKU[C 9*P0mdF0  xqBr%d,8YTN`o*) 9o E"VӒ#VS Xmɠ[i-r 00xe &#m\p(JJ%4 1U},XgHDbInwAܳr+iȳǫdjJt_8Kce Gud3VCV9!*<+JdD̹&[MRkdj\!1E}*!Nx88Ȃ$Y%~t$.$;G::!1bu!HS YMR6C,e`CcD5Cz ~PP4A"# %tzrJ8䃊P%${ hN֌e C~6*"r/kɷY/QUi5$]#WDA83E " xl8Bb~F<k1-p ]*q!)$=eO%UvjzٻVfY(P Y\nAޒ%" d g X$âL4."4-30EAZT䊍Dbyl .&"9#Gũ^C6)qLN.cmYe͊x% u-.ʻ!CQn˰PC-xI,zc ,#"X"I3W0J*+$˯ l4 ԧ7̟k !RtV Ҳ[.Sp~Po])ey I-c2~'0^],NUQ8J˥I~.KP>nJȽ{٬EosJ:!$KJ66Py< ZP~М<* ]\D/bD=ߋi T#oIENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_e4d38674b70d9ef559c5df72c9262790.png000066400000000000000000000713441420147000300345210ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖oIDATxԽ_hۚ'* g8=rf`A1-%vX,ti542:~ˆf|~N`߀F ly8H)NKrIvվ|߷j8;}$ٖe^}Zտ㋯6}&$cpJr~^R\3gL 4kHKӴV5<:d]u{tnNKoQ+hE-}~ow|T]eWRv eJR&"aƳV" GZV x>FQDot9kr(X\#*`fGx "ae-X D8x&L`"I@vDĢi<v9BR]gt]78?:zp"H%a}`[:`$g`gHFkaJDW0-=r5=rt:C;3}c;tk`X~+Ӡﳯ;}TL)IeWI*p(@ l\D6)d ÕS8B  ߟe:~Vϳm>l#q&1!I CRq%P>l~ "=&+v+H;G35]H:]8@Ё66to<_1f/b|2({["DڑH%ဏm#)] #$u#H0 ,\o3W Om*STrLmZ0ZcEhp(#P=Ȉ>} *ar`!~[6]mgqA  DDBQ\,RttŽ/pCGDZh )"NNop.tg jHb"]P9s=e8ABO@("d?!\fuGp]wQD@ ^$h ! ?!tl!Az VqUA2dIej^z\ްK.VD(,$*:"0*+݁+Ds&K.|zG@_yO8.d-֔7H$2 ;!Q rDv! 8p:wTV !gH(o?C{Þv{=o cPѧ0Rt1Wly#4Y:Q?PB0`O pt!E&L~42}+\*ϋAe kl~C0Պ)x;,dNB70$+B!ap]nrpg{v7}_y(:.VRbS+zX1w}) W 5$:Y2sxXA!?xwC1^u\gNn#KQ@KI^"V}cX׎(.趭c$qC- h\ӍF?/s\]R)'ʚPN)Ƹ`y`H^Q;rĝ,b+:/i+͚PLs],1uҗ]&Ͽ^g݉^Ƹ$$91awqm;q|޶Nq&&\;ij"v/ _L_Ǿaȶ*Ϥ2>֊Ai]{ha=,E(qu֥<ɊZ67hxEǽ7Lwt:%vI{2YEMYEa);!3^'>4-'J|_q?ԟ] 0֔=$hU  nbNd0͛:5l_UW;x,);ad<>vyAtcQ@3ej A&Cl1ْ+v5C0j#Jq*邘Q4WX~ߠwԀb2-[o!҃! $ʔD TNB;]Ny0!0LQ`6 ["!u O3X\}V7 ;ջL${WCiƸvW0] }]=c~ʨPVэMCO BzOPޟŮ@jb⾑+'0myM+۪ƒm;Z9QA:"Y;()HdQc{.^>iG|ՍN(\ϧx.ye[;! ґB4.Lg>T3'ϋ~LH]?\@iE!˛jG @x#z k:v;c7ɧ*zW}\756oƶbSɾY9t!;p֟#Bӫ",wF@1?by=m_={oهO=o8.H 1=6/tr c3hb dՕ~p5̇@l=`vsl+!{JE0{4PHZNˮ;,JF7&DW}N2;ކV0Y_yrW z_Qh0I%8Iz k wjv$u"׈ Bj>3M B>!k\P w8Rxo+i?;ϛV+EBFGD&݊0d5?}v0&^zx _};m ҧT8/ >oW{kx4йEw:[ z,ϝZmg,lsd{4/E>dSbȃ$ꉞ)^jhAo}jGdކծ"]Z: ;AqۧzF?\Qyw)l.`j S'!YHy ݱ wf9м"bYCN:3;C}-y0L1ZD)i^p&}&m! n G4Nfw5d NC<7Zl k!^7Nh+Jk )"rK?SNbw6X4!Ğ#5b7X#9([UZ:΄tݝYH5ÑO +?fd|}e]3}nZ3."tԮZwU'QU RV>qMe`IeWP&&渮v^2[l鍸 Ѣ4Kv \/N)M#2$?Tw%;~p=xLq'u.: x֊]W6I*݊"imӼ H3BY,年d޵8p& XXT({?bY=l?JAwߺ}`$.djؕ6x&B,Gq ۀHh޴̄%&,ȧ@zGzHz 6976Ő@a%YT~ӧgܞݎEZ`wwi6ML NJyi#rs@A~Z`ؗx2@=l<ղGh24y₟VBO ew%IW` ݼ1aNz$ֈD”Ċ}5 i.x~@ju5p7PMVLNv/jc&Ce,$2$xL  MtcM)b S!65r'az q [Dдq <"8 %#M^MÃ;wһjqF;B$D0q(UxjA2 ~_5YbbIV8ϙ`k_Q 1%k(n='wD`-4]k|aGӺ ء”ڶZ(r3aݾm%Q+jEM{8jVt.7<̋FC+J Yq~ << ʛl3ʛ^5EN? gњ Iw9&~f0N>HERzHER5M.]RņjnۗAG|Dʀ9ײ0'|>ϊ|^i}'dhuq-=ՓkBlRJTfr4L h4JP Ts`Io4ƾwmL[I!S ?fpbz[eV~ijELcNDzFmu:ǝǝmH : ZZ~kVdt&S| cmdUhTJ P7"۬8Kï6 BLMV9_*ҾObS*N+!XMg2L۫2"vLf2BD Z-! ҙL:Sk\:tww&MXLƇe&]h4H"Bt)#S?.N\d'"Ay^d9Y._.m7lմ3;~.  IYU^A ꚬ$n9+\itCV$[_+yqQJbәji"B_z^tfGuN$A<~ƊFn/`:|·\b_"LiTr9v#W,,Ym&'mH(7Uu~M"Et J+bTjL@8?1TH%SjURERzD[#'i(%Lan&XM""~?x~}>{ ޗQbY6Wb%_*Xim2Wy -TD Vd( `J48+++J#f|LV$S[v{A8t-)7J2uDnED[`MV̉{΍vEM?i؅l.Dz !#оA2(+vC bGC.V*FR6Y,$&̜֊"ͯ pED­9lWr U61yl޴i5KʺMcg:#lR,}਀hM͚TiB,qRkEI%RZʼ`mұV)¹9zJnW_E0YtAۉa_@C 5N <ondes`-­/f`H8;+(Ky$drb^jd|d`"x<{k̈́fk5:[SsM=z31^nFVmPj-x6aZa_DIՃCxS_%\v]_Ȳ8TXilB/D%,kY i%D(A&RDM 니_?8P3Y}Q>Br(4)f"+e+n2KEb_/K/wdR=^736kVvU3""iC2rEn6e(E@sUl~@>ւnXZ]x,V']FE`dWշ^/62xZp2QE b*`?dwYIR`5Yx] -յxLi!HJ׮W. ?T uQ^&V溼=HJ$D5+q an%_?o _ei~6CfͲG *yq8/kʹK,dkd=$5?ؘZZ,vIUᑡ]~]1WQBֲ(t !kzDg-D Ѩ?xՍՍUъbeuXr7Cs}A;Hr4*9Lx*2|, ɴȅ#4>Uo7µ|MF8 *.O۫@pzUQB,+jE+ѐ*Fk1#U?^j`BeֹwR*QJ/ȳb.[k ǘrP?'K\xYz^#ZL2" 4md׮WiyZtz uY; eT-1F&YDB ȭB4,,Jgucc59@2HCcȚ=$H~(*k9VE@@ Oz.FudxLƸqJ:`ӆ Ψ-C9U `;iQ "ȷZX%DՍ?leMc48nL&1.,f:oeEf?;xY c9E0z\]`7DH3KCҭz[|6a1~HjhE 5$OoiUռܙU`F!i8 Z,o`8E8VWE;em/E/ RqH@$V[X^ȶ>T9\BBU^YaH>rȐ֗aCb=ie b0o8xqȩ a7!bG{mVS9KF-34I Q}`xGD+p|W BMϋH/5Y9x>f/}/g{+uGH7*KueʹV϶\ҌƓWy [URMU-sV5GN љsZLB7u^/,&2d#!/ ʇ#R9/^Z.o?v}=+jHnRI5 ɫÄ``YQ!ht5]X]mFG"XWeyڲomK1poײ=^VQ񘨮R_& xD4E ?Xtg(4JeV{jN>>"[*esE`ɷ&%ӎԝtI#;a-isiiC7:bͩs윧!G"" AIQ@B;Y}Ece3 d{z=# &F 9h㠔X-:[)R]8RO_˜FưpƘ6fԶgfOuUc2=ߩDv$ JpYԣz(\5PCPUr@g~1Wa7*Y(G&@Q!YCC[&{c8"Kbȴaod]H@QEVk!̐~^'0 r7zeˊli<:د/r²Ղ0Qs{!auM;MhȌW=GU{YkRKlDm@L'C}Eo}&+/r@/ ˆ ZK^""좐MUg,Ǿ dh1 JJ</Јh5f3jLɘH9kV<&#CDԛ˺ !/Ar1hc8 4D8v^0LN'rD]Œ@r{yCp[ZJ%Vb,vMVX1ve@@+WMÙJ-=jyZOKˆN sY5}p̩֬j]U]G6& IDQF4jT1fb%W3c빥~_4Nʗ{yͣ`-+8/Ĕ۹<;RL.*ꁕ]16ei-%I&e)y BeYkDz|N rٴFu4`"j=xFf4z/P39p`fb֊kJA>shC*{@J ԽW\FORRF~&J9Xs O7$tyWR@Z R6 hgo yUn۲Ю ~W^yY^4LcPeuZoLMr~YlZ4m IDÏֹ{mVppL' aX S,nܷZRilRȂYeU2Ri-TCvl7w ʡP\f Vk@/>88`K$^vӊZLCD4MR;4g=`1[A[/e !pN>.7 bA+jh$KnjsU$V*4S [v`o|oᡘfs5r\TD.rd5W4qscX0 p$&d"+X}>U\ z!fvI3m,nˈɴn3:c,.3)bZjY5Z@8AE <$ F8% E'm#BLd7 a`ٍ\1W؅ou,ʂ[rBpdCCoy|3pMJ !& H2) 1) hH|++x5e10UR!."d  \܅>C] (2xS{y@/e b4EtrD0BˈK@1A\W%$>I@8^ky-͇[# BAi>m~g H7eP"ؙQ[YTg֚n4 z#pۺm-,5y^y_{C0 D3EI^&jzYJ.K /<?_,[`FTBɗbE` 6kؓ!1"/m)BpH߬5VV?q0WZ+L~=x^TFucmX̀,!: T fZ6 +GA9('3H30"%ڋ/Nte&2.9r =rqb pEC2diB;F͚V8Ҋ$nkZX"礿L= TxUyy33bɚ똨 hFM.r㶵_G 8|mLD?#F8/4IT沎Te/rYv!֋\=̗M$5^Oɣĥ&9l}_#Lp{-qOU qc3B&a kxɾdTsyY7δnteH2[jZq\%/p Okɹkœy`<&]I&TR>,nsz[8nvB>B]Xp@.NDH9}8|aJl$( 6UhIlt3yQW y(-s .mXn8q(?,`*ϛ.r# 9lY6GY }0N\.Wb1ZDa-"K  ^ We :EB朥\ւ„+|s]˛wD (Ɩv's̀/#'LjEMZc}žbۈW0ɀ!|C1&O%a Z~qcÑ_=\ꛗμXEf:(*.1qOAP5`pa߱m>0Y_|)K1(,bs!Bl" $[wlLX$O(SSlbBMJI @{~ŕ0_ qFБF$EgK1m\uQ"DTΌZ \G%w]N؇g7\T3k)_آ*ن;gX$KIbZ& 'OSS6MҲXvmK5bv6u59"GRr%>$^zӾUB` W:aYꯞJPur6{:݈|2ρ5d'  Ts#GN$ 98L?h n@9{WmTrj"$) +oŕ.iqVW JEZJ{ҮmL50p򲬫љ7xJ*{`w]ߋ3?+{ @V*J ҏ8\Z0J@ _{Nm6\hlTZkJn6&*Wa&W7$liڞBeSɩ$$)9 C_ݫwxmqDDNi׌|͸&|\#Wg0QtG5}VK%]҇^ %T Z͇Mam6!4@""Ȓ%0%6&_ҏ I)$i+#[A$ yn1|tDD# ѮבЍ+h s'π,=ߝ호t(eLXC".P?iGV_zh F?6 >7̡jRGݺlɩ#=n쨐qQv$HӻDY,a\OA0LrGqR׵+H+N}Zg:Ӵ8-\C2Ek^HA_\Pj0 <2n7@1찄AպH! /x1)J?v|a1a?Ev)OMMV (hKp`E1cZG|aA3\RاNa/-e˜$Cu^2;g[&"IN + 8c-fv]qm1;u)8wsδH%0 S0&BJ !DZnSEb1\AlpVk֚Vb='Q'I' )S14L5¸<&T} fE{CHDTRZJX\ 6AD03X*ͲTs2՛fZnM>$hC$ևMS ;f6D Y{X{iQH)s'~Y8AHhWٝbn29aoDZN Tsxb Ӵ).wŸ"ɒ1ѷbgQK!#`>XsV&ȺB̞x[G=\=A պM^or՚"4XB%:b{&S,ɦ25JLHJUWt;H"Dh6v4= SO+\g1XnjY:;jY7qo)WY"q`-BM_U4wSṫ.\o>`&K('='gI& ;V5[1%9?5!aKCrEYimm}6uRp(8q#nDb0_hq-Nɲ^VY4p8yZ֧0f:X*4U}ssuΚ[xv{hM@n MZnelb϶%LVMaGΙ&甇HOlJldG=XRڕLHpԷ[@$F2z,񬢜JtsQ˺lv 1-Ԣ>ӑHj"1pPb(,laYК.'P0:4yB@FJ=GP7Q/$u4]/Ȣ*tפ**{zYph? *B"&XQ$qco麤Hlwmoo2(N?M$ű$eWZ&đrIHdvF'I ʼ5lNA"V7pnƌEt\H@gMks(:|fYւMں11`Ϻw1[l٫k͚wUkVK,Hb( 7ǀ#x QnbV Ra#:WZD[l7o?iƢշ]e[*΀6՛CgCH a>mJ2mo z\I*6ÿͶwIxxxó\_nS!->;fkMSw%eTufkNK +ŷ[0[gbh0躉m:!ٔ . j-*겺YT;3 bxp GgVXH# |v} Qknל=9y2d?.#g6wj>'FBp䱸Ka{qr m愻I&'% ?VZ@;6"OZo| kX+‘>VyDuS]H8pۣiղ:3*<,:-G8Ezu-?'I" x0GEBz0E8ޞPVºGX|LjᄯGF^u-M' \-!6Vgcvr$oP(݉dr~ iA`ӧ#O@J0V{Պ{xtSabDL3:ݙYMp蟫Z؛aqQ+Ev"%wm#H)%.LGh9_+.EoyFkYey%AH&ٮ}|U~1ZO:Hζx+E" [7"Tu5 BY^Vm |fS仄 $xqwUliCӝbmfظ0E2IZ'e?LZ`QMlMRM$YŷȹCk˗O_r5G0^IMcڴn߶My$jݶn!pG!#j;;nŲEu>K͔WV{l!Fcq-+zBQ?V BP8VOOkO_8$xcG_}1ƯYɲ"f 7i3v*x0))͟}?v'xCi5S};UΖ$#],S$ˠQ5Q;t:coU#LLߊ>F:Q}Ea''4|"w%s@,`ZpZ- Ӧ~S(N߾|bۯ'g=#0U Dg=eazhf]lge2!lMHLb.pS}zO18pQqb@ ?ܡ$MhC d^a3_0.$~71A>ߊEl_5bU!;y?0( oo޿חəs 9<*t"*vr~?L4E[&& L0#En^Ҏ/]q$x];ko-X-u(ȹf't'`YP+dp'iB̾'NU"<cyZ+w߼ ?!y}va1F^~2kz ABed⑔֟AӧS[ >Z1|bZŕChWb&l%0p{^ז6B}/;FϮL%ɽ{lW LV<3xwNy'NO9 BC4_tYޅJ q&0]fFJ,g'6GTq酗wu &0l=9pk^Kx WqxmdlW<]rv&{uȢx=USSdxtu_Q_0qmD+}@W@w]*|*2M VOwKK9;&l-M%h V`YXMq6Cl!~ыxuƯq8y ߫Xc!rtZwl|S5J htccc4CHA8'?m"&kPñ9~ W"<U)L,p{)=Wͭ3NOO_~zs^d5V#r@buz Ln8e!ڃGƨ!;5_7Cv⿎W﫷TJ7rZ;tȉ-?ˍ9Mb۶+c#s`knsM134ZS[A?N!,T4Hλ7Q /Fk1\z#lkXR` MPACi1YC^غ Qm6Y @곅!'[#@n<*ccC4Y|L*" w[iaa(َSp~fkJe6'4z5׊\RfxV *_%&[C/I$V^hH(2A֞=z=f. , ~k{Xx-mZDɲ78I16NZlovY_X(Td_rB߽ RK$5; Ƶ7p 4$!_AҒqȓC=}y=*L&<2<2fT!o\@,5dNyy'}̕%$u[){ACf5 Q6LD=D=:Qm'GҊKX0Oj#o`QS~IKmIܭucI9 0|},ҐCC{`<ЖըGC = 1Y~ Dt{aGfWʡ7{ٖ LK .ֹ3b˳ӷo_Ų ySopolVes9=y.݃%mzޗ>a{dXe!DM`z%$Kh ÝdgN1ߵ5sȐ}sss}gb} wGԐyw*5O1v-3+E-%d%wGtXbwKu~ǞҥMG˪խ!ݢ O 5`R+`;nzF&KA@`w\`T9nKr'o:$xgkb9p nrg+lA݃Lt8]X$/O">1aȓ[#a&z␏!Ȉ.Xpm\s1wWd9C(iprݬyJm0K>|ޕz"p5.* wG缃cYvkz>ϗ,./PTbgp, ![w꘯94ﮪ!G!:OFp f8u(u ]ILV7G]P'Z"&u[7_z;]s> H@F>o0.y{vL=·f}/."naD+eivartW:u^b|#8%104h3!2Y~ӺO[,4YCwЂI O.%0^Eqtbޡh1D@j6gϟzWO_zlV K㳗PI]m^kC؅<__E}!TeUROr5YN.Lq_.aH߫ ]xi;{B* IxAD5F}Z9 JA|oo{7\{#O|sZxS)#r{5luΐ |0l KG)pwL;q!B@ԻLV#CwϳӑԩjPut㏫t ,1!D1Y;n06 ۳ֻᄀ}gx-Fq9>>t9vc Zs-edYv9BsX}wtzKKR]B yakp dq/GhrY&Ð!ҐYRhq3Z&ߢabrw0A404~ >7Roحoͦ~Vnݲˏ]Y@D%BQOd-]vqȡ})&yz40@Z^9& +ugCLtzm6cM!zll̵VjaZi^Ib{Yrx'!mjoF䛭Z㋽#k,.D~wl/vWbȑ%.S.<n#\g>\dg=>߂(CC;UwD wuB3P0!\DVo",;fC0k%޶{cW o9~Ȳ졀|mC0M'cO8]qU2`2px0cysYmLɺ>gNv&BNxSgCxA] ŪL æw1dmK~z+o޿{nm묍>k _"/m77rzLVEXaȒ c +/!.bQ>{Cӵ.e}~Y{+%e9޿i@na\/˖uz#^j(NW [^ˈSp-e8- 9Ξ?Fvfk7Neno8[st-% #[خ C@S'!Lqxp&<kj-߫71nYqG!wlG` sC :55FnCq6|?{e}##zf~PWczjZ0v#o/_6p]/ٵrl=W)i5 Dd/iC([y*tᓑC>{]ךBPxjuj3CG-nrQ`CA7:`&LK%Cf("85GwްD]1㘖*Bڌ|!nL2is@ťd8 Y't7:RqB)U*x['wthfG>abNˋ>tPd`88u;-6bϦERlXo4ydT2xM膖 Ywj}!ܻ8KMs. S Jva-le+߀C$ Ein2)<>\^tη4cH{鹬b6856 Z2DOJ١yYFQ.xn'E րz qWYl@< Z}-Ǎ|sp|8/@@D-pJ;)I%f9!%;+1V!_rkcRs42tJgG _{( VՔ#-)od769@{ߖ[4q$("p|'mW\YaqU͢!]MN|땖d 1ow iwA&ˊɱDEJ{ז`:H!IKɮtdv#'-¸FF,Qmlh0y/}{0]0„wpϿ*aYm.x*$[Ri?-Tb(cW0ZxPÏ_Cd}huln4`6~kmQ. '@gx^*uLnAn4jOgFXKB:@-hZ+9F1_ S/g_ $ɲRhG^5|W0(C\zL߿\B*Ս=}a?tݐEw(: @m϶"^˹[<@8\q(.*p?׳ع:I 2& auKQCϣڎ1^ MНD,{ aKGOQR.Y_V_^7x=gҸ~lWs=@*jN\ץq9 |H}[!yVc᪳,;kYc1 ؞~=6 ,}W*qf>#)Pxg&ț-CtisY{q2iR jh%Y-i]Izrb]fZ%lҋ;n+0y'PԜ\ д(b:C˖5ČW.CYUFnbſl ϋEa"v6AURȸ7Od 8$]f(:uSTez-)|RT^!h/{BFR9,>0̓-|XαX8Yu͚ R"N\`&LjEVRglFlV( MgJ~ѳ@<2Yjx|9%V_L8n)ԍ٩a&(%#NfgB YjbF U;ˑUɿWJ^wX @Q \`1 CC}b[mD+|k+X_I!4c!ZOvMS"QݤztEpuGty5[@T]R(] F)J%R6"_ }D"p0ec5fSu&J1f@tlCĒ <8"y^oxcoD>=`$lI6)T~ir^V 4"Igu<(ي9:혝T"&߶IL ]=؞pF+dCra%Š0+z5f1@zO$}mzVtm "">[VE |HoULx~|^Vhb;TN¤͹P\Y:鬷աh"/jI7 ۨEjƪ^U3),5bQ|WyzI9CMGXV@ҁF; O Z rA- @, ٯnH1y2 4wQL7~4/G8/u?Hfi_Vp\___ʡ9J!tx:$BwC P@RVi_~.̡'ϼ H# zA (E!SsХp_7f)=',) M~8Aq'χC1ѡ+dS/E|-mWuBh.UzWW idI6R*a҃ozV"=e52C[i #eE%za E~,#˚%pRJ-.F爩a~Ek-F}ߋèyh A` *wXyZ_A.@ERރfPec(CU0'n3BU1 iV\`⑎Thޅre%Af:gW2LLN={2Z% b]%Em[ף17,6WY{˷Gy/X .AMA6fSȮȼ~{#U8^Jc \OU/yǰ{TwzK`K59xS*MV0;fȐVҫfnh_E+,Ctr~lUsđ_ bEXa*@AYUΑSQ I$јNA89aվkYgY5']%]19X?Miz(&m3”5lS^]q׳I]^A<žs1wnKaPy ]/Yg 1 d;h[l& 3)9'tHae3E32"@)qB9H(fq+12J {#ޖ a_AtH` D-|2T+z'Qo~w ,t V9-LWCLw83*kHZn[,Jr\]Ή-" <_" |\A j=fh9ltwn.шPW݇s?_Q(w/nUe~ᎆPk;tx f,څ"dW +ޗ^Co2Ba$HNJzP|_ R>H:0Dz uCz0DcZ*!4sXՎs8~5i-]^zq)qSWLI?Lpm_&O-D#D ߅Yz̗Y@ *A泌U3T,DȰX[áCFCb%Hsս.+LJbD ETWTm"%JGBVo+ycꁺ3A- 2up?Tw |\Vcj9O! >r%֑YcڀkE!C y5ktK(WHӝ X@%@t#a`Xf8Ƹ^$E*eouoffiH/dN"^wtejx=ڬ6=Z5%?gvT"hWHQIH}z(I"(Qkc &RBHAxa1Uf9כ& 8\Qw`-N- d k^?uCd"fM?-chF 3 Z@h!8Km5UAP⩨uZXe;c0'jrBVgy+z 1kX|Us,DZF/b E}:+Xc &YPả"SؒHeXk >#X6IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_eff9583d9b94ac79c60cb099846ce8f3.png000066400000000000000000000432571420147000300347520ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖CjIDATxԽ#.zd9$7ϰ̲4lKF!L 31Ow: #HFY=snk*I{/t2'..O3YSǰ ?ۖo;{]ҡ_vp5&`Xyb#ǘb q`P:j=H< ].;_i6<&凳)Rn $4S\ % .D=i?m;_wdOU B8 j\14ё$鷀BL)ObQW.=,p0p"̖X 9#cL5톨7lOHRAlPvD \~T`C#$i ɟ~[zK2C9p`gÁh8D5)4C@p{ Qh1ґ%Q$~ j Ou93(nKሧŘfᲜ'.v'^ I VfBf[[O},$8/2fCh&d\9bӺ ?}?{Q+'.#8X`9& s0Xss=sv.V gflNvO'*w^qE(a|xg,ĤhXQ9|gϷT;胟+`‘YO q!@2iG<>DA&- A-nrd y^x|_CCg{!2Zo;m|AGɡ:ȒHY^睫p=VvB u{V1cSAU4hd[qˤÖ(=RESB = ꦆTI:4>g7^*NwY)B' 2LM-.g2YudIh*Vԁ{ :;<' սWxXa1: c>O)Fz1aF^Xшܛa;myw^Xˇ H+*"ϋyb srY!z[@'ܽc>,_ "t|X; ?6L`8C>D5Ƹ5K|km9j~F܌I%$R4]XYRCDV0YEUK,uRٷ]xO@˻bތS 0BXHR,tzEt# lĥ1LMTӊ*WRyV1;YǒTLX>U^idtX@On/hg yl;Xoe/SX"Sұ݄Lbx:HUM x5Q'pA=oJo{ZXt 5FI-j$!+9RNi, @ FdMԝGOk{1 f1XgSVh۱RIҼg,]tձ~׷z7iQE@֥3F(zr c2"ɮE "`FW(@XCFg푳[76XC'֙҇%ʷ#X#uI 4Xrx56.2'!at,%atth `H-ꆢe; AlrqJ3˗Bzsg,#ѻG_*&$h'jcqaRc̐vXeD7'!̰uό쯽2]"i`q'Vы$HW8%( `1eR0M-h~Nx2"7!t[ꍣ ) L@HttEnL"U8b[9TTJ59wyvk @)hXX,čjbXzT}Ji֔U-!Cs"ϡػhòY+Jh2#4 )HGI BzOԵҕ՜6?&;=bC)Qڑ΋$YJ;A\aMYQO9ޱBÿnG6Wް{i y2N9p-+ #\K˄$ϭ :>dbVV5fImFZ'ӴP6AeZfPGû%&ǔ^W ̸<ܬMf^Y3lB4VMszݎ-SHןTy~"-,y!)N LgR"HG cH,&M䄻7֡.3HB|˜۝9!4"?]daA:Pd~ُX0!evZ֭ U%m Ϡc~4pMt&k#\AVD + . :jȤ̾LMgBY:1'kGⶆp30HiZh4X?MZu2  !!X^TONwYi M%W-e."n^kq֙\VjH0Y$ธx\2 m(A J AFp08N"QAˠw:43\vTOL"d]Tn{\a@aNHh z-rkAF\%>-:1Bm@xHGC*d" !BM>J$!^w:Uzh94nY4/Ų7tRPR.beBGPc[LV*1Qgɧe~g Q5hD'd 9c|-}M^/di>?WM8 EȀ▅r'w2g'?MUs9?rqH>4΄%0l ,q&M͐SYТ>EK} ]3zH Z %gè@Ҡ,*NEnU`jA>]-f-T-b)$( !gHZd!i C^,N=x:ewvA;"wi2Dc6j\wޚŞ|e֛s T2}b 齧FK.@UfF7j@BF >Fݲ@oiR]'zCC$ A?Yu^kG)}$w.X$:$YIZ,o1`{5unar?1D! L嬦ě63t (kMYف*{O)`2)!~OcHnYfpFL)i&kXDAaH0gַbC:L!LCBc"_bal38L`OPx8olg(y 6HR H쮖gP?hoZmYGż`ɰԉ;K.E0`H AF*!dH<ɀ=p.;vC~;IۨА#Oޟ|quraՐ[ XZewqdEkX_Lt 'OfcTxcD<QӍQ$FJ.ƻd8D!\Vx5?IJ7௽ڇ uƆ<, ɹ"G  ! C4eH]$b6Vҍ&9m3?Yo~\be؍p4Ř^QMs,X\/ t:u,F]"mOa-]'d!y>!e02!)Y3Q8VCXfiV&󩩖lp_w'e#P߈2Q-qhu`]H qǮ ×KB;0Cd`Zr(Ɇ[#v{O~9M+iي˜o`5Ŝus,iYc&}V僒h)́i`I,mN䍸IaZOQeLO>[HWO9fq/s ]#?IdTe%-(¿,:iZ.~VRo~cң!{xLSRy1K`ɋ90W˽;ͅ$^ERd& rC"r:zLց&]7+g1n.]n,DT2bb,N~ |my_y=ħ492Hy W0NZ'Wכ 8CZ1 ca`s4I;nK^ 6MNVċ9͹=cjzRcG57h=\-ǜ%Β z6k¹R\-iiϿ4k6j.z3^W̢`b[}8o'Q *2$VK(#t3'{{طr&K|.CZ#ިz+ל=-1L71 nOnP9s'h2p~"^>OVGAiv.;4j#o _Eרu^‰:!/fR}AM9ƽ17j,¥N@eӳ޵HAl>]UzI QÁlFMVYKrsUM\BհWLL/ hLpT֏M;IŚ A3,d20l܎'>z`[ YUȐ!ME`&7e5tvE@$ H4Xq8ۄU M -o*6~BcCxpL縤$re#LQldZBCMNmo`Y-ƅ" &WlÚ`MW ̆U|$Rh80ˎW>[B͚#:_m/8b()b ''1H;Dnj%D1jFptPF{"({T$8I"ZIٱ5$dHL@}4>h`*csɺq0##9ƙm$DL*ek׷†K ]X&褚F+^=h]лw]Y#IMRbny񟆾@A-T6~ބ:W zĀ Qxx W5Wpٽr]!bsy;=,1 B21Ax":Xu cvB +\EV?i<%Z0P{[ga.N\wQ" QBbU }x7ޓeGx t Xc$n*qn_j ҾwV8wd&uY+Y:݀-a.Y)at&D p7ੂlG<za5 ])&CeQV.OS_x3c/ƮW|W8ëc pos9LO7XPzS4L@#Ir"#bݙ| z]$, A`OɁU)'LUaTޗ"X8<aK}3F@^\Z:ܛ*"2FV Qzp?V+d 8s<- wzKi*Yc kcڦsNB{0I@"җǹ.[*&)/Ԍs]Q#].C+od!w@z}}}EP֔*[Ro7. u(=PXS*+u~qcX7H)LaH_>LUSyDcEHB~82b$O09 IyܫL[Z>#i c0 rT¬!`_~-"qE&* /Q(W7[NJ\d=c9/yĭ]p4kg~fPt o]29IHH^5aq}eu}*4jQ)^^1%ɨ5$ۭ I\)93c5p sǤϣS*.BO]Jtǽ*eujČ+ՐG$Ӿ4 T,nOgu _FsX VHkfȺoZ̗rf9g 5\ɒZ 6prd˙FAI!4Đ0K0v讔'߳r_J ]GtPqG6M±puEmcmؓqƠQ9E[hD#@p>9/DƤinxV.! ?n]GZIx^ ߅kx\ 1Z+0Ō1ܚ !D,w6o4K"%&3~lb(s#Cu>8?ʍ؃c0[%j_;4 hoB|xOq/K]zcn=qMOIkx9 3҄m2'.[ܟv!}ç-50k=zZs䱮W9$ɰ!XNáq]O.f#d,%^ ,?Z)9i09ΙǒPAT8W܍o^HZF6> ;‚x+ 7 ڊ3~vbY֝lpI*Rc u^3'&=Px^R̻f=xZе\uS㑏 d:CXs& ?>k$LX >%rYg[/mzG@Jl[ Rg HC}vb9m-tǽ98.seMU3z7N&Loշw&5Iy1b4)bu>C֫07+cȃX1p+{qzZ$;]1LLl)ȐFʕ/,szMD՚k6"0Y][݇c8aW#&KVKI "C= %2dk-)H5C""Y\;*yǒ2\'6>,))Cxq _ Vxosvza'"N 9EFb:5q#C ߦܑ\_oO#i<7eAhÿGQ8}βddR*Ou}t ýį乮PAfnvJ#f~po#'ꙇ((Tw9.^0Y`$*TȐ.wv'l:ID[ Ɣ](=1b_kfP&;&;틣UBˈ1$>hEJa!bZw߾}s'1$:,aL )aH]>5` _ӝ*H#t~f,6 J^ɸT&G~@.R,ؓMmppϊ^"on/zXoZX1EJ֤9۷{/tÕ`ѢلۚA"$ +he4{fG4Y6ƌNWDI;,OO[ew7nl5,a04⪘\kRC5+ )~3H {N-B\D0T&AC9AIB1-4Ku~ 0JHW!a L ǣ<)uEB Ѻ~S|$,BIKu!eHԑ!?ɜď1!Ci&A?=1HZY͝KpQET o^!qH\\ERԋ^ye}0/=zW(z8=Ze{IKAbqqH`%~+B`c/;G83fHR.hVpUd > 2~P 8̞@`\C+dur<ѧɐ012;cPN:2E%L a:46[Ó$caƿ~jYr~;˲8dۘm )^7Ng-<I ցdG{-}.Jh5byYE}bKw&Ah2!0쿹0/D'#AC^IOJG02D',+n0%nRJJu]CɦYD# xݾ8=tFlM]-Md1QT5͡䚢!7j1o!>G^n]r'ړ1P4uc"hJ[oQ7tpy-q-eDž`x GD`o~\׿A;/4 !㡀 dtC =ҞhB*Bc S'$gu=A%僺.?}||{ 9Wkʋ=B%!T*U}q-c t" D,>~,HeԉK7!M+/+-ZP0T:5w2ZsgŌV;:y2e=^`yԤ.%ur~/q{1+/S'lƥc3p\;KyH I& s뽺Źy3OL/^U a hGJw%A0Ѝ\,[͵$ ^l0 ytbXA2Lq?b:xZCR'"u1cU|4s>%2%tˉROxTS'p4H&r׊( 1A=:?LXP+Ĭ)^󺊲RZ*ei7İpl ȟ[;CY1-mԮu+c4F彤NOӵfGL7UݦlB$:'){"L ԌWGa!nڗo)~VEW5p 6ڕxOSi:KؐhH99|-FΌyA,SJelR4ܯRSDӪz:4Of~2톫 cjrKdi*_mɎ A Tte o8J f><|B|%e,B+'08S\2,|HK8fMn 6S$37> s+LJ"H&H1B G:X=97B\#/6TNɘ - /0埩ڲH)nZ~#  ,踆SKg.?)NX^DÕG͍Wh$Rg%.&NfZf ;A94kח@Q#Z $Q4[Ml|Wձ1.>R,RN WH<A,i~o2Yi`H0W˄+/1)L3I8usĖ0YОdɝ 1F{rhɋrt!6D$DE0&''/וZ( kYT_q ؔ" ~␐6No7ZXPXY3o`+%#7d*HT#!5()7$H<_7 a\n婽]b`j=r˚p)x? ͩʋT leE9#f3$(}+*wfT@Ud0^n6`/8q_R~/_ KN4%|21J|#WZ 4^.4##ז*Puۥv) }\YRg=W#;۱!cbr,38lCR8ܢ0k%`^^L!v@RsHgXn;&( BTY}]iR. QT G${c,` A4͞4`kj<lP!Otl\+4'TЀyIb <j b )`5_\TB%(ҪiWߊl sY'sC< p<.xd,s'.7tk7+&],lZhl\I|1NAn- I2QzSUE2cnr#\`[>V7VPJX)8`Z]uDǘGa֊ML9V7[sOb~^C!5\yB ոruѕϠ6\3A _`skq}me6I*!y50X3X)(<î䧸/fks+qY.A[SBZj M y}Z*șM-̙XڭxDyw6y e4H?k=^h/gXT%:%Hh&z͔(3i*wryD߹20[C Rd@,!qk<7Ks%%CZ֕tC%E)0T9ľaAZB-98 [9-f8 A;'ViVgn fR[֪#ʹ粠^^Pɶ\a3奵6}&E ߟ;,c~Ў3sńYy"kGxD vr9qgysdy1^r@ZIP>NXx^_YDɺ VK0Ip̅"@SzW7vVG#ɞ(lZ[u)2':XX>0$4A]o10l=ȃ) @BžE '+= JxK/Mj.Fggaa3l $< tsP u.o1&U):ED t}h,!gbPBnHs-l(kO@$J;9q29"1HV} Kэc[آ*fR+i^"&N3`݃E'i@QZȒeY$+#<9D%$dnL꤉XWA"} Zo&? IENDB`gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_f17bba59421e7a500387232295512fc0.png000066400000000000000000000646321420147000300343110ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRGPLTE~( F G֞ ҙ ԛ Ж ܦ ؠ ͒ @ˏ  ٣ ީ { y+1 uptLDR#Yiza ¬F^wn>7~iӢ $@GxDLSɸ%'Zd:I69E˳1 %Σ¹-.O{Ɍ%/TpLҦC@ѫLϯ0KzNPl18,9::7͜"% Ú)pDZb\c,ǣpP(Ti&ê˩Ѹ-5@BٹA 'wt "rg]k?fX=~frZ{5{Htm{I٫ >vnl`ݳƉ߾cjyD.brƠֲ bZ@WyY*mÄ $>d&ǒ,v ơHDßȐ ا2Xx߿)sQNWȷu/kϱzvDs̚qcۮ5TTS;87ZMƢ=֖fUIDATx \Ug &q Q0,CĚFjSiU!4E!&(@<4fEQt3nFEE*&'k]puFY{ NZkiFnx8aGc,SјchL6mh0^@_|q1qĉ=s/'4ywF-4D^{h9r3hd`axy?x_P <ȼ"7d<0ǫYќ@! bBy, NCgD5IсCyt1XcNj1/X T"sCx.Y,AgTc^`"%-hUS92CX d1XT!R@bNA&;9#yN82Xz7T0;}X9"yy|;Ct\ª&@^\ ރLU`@_Vc#^^/ K=ZE B>ÂYw-B,^! p H٨i>Pvsk * buwa"&鯼ZVc^&1|N( ujU"SQ/Gi fbrżժhTBYS$0Yb宗b2jha jQtj39Z j6LCB+iD`j3UV@OXoǼ@UsyT@^ʊJNxEy21YSeEj#u+Qխ++}ŨAX ]jcUu:~j4Cګզjugce Y0OWdj"y-MLY_UMRWjRT91CCu1NuP544=jeBl ko6"pfc5Mt@K%T&L *SHՙ['B*BB5h! p5C ] *2hЕ6Z" LVf94ʀ<{ƈض&XaXf?`,WQX&*]̃XJtKgUGPHXb_VR@۪HU m de2ɇd%hj1)*`k4(6S(JWgX(kK 딈L]ȿd&,3$$1VI*M;J0j~gڠ5a:oSeN<|P}bG!_7jѳZT!ՂB5<]؜ZMߗ8vS\WQ杧ҌeDJN] ʉ)e%YRYw+LBZ 8$ZD!Ⱦ!> } H2@9g`P[EEfx(-M 1/жY48` `'@t[I o݅BUHUפS+j6hjj0ȧ nFAVhNaҙAC@!js٤=&KK.yeD֭b U,̔zw#PQ6ZИF#} -25VЎh E&+h0&&XX̙h>YݝSimxCH %2AY5yZ,@ęBN +Gy {BBPbJY'C◀??ve ő`W6s+AKU ^cI 2eQ &)y%)QuD;*Az]VJ]!8E<4:J}PwWJ{MTys)9IJP\.G!=EQyxɫB;/%۝u+F7>'GOz)DzoP$.QO7uy̫'('B&+t d$2gIѓ'E%ZXT ȣK@f{ PHc=($-aBlE#Hx2,,dŔ|p)jRy>gO4BBG57jԨQ'GsB7G$ϨX ,6,bXy'#KtH_BBBx @l0,|.lazrT¨QJWz u^YYX,Ē,nőT"xDG@'!]w aO7JI UQ8{GU]z #_T,a#1nEf@|||nY77tFݻRDOqb* Iq<-m |zԨ~oԸQ+,t6SOL=p weMd$:Aє=IN I أM>zz\֨qY}b[9oNBe.żb[1>P6 ;bD,@!OJ<,ll&F}MrޅD4z:뽬qO#x(6̸шșgƏnw0~'Ufnfwcx` s9H#BDmQɚBϋ &")K;""r&41lC0I 3N:u&+ "rf3}|ԩSNn .1W B8^|>2`$+^xqń'Nwy_*SɟJyEom@++:VQ1k&???wZ=K}#"y VaY qB,Of<&k@6 9u B0wߝ8|i]0w\$Y#"_|>Wxaŋ+b_0a UwJJTRN@d[o-~M80XHKrv^~ $ĹgODKH,&>}dUuè{ r%T15d6PPȩ'O:u:;CxLn)SL7esAH" ܀G +VXb싱bO8h⫯=W\s/TRq,*YDp,~kZA@!11u7m#ٙɧ%bI<:a5`KHỲC&kСnnnnC݆q@4OS"mm1e.3f͚5m֬iAAoDEFFFq 1q?QjƟJ`Sh"db 8 ) lߵCֻGLD9Iׁy:a0!gaYN!٦s2J(/? )ׯ e'+O}OuM"y  r`ʏPwwrDHu{:&;CB֣K)ޅR"D(tA 6MLVNDĒ%tiddH*8(UFv/R=[|m\h17 ?/VAB};7ϯ_~;ߠ1t8HS%Vp5d`{+c[\⁉ںx 2vAH% \ A@܆qɞ ;NsDĒ%K*,Yf6J99{1 _6"#q*Ր>5\,u(-T5&5ªgpILL!MOC@jݡ|AlT"}T Xf+#@l=0 tx" D8th?H=zggL$| :D1EE 7@:).(:QtlY4)_9 5Ik֬Yf?>dE!)DIDUy !F)2Ѝ/$b@h Ũvu(cqy@ NsttLVEĜ%KlYb84{0LDIL|Jĉ UݒBk4&;$,=gWHD $.}u0CDfa$n݀G? `KFDDĜ%[d]پ}Z%&&ޱgq4 5IIk/_3r9>%S!%srlg ƴnk@2V<׈ E t0l:5 ~/?fm7gNƜ9[rC[Ξ=($nOLLL JB,~[|#L[~\-|;N~͝59Z 'd.ݭ_}5?xV:]W43{a0<<XznmF9s"dddf=lo@@FbbbK?(HoBݼ8i9&2Z ^PH'"N  !qyw擐@̟?Xs)1y׽:^j0K ~d$#cKF&\s钨DȎ6LHzzzKUKVQT\xG@B#D; A1GԯyVJ ݆3 |4LES?G9nU ~Vak 6$g̩SQQQ}eϥK2 ;@4v$Ӽ;Ν;w[xMIM]U^DEz_d(4}?C×b(@FqH?WOJ ֺxrpı/{ۮ)fw9k+ >vع3PDZs>pO7# C_n]٩P+BlIS|Kds@FM KW*  (>8✞I5D.i\Qb-cZc51vc2BPB6s{$S}q.٬d!΅YR҇ۺ+ߞ/84Eþ+&h{mZvm mdޱz5d! ;+(dÆ ! H<"nݺT l g|5s~~4yuBlMk~Q*]db>=x]9 #ϼhR5TZv_Y6x|V܇ ZX.CTȅ6l؀ޟ*dxTa,ƒg\Qvp}SC0[Z]F{BWP 00f dıJZ]QnXv-U f\Ѐ1\ ج^p@dI^-">>AR8*&X.뻵'o#/&;;R=*_!ј]m;G.S7 |e9H kaQ*L1!ǎ#A Dx ">G4q!2€&d>PeI! ڽdh?MW2깠|8i;ڋ͗e9 L;B4"cCB8t 6\H"%UDžħKIMI"&Ks<\NDE!ee|X.6U+4jGԯ`TFȟq䝺i4xEw%cϞz( `GY<:* yoEx  + xtA!H$w,z#'.٭ C-@ttfOn|RBl+0|=-r mbr΅ d&A۴)<<<%%%e]L[#%Da dQNث;㸗fYGX\IWlp ј\ig ̟Oms !UJB~CvT Wq|DRøp(Թ'6# )))˛ AS T*D2Y|UyWŽ=@[[-h4Wއ (^!w*"ٳiKjZr#Ɓmֹ]&0v1l\FòṂ[rzy ;ד$FZ5r<}[GoUhJQ4x+練i^UuK+WH+|pQ$h\\\ܦp @4 L$=))ϝpeSN@K2v sGʻt~9@F#]vHEXOx/ T(K;M'%,3sfdgd{#\ڱ};v\@eZ4 -H=xl OȈ |LC7??x焔Θ3>TF -am0',KҺ6f$͠^󐖽ɔyr'O,,_x.Cc˲D${o6Rƍa\ L$8v.EYf i,},\0,,,,7,7x;GF|x<#Ñ7hP 6y ByC'z0 ҂DhQ&pgژf-\ #܍1@dxF9PYll&Sg7bؑHM%O\,ݹr׮Toc40ù#>>eݺu)RRa@}>*?*Ơ|* ̢7z *`9A,.T&W ranDXkG|cpm?u'?'O@*)JP9e&‘qލ0`vc;Rtu2ag{8KJ:OSRg&*P{J=nGO!Q~<(+R"!, , 95ԩS'aʏ+Un[m6#{lB$ٸjUWQu $Rd,/R/"4r㒒XuRcRV~@#*HK;UCt :L8sk@$ &" D{"TX+EهnC1Sqmg F2k,coڐLy,]wX2 @.IIh''a)R #*4<?iˇnЗ ~|RR=HZ>S7Z)g` 85Br3ͤ<̝;7{b1h#EcU*ٹt]U6XhQ.lĄq "㗯D0t򉊎ΏNK8z/9` dY_M݀m $@ɞ(QbBdNƜ9šs* p9E)xfx$;e͞5 id*IUXP]+W^TĽswy,]Y 8'-"=5f6򉎎$Di!!=B8GΒJzf֌0fRL$Ք脅-% ;G)syc =>Oe[]~|c~m3V~dYxx)X~},+W˼pNYn+s۪,i5H<^䉁Ĥh$h,#lx8c(dr>Thi#[Z;;nQb)y,co}.Q) r@ [+fϚKyVLx2X2܁w4+KdBKB0-'IMA8||1#  ,z:4EW ڰJC0X c><"{#g`ăLV qA l>xL!233;x. AxZ&BdL d㍠WBǻ%#K/JD06p $l!۝E@(婩4Kh+";+pz!U  2 65(((ih`TdHDṫ 2B{35XΜnSBV"ا_<Iߐ!==}!E!Tֱ|XFc#<ƹ2;8uǮhk DںH젩RDŇP$O  ΄ 1%{nv,L,+%!ll"O5bKe@`Q!HS%֪'GpwjqNs"b~FCMm8b ID8!/x@8n\E<<ŕyn ,xI$u8K_Wi7:*:dIO2S%yѣYj/{:5U꣦n L$n<hěu)NxR `gmT HX .ҋ+W^TFRtV"QH>԰HMǕo[ ]?gB'6" x$#{t"bQ$]YL7OZuޤu)H Y79]_NbHWԈĺw@p[DͷA,:Rq6>E-[F{r߻wo#CߺGLIb~T 8pwwO* `ނӂK i 2enHV )tL@]?)r4p>7СΊ/W^|TOۂXg!CN 8u\ؽ9dny$^;A>&ÝJ^0慛a& @#Y{? ֭GJ,_9k&7n{ q[L$HDj-\ګo۩I}ԉ53*m$űe ALJ^^^ckzۉ@zҝ;@I`aIa$pi荏9=d+[J)]J5h(xւ=c_VI@6^\oAOv-3[譮,@*r2vދU5Dz]"/FDv" 7W/Vf3utN> L+]x$H%d͔;:v %:+(;=@ګ7IFTALj8OV.@8*vGॽ֋N\ $KAKܵry߽{_@Kxb %u|!SNzzr4<=㋃8z(t ]igdEX(ZuHj**+*-i39Y^^~|IG=7o?hxiMδ1}:YOuM @DYsD@ywT!xѸq3W#z$S6 #g-{`&6L)(:>yEzJDW#iijh˶Sht;pJ)8ʨ_:3]WxyhQ;`]x=JVy t(ݻ'*zB|;z4p|p2,s%;iE\Hl+7-bA!}4*Er]~ ȭQrEH[۹%cNFuǵ1z.] s.yʳqopPDwfw'Pn8%eqG[0V2$?_rwYj :A\cL .KS,;~s/O"H͍˗_~55P"w:X$"b˜K8^k0ٚNтJ#0u}9VQ:>@x㏿-/]z~1r.r8y&Sd2 WL\'nY;Æ CoȻ;?5ԄZq ƐGC,vZ<>AdDV#9֠ѴSѵBH.q$ $alip*ܨeW HC&{ztXQ Ac:މ[`K ~] 1s΅h @;f HoD AC &ȹ#vɌ 3!] S޽{^yyGO<6 ` ; sr#M.'_؉,gέs@!q)?q%&Ff7}rO> ~#o]:Z'Z[s ?N+3WF7 !izhˆ, ' WCh\VU6/?56ޅzdW{G<;bK7ug}? @zn$"ɵs- L2@BpE|#R|*#f. {HxB?z]+*}Ј@DdNj>DqF^p ޿΅ڀd"Mmdi(?]Q<d]hI!PfQȁJӤWD$V.?'Ǐ03B!֩NG3*9m#D}FQa*̲Ql i9=="PyчTZ">OQ<,w ?,y @"만@nFNXlɒuB=o_}6 6~ ŐFcw@PRtE*HY.HX{@!ɒ+܇LPsU fZ!Ɋg' o+3XK'I!E~n/qDR Y_ʆP6R~k7mkhڼP[3_"qakhBH邋 AtBCCFH3"T!41)B8BDLRUf69Eؐ H;D|u %5( ^We!-& KopcK߳‡(xN)1 $,( >;~~X!8B,֏neQdRMeQHfSg>D"Hq` em f& Y3K ِ̪u66Jb`\Kx2*&rWp!O;u^!SkY’u!b%!O0,I:!;j Wׯq5ַ>Pi:+6}5WZJb^Ʌ ɒjYcz^~{?ř:"l( <|x$N!CCH%%D!:AZNL -EY}AMCݿq3^~eذ_]f5+3·`%*3YD%%yyBU{`Q}h~ZC M!d@j8.$g4(A%1Tkq㣏>>}Idڰ`Y4/Q<İ0djQ"22܏*·R "f)!E>1qvɆѵ@Lŏn y(7.R2C(V'޿[1ڭ⪽E^&#g!""&ˆNWx3)llXI& _I@>jBuE"ml8+dDԕ!ӧ36_R3nƐi1ɷcoSyLr U&M ePѸ|CDSW*$)z1nه&^Z-J J'HeU^@uS &nBy!?cŀ2:Meߓ >0x.3Y6:3msP+}X28D/i~zjD5<0TH6==_Y˲1'B0Y|I/C|;L|T駊# H側H 7rpAkǦn90> <)IaVULfH+ fCg*]Z//meetAGZDtaQUiK&  ŠB_jO:;]'=Ӷ'pŠ{`kܟ_旧]TȖ9{ܻyh>f@7i^oOGhaMYO7 N~DS ~)3d[+HsFg2Ȍ& M SEe+L\]]`mU.嫵^ZXމ Oٗ',zjF=-/åZp\|bfJda.2{<(x'FwtЧoXl*DBEDd=> ,-eXq|wUCϛ?ɉ%?tK)ר:ź~汨ϯ<"l{IBpmLdQVVnw"֊(hv|}J!Dhءv@a+g$u[݀f]grgz4 ګoܰTKd@7nVNޥデlE:%}{o߾A%^^ϻvZ oʕ/ȼDΦGHC<ؿl4R)H`an}R#QtV {1F"]Gw0sP X[g\~8Xz B`KX8&wF8o_71Qv8A9q"=,"-gm^Gwx @J`E\OCaș']\@;84~iE)=G#@{q]ҧ+l̙fdM7ݾq;>'}ǽ`jΝG.80q,qva KJDp"D*KpKYa#b>q lXnXaWRZakW8!\o5m@#(亗ҧ'' '#5@@w.-/fKw.]\z(*:Qx8ݽ-?Ml`LaبtJ B8z@B".<qp'1ї#>A!}so>XN9ڵ״Z.;Z*Q2zRzٛwƽDB嗐yҋK3 <ΛG``z$_:擄Ull<r&-]·d 4P}W!q_Gq,|踁 'H2H.+;h dUWw&=aׯ_q.h\(**.:[\|lم% K x\#MIs_QQ8|}{> H+h"VACC'\i?ow5Wc&po4h_ VFsY̻DF|=#$q5(?(.>[\\rlX =d*N6_DNC SgϞJI~I   8By֞?WiRCh2"rNjWIC@Ob2* S <0gKJJ@#46O.-"4 dP>,COaȏ!Pz +"Z5r`0hǿ#߮0"]{2vRmxSb$gm bHpd @ h "%aIn zpԑdl|4(aG7|A~oRg T LTh#8dCyJZ-0G.a>~NRbn OAUW_K΍xL?բW+z))F)t>'s#gL&y; ]4':$(x}z|&F2q&ZsE=Ẁ`,Srs\5#׍L9>}|&DGO&< ;:ՁG_]ZhPSov y¥*s!B7$x4}x 8P5 H8 :{ wR:QHt =WuEl싱ĉ@*~?q䒳0?/gFgH -mRtH98 4dYt)V"u Z-F;#b1G5WW4!^b^bMήι⋱bcAD ^E^*~O%DJUBF.92g}L4)zҤI! 9!qY^2x+GҡC7ٖd9)ML>8S\( ݯ"@.!\pZ:e)?%KνR ZO?yHݣ0(ue#垀r?4QdHA8oa"5GEOFOF%|# !~,{UHjZ,WtjZ hns|8\^8DGۀyE^IΔ*>UzR]mXȗMd2!%{xFߔ_H4*2=)#2&דp8k4ffs" H qd2ٽ(?'Nx<~NC vz^d0AGfTQY&JtZ!NrM>vwsgr6Q6 3&yKH?GyDI ac֘5gfzmY1`~tj,ߟ?>Ď؎u9u}Kg X!bY+C !\ bW)@0TP$'&4ϓ\|d@%8,`b+ vp7 *֕ rq,ƴbB!@hՐ*A:B<| H%XV,USV'n&5O// Q:]^ vP{~5MV׈|~UȗĐ@MonP-9ѩ!LgE]bI~ Rf3#%oIccc[ǻKIENDB`gopher-hero8_huaa0cd7d2cfc14ff32a57f171896f2285_13327_200x0_resize_bge3e615_box_3.png000066400000000000000000000127351420147000300352200ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRnPLTE}}}|}~}~}~}~~~~;C~@ܸCn"pX-ᔯڗӾ8MyƮcI{#ڬ6=ד,0b;Uyxw!ܹ٠>>jkk'~r]P `vӼt/00yzz#1:eW,λn_o>~^Fct[\\Ǯ#wg5JWRsͭwfIJμ=VeG}Q@8˺sýԳ9[䴣2tRNS@@0`` P0 pPp`@0 pP@' IDATxܝ{wGi,Y )Ҵ1`Dᄇ58І$Cl-g{Vm\%М(HFa4€PVp a9ƞRVFq~nrs3ONν VIʤ)++}b!ySIb;1L[c[ê̅Wag詽.1?@B\%݉ŎDdZ$Xry#tLz\h.}2BmvzI5;ey:'Ii..,7]JGhOd-}.:o.j舱1E4G{ج'I$.!/ 6&Λy/!v&#1*2><}PH1e齅]vOk65$KJk훭.JXXlayE?M$Xasyh)@B* .D >+tO2-)w3WuqUUZtaV+g1zXٽ A8 2unX)9 IoPh5Q i=22GY*덏i'Y-1p}ĕ_wo@KY) QkDR|N傟]G ]P.VIEmF,MMUG_i@lawacDBoݨtȖS$]*9ƒᕜ?JVԭCOy-K!#)9Z%SEI:C.ΖX(NthYP4j9jT<?$[Mɼɣ-o]xi9޸qs^w/wx7tލXﰣx_XHvmpHzH؂sd&ȁ-(DqRH<~K>F 0Y"?*5Yj[AB#'ݶH Gos1fKu DRs|M ?_1I~=w^Qb=Fl-vc)7MퟺA"ӈ.yBX6-{l!]V*ZMe,? bO6WЯA \MN{ ۞ bH6V!AV\.J:! r8/%eVKR냐Ƶ^oH*tRgP=rʇ!k*I+sb5Z/`-Ȇ?MR(@^P֢rqR$aVZV)h/% @8W͟l"'dʩ4~󛯰ƷPD5J>LU5Դ3zWp Y $+&HҿB5@+9B:.Eܘ+a amꕓ3J&(F(Ȍ%*N듯iY)$IʅJ09^ YJi>U?VT P/mcФ22.L1Ct%kCbbϙ$jRZͻyAZ;#KYoP<Q@8؍Spfd}#Dfض]dyjNN-\ EϦ{!A$)+B- AD¶O 7-,Hgtbo qP oZ| Zc_FU>ə%f[!V=^!_!֩"!m@h(Q> >!,Qa״v%i @I1pJկ?$'Jv rsCWx+(F=hNO_w禫殷5n x{ ʺwb%WM*Jj_Iо#. Ü>>R2r'4Mkx<YdTǕBNr`jR,Oq9Mp& NX(3SfME=%4':gWX0-}={C6lbCt} zndUNU;,Yy~\~xzD s@6.*m-mT S\$>q?edu+ KW,`]=*aMHpObM^% ± ֈ>`Gz6^s=^a#_cmW12#Q,zd֋}QޞɗKy`Zžcݞf>"+L۳&n'w-n]~qn*a1- .lh8/Vrd[¸_5xr5YM 9hvM!]04c%q1}# qz̻ y+i| \<4(UB p4~p  "2֒/m{A~41pF{Z!u!˯bHUfX!# (keឝɡ!`CƉ,Nڱ3WϪ)uW]h=r!g ~ΚAjx-aZFrL u: eZؗ"96> L>u-B+BGğn*a[0PHtu:'x}G ttC4f\sǵcu%yo!h$'"妯`9mh5u['B tDό?ʔqXtVk#v!h`#ȴX'W;`x@gg>N)@9$ 8mSq\m_k~Pho${ː.H@&= D]@(f֯Q Y—O9;FzȖw#Kv #\XvV*qBPWB3B|L̋;0rK',KRH–? a_iCL}|^ *_5Cc29<%/ Ek!OCӾ.U)bgZtPE H'=9dL"d\4 Iv-UXOG'  >A-, cf=%Sx<[+KW?QUv$rXh{-8!G v*U#ܞ3E&t)4E\oEPU_h:H- 쇄i5;cź1nCw͢i Qf ["^HͧF>f~g0)%@e&"*IENDB`gopher-hero8_huaa0cd7d2cfc14ff32a57f171896f2285_13327_200x0_resize_q75_bge3e615_box_3.jpg000066400000000000000000000167301420147000300357070ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?(#;B((d,c, -Hp8_Jr>hX3;ZP-=ir}Wk?tz+|1ë<-3˩= 7W?IIxz4/D)[8$pףR-ԣ*+_yN/#Z~2]j²ʐGeҫ2 G Q9a#_Ca8=MJ*7AW5|Og^6gJ*ǚ,(4 ( ( (  sDcנ[԰@YSIW?foem81a6Mc-"CK^"-[;~_C)VNRm.Վ(f ggmriQ_QFQGm*QEQEQEQEb W9__JErcpTq^hҕYS4M#,`r~~Y$FVE@y5xj7bXn*rq_=Kr~_:g8F7vjT)j/fXOWOp9Q^QQE{VMݪ][m:0Gq[T"I93WwtTqb~U8ReFvp:ZxFk^ S$D(b= ƿJXZ*ԕ: xJu;S'ݤ ?$E <-?⫛Veͭ8Rr>.֚9 <-?m@TZ44-}N9w^w2y~S,~&ͷ#$ 6Q?Tԓuu^>][MzJGA*:S*LW a+Gzg\΅ȿeeRDp?]sZEkӎ|9.!В}-zm(y>?HcGZ*^uԊz2qs>`(F}ݻ~VMcmG<[ڏj_o*'.TRoZe?ʧ.B˲~&񶡟7Rn wqF9IUa)\̪_R6vv]@qa޳4->[݉0;3Y]BNU0Wgon͎̩ۜejGWfYɌ+ #]Vk1{i-RF(M((o" J++ $^Oٵ5m}GcWH%+;gA~oiwMDˊ7P@;ĤQv(W7#Y)I\C^m3g2F]aZԔx׉~/:l4kkyqQZINq!A}YLԼCZZ|W^\")mwR8q_7"x:%ͽ*'SYY&-5;b\Z΁p d}|mXgK E'>[u]ǂN "U*z20+?-qhBoe>$ZҌH)#ORA 7F;p*:v!bi:'Zz#IKtR4y#KeqGoZ&Kt]5!Y$ۉ3q:WM^wl(#xT8(8>^s??Zi9wf/?P_[]ڢA\eJr0Aһ?2H,-*r9p~kx[m7xSdcb ]yε܀~ζۋd~íh݋ĥ.L|{k{u]{`%e) .z~] $FE@Muaf}NEΩM?ST=.i[.v0bkMtY =OشS׋ő%+f*QE~fwQ@Q@Q@ӌLZ|[q}hF_u#Pt ? Ddj69?5ogsvmS“ZI]%Kw>=8ְjoN ,O~I]ΰHj6VG(U9ZV-34= \v#iudߧsˌHCTA"iwtƃj\(ч[|?'OK̉G"C4|v(?|k8twZ2.3'kUZJ- x FnDιbg@mLk$ LߏJYWe2t ?]ӹ/9sW׶ W^1̌p>JVj#O 8NvGv['ju#F Ij2"y2DiUR]xXGk%I߮ߢ:yi*#=v,`~%:ÆUf:|-夺.p 񮋱,[/Ć_G$Vc=̇ody*;x--UAml_DP*Z, WG3 ;??+tu]5Y_rM_Cu+HmܴL璹zNNP<gX%NZWzV*=ԥVWn[EW" ( ( ز/g[Ү3ǗO*PJc8C)}gNK-Yӄ+F/nؼ}SwIU4ݩ1F U-I]-"r}[{ ( ( FUu*OPFAZiCOזo¹ oQG5B~ҦRQZ]qJ NQ|-⬊|85ilNH|(o˼jdq^izޱx}^3TèB]/Z+|Yovykӹl,+F(g(QEWx6ҽo_%c1lódD䕓g̹q2Nָ%7'eL6* vQvcǫkB޾ i#9LX ?Q}?Rgne *V'ĞI(Dܯ < 㜁YV}=]ğ WZBeB18DS:žIedtaօr^5u't~qᡅN=QE8[ knA"2W)+a>7I::5TH{'?g"}qİBkɼ!73ً!T\W].LzE?~؋AEW̞XQEr2[jbVOoUׁUWTi-_໳j%^NWz6ͼ9,t>E =ѧUN4v;E?KT4YƋg 9ҩ*vWYAmQAx\&F #=wq\4#>>: ѧQz6X6^S_4?S fuyo͈)]#ι68V\ܬqR61quvgkn{vמ^be q?C93%$s'e\O\Mv'e\O\M5?T?VZOOf8~{1PQEGxݳj?fyīǿPǧ?LO+\3+í˹Fƾaj?}.t?P+Q%-pגݏ^Y$,$YؒNI5xDMQKMo&7cOz`J.|UR *PwoQ_@z'}ۏ7GhIDZ*yjn :`9k#}tq-~QL/75C:nߜ~ sb%d{Vuaά}?f0r+imz|>Oȧk^+i_ZmsE/KIUnwůCiPVUPJAll_K;s48iRğ WHPKMKxRUhjPQ՝d-om`FR0Z[qJ֝˾9:OayVcjwd~o⡋μ (ڵA2p?z|4.{ppxj$} aW~WۣF׆Wڜ*~2^/ c]J `2^0b:Nm8 Nz.Gta5(K b Z)QNX`Ld4=?XmY_Ƹ߇J]"vYrWx^6%gPhV:xу)zuzWQq+9ZtRmd?>bl)85O_Ga))ђsw4R+Pr"ڰQE+"tVɚ}.S"u17]Sp9'+Җס ܗ1œ$Bީzw2tiptZ^+c+*'VWaEPbQJȰH"r,?J֕)Su& P\]M9|w5WG3X-"ݩ9-~ fF:`pUpFj^9u*4pFWK6?`_)x{}Ŝ/,&+O(((n-|Gozsp++q$ rz{Uy* nkl02]^V9`if=2g*Cf;9EvNJ2'Iy6 lJ*~̦megytbd4Tf4Em%d *qi!iͻJ¦{Czr%jkȑ`_[4XʼҮ 1I?:Y3%9k]9?;!E 3݉Vqc?n[Ka>W.KmSӧI{YaE@K,/kN5QJM5r ּ={M̅d)>ڽrk N קg3 tUkc&1SZ(#gopher-hero8_huaa0cd7d2cfc14ff32a57f171896f2285_13327_30x0_resize_box_3.png000066400000000000000000000024421420147000300336320ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRDz5PLTE}}}|}~}~}~}~~~~;C~@ܸCn"pX-ᔯڗӾ8MyƮcI{#ڬ6=ד,0b;Uyxw!ܹ٠>>jkk'~r]P `vӼt/00yzz#1:eW,λn_o>~^Fct[\\Ǯ#wg5JWRsͭwfIJμ=VeG}Q@8˺sýԳ9[ 5R1tRNS@@0`` P0 pPp`@0 pP@5!IDATxdkQǫq&iLSIC afTm$3Ҧm!5E(BTDzQBsPՋ'"yo_v8afc|~*?7͈Bz^mARLD8&)Ϻ8XdS5M6MfxxAD-D"/Dֺ'jO}q*{y?-uЉxXmNS@ n;TҊuЏC1o80񼛅faeǚ]=ѐ!!DQ脔 9GH]̏>gK= .sz>{p:Æ4|k x3F7Q9kX (^Fn.L0TzesϪI"Y,ݽ6:Z.j$N%vpm{|qlvyskphkql|y`rbpm&tme*pz|.Cvi*I^}db4^tu<[{f*6`xgw#gUY,m^0a6;%4c SUy}-c08^1A'LR99@Y\ +oW.k49\"Q;68]nO?,G%uOdDW FATROnvy%fC,E)'rwR9vhr:1gui/i_"kMrktYJ{Z%Nw״==X9;ZujVL`z'eA?Vn=g?0s=3W2]HsQ;G&rǟ4>KRU4!3eSFL{T7[k?xDWK A.pqI#OQeatjiMAh aFoʢ X/hAm.d0+"JBQy6ś޿%ٷ(Ա̥cHTb|^%ܼY.WGJi PDNcKDZ,MCOfLB{*dZHIÙΨ]IGrЫ{]&ӮrlFV{ju8~2{sjj\(`JF|3ۺ[*\)qlѭtiskskrk|/KL (tRNSG侴o'qY5TZǪۻ%y9 IDATx윉SߟqKpqQ fq_иFM"AP1AqH&F,J)a,:}'tWs} .3 v b7 v b7 v b7 v b7 v b7 v b7 v b7 v b7 v b7 v b7 v b7 >0#WTT/FTԌ܉AfX$[+X)LbM?PZsV`D1;O?T"ޱA?A TDsf/yA|8OzӂÏ/Ï$1ſdF?fT/͗'17%Ț5X(( %ȚZwl,l[#օP$$,\0! w'NД{>F$6dɭ4ܪbVIFBO)--g]^G9M,XcѸuk㭍q(cayI,ؐgg%|Ml HKss X?~eee%ħY)@{2Hc:"q %cs3.B\ Ҁ4 l555X nAYYX YPSAJJ*xUTШ"p +r@[#Q3AK?nk{).fʔ*)!#iU \Wz&HW_(D\D6^-/2BbwIݛYmYԱcS6+}+}S:Ǫ Mǎ-ަJb,Ps"UAJGd0ȨQd,4 UϓHǏO8y|HhWRg nH*D;RJ|Oo .dQ`.g*Pq c8H])<ٷk>\jB/VExظͫ\;n渙jϜ?|D thZ.@ص/KҚL͜b4 Ofd> t? ;.nmz%kׯ]K":sm&W*$ K?o);1vq&bűd=~ Cgϧ2+a8  Du Y lE ac @z)dH/H#}}aXXX0@ 9X}t*~~3};?\!L@1#KIRy}V$9iy'ˬ '1Ük>27a#`+|Ƈ%A"[MK2L{c YhROkÇIY$r1V\2~f^?jq^\K5daA~U8#J\Ƃ4%ŗK x+gfeEߏF2͊#Iwhe+^e?z/b}VweK)ĥd0nztH^q.m7 v b7 v b7 v b7 v b7 v b7 v b7 v b7 v b7 v b7Ҙ@IENDB`gradient-circle_huf3d35257a40a8d6f525263a856c5ecfd_20069_200x0_resize_q75_bge3e615_box_3.jpg000066400000000000000000000055351420147000300363620ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?(#;B(((((((((((((((((((((((((((((((E.K)s.rh}))i)(((((((()@'GB+)Զ;=h=k&7QKah=hc4dz Rzj5WF 5 ((((((^e#sp֬3*)f ($:~ߨI*7g^_M5fv9&oz࿵ڥjgò:wW(?ڥH,wkWKO0jZ_a?ڣc_{=iGjc~ac [rGzWlWl;dzLbw3dz%ފ@(((((/2"6%a - ~5loZ(H?,Q?8kzW5J \SE4K6#zWDر~ަ#QF{;G[>}ވ{I4}j/eoJ?r/bɾ޴}j7'ٛҋQdooZ>޵_GҋQdl6Y2ۓ?B+1W;EwYGEL~U>yRٻ^h(LB((((;}Fp׬jj}SVgҾԧJ0Od}f]?$sKu[jos?g{WKeOZpQ9jOjʾe_JCD?ٮGWҟPQ9jOjʾ}}*ꇱgI]Gҏ/?튂1"E1S^\-j׃b";|g]( ( ( ( (9&ky:u]WAިyg{n =4=L>?P}֗\TCPN'Qk\T_RǨ?8G֏s>hZ슣ҏsZ\/TQ:/j_Z?G/Wtj_Z_s?#Կ>ODyJk+Öi@bIG1Z][Us (9Š((((Fȯ/"PEݻmZzO-O=I\}׹fqbKG?sso>}:ue{x P}j~ g(:Nyֳ>>ֳ(J}jhZ?eG&jhZ?eQKt&khZIuw6vؒrzEO qVw1XDdS;ܓ ^֍zYq̎z=8G/:ĖKyXWRFQ_QEQEQEQEQEQEx^)LC{cZރ~rU=銫iZZGquW=ǡWuQsSzrƮF|Ez4#O?5/ kZA?nn"Q{7'2?Z/`q{ԡRČ(S <1~æHvp+*я=Y(j.N5x{R-#pV?נ?e] :ƽ.O-8 N}n1Nߗ;h-g2<++ Xp~@<QE~iUukJ{ԌTUQEŠ(((((((( :xK\S1$ "!-mQ] /VK^mVD]2;^u'QmRIlQEHQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_0d1b300da7a815ed567b6dadb6f2ce5e.jpg000066400000000000000000000144561420147000300343560ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?`)qJ(8 P)(iBӂд `ZpZxZpZ@4-8-<-8-1 J J0-8-<-8-F.ڔ-.F-J- #J J" JJ!KJ S @R@S@lSeA>6P)6U(I՝ݔ\MiJcE= P*E)(X4Y)HR+JiJSFӂ1ii)hSԁ))%8-J% # N RST)BP2 .PJT)BP;)*m(]8JPP8JpJ%.ʜ%8%b]ce.WvU/@<%د՟.URJc%[dMBRRl죘|r•h0>`**JaJ\)S*J.`BJ'L{T.rJ'NTd `EOReuJxJ"d):"{A2]_^̀%8%N#T(u TBS{T):j_ N SCBSQCّBSR{"0 JpZ={"0jPhD[ivԻivCmmM{Q" l5>M>2  L0NE0=dj2dF—AXFVXTL)R}ȵ2F!s2RR)W>пf*J)Z^Яf*ZR`*EAH*@){A1BSP)◴+يSP)qROrR RHWF*pX׷Q<0;!k~<]cKd𷘮 r=a(.s秅+Tو8 TLn)SiRpG N F)+ـP)EO v)u/j?f8 \S7Q1EGu/j`T{IBN(ȨRn@"HfO+RE0␵4/nRڂ?d٪j8%@$ެ$ֹ%69t[j] <5^\ZfGQ-֧e۰P;}bsYǭJZclR)h@~}};B=jUz,l2n#JKjSYH&.g^=J)Rϱ^ΔL=jA0di?=5FrΧϰ;0zӄֹm|5+cK7֞Z|=ju*zZ}SV" \EߞD`O覼$%B-%“; u]HLro΅bQy<4j{-S{?Zpz VUYy^Cm G8KXz*ǘ=iAX}iR)DG(qYxSC-@ZxqXz/\JFYnޥ֓l~f KRYQ Oޡɇf(+?}ޡ͇fF.=U=.E٧5ijFe- })mPLv3SԤ UF*6Θ+7FPiXoʝV<%[=u²1Jhϱ [T{ʸG,Gv3EOvK0+J}D~T7\ U_dI<,tTgIk?NUxSKtR~߿9*.ǢUɠk#~65ĺg#T'TuKA==h̀'%GiVa&_;\$6%Ld18S^Ys>ǧ真ɧ_9^o p!vO![ԟ])}|T<,gr]K|u4=^mnA1PjEܣpkdbFHwHW<VSSN^K7Ǔ 1Fr *}j|r1*PΣ-\S0уS8J/}t!ҟ3rCl"CX'v>OA]NZ@>B!d59K=#xsqŸZy6Ѷz(PvzUƫn3 dj3 6oN -sˏT?7i<]~y_ =mQyB3?\pA܆J/O̟Q"2|GBxt)'5tjv!J%g~U'-P A'S>[CqR]H ɑ{m~t>GWiPc9ϡ\` '5)q$l/*f$ȧc`M+h>2=1*EleN3UTo`C(cǫ }vfJ&pO}ÏTnr1?{oO W:յlT,ષOBTH=ilzӲ%͎24$cOsN3zR}i,׭POqzRUJ7{fe7 +naAK3Zh.ǭJ69JQ3H {&F2XAU\gހ@znВA#7Uy;?!1@B8ݞ;x F n9OD`1# g)_.W fY+ҬREDZ4i0JGB~:UmBc$H#娞6A=(TF =s@r>n4}hsG81V"ZNx&Jw8 HIwsiqcNi#⤖A+߭Vy '@"#\'flRO'@`0; A{P;$0 a^5ԀEBv.0ې!C909z}*yɲlSA Ā=)TIsMf 8HͲ0@RV\2$K$CjOCLFsg"IXGaP2)ᝥݰc8$7_Ґis4t;aO}QS` QDfeSrHڏӚGTOQM r;?Yo攷U`AUY[m  !)9)'֡iBA449RɜZa# $ª ǵO]:ؠcD7ڤr&7,pi rF>ny~|eC+^9c^JkE5ɧn)(E*p1Urjg`zL0>f@Rj6_VG!kf77 PX@zr(9Rn[v2 (=5ݍ}3Jg)x(2 O;09Fsۃ='F|qO"`1+'9a)mA֦[x'^YiՉmq@ ƜvSr'4P!H,r8v"-K #c۽DIV'Q9U>"Hh_p2}i"`?8JڡN<` dQ9 34s@#iAfK}2EIi Xs|` nj%IPԭ ~R`AE*UU {@ܱt2fّOBKeS;M7JJ-S|9՘Rzb)g":( ( 3ICu:2s ^ƐzIJhdI<ސ$u:SB2ր%8a.sBVry8H0Uzo* \qju5Q$@m/AE2Chn H~~Dv4(=?Zku |M4<EXiHR{SxCR}i!T \X}UI`y`Vj.oR-_[jmڜ-QmAmEԿekK_j.#ԟe{QOj.:{TN{Uڳ.uڥX}S,Gҗ8JjJ">Ô2{UڧHRTmWjax}ڴ4'ڎp2GOjy>y>{AzZJҧUuQ^o֎𥉉ڦa}EgQm3@ʪd.6I]ڧK~zUmwR2I.q5YبᮮD{TH}jUe0#X*e=iᇭCD4*z_1}j`_R#MJ$?#Qԣœ|a7`u{=+JAQUsPDg?{=;״CX/TҀ:pAxmcpW.0`޴!OG N.3B[r 9$ke25ʠ{Ѷ0}+2n?Pic _yU'Ֆ9}_9T}AVV]|AgsO&UϬzϚ\no?m'Ggu?bH6:l?:=WVjE}KgE#Dz4 @CHw6ni|f7)6`N)8Ρ眊 f0 RcdJ7jiHyUAzR'?JdUN2=y5RwO N;ԨJF?5,_GҀ%Xԣ7C׊NI52o1MGLkFk?ʚiDAQU5Z*ZC aIs}JC?sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_17fd3c558d78ce249b5f0bcbe1ddbffb.jpg000066400000000000000000000155711420147000300345400ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?@)v (hJP JxJb O O HcSԁihi*@`ZP(JpZ-<%H# K K# J J"J#҄":pJ!|e(Je(J%8%BeLeAeNeWKleWFʱ_e&ʵeV<+][M)@Lt[)M134[)M)@LtZ)HR**JiJSSSP"0 ZxJ- @St%8-L%D#BSR (JpJ%8%M%D%L%CJ!K J"J N @eN+V6R ].ʰeWǗJ#"GV|P_.˫~]'@Ryuwe41SLutM1P#4W t”L0]1SLtS1S upM1#<-<%0 N O HBRiд ZxZhZpZ-B OjcTsRӄtBO S:9Ô-<%J#|!==PA%Os%8%J#9Sԁ))9Zx_j-8-/hW!ZpZ%<-/hAiiihF<-8-9h.=r 6h{hRmm|xRK d{i Ը"Cl4JiQP{6DE0afH0TdQy-NQ!9HR*STԫ^|*EAH"*jAK UQOUR |*AK|)@ A@QI RH)EOf8 \RFh)qM.j}1ii/l?d:SsFNQMFO5M i4}^M0ҖaQR{ &M j%<$Q\HD=2sՈT{^=WϱȧYGJ ZC}x7% Bb;=jEz1tFOo!-YOw]Ωe"=k#?~NOZu{Ukz]}Ne(iu,qjU,j D% W6u$u򧦷h.Sa֜&#qRl~Y &mG=d/=zһ!$o/}ޕJ8_D.aY;CE5>i7VPŤ '߈!{m=i?#\w2 T[kj;9z\?Zpz0UYy\LQ5ă֜$z=iz!ZpzH_Zp_RrcP5|JVPv?PT0֞VHާNcTM8϶P.ǭK3L8/8]ZPH(+7c֔\ZeF(gzzne2D\ZeCt-8 (٫3S Jk ҘGjKRqPO(SGl M'Wyޫ=$6\iE1C֠֜g#Oe&T ԂAH} s 2q銑sJ7i&g2߅;O@sdoT[uߚr T R*OKiјķe~T 5ƎQ FA~Wo;b)Ap]nfwm=nJyfZ69x?Y ,J|~:Ԛmj CY+Jjn|TwJBzWqic ?-%?4ikyT4е773cn5+a5qIXMy@7-#.?g+ZYeQ=kWMQAE!J9(?2F=22͐t->V/6k]޶qm'Xrxvٶ@5VFvZ?…?ZY].2̪#=?:I!Mq&G '5ItY7'/",lhq"2'7!dr1J@wՆh>ѻpY eRzzT B8f'mOĞ\b=>EFlnٜ}(7%#}`7u)&/ ĐVB+v6oMVYvSGq{rŜ7ߗroS#}L_TײQNe~]7jsHnګݠ VoUwU#]6RG?"hէdW&|_j{KuUUz;#2!ܻUڢݚEfvǰݤhj"瘿kܓzI>*K!V۷5ku~7PH[]dU|jxaWmċwݠ4gc͵ú]ݭ?5YvZ^o>mfZhdmf]bvE Jܲ*@ Fm[Ww>*KR/CvEe]VwH.X}]3mqFٹT-3-$L˻-c߻fR$Srr٣HeVEo:Ovr3"iJŻu2I72ƿ-\bg)#*_eZKXT|SmnU L&Dwwv)wݱ:wr*xpv2:(qUەvԊ=)vie;A}KPK凓{"[n${!k7#ރ$ kt##XWV_WeC.5˫qDYJ Qo$`}vM|]_c ,~)?ڕ]vo,hf:WH6c@XxX7nU꼛aXM̫wfݭ:9mDKz<$3C4;Y%mSG-"$b}Rgm֭#TEe;|ʿv{|_U>f<ƇnZ -vK]nf:}ڪ~O j/^O5ۣ\Lvmga~Z |ʩLI%U>un&Y#V+SH'O+t~_᩼pUVp;y"µn/wu:w923nԱ/;@ZBJnLm_&nKoğ3g9ѓ jto5E?nષw4WX~`ɶndYڊLw_VO(g]^L*:#-]([ƬlJJEfUr$ty_zoɂ(i8q&H|hfQA7Gi:Q󾁖%V87+|ؿ>ޡQ*bTgS?HrKCZD&ůmNᑛz.$}i_vF_MǕYie[SOA9w w|ŹUQq*_yGIR%ꈂ r3=Ơ }> -ZՋV#섍jbᅦ[JE#tQI CZ_ΫKҝS)J({7)'–${= K-? _K=3}z2<{GI*@Qʖ+ojT@lT#y_ݼQEG"G9a}Hډe&R*5PY[mۊX:ȳ|-?~j`Ijԥi}W_zw wE/"VD #OLOM)J -g,_jtW.ݛ)w~THd֒m?"_wȿc7MogV!j*hsunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x0_resize_q50_r90_box.jpg000066400000000000000000000101761420147000300336700ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden   (1#%(:3=<9387@H\N@DWE78PmQW_bghg>Mqypdx\egc//cB8Bcccccccccccccccccccccccccccccccccccccccccccccccccc@" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?ZjE$jUԫ@(TKS AQ(P*e EK*jEfCb)&m2*6TTl+ΪhϹ\ :Y.B)ʫ3|t@~[R0pyL*BhS)qǸO @8CԞbv9e<ɋEVZj&Zj%&ZjV&ZMB*e52MJ04545 hMHSR&mJF@4ҹ&tħrx5}ϙ~C[GX7v\6UTUW3_AM{Pw{^p #M'sHy ʂ>jDcށsNz=5& `J*KR-Y$RD"RB*jE5 ԫH Ԫjc&SPR)c&SS)je5bJ)7Jݬ;2᭻`߱Q!'is py8 (U 0A@HÌȦ7|jE$/֣Y\c >0FvKijUZIVZjE VZjU VZjUjU5 ԋHd@ԊjXɖCP)T2404x\:bRSD}Zx sI~/n*MT9jAQ UT@0%SR)H%SR)Ԋi(4j i`ij%4jYDjt5YMNq'#)3H7Sl[:mmTj۷ [RΦQ?JT8j۹ Bx5޺ $NM?{a@ YSp=M!Ri&?0LӘAȦ! =Fx#܃zPH:szRnfS4SP p p<x4x54hPi@2Pi@ӁMJ+TՔ`kfk`Ѻ3F1VҬDOLnx~{<F{#܊FO|u ) AןJLGci0 `{ӱǸi>nZsunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x100_resize_q75_box.jpg000066400000000000000000000052121420147000300333410ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222d" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?(JxJԂSS5tCOP8AW>g=ڴDfj_Vڝ{P_ٽ7jڏPIoj?!.cojaoLkjV ژm\S XfIڏ#ڴ'ڋԋL !HeHtژ JեXhR,>qaV`RTjTj.a}ENևrڟJm}ҺzY}E/uj}Er!$g8d,Ulc=4] TTU-L:A_ZmEڦ}iT?f-{VPs>SUU}t溆$@{v)VsA5[y/Ʀ_jQz k !U4\KL۵Way=4#FZcl1Aq^jJjb),L HX@GTn5N]jps\s8jr#!TNjx|c #pVũ3^>Icî:TGIlk͖:k=_}jAkdNG8ym'Ֆ rc;>p!Q-@jf=qާ.vW# r1&g#eӹcNC)>9EQx[X__^ |<;aL7$KI_G֚݃c}M6~p9c02k($`ܐ=ixDž|aOG6=0qU VzǨLÎOK)|NE9JI>#4>h ʑT!N|b8e4) ӚTH8uHII.D3w4Fs@g+К=( QcZ@펦1H}g,0M2%4ԉ1j$$yTrόSGRGG~  O\bqcB)U@ޣAV$gN3@XfÊO[_ X  8`)~XSuZLH&jD\ޤ?>ҘO+D` dfƜGF<`r;⦓gL_~VH Eɫ2u?ZC# 9q *4Ԇ!cIA(Gsunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_300x100_fill_q75_nearestneighbor_topleft.jpg000066400000000000000000000040211420147000300371100ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222d," }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?RJh@ʹ-8-H# N R!)*PJQN ҄)Dt@#pJuge(+|tW˥Ўˠ UU[|{QU.*)TW]G1U.ˤ*WT:R鎚c ^]'WLt )tyuhI2N-8-8-<-4-<-<-<-1 O O RST))JxJ%<%B J! N SSu8JpJ#p+:#KՑ/@|_.yt]TחK?*ʫ_4@T^1L~DL1Fc F:i:@S1lf:g@!iij@0-HNUUib=RU(0 J%H" O RA)*PJp N @:%<%@#Ձ8G@tYӄtXGNՑ8G@T][^TEK{U/@j_+ڮ|RihXTZTZVJR`2*S,tsUjEZzRtj@"Rts)ZxJERs%HT*\@S:9Ô%HԋDRT/hȕjEZGO9T*E# # O R!J]8JP6Qytl![e:{A t\)L)K!I:Q2RQh3]dQQVE@a) EL*$+TꂢN2ҸJ)R+AR bԫ֕9TTE0TcSŠjWG9TRSpQR*jM!E<(x˰QN )]]>vՍ(GV|6P.˫[(GV<cَˠ :O.t:@T1Lup4)t:RR*6U4VIp ZpZb N LӂPa)*@JpJ%8%B K" J K!KK N S6Ru8Jv.@i\,r ZrHEBS)j@\,0%<%<-Ha)*@\,F O Jb0\,0%< a))j@ Ea)*P\,E O E!)?j%<-{S{T))\,@ڏ/ڬe yt=6Q+ytZHR`P0\)L)G0Rh6)sM3e\h34sEV OXE|j"HԢ:9Ô%<%LtDO RA@ S:\ N S()JxJGNJ Jcu.\!)*`rBSt{@# O R!ZpZ%<%/h>B-j`h9vR!6T(G!_m!J9 )*ZaJ^9 )hFVB%05i+9Yb/jEH̍a*@{2!ԯf0%<%8 x{1))S솄N>~@ഢKۏ؍ NKKKۏ؉(ݴmRIJT88_W"+L"5ThW"aQ0ZcGEr&DVnΫ XV0*ZP6 Xz0H֖6C vXzӅv° [R K)ѐ\gd5 ]l˫mly]f,r\6گsIDWSxwmy\^ji>e l ׋o;X«t!<0|zޯ=ɝaN Y}izɏ )f Nc֥͖a֞/͔֡A(jbҋse*f4p_Zp)R43KVڇjhnnC>z:=/n5QeNdؖ4X6BV\U[{v#z`;W5UuNz=jݏZ.zֱ"g\r}HI=5[?*l`}*>G˴zn4E8sukgyu5!HC[DFxK~K˥O'SŨFFj]ncSGZk$fnԝCU;?50@!y輸3JĨ㞔\O\'$Vo hRG.erk#\O"?ʹHogn=yylӆw2n+v0=k5$FQp1 }jwgA+RUcfEzO~58(Yhދ~Ur}F=ί>Ǡa?N~xLq8޴5x%#k58kIh|MxXXrKvFgZZzX֓'7O^TjTdӟw #Sz@֓᭧̏[AQ zxnu{:CtAK1w+Om?O߯0}c4>0iIUc銗.d]j+SwzGi͋XyJ}MVp=5uxO*ꐟjy 2G61odvP{/fcGW{s'^6;cnl;y|ՔgO2>[[6?|lo a*`{־=߆LտVHZ7ewȖWzͲg3'X7z^gw6G*͹Y'Z˕&x4tC!U6m^!-+_:z|cf_D?No[A ѿ*ēŖY&=G>,8uG+9M}: u5s ` Ask2{n$2JJq^susw0yQVxHsLfC9eZWe|4Dw `{(pH&ra@F $Da xwJ|Fi>O@NV"ڄz܊Ed{g 6rP:rN2Y^QTlhBdwE"?'> }1IwbRG B3Hn`1)bt͏Hc`cHʔD2B88A&Y;c$d1k|Ƒܜ֖8ph`I$S:Ν[#P94moҀN*˶@4J~a9'@M-IEB˒* ;=!֐ EZ((J:JJPIOO@Î>4LY,s3֐'4fU$GQOg2oJS)pF '8MNO>F) zSQ wy+j>w MEvA)o59t%=hMsunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_300x200_fit_q75_linear.jpg000066400000000000000000000114671420147000300333170ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222," }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?RJh@ʹ-8-H# N R!)*`Jp N @pWӼe8%W|# ]/V|_.+ytyUo˥GV_.*yTU\GW<<Q>5ITYk BVV8?[ՈXTL*f5 >U!aQH-ZXvyrդW ē(Oֻg2IXI .k8qQ6䍣K>Qz}>S'[џM4[g$ Ñ"AnI)) [j^b*s>'WUQ98$/J?Z8 3\i%lHNtJ][Q?D+KIc6))$wˑ vkw=Z˝_T$V"cqW[Ƨ>ʠHNj^ RW_h%׭ʖ\u⦏^jP}+\:cMg81ޥ{,BGAo}F\mO+vnka&ymпLGV{05/R?Ƶ,>!YaZ)0I^y/Y۞G[(5kCEs OǶRBZ r~3EfG}kΡ+!]ۚ<5JNRZ5jQy~K|\ 푚c AH$9Nk9u%3g$ǯ"[jyW>zIO=kuFVfLv֤Sn${e,=k/lԨU;Nak4rY{J5EOYz hd[e%Y؁ؚ'9B''ӣ~9P)LOx [XF@NsP"ܣ:Se,O})Q"|֒.}:l{@⚬?{ݓ5 mc{Hh Q i+*x4}ENpˑQB@3Q9=I( H =V\8Ґ sJ bPvtdLN 17d8ܳr:TX өwt8*F(Ƒd$a7,qU,}})#4i O4sҀ:9;R#'q@Aj\5\ I~B t 7dIt*MZh/R xs=PnwM%gq48£)4<${ {(K1~N{L>T 0Mim+d@d$tv6Bd9(E 85qAȨZ#€v8IMJb cf̌)&OXF0=xA>BF01AšTp(W=8"8FDZBg֗w9NZwO>Փ +esJm{SZ2f㷌tҬr*-;Mҋ|2pzf+MFAh-Gq 0G3 ~v9zoz33.lsL Ê bT#֢:RdqA\ZbS)U:\㒀p28Ԡb9cv%zz P"*<51iQPs?h,G"X~jٙǷ ,TZDI7=ii:QPn=SFDrJM3LaߥN.  ^ $A]ƣX**J qVa"(~@/*|fcS+_`1L2Np`I8 4gp'Rڤ3m|G^6q*a' R9#kF>S*,p:3"EP=(SOlUҋUpyt~{S>pZk[J$k>ji(EaJ*08Pȣi`@/Ph,L@n?Z$2i1(q7 if)((sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_30fc2aab35ca0861bf396d09aebc85a4.jpg000066400000000000000000000156571420147000300343000ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?p)@Jj@Sڜڀ)NiqҜ@ӂځ iM0OcKzP.Sl4FS4l4IU,cO,to,PPUMc>҇=OcM)4T} jSM1PSJjci@iCVJi= +8L(}OcM)h N NԆ4/8/8/zWG?tS g)?zcdS g|utS 8)<)ƅš5Tb 3@SG4hQOU)(E8()M0((SNqڀ# )EJSš((COsژަ i !)F*`!dAE(AS>ځlmڜPE8 z!>AJ{Հڔ!zpAVjpC@cޗ`!/}[`ldF}3@<@Ao>ԾYE]ޏ,{ա}S`ǽ\}}f1M3ޮgQQJ)ǽ41ޮϵ4}E({ c}EQ(=1W2jQ(9L(3ޯϨ=Eq *jE^)BԊ9 1Ҟڜ _zjxQNUHށ ӊx_jp^րtH1 N R ڜڤ Zp_z.a}}@NzS{T=8@4(_zpOz."-ƥ N E'50N:ӂ{t4Ʀ N JBO CS@Oj`@#ddՀ=iXOޔGE_,t՟/ޏ/ދ[4y욵ލ\ X馘5og&z.*ycc5pSL~+c5j鏞4_ҋD4ƌt^JQpL1M03M]1f>zҸX^zTzq@Ԋ:PT8 GJ.ڤU(QTfE^T}(QHQpSSxQ.BsҞQpڜ<(1N:ST; b0t>(AN=X'8!zxQ."}):TE8(b ҜL{ӂzW 8R~zxQ."pSދptTFiF(XF)3S࢕"3O \,@#dSEN{Ӷz.;K*J{p[?yGl\,UE/EZ(=6 wb) 슴P{E3?tS |}W )SV=ie:S* 0z.<jES"=*U^S*OR*8` qR9 JW\, 8"zqR*RX)N)BU iO^zS⋅ iSS{R <'< J9aM8){S{\ðԁ}= iMR=i6R9H6g.G0Xij}ԛ}s5cg)hRSaSV{aOcG0rJzTlڭPҘPZdQ.`cg!\G#xtR+y~gdQ={q֦xtQ'HӚF)E'PjA==`pOaSJd!8N S—fBޜޥ )==Ozp_z!_zp_z'8/=_z](_j]{Pd[}vԡ}v ={2-mQڏl?fCލ.j6J^2HWަHWڗA_za^:{SdzQuR=+eXa֢a?j/fy(L8SP>Aꃞ2MSRS 1ޥTM^2i{A0TuzE/jjUASJ=ޞ8H5 Kي{ӂ S9= 4K K^|cP++"Ӷp6t}ko3|a+X'("%e+fP:`{ )ESKR&)FiE((@KڏـQNiRي(J O v)/l?d(.j}J74b4n$~\QM¥JTPbE.iSG5 E)}d~ nS50⏬ǭDǚs0f#3gU^so֩X/DWO檱:R>qW ShJ??:pgαE3ǩKlk8H??:gT923dJ??:pcα?pK)S6|?z_?zRl 8H??:gT92#[zx~tbx~ugS?sܙjy VOfY(Ьs>O֥I>Rt.3ڠ;UB:Z xvVJ}Ӕ܀>w-W@=fr6ݐƗ";6 hx72 k {R/DҲshh=:hzZM]3RŋEKOC5/Z$v?ې 6ݜc椟XQrڸv!w}dǠ4fF򇕝Y!sWSkU?d, sN q[0n ֡g#nxjZ3쐝ʨONAp"ƹ,.IQzܿ=R.\k:H?J!|p8Ƨq+;4U_jjp#?Q8?4#Іdڔj?Ozߕ.O.۬p'j~$z*bOͩ`uj Oҷ WƧ>%}~Gk(u' Cy&5p]8?5jO7d[=8hΈzbjԇjz[h?V5Oަq>ƞ'V"5/-K2e|L]G#>$L/ymC Cx-T<,f]g.8Hԫ/ּ|_`&o*_?[y\cEO_s3QRokɿ4CU4^1I0Uc[E= ^9 ѷl>Lwz+񖣻MOSGMeUZc#g+_%Mϡ,]5ʧXϿCyi9{!WZT~-To*zBg p'nB[q5Ə^n1[ƙ uuC*%[%Ms1 T{M'O}~5Np'k9|<Σ\xc@ }BEzG[ITgR TTսHzÀ{PR(pFyyީ5 ?Q܊ϻd]Lz4X b4xK88t6BɌc?Ƴ$f,,rj1Jv f)HI iqN dPh%a",ZERH4)Nμր%J TF}(;A?:n)Y-)Wq<攜g/9Cݩy4**$X΢;eրv{T 9bIu@2GRS/r?:ct$R@N>nҧwyL8!N)pwasSw1H2G4@gK Ғ6py} !ܕ%P YI(RvhƸC٩*U7Zr槐QL_օ~;X迕 i~5:@g=j}tE=WnA8J8ɤL=hzS(,$PWޑYp3On\&9#.OZ `uH"FiCPODA QpFi<|qnZ#ӌП!Z2XTNHF XTtZP;ҚBi~'ZT¶[)\J@E*j ZFHl_3D\ڗLDQ;dњi4,E<1ۚ@Tެ>DwxoSֈOvJOJ- rx5Z^B*gMԭޛ@1Ra@撊(@.RQE(846@}}P1w3IER+1LPoPzd>Ԣf d'2Bo?jxEÎQ/J) {\@-!RR 9' CސFi$CiqJ)Ji%!4sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_352eb0101b7c88107520ba719432bbb2.jpg000066400000000000000000000144431420147000300336120ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?)qN ̡J8--(Z%8%  N Ra)i)h𔀌-(Z%<-" N Rp" K KJpJ%(ZW-:%8G@tO- |˧pӄt\t]N#\e.˫":_.W˥חGEկ..WˤIp*yTU\]U.cLM14Nbc:icَET1LulL1p9p)+BFSSPTijPF O Ra)*@Fӄt\t0GJ" O:p:GNp ӄu?NҸDt:GJ#Au?J#p |#NՁU'WoE*ɭ*bpbDL0pb@QE0W^;bbq TSV hZ%8-<%  JUcBTj@7i*@!T:-<%H#t2L#\DtXӄt_˧t!:x]U/EbNוGE_*W<6{RXS<ړg;^U0WUF*WT;1sҚU0NP1Tf*1TF*.+^REJL-J@2 C%HVUp-J-JcBSSд J-FԂ:WZxJGOҸaH#qa<%+|x R@#pRD|SU0 JB"p\v!SU0Z-+NT]H#+/j#\ /jxڬ]+WʥחKp*y~y~oˣˢS1U'ESLUpHcQ1S UtL1Ӹ T^1F:wDQu}t<25VUʵ"jUZJ-JH`R H` J JU*ԁ)Е ഀh ZxZGJ" N jQ2Squ ڬ5*JYcU H!p]#U 8CJ+AXST {S^`ERʞ]NTn5Ȏ$F?\W|?ԵX[wWK o5dlnAq2o.Vv=-<- O(PഠSbb p )())R-(N4]Ԁp u-3u.u};b}.)Q^MDzbһPR yKVRa\04@|9xx] GpZg-Tx7%42;Ĺ2N=kĚ{>E|v2n>cYJ'ǯ,skDZv'K2:8;sHGd.xt׋N#ֹxV%' cbcʌ}.Q0zԫ0hj> ԇ.P htj~{~! 508F;kؾkr淛KVX,sދ|UL؆EK6Jc-[HLtgH1U8SVl $_z-;9/ZDiC$³$Z]D֫W>z~ToʶsR y#sXO<mVM:}A,dps@6%gK~2 x0@yRy[xϥH$A\ñOߕL*ڎEߚz`x0V?*Q*UⰌ$#5À'眧&MOR Wo;buJŶǞ0>V[:Y$=M>V.cVc4_$ոy)F (.xMYH!jvtyxvWG֗w*J;rCJ7ÚF V+|i+t- lM{wXXz'ic52A!Iq<|Ci%?v=ykn5u 'k6}Yq k?1ք6rc^?ңOBeз8qV>󣩟V PPl_ʰũ8KC;m3襸?Z\Ȭ+`8Q$cLzUF1>0UydM^*d3rpqk:0)߾OliXe&:=1*T|eN3TyesR0@633H qɴn>))| OORk<#b{:ͿJg v'mFs^6Ie}Mb?^ZxrEcg=NIHCcִPH&<,󴲒YI=;p\qJ[# Xr~^BOqzqc2 WL@'jV]p?JlP2 Uh!qSȿHTqLR Z @`z"%,qOUJBϽ Pzn&qZtliU1@¢9N tr`$ n9RXc=(JyPwiA)ҮyAȨ E>W@ &ĝOyjp;ҩi O@\ | 9r20.@\Z|zi31qJ`In -/<V0TRF*X|<<bNiF:8faJU$y4!p#>}sK/s6 튈)'rL.1'N1Usj& WRrΧޤh'4^ g^2 +?909z})X.OlSA Ā=)IsMf 8ǵL!PSRaq0)z恐$*iaU9 yȩTq\K1RgTsaf;aOϹ ; zIZȍ䛲QiVͷdX"?Vmn`S߁)qf癟 Zʐpz'9;}Z1MGަTg g֬ GP ~HN=:ؠoK!HMVoZ@ {S!$?tTll`Fhc^JcC5ɧn1'?J@Lcbs)5<3ךd17_J`NjRj&d땥A/Z38 IOn)sry qAӌxn[vQ"Ǐ=5ݍ}3K!H+@c#9;09Vz|V9b *:}iRϵG*2stC$l;Rfsu kʼn>Ri̇`l5j(Ac 5ocO;)f}(H,r8yzX#&VǷz%=rr2}"0$`qFv4/8>ԀҞ&fUx7 (< 05L#iAbHO,"V,'5d9*뒵fW&Xh2U*IL[@ܱt\jN^G<AY٪?K}*{`~AG9CiW;˜P5*((@  9i;|ORi)Z bI9'?aK{PhJzTwELpï@;~\M_t/+HO9GB~ @yS $_?~"rFq)5 i$ҙl/AE0 :9nJ~~K5!^g(=?Zku `I c*M1?qHAny9?%-%?sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_3efc2d0f29a8e12c5a690fc6c9288854.jpg000066400000000000000000000105411420147000300341010ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?RKpN p)R@J <-8-08 pZpZhSӂӂӂ҅ӂ`RRӂ[ivԻivP[ivԻ)vP[iBԡ)(-j](-mRvѶFmj}l6ѶleVI@Rm;) PRҵh4U+HV i ՂҔ\!ZRR)BӀHc@ O LҪԁhд ZpZ`ZpZ-8-0# N Rӂԡ)( (JpJ%(J%(J%(J%(Je(J%(Je;eL%B N @Sl )vU(_.lGV|_.<O.˫]'@R-mѶ` Fʟm&\@RRm+G0rJSJU´R)VTe()TFRRS˂TJR8rTU)*.qT"R,ts!HRu*K9U*@2R,~s%<%N#{At.p! O S(! N S%8%M-9ST)(D O R @%<%J" O RȂSTihӂԡii{Q20 ZpZ^=Z]&]{Pd{ivԛivCّmK{Q2-jmi{Q"j}){`Dij{`Dj2`/lȮL+SQOڋٞdS*Jje"9IUjUZbR+zJMR*U4*ԊEHR8-HMSR){A  H){A x4rZxZ@E<=rZ\b4l \jU"OB,tQʵF]V+9Tj-<- " CZiP (5>~P)RN pӁي8 @i٩BN ;5>~P)qI\b!qKnh/n?b:LњO?b--K iSMOQ=FƗ HcTmNf{j2iY&jb t+[S%p^Zo}t婣[S-eo}etjhzp=k[zo=+*ZnskR/fƦn<\Z<_ԺldtzԂz65zx={6>dtzֹ=Es#Zxz>֥֡ŕZidzߍhQcv 랼.?y֨j?ZQ|;jyc89dcq7(浣\u XZpVz=k+3K#lL)aXzӅw)$m(z(z=jQFИzĢ RR6֔L=k֔_ZrQ%(Q|=iz;4z/(E/+(]ZplfA'(z#֥[Pp*sޭFrFRГm5J"!V>ՙ튖iT%jM\sP4^K;I.h.L=k9ǭW{[F2y& Ս8%<%+ vH*+5J0%8-.DJ޴11"9k$wa6IsGCqPzK!FtRO>}iԺ(YWUGZ}itOz7Ys=iSLM*EiȬeϩZMOť^:ZT7{Sj|}io>VE`F(?ڮ7@}j~'g8jW}iF}i<")bjS?ڮ(j'֏#SDW֎W?\Aԏ'h[;ՇAWH53ꗃE,a.?OpT?ާ TzƝTޮj᫟T< kz2jSZ?ިxKU_UuUyjkZ^# ‘ꩪ&>6]M1I' ~ΎT^~j̛S_W6OU7I*駗*'c.?U$rmUj* ㎚Kz6 jpHXWj 1`x5X=<= ,O(q@wLi@>;i.}UީLӰrj!5њ`?q,i(u.I(ۨL\E-;qj:(q!@ ;4Xw$2oiIra)ZPSM2Zu!4%2ZO4DfSOZ 8,;|M7֠-M&h>}j49s-Gڛ֩4Pv޵2ްYAKemzC~ǽeo4OEV_k=3r޵SuPHM֐7W#ϭ0}j#L&sP585D 8dQNc̘lRcUBi]MDAi3M Af N@fu(juԛ@isQ@&i7Rf3LHZZi4fKLZ)3Fh(PKIFhM&(aژh4fQAch(٣4RGFiy4Fi F(-< jQH5SJ5D0LiM5!&h%4KH4PQJ(44PJ 4Rvh%u%%;4() Rii(@Pi J(4 Z(IJi))(?sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_3f1b1455c4a7d13c5aeb7510f9a6a581.jpg000066400000000000000000000154351420147000300340550ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?p)qN ԁJ8- ZP4-<-8-<-0-8-<-8-4-8-<-8-0-H# N RB҅B҅҄B҄R҅vR쩶RvRSP!)vT)vP)vT)vP}*6{}l(@)6U=[ˤncuoe4U1JUT)M)VSJPbҕd!J@V)M)VJSJP<8-! O N N @iiihiiih0 JpJ`F J# N RST)(6PJP0JPpJe(Je.ʜ%(Je(J%8%@gN+V6R ].ʰ#Iկ.G@]]ZO.˫]'@O*t):cc:a):cHM14@)iiде ZP"0-(Z-(J`ZpZ-<%F O @BSS 0JpJ@Cӂԡ)( *`zpJg8%B N @ S @{SP:_.DtSu`GNO.#^]'@]]Z| *yt*GE)]]]8GSlp#SQp\GNT)=W|ޗg h6QpWVRlbHcE) QpLM1ղ”)*Je)q)EǙ(UUUiVVU-HER R*p*ԊҸX҅qhZz9V O0Xhsӂ%8%.a`ZpZ-8%aiii( ,0 xZxJxJ\aii)( O N O G0X`ZxZxZpZ\aiBԁih ҅|{hRG0rmmMs6ѲI0r;==)X0Z)L)G0rJTll0.`)S*J.`BzpJG!JxJGO%HR'PjA)=`>ԯfB O Kڇ! N Rڇ" N RGӂԁ)hBڇ"KKj̋mjmmڏِSKڡ&CM/l2µ9(= +QTl){dɕlaDŸ<UՄ49zJMSS.*}\TjUT J{1UH){A1BSR Rb x ) 4K R bb:m~VA\=vFaT]^\M_>{ⵧ(.JIw=D-<-`{0 N J8 TLLSR@ ^~ӂN.R@>~P)ؤ4R4*"sK^~Z1I7RxqF)7QJTPbE.i~WCMFi2Ծ?b5FaQ3QXLi 5iAb{Մz_Z]zة:s>h:a0¹XG/^n_ ϰ֜'&l价oeZ5M.V7֤YG`zx:Z*H(Y5j'< R I<'?mT x]77i[y[B 6ͻEm|P0 <??k˳|V/Sa@'utx}=u!re?xgͿv ާ%]Yp*Udw$|fԮR17C*}U2D;w\b@A*gR{<3FGQg b&k'K7ۿROOi"~ok28ݞXn4p7Ͷՠ?i"[k4O5$`Wa*G#mՒ9ۻ=O iX v©W+/|ם4֊LK3.=[UO/gۻ&r<dұ߮O˵q?pk:foYj_ H##)n "ɍZP+wX_C|ӆ=\3VtaO. Y:?&`WקGiX|%-W_%kTdv(.ǡY/jQ&m5yN乔Ԯj:_-2yN? ?I=Auv?v)H5vSYܙZZf0~T?/T,}N]]Ay-ʤ2U!6ȕ*4YDz:HWGA+R1R&ݺ_ave ~jgrkGJŪjojY{2v4ZJ[ߵcE'b+9U,#7V.f\AuH˰nAv8]_s.ADUhgL» MfHT,I2F_RquzR\e4G3>v NFo4r;?"CohX$we_Mۜ_QU}ڕ#ueuۻ%9WL(%:voR۸T%[O` IѿکXh0ڪEg"1z\ %FL1ҐJMjT*gۿ@ fjcp1VVhݜ>o@ Ulՙ&TNeIwvy;y\e:I#uAvOA+_z<ɦz.r{u/vnfOmROx09\Uu vnNyHw&I@pTao_?qI+Zlʪhd1\TzӃm=G?ݩE*䀿ݧP[ST WǵL!P4!j*z恐%, = i?S$‹YQRow1kHqW;UBö6MϵVq`v4]IrEz3RHD-H5BUa߅h5gDW UUmls'Z;'9NyǪp$ f&?1n87 ʖvUs06=:P75+0Pe8jr"O 1cJ#u@+PNݦ<9Tk "4HiDL1”\EHJRiBԊj@ ZjH O O O E`ZxZpZ-iiii\0-8-<%<%0 JxJ.{iBQpJpJ%8% BSt\,BQpJpJGOҸX:.! K:.+yt`GNXկ.ˢb6{U..MԞ_\ t\,S1 u{˦\,R1 uxL)EFb)\v)6p*UT+ QBJE*Ԫ*ԁhXҪԊ(X@*@\,0-H<-EBSSpД\,4-8-8-<- N N O EBӂpZxZW O N O EaiiSb0 ZpZW pJpJ-8- llv҅b-*]hXe*}m,@VeOe.aخRY)M)G0XRR,T)L)VTlFJ[d2QT[Ap=iE)lxqR,֎arij0G.r5¾Hkgb0Ey47:]c-#=++YWJhPyLԺ9 wR xuՃ&MIj^ I==*R\6jcBҏZj-SLg4֡y\kt.xXvS&v%c#k+tti? }{Iw6?"E>?\ጯAak?ON?/c{Yw:d%44 @Xo jxMT}^{y@4&#|Af>q>Mqy5<[#R)b$u[\__k[iTo7j_U"GV|KhF/ĖH>\y=`yO`W$uɯ0_*hw`:xyl.eeQj^= Xwbޞ5z"-Uȵ)dU&Wb2cY<$,Dz$\/$H(  p֦ [{ڧ+0r@4YN29ֹW֯,8:e[zE3O5*OB 4pT6]TE~Y8jiz4 @nF=ۦkʖiǩE;nuQZ㎡2̌9$ =COJ>b5 A}kМ6P'^}U;~?OF?ʝ6@'Zص^s֜5\p.?ӿ.?}Rbz]@z/ǭq*/\r@B4WJGn/ǭ8_ZoS.GoVoWjGcJ/qt*QVoWkdukjʮ??ЩWS ?Y^Ɗtz8=]M&ca*+E%Lork{ԷRY8X)DE?M,Qjz͌rǖ¸}"Vkuoȕ^~^VSc5<{wZ!ccV-ζpv U Gv/Kpz`wBFB?ƨMM1}`*ڄw7^zi5?o/|ت>.=w [S2;g0  ӥ3iϓ;΅ %ϾGJ$?嚐>NүaHdd1#׎*Q0qxrGsң6'7*rN[?y "srgw$1ցFI\4n@ 5ڵγrO 5 7MzLJY#p<89皢<''$pI`'ipoJa,OE̟.qO*XҤϼƣ:\qFhY 1ҡE#4L|6 4nÃJq=p>+4{cڒ?Kj {Dd%RR9![+&r09}BP`914D4bQ#V=|%YA rN ùi}Au.wowYBv 8" #@8`|#@ײN\ByBN *OTcEկ"} ;[]هBd&RyZH9B2; ,v\}R49Gd,nVT #Hnvh ݾw #_O&=\+kz` ~稩Z>xdfVy';)jk_?bx]0?Zl9ha3v?HA3cTJ|m)#bF72bB;+R`s~k8+p#PAڊZ_j*$ܰ6LZ -zb_Iӏb亝\^6GasgEE~Ie ֭-2z(%kE^xPn[\)-[@Wcck\ƚ'?*T3o3$1(5pwԙ$ҺcF :ӗS6 LO]MgW/z2@V{}NON'?ҫ%"7l\=})y0Fʝ'U~c_RS6>S INOa>@O=ɻ y:╀$v_Qvm\ed-=’MRdL%3q`Ry'#̼՞U13?yY3y F;T!`$ސ1 r82 @-aOhTR~֐zTn@l(w+zw(/"*"NN3T*Ǵg#$%q#=4|ݪV0{#aAULnOjb i <ڀ%+$u;C6HƧ@ sR񊩼' <zP ܟj z--YGHsRyZbђlSYm}{P# d22rGdf`@ `3qۊ7%<E\ɳp5 >YCvfcrieM 68#8=NW$ Y$iݩ@&vڠjD M8@& Jj 9 sN sL8'#UpiXi=zS @鬹Qp:І(D`fҫ di܎M2Go9pj_399hiTOvb2(BS A%ͨ_s㠧 $~MN;9b?Ɛβ6©0*5%D_!kBJc1/!np9MRcoϣ5o/^*!IqNr-'OJiS jJ'_Z((t#ӖT^TP2ڄEELNPjiddf&I0'$TAU9JW*eHI)9G#1R$(Wf'S+Iuy~IҜ!Alb>.w8G=Z+tGjsvF %I42r}:SZ26R})RP?L@ A# 2sIi'~򤎡GҘIm(h &t( =֜LcF kR¨PZ yd{ciB2̪/EMhX &P8+r@Rz]p~gQn (?2瓟Π>OֈUZY ="sS֤Si 9@T(~BVڤq4Ⱥ7J:N܏MǏTGShT gW7JWhIThjOqS^ywoZ[BǕ# I'M'2[i Q 歮 L,"FQ['?Α ^88q*TͷZ7m,ʤeΪAQ)HYA03L q$ĤKՋ:ӿuQlU[Md;i i = +L+SL"l2ZEF—A\FVTL)Q{3juZ XCCT52*J)Z^~UARjAKPT*QG%<% /h?f(AN @=rROrZpZ-.q)ъ0Vi8zp}jp-g +μhY"-+C>܃~+H'(.JIw=H-<-b{0 N J8 TLLSRR`){Q0 N E8TbJTa!@b\BKL۔KM.i{qh&hIFꗉ)QAi^ 5RSDGC cQ13T,դqryIVQ\xSoqΧO?5֯aПcUbu0Voz?%j|~']=5S~g*=k^l~HY!-Y)/=Ωf*=k!?|NOZu{e7K%Х8F L=k]z?{u3R>sZL+:uOßOMvѺ\s>h:q8 ǭs[n"?G*j1dV>Ɨ+CћaR,ְE<_ZGo G`1N:E㉤<|Myׇ+tVG;wwgj-\1Vߕy5%I#!\*=WPOndygr<dұU=0ߕ;[sW &{:yorJP02? zec%A սNj8Ȥwm9Ě k>Ǣ _ٿ*pxRn_ FKbxO˥O| КzOʜ5cϢ&t@01H+nr=@U?+F]Du@~}mqk7,FNvk1yԃzziϱ+1|Ƭ$My>(ٖwv'?#RI}JKcُp;Լ,}N]Y真ɩ{/k4n0+r?:k ϯr?ꇕŚ,k=!ug/jUՔ k# BF:*H=n jH ~\<&:TM]Q3q5f=V.^E?uqC inE҇汞MXu>$}^Ƙ{cPqxe/b*G`\9p.Gn?ּ-#mo{-R bgOŹ-;K 3o -sˏTG.Zl?u7WO&]D(YE ɪjl3?\A؆J/O̟Q2|GBxuC)'I|)$ڝlR_^6qo'Xxܜ-yqZr3yW;ӳ$JN tj 9qJČ1|I^p; dOJH# h/|}d=p;Ҫg(,E:h$$*A-Dd2AG0&@\Zp}0GDs9=(b%j̯HGsTyhq9,q6DuAT0{!$i!]s_$͂{b I(Pr av~2sjC2J3YOHўN)4Teb] oY$g9qϭ86sSȋUY6Ch!X8*I i!GI ހDJi\`TAU4 'Rn~LdT+ *&@<3 gPH 0}JN?`gͅ9V ? >nQiRzsHꀐ))NG~A.4uUTzumynTpz1)9)'֡iBA449RɜZa# $ªIǵO]:ؠoH0MAnXբ*|{S0R˚xVhrǀ֋'j=ہNS9PUb3!53d=yE3u E5n/+K#az3@{qM(,C fG9Y )L ʄq-;S\Tޚ޾sZ~x #9r\ϙn0i#ݳSP~4!> dF)c`cJ[~su7Ef,I4,4j (QAӎ3n@晟JR *]RƒD&Uh9U>"# 3y~vd$R?$p~bf9JҠr~?R`CE*UU {@ܱt5#?*;OR5EU0?(A"}֠ Y)H3*EE  3IIK@  9i;P;!$&.N1A$'%JrTww%8a.sJO4ry8HR,ÌSW 4PRC1L_j&Hdez/AN?z ÚSLdzMiҐ 12OO֘zzRix48@ $44L!i(?sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_510813cc53c37e2d489d2f9fdb13f749.jpg000066400000000000000000000505221420147000300340210ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?p)qNxXK;FrBVS'mZEVUid\*`?}Bծ4Ummej/HMX۰y#LgoJ#B^]mYXp?Xtۍ'Sż9ï4  N O N L Rӂԁih0jPnK :EQ J J#J J" JJ!KJ!J Z ]m_FCrYz3,%.ʿ}iYGEW@6RR )vV\7 ڪIJES@(V6QRl[*ޥ\7t$K2l2(yuke7e+][M)@Ltҕl4@ SJUҔX4Y)HRSJUҔ5@c~3M--/:f2EkwUgR(Qc3W?d?נGuqkw5roDZۺŸL|/$xW$[{׸Up/޺ki|\4`2;yaBPqOJB3Hoz,rɬg%EO,zxnֳm{,ʨօH|(FKfEM20;x~<֛xOh"6F?UBLGןGQ3F9rKK^w6 ɖtus,0_FssT{g}f@$ wzgt Dq%2p{u0&-%~|1>'iRE x?MOX `~66s1sN—:ΡzUE sǓ ꉠS68UAN=hM;M;DK|G>*C*[Ab'琌όp*.\RAmx^9-"5nUԴ9M̫4('\ӯjjw:^̶6[̟v9,@ cKqY1Mɸ 8ի4KMM9e2"ۼ7ʂr3U+ՊG!W*_=3Yk$# ԅmsKP:c#EՌo۝1޼hdoRxڕܸ3h͌#>⹖Evnx\S@Aag[\\][dI|@R>cNxd[xwJ5TIg #Z[ (mTwA-2=+1ո.ޣrl$y~)j2XDUAԚY vQm ,Ƿҳ*լmf>~`pz0=AR[Zemk sw6BVRFFyi6hdUesF.x.:M] dfI 6n6:[Ga489?f˨w=i9U; cJ7 4#XD\ g>jOZ\xkF=*Mbd P\Fo&1@;afPg*Бt?--n ު&b[`z^x]{CM4seE#iPxR ~\OcshP\|+zLֵ ucFIG_sɬMNRqeq{q-ȂIX(2},qi;E,p$F7.5+k/"A* =#aӤ%X{ڽye'$#$[#i +Ʈv֦mg6㬢3~=+VIzLW m*I[B❶m,Z>Q#Ue^ Ǒ<tncOݮ#O"JI bI!IE'^^4Ѭ4#X!IGCqƭ0˺cdyvo2@cFEdu%YX`:*~}|ۏ1H啥I31bz{yyqR}3TӤc2{MG} FA$dD6VOT4.[K*&p@l2#ؼhd?lIS2>W?i.'IwRbvsAIm^]mg/SeSWvDl4[fwR~Ѹ'}r 򔜏 pt1L6KY`4OH#5ìOkET/diN=MkZ]÷D;i!7 SߟJ.) tȅs\Լ?}Em-Gd𬠨8\ 7+t5'ծ\G"|⻋HiM:'d.HwrGsNq_Ooe=췂Iб*C#u*è#WTdO%H𛋙>$D$}$v8ZuhdgYSK-ys$OlTFi͆yIl9Y:8b =K}GXoA$-eޕcλ,ߺOݟIoasvm嘎4-ʽ,o8Yy̶Z8WY%s}s>dCW77vyumla䁎\v9#k(188TϦ)g\A$,FBȅN?ﴭ9c[e̳]k."*q]ǮYךyç [fU)!z9cM6X |?}kZj/0\+rHn03=kmm aT(:SO[}M]oҭ?|tUV"S 鍾P/"}U]5:>x}j+Ҧh⁕! 21F8;JmY+%m`c2O>kO떶1YEŴsR@94[R62۬WnVOCvŭΥ\YFHntF9jeuf\Lg#qRI%([oG>}KS|)f%ax%Ke)o:iȶE'}Hc=ywqMyw'q3z+oAפ[ЛQAe>A-2yK[ kfu.n#eCо߻қ;<f| -(oLGR{TEfby'nۭ6Ś͕0A< Bbv1r?:oYmBAn&@8|<[jyJ;F4;ލR WJK[ 3 r 9$/{VݙTvm:t1Z"]-WVs>V'N!{c>wvV\BѠ5u{$36#Rdr'ƾ:j!*Lf9'8N+i^1dKdtA 4:M [%B`cN6#ZWizv33#pZ-[T{k2u,FOViq52Kis&O<|^*[tDO-L~5RTP MF7#3sZV Cpޤ㠦Xhbich Ivv B(>ii7xXLѫ[ [(dvLC*I8 omn\ĎUJ+މoC6 {hb9dR*knOk7]46 =AePMe :_t/"W# 3tl5[[4Gd19'=z:ٺdi2Ʃs9htAvon)fVRŜP:U}SG}42\[\&g@@q߃#m5Vl c+뵈I.\7m̞Zd#N;ifo⸸t3pIg.-.c`!a0`e>zW@c%`$FyG,3*i5^ P#ֵo]^ *]?VH)>nսA|2Mm, ŽwLǽEء. FrpIAEWQ7qU6{b{_)\I8EH"`˯YdxP$1иT)-x`Vjڞns^LcIiYADHQdVMCS1^7#f @=ǧZdZ,2$ |c6˱^Qtj7@]H.ɗЮ$fQ/]fg[nQVƂ ovy'+?Z'JqlI{g:(s.OFgIlfσtɵ+{ $m#\Zu)-+sݘ3@tތ i0*bldv8YΨGnt{[;r.bkCRp@<¹JW{˷ +`p0\%+뿴oE˭jSCo9!mdB{|='ŶwjO5̭毘͕W0mfHfEBBHTb:]t5k EB<⋊Ʈ:hyl"{H-Qd65-5N]r" 0̒(RaǨZZuLjN;:=>59.i.+-ɄnGVGNu?My4ap#'8%8- :{R[ 5+ I"Iń1>խimakۭ^Mbɠ^z2G=+ O @%Gvq]OqkZ-d`mma8$ S .+&O@eR61=rH#*)C,˹;AȊE4gv8UQO#.77|!obC$ T:y{}dte>jzkzr:F^ Eh/%5][]̯ T`p:;tѴ+mB9 |$}@٬{QӟL{Wuv@rhmHg.eT}h]ZVl^h&aHC>ނ{qk -i+x*M L =Ec;N'D[1o³/5J ? ktGZ NE][1,h齎%H6wJL  ϽalES.6yjylF;oZI [끤@eL ,>ofe Xhq+/ d 2a&+R ҘY;dӯ9Y9`=2her펙'4\,^hմ=> {B420WhuqM6Rp8R t[)L)JbRQqئRW*2\,y+_ާz!$IHJ\ʭmk>G_EOoݠm=zc fg*^G)QZ9.WB8 ȭ :OoHGTW9g;Au "ȹr?tZEw}qkr_G"9f qߎisj7xGv3Gs=VhƯq^s5U8ZdA#<, 9)4]DBdgb΋4Ze07}ѹCgcoc"mH)HUIV"kLϸX"R1VWmXj˅qA+;tcG#MD&TsR\>6K r\(%ؿP?.LU 5kht&8I$c V#-[I/Z"r Uq l4D-Yms K+G8HATem$Z1$0wXqŧ}kRb6H8?aל \cJEGl..: +WPowRDN6}*^aoՂ\Kk8aR>k7LW1倿]uXt6򪷒6{zZpxK8ߵֱu6v qV\kE\)l?a6Ahe{B *T2V-ZN(Dd0>3j,L-<w=1*{ 2YYm]6u Y NB0þ@o-hc 1! ~Rp9fGnȌ|?뚋9a]kQ[[ 8G$.rF ѥ㵻qlI]yy?i6 ~#R zS[;$i$k*ڋ#6mL ܱX[ 6VuqȐ7A)~5hWLyn&S{qҮdcV7eѴ # tP⋅< [>`Cger+NBBe>ٷ~gmޕ6KoiTKOl?JrfAy3el: jp.r1׭T:56w_tVUa co9i v1VpkGTYߜsqmF41,\u x=rRU+;RSN*G%Ty]J6ké[)duBLJOL>yr;U#kg\:h5fȞ5r[p)FMxu?]#$ĭ9Em^]";1PGL?w?Vs_ Ċ+\;CAPMQwB8NT|u9Ym$M#E,5`!YM^9/#;pFm.Ya*G Y̒! zVŢ_˼Ǎ6!("'m̷s$EFFs4I`bd@YGu8 66pIWqis+9^:VV2FɐՂ*6dj6Z¢aOڋٞfZV$WAe)C]F^hzۥwtQݿSRm)nemKh$>w{q'KR|Ϳww;f772i3jJpH4=&;.iXNdS+N D9Kt۬ipKq}X\\[}irЏDӬ[-CP:tۭQJGzʭi;SR9G4`ȑum'׽ R|skUKQg$+G&_Ty㙵0B95wiEԷSHE K`v'/n1[sq)s:gޟ%"ʻ'Vjl4ly ׀&~ϣf7cqW|cW3GוmOOOAm4mة*%եL-!v»7ZU4 ctHmpr:y5q1NI䚹A q_пbS+-*mpۡwM޾s)2v3_z.nVH[Ļc`(=9;]/(b;ֈmB[yLvcLD4(ehTGOƝdC<FPح;bjF{KR`22;Tlz>,"7%▶ǥa1gvwb$ML oev K.U7ֶrhƝ-йUPUsۡ\$ n<^$ق$hޮ0{'dsI f!O<˶Yn-ry=OֶƟ\K+x-^qUg}=ldƎD ˞՜ܕJ.Hyr2oRzN'nݳw˞ǭn=Ml^c,lڠ3 gRR)l8\W˽Wb󐾃ڞq%" Oǽ\M++pV#b{jp'kcy We&!D]r<BtU @&eg=֯p@ tvV( 2tbzL$Ijo2IF!#LO)M-WUV᳁,VIcHSEI ā뚅)ܾX@nZa3\Jd^9,+;m˅=@-biwl\ n.yu^*+SK}0qʏoJ&M3AR[B3'iY]0ܾ[ǎ T)5b2J#;JHq>mimfwh120=IXi~US=z**56Imr VD*^xq?Z[s)O2g9')-)eE|`{zNSo|j3YE3$lNjF*7e?i̠+bpsQRԔ Pq[eGć/ԍsx g<XUӧZmwiVaxZO_8iD +P۷4FMᑑпў.Dp Yn7YJn7Bc+[SDY}d cQ13T,դqryI]5gor"G#MN:pE^ Xx#8k'F 9霊U.4z[$g+cyzc>EoxxkcVKeӥ;ҩ|5RG]oh#m#kdsuGeD-ͧq=;gy<gvr;C :^FM`Kߋ~$sѬ߱W&x13R0F~u->t]Fw 'Zu<kCLԴ놊}V Ud:/ԵQ[h'{΅uM{5Hb0pG-uklH5: Ӯ٧[9Tm~<:Zн="]4顟m͛,) 89RkAo$z|XIi#nzW&n师TX=;;xj /yn ^Tp'zԶ7$z}f) +95 zx_WGoeuea8F38yIi m_l9e-ӥpޜ/UI%k[sZdz~ֺiA5;b.ܺ6Tzc^_n쥾+WilE2\cqOU & ģi zYSg UT>Y}j2]±yOBqׂ UG\:mo4mgA, `y#[HEݓfq0CÞq\EZߑk W:xtղ_9cR t`LX2h_Zp.u+lh˕ǹEsnzGo1[2#m?vlʝ\oG(4Iin>cw~N6VY U *{n|PdE $N)KXrKK+v[:WԢR,v;pyFn`}.ɵĿN=\Z&g,\_TQқxejˈaʞ$qf9¬Tc|h$dkN3SM5-=b8ZçU h 1sҰiVsXiX[/,K9pzd}x"[v"ksmy]ʑ7u8=ZvoxWS.[`0̛#?L[ZFxz){KKԂ;dTF g>kw&O8K hAܬ'@偒2cte )Ŷoe+0I"њ3`~kZ7<9mj {st!Ggr~R s(-MĆWvǩ/k֚kj53 3nq|Mty쥵fM^]RAk0}}i<,^)bdck^ _@Fx\4+mdp2ī2RCcڼ◉o-?P EܓSOԾ,jw}ť}s%EZ\-?}Mts&; )È+dZ׌[P$6#F ּzj2G"0uu zV!M2z)P$0ho|Vq1Z|.f{ˠ^gVL*yI#>eOv4vmIxՇ^9tA6i#Qp6;dU55X\f#<) >=*7 +Z޾z;in4 VDdAKƤ``tweCy! X<|gEx|Ocbldvdnt?/[NҴpgx"}3|p=C&_49Ŧ6iEºko!w$ xo}a>!chشG 6 ÷AyūԱPtB(!3F 8uaww ҬdIkH>\։`m奇{W][DѮrK~SqAVm."o$'זxdnm $ͤ_0i @ϯZ|pE)i*#F `f#tCJ+[,]3QM[u$dc LD |avJK (Y6c';?ukMIlo)|1OL*8g WU[mnݬُ8zm5J=9{ob"# ٌK<+\1p.Gn?ּ9n{:J7;K:Š5s[v?^f;2[B]Ψ\{kc~ny2Sӧg+&M"MrƖb9(?2F2m }㏧ q%tjwHGҩI}xżcIrpoUh vgKp~sO5"rdlGHޕH* g94a$#.tW ܜvZ~?l~=`->f\g0EH6=jesR0P6an>)VB`#4qqUvZf'mikv։P>[!h*gW$V^s䞴6=idfBK1'n=)Kday>O֘ A֟3^ ) 42> oH˴nMWv*]#ZCiJdr֢g @.LDd%=)HUs4$}i^@NszP(G;ЁҒo8 ;Fy8Qv6)qd 9>OQϥO"-Ud )b@$9dU$Cd`zcڥ(qQV\2$K$CjOC@-ɟL%`vtB$vvJ iRvŸ *A֣AݕM?M#j^X?NiP?AB70)Yu -UXUGVVGOHAwjPHN0}+dLqoS@,0@*{TӨ݊hTQF =Z!@H§׵1c!/w`Aր',x Mhy&ݸ941JQ*2S;CךdQ7_JP8Qr81X4<ѹbt<`8{AҔGr?y`EEL|9)mW;?H+@Pxف39OG,OE"=?:E}sM23@Hb1v4=ZmtVbğS@\L @&Oq1@ 88Ni ؊,(0LnIm%XƁ3xQI(@08;x ZCjHlҜ%fP01Q9 34s@#iAfK}2EIhf9JҡOZJL#%[ꪢ!h{#?Κ?{hfّOBKUS;M?J ;8y,sQt^K?4?m@袊(@.H% ֊PHhSH){oBIM%)aPI'$GzCր \ޒ@ t,Ize Nuho˜)(_qQH:`bʾX`wޡO?ޠPRC1MN~I,P)G QLAZA47JA$??|me?R@Gcd5Ӆ>&Tk "4HBM9Zn@CMmCmMmCMmC.6 v) @)@(RN  )qN8 P)S8 h)@@ 8 pf)SJ7i4 PP1Kv(R @ .)@ Jm3mjLRb&]ʹb.mjMh6" lQ+eO_e&ʱ[e!J+%) Pbݕd!JRR i*BVR)@Q)F@@)J((J8 @)RN8 p(SN4-8 p(NN LKpZp)qOKv)iv6m?m8 -.ڐ-.m;m?m;mF ZPZvڐ-hivԁivaivԁiv{ivԁih-mQ"KJ"Fʛm(].P6(@mM6T)6P%i6i6P2*M\&ʰReV+M)VJSJPbҕd4 +l)V Rl ijZaZ&ڟmh()S ഠSO piiS4-8 pZpдSӶӶ-0-8-<-(Zf] ZPiiv6mӂԛh@ K J#JN @ R@Rm @ R@ R@lӶ[ivTiBP[ivT)vP!(S%C>]]6]_e.je( *MMce&>6Pb*JMT4Z)M)@JSJUҔWe4Z)L)H )*JiJ`&@@) @)RO8 P)hS< P)PN N-8 P)PN-< h)SӀN ;m8 fvpZpZ~PݴiiB1SӶӶ!iBӶ6@ NOJmH-F K#K J# N Rm @R @6BvѶ" K K!KFe.ʛmh*}l6R)6) i Qp I+ME@RVmW)L+VJJR)jZaZ4X)M)EVmNVm@J8 J< @)PS ഠSJ8 ` )SJ8 @)S@ 8-.)Sm@ (PqJ8-8-4 ](i@mm m(ZhZP \RGj@p# KJZpZ-(Z.aivԻ)B (Jv." K N E-;mIv҅bjm(Xm.ʛe.. Fڟg(AeMmMce&.}l)6RXRPU(XRbJiJVRX4Y+L+EW+L)VJJZM9ZM\7 T!@@((((@(ҁN pZpP@Nдih Nʹ\,0-8-<-8-+ӂӀ3m.xQq N Nii@EhZpZpp8 .BӂӀEnP)Qp8-iS҅O # N O N E`ZpZ~P\mRmE-.ړm.."KJ6Իivp"Fʗmhȶmvp"HVIM6B\ vii\J ՂҴ\ ijZiZ.rµ`0jbh`" X x\,S x\,S p\,S x\,S-8 W (NN)Qq8 P)Qp)R )@EJ8-8-R+)SӂpPh pZpZ.@8 pZWS N E@)S҅㰀S N EN-8-+(( 8 pQpS m8 v(Xf)v`R`ʹm1F(Xf1Rb#6ъ.;mK6pB.1G0Xm!Z&.!+M+S+JZiZ4 JihXVV+M+JbZM1ZM\,yZ j@ɰO-<-+ O G0X@)iihXhZxsO0 9,4-8-<-8-aiiih NO N K,F N G0FH`Z](ZpJ\ñZP&v9[iiihӂӂ-H/.`s`ZpZ-(Z\# N Rm K9HӂԁivӱO K`8-<-8-0 Ps()S҅>Qmb`m?m.9m.~)qG0rFړmhR=m1F9bF9GmKMs)ZM6)%iTihR*r´s) ҵ1Ҵ0NVV` "mJE&( VR*ӕ*P| OT9FBSRR (JpOj9Fڥ O K9HST)()JxJ%<%Bڦ O K9HBST)()OjpJ';eB N K9HBST)BQai*PB=i9b&)1Gf3m1F(Ѷ&){Q1ILRdxILQCّM""E/j?fFE4i{Q{2")ThȦ ?hKFi)ƒ'5ZE1jUy=VTK|iÔԁi\-<- S)—8ENs(iiQR6"ނU 5ē؃Z*<2T}}j߁Ю@.(1J(( ZLњ^~Z(j(&(5.^1I\fИ"4hiy4h솚aL&d0I&M?l/d4a4 UHtFin=¦Vj*w"ښMTW.Ű}Ej$;SbJd;ZIJb4U%+őN\J)AJ`SQO.N\KOZ\ñ`SRar3@5=iCZ|±`SWS)=-CR>RZ|`3=4x\y'\2Ƥ?ՂF@gn,n.;kS\2n&bo*Xx*GZJ>>ii¢g(zOp5zpz\&x#8.af5PO\;.K9IK8KQQo֥̮BQKQS>RLJ|ERI\{.RW! _0T(QQyy>|5GK).hE.rfCRTVE(5>Ԓ3M5)Za"&M=D{R1ٽ{SD-L-L-L/O=f*V1YCy[jFJ'o\X}sî{gR'fBKǵK®G|.R-·`~g#aN)}WjB_zx޸8QVt#Ϯo "xޞu{mha?7RxYD=qZ&ˀч_Ʀ}X<4bhǽ{Xw:qNǮۻ;=qWVOGsQ*r(qN>zQuQ7>NH1uN>XͿZfDV<}OֳFxQ\uH" 6ۇP' ]:nR]MI(6W3=~qC6y28`’ z#pA~{WgВ\ zQ7Z}< *]{׆ӱ+5st\Zwa Ng֧n ǭ8N=k]Zp>Xny֗1x}ilHqXbޞ/}e$myOXzӾ=jZerBqN'=~J|h1yNoM\)|zzҳ)ZwXzҋzJПޗoӅ߽KL@|z~jLS53_n|AҀkd,mwNTc"xSB9۟\kdGS#*E35ϸ0M<1*1OKxI;ap[ 'G~;@k]ayJ*S @ 2AZ <@10Ed)¤,. Jt:$p0SRI6: OTPF aKn%VIn@ :Ѵp }@8 =juy:7aj!/yufX"ljI' T:eDzlToT{kVvڌ֊@?+GSx2:6fCJc;FT留݃_Us6nmvxkHRQ"u\ f ݰzsOlZv6n$=놳q?Ϡ\ŶGa=Mc޹E+iGSc(?aOQDW%j\ܟi2f3,ӽ[> f;ms)}M迴/5Ab"-%V F&W;F _SCtkN_Z*8zj%e.s/ӍQ}iFV<4?ҡČ.*cvGQ_jriFAcL?ҭ'07ذnXO}jK7wH >dzRuکJ5TEO4V(2JZ3_+O$;w`hV'(ՓL۔@?:ԇzK)ދ//E,7᫠\}XݯoSG[#AYnd]V+^n)oz8N.u%&@G!q[qK2jz@95e 48 75m͑|)8Dr.r"uW&IzFߑ2 Ȓ@}/8P7Mzo 4sO4翜637k@4YZiAkX./Q'?.$ɅeϦKq†_L^##8C;oSԄK)wig0 %93؆~x#zjA!^B`RрHhR3H?eP5Gy@g?ҟl(TJpM)tz-zrqIlc#&"Feǰ'Ӈ˜˩ϱ'=F@ y4퍷T2Ӫl+,%"$ {p(gH&qu}Yv=[۩Mĵ;w*y0ÖS g#nVoZ1BsVP`Pr+u 1H66J4y؃`jU,M1h$zj 7;1j+y4qMX9,F{ teNj8IpH#D9 ƞ{Ui7!5(@WUln鮒G)i#nӚ2`n\UBFpާ_>(rJJqёf'9VT˃Un y'SzP&S銙#@8P*!A!a jWh QCrJڦ2{d-+RnrrN D\ CQKrT62֡R$PJZFwَ?l|va(fy=z`W=T!1rp@ ]R¶hW14 v `Qaܙ't?)"F3p}MQ 99⥢";pK1Tk', '41!wVR ; jvx9q4r&MZ坘UgE(^[n(`;;YM3hKc ۑ`l5I6=-u4gte8?W-K"¹,Rc}N'"|UtԻ_9F'Fu)NsLzq|G;#?f8Ӑ2}M6Sc"NOKBl{ Y֠OO@i犪zոx4S0(cd0S5#a\|Tl3==iP=PWnO&92F>㟥 )X{P0PzsW<϶jepXw% AMq[,x5t!#8} F7u s.40(y*]9RGҤvJ,'d$p*GP*\9b͘1y۟_J$z 54+HhrYPi3W$q}jnP2XTG 6Z Cc[f&ylt4 B @ b =)C} 0yUoPG3NB`ۇ$P"TP0}4{(Q4Ȋorb sҀ׌?֞@" vdޟrHϯ"c Ni}yFl&gϻ T.!,UhϪ d*~n/n.efxr8Q1.ň96=P=iBCFH śj9d@P0pI2'@[N/0*8㿭LquSR3Po9^dse b}=vlmznF3Pȝ<}JXqDFAn di< 3[nMJFC3Rj0lf 8=MV߭X Gïrzgi%F:PNs?i=E (@*})Uހ!@#>&rp:4 Қ r8$D2{Le+T+ hr#cL9N,QH0}h p UlԲǒR WnQHbI!n@e8+d1V#SNJj#n;W$)e8%T}sLDr\#mJ!!{U}2697$Kvez>&Ux kdtg=z?7S1թq! P6R8&)7w P0;SQyjTp(c! ӭ"zP0 38!c)ᝇzrH4@GSփ ;d:P'4dPO4FFA#1cpTj4#|TP",*1.}MJ"B[+R #,r̸GX2xD!)=jS0fPdҰ)2;d#)D'c OQ iȱJK =0*`*{?fIg#@'ܚ.G=b]70Qn)q!PIlePR*Cp0)m>eiphDǠ1߭ )1M4 )UJ(a>FTj)Ps{Q7z&lJ^{qP@g GS nz4PH,).h &d֐͸Uz(U䎾,EEE0dcޓ6@< q4\€$KgTT1bĞ;P'aPn`qRЁI' ~Xa4zb$Fj}tk!Bqi aL>!W$0)Е2܏Jb=}(R7)ı>PsY9E\qd+Ԧbˌ @:R()6@ ''4F=hQuht+OsK } D1Hd AQlӊB _0&zKIw3{ `>%,s9АaH}JZBvӞMߐ 4\E%QEh8DcJ)œ=K~ &bcNeޱN]:HI(HPd04"(}ׁHsGpƚ0'ԊΣA@ ` 4m0c=y3'q(Fdi\Yb/,6?% 7&ӮS)F=\-X}qU2 oϨӳ":jlChlL }Fϡ9H"Ĝ/!AL+(޻Xg4!TCg;|VBZTN)'Y# g<zsVYiUh([ۥ4 HN*A~Rbvӌ d ǁj 874gڞ>Ahy;fzSE c{;? !,֟B},23q}::`BT%\R)H'Pq+dq&~]!)sK⍇HNI P1)~*yhA9{`ȠqrƛGpIᗨ{sNf݃h{Ѻ@cTt&6ց @p( hl!4QEj6J, 9crc p8f@"яӖr}IrH =w7}爟BhU#$֥d~&G` 1CݏKXSҠOK֙YOAf9M]v`OE#D~f89S怅~g p|go,:;lS.b9b4/gưWOe6O(Tbq6<]Ϗ$(1̊?ll/@\-=cbg֛'Z?B켰8i9Y6lwXA*tWR09?ʘjMc)H r6<֦m ~ ҴStʢMغG沒SQIK!~IF)3"G.q'T?֦ N협 &#Hq؟TAX4,C8JGOG&i#}ޡ ,teGQA_£>u80f~8 S;6u߅Mo 4amB Cj$">`,u4W*9L rfvR;?cԲXq˚u}k_Y[H jۤ?1@EpKg#jj~"}'kr]6CP`COuӠR){v1qBB!.pr2H|P2 [_{/#*5At(U=?J>SUqJ&?pR1pwS)!lL=i{ N3FM%QE ((AEPsunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_6673ece428cb7d523234ca0d7c299542.jpg000066400000000000000000000156601420147000300337360ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?F`H㓁ҕQA'VAh18}jƑa$@+p=a]n} u=ݶ*Tiu2Y^X3P\Q[ J@f'cm.eK*ƒ4^ֽ_3۵P>lASEmp%])N;r}-2ZpZ *[+@T U#m/$R5y}t}VWwoRpp( Z6K[g~3Jb5fGeht۠ *]ikzܪ ]ܴB@ iej `MԌޱWɒR N R"0jPh0jPh=*P( *mh*m(*`J]0J]]8J]_e.ʱ_e*6P}*M[ˤncuoe4U1JUT)M)VSJPbҕd!J@V)M)VJSJP]`<]*XY[j`N3UP)jF}xT6zL4yLcՓ}ohu,2Il7NflmK19Uߺoio{3!Av,ylԩ9ǥVy$;@~BUVhi[0╬][m%Կil`1{T:=+e6᎙5ZxZϝqMd;i i = +L+SL"l2ZEF—A\FVTL)Q{3juZ XCCT52*J)Z^~UARjAKPT*QG%<% /h?f(AN @=rROrZpZ-.q)ъ0Vi8zp}jp-g +μhY"-+C>܃~+H'(.JIw=H-<-b{0 N J8 TLLSRR`){Q0 N E8TbJTa!@b\BKL۔KM.i{qh&hIFꗉ)QAi^ 5RSDGC cQ13T,դqryIVQ\xSoqΧO?5֯aПcUbu0Voz?%j|~']=5S~g*=k^l~HY!-Y)/=Ωf*=k!?|NOZu{e7K%Х8F L=k]z?{u3R>sZL+:uOßOMvѺ\s>h:q8 ǭs[n"?G*j1dV>Ɨ+CћaR,ְE<_ZGo G`1N:E㉤<|Myׇ+tVG;wwgj-\1Vߕy5%I#!\*=WPOndygr<dұU=0ߕ;[sW &{:yorJP02? zec%A սNj8Ȥwm9Ě k>Ǣ _ٿ*pxRn_ FKbxO˥O| КzOʜ5cϢ&t@01H+nr=@U?+F]Du@~}mqk7,FNvk1yԃzziϱ+1|Ƭ$My>(ٖwv'?#RI}JKcُp;Լ,}N]Y真ɩ{/k4n0+r?:k ϯr?ꇕŚ,k=!ug/jUՔ k# BF:*H=n jH ~\<&:TM]Q3q5f=V.^G7oǓ 1Fr *}J|r1+7Ǹlso{ < 85kCׅNd#SHm_(kn%SG};iQ70;(zs^m؊?: wG [=H[}= Tsv=BXÓnurNksKh\㋖/mlcMyO&]AQT&gH&Kbu ^?ң_Dd6ӊSO8R:I;$#TlOʱu8[cx;m襸?Z]Mt9Ց926mΤJzUf3EV y݃^R@:mRnN;-Q@ٿv6 x?Ұ3.3"VY5UF2F9(NzYG7nVa!l OORj8 8uBX*-\3Q`4kDبYUnSY- ֐{3++/9rOZEb㌲M3I!%ӷ 0ZE'uLOqzRUJ7{fe7  +aAK;Zh.ǭL29JQ3H {&F2X|*XMښV|h>f wg9=(H#@Is :Ar㞕"#c=(Jpw2 ^kzF2*Ѡ>_@ ${*wU>PXt.;12IHT>Zhdҏ5KajL>g#L`'։YX 4szP!*KIՙ_1TI"Ns!Xql:8%aJUBICHq4IٹFPrL.1'N1Pdԇrd 5[[fzLb n87 ʖL P ~PN=}n4M|ݪG(j r$aSژF\;° @<tYf׏v6+NzФ(Fs"$Xs|` nj%IPԭ ե&QUQOǴ=Mj43l%ԝҦPS<9ըRzšTj6dtQEQE $ fE($t4d穤w!$&0($y!@.II@:SB2P :4~/Vry8Hݤh1Oe_,0~PPbEˡSQ?ZC$C(ͣօ(  Ú }6ݩ #12OO֚i€c*M5wza$y9nsunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_6c5c12ac79d3455ccb1993d51eec3cdf.jpg000066400000000000000000000146431420147000300343130ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?`)qN 3 pSB҅дд`ZP ZpZ-8-H# K K# J J#J J" JJ!KJ!J N @S@lS@R(@QleWIl@O.l :oVSJPS4[)M1Bҕh4V)M)VJRbҕd4siiSԌhZxZpZpZ0-<-8-Hԁ))JpZ%(J-8%J" N RBST)BPA)BT)BP;)*m(*p(*pJ]8JpJeXK+t*ˠ ]]YDtVח@*yt]\<yUw˦,cb &:i:cښc#4W trSiiihj@jEZ N @ N Rӂԁ)( (JpJ`D N HvSԡ)( *`pJe8%B N @ S @{SP:_.DtSu`GNo.GV<*tyuk˥,yuwˣˢt.yt]O1e#4WLt0):bc/jcG@)*銘b)VEHP1ii@iiij@jHV @ O N O @ O N Rij@ F N G0ӂԁih0 ZxJGN)(#tD N @:GNQ:xtsXGOՁJm2sfRUx@aRP3ű$~*]=5iv8Va\~ l~HY!-X^c_k:Ŝz8Dxl;<}j-dF5KU`Ҭ¥Zy˯ٞ>ҔF:0¹c٧[9T~<:cSG:8 ǭsi۰n"?G*jQdV>ƧQ+ݑ GHZWp0'3\gt+s5`WўN-V>2NZʫ"U`}5 G|칏r07D֜$AZxGG3+8H=k j O)~hH+_ xިbly֔H+_S5T=6<@VGhq + ^ZpJkoy~=iE`O0Q PHu47Vp*Lz͒4] x#lոj=1>JJHkc%=J1P9YbK&(lꦮ?VݏZi͝q*o0֫I~Z*Rf6*oJ"Vliy#)|Ho7J#Vʘnb\ 'K~* xc+q*#q*F})Pvs_T[tuߚr T OR*ORj:vhR<=~﹬|GxW^X]|CryYOtȦ_HT^yu0E(ŗ-G(ʧ%lOODu@}mqkω7,FNvk1yԃzzmOOR]aD5v'k!EN̳?u|(ԤI= ~KɠR'5 ߼RkCB#8R g#OcOu=us<MJ? Hsx.sR/Z084NN]Msq5f=URɯ"Z8a4AcZ_JCVÑYBY%W{< K}^ׄGNd#RGܐP<gmZ^gZ}riTz关&"Ƿ`\1ܑŸZy#6_O@XzݏTm~r~%αnIc5-c%.}UqM1<J맒Id[|)g՗+&M0"MrƖb9(?2F2m }㏧O'K{,GI6pA}*[VXFַmh 88*k%AzbxrEeg=NIHCc֝;24$cOsN3zR}i,׭POqzRUJ7{fe7  +aAK;Zh.ǭL29JQ3H {&F2X|*XMښV|h>f wg9=(H#@Is :Ar㞕"#c=(Jpw2 ^kzF2*Ѡ>_@ ${*wU>PXt.;1Q$$*A-Dd2AG0&@\Zp}0GDs9=($|*ps5bVG$`3RF*HSHacNi#⤖A+߭Vy 'L"#\'flRO'@`0? A{R12Jf> ;Fy8..50ېŔFz҃T4hl{sB JpU$9dU$f@R̪@d @Ih2ȩRViQ@T"Lxgiwl >`f.1l)~Ϲ ; r$~j=҈ʦ&/,Aǧ4 rwJ ]BiK}VQURA@8|Z3@e1 7bK&r}jq(l? e'>t7b&n#t5QcOVP0uLXsEK#.jXz :SZ,InM;qLd@TCd̄`|Ҁ&>m\,1LC8!4nn@49fPs402?*ܶ8OdQpS3{ kǻzf'=hR Pd#9$,v`sD{QQp#>fvNB0e\LPPR0ƔSnXh$,4j (QAӎ3n@晟JR *]RƒD&Uh(*zLFZ=.v4 Z"`?8JڡN<` dQ9 34s@#iAfK}2EIhf9` nj%IP'ԭե&x(Vc5^d}PTiNSOҬE)Kj])WRM*EO5RQ@QH@  9i/z]HI=I4 2q $hHzK{P(s吩8Lu)s5~ sN3=#iZVa)}`* \qju5(Y S6Z Ú }6ݩ HbZpʓM`s_ހIi3i[7Q!IKI@sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_7d9bc4700565266807dc476421066137.jpg000066400000000000000000000146641420147000300333630ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?P)qN BN pZ`ZP@4-<-8-<-0-8-<-8- ZpZxZpZ`0-(Z-8-F N @R@ R @ R @ Sm @Sl @ SBR쩂R6RR )vUl (V6Q+VRl ]'VSvPc7˫{)(RJiJRR*%) RJiJRR0ӂӀiiii`ZxZpZ-1 O O O @ N O O @ O Ra)jP(0(JpJ%8%J! N Sl @ S @RvRRvRSP)vT)(]ce.:_.*ytyug˥[ˣ˫^]:yusˤIU.c2c:i(:cc?ji~\1LtO҅ihZxZxZxZhZpZ-8%0-8-H# N RӂT))JpJ%8% !N R҄SP;)*]JpJ%8%B%N%B N @|#NՁ8G@QZ鈃ˣ˫^]/He/.˫]]TMIҸF:i*cb &:iRd*aڀ8ZxZU"H<-("4-<-8-HԁiUj@д Zc N HCBӂSRӂaij@#ӂӸ:%8% 0JpJ@#p\d:x N E#p\ :_.E#yuc˥_.yty~\ ]:\ U3ʫ_'ESM)WLtMS)L)WLtƊ:.#0WucUj@(P)T(RNUiRN R0 x\O O E`*@2 8Sb):F)1E):F) ytNS .+:S W q<- *-8- *-<- TOt+TXӄt\,US~dGNV*t]Z|.*y~y~oˣˢbA<.)yt:c1pHM1†PE#0WuaLtƎ4u``TҬ K,W}(}*]sMMXGG8v܃~+Zikz-Hqu R*T:Q iMLRHfij}r:m<-K>R *QJT}`9HBvSK_XRyucm.*>5 a]C+l\RxN)xxQEo(LFSN*~>TS1jFqSFj6 Q0}p9 _qU \ I=M\(p.0'3\CmR%H kFhg OW55VEljUx2Тm8IXP_Zx֧֞z2߯H&5\8+ [R ͏V*z?R 65X0+ |=j\ P¤R+(_Zx!NȬ߶ZzZ͔]}ih_Zap5;uSZ%f2\,i "4f2vԀ]KCC[RFaj fΈj1ϽDQIqQ5)3u[gov=jyo7[~UxqH~cƹo7J_7Z2ޤ8s(,oʜOʶC(-Sīcoʤ oʵ``Ҟ%A,X @OZ"9dv<JP?H*]GW G#5/6眯&Aa[c]֯䘸xUy.`+$ww=?Je;c =*}(YC仩$d+RG)̘9l e.ceZGwSO^c&}:yotJP02? zP+0(* Gm1yv= UZ)'Ŕ񎟗JcėC? R|u*hQ% :)@?LR?ȀAŸPZcXv=y?GZ_?AyCdg b''!٫qaG?\R#8uL?&%6 r$,J Oܑ[P<3V'>#Xc2;~t_&遐G~oμzEN$ps?I|Ko8Lq{Moq)r‘\xr$#֬ɵ-VmߨI >[dcXɲ926mΤJzUf3EV y݃^\Gl/*f$ȧm6{`SJZ|̸L`[fl{U29`m;4ahݸ}YR&pO}ÏT/51?{oOR\MV5!i GS<"s֑X:Ӳ 24$cOsN3zR}i,׭1A֟3^ ) 42> oH˴nMWv*]#ZCiJdr֢g @.LDd%=)HUs4$}i^@NszP(G;ЁҒo8Zhdҏ5KajL>g#L`'։YX 4szS$ ps5fWG$`#RF*HSS`GˌdGQ^1I, WZO&ǖ"#\'flRO'@`0; A{R ( j[eRmCNƓ_3 oK!Ӄ=G> ) JvIsQ3dU$"0@RghOҥ!5' AϦEJ;J:¡d S;K`pHn2G4oTpjMs6vd?h=ʦ&/,Aǧ4 rwJ,J[ Z-ʐZ?'9;41`-1V&ަ'*Y33S$aCdUC)8Q7v 2zBOjbC*_1sP ׭NXҚdMGp riۊc'?JJ US&d&v 4ȣn0q&midq/Zb6hyn)sry q+2)Rlqڟ0qsS^=4v9BWҀ# !cYnn'r#nیxl#_4@?8ϵ!Y9,c iKoz:ʼn>\L @&Oq1@ 88Ni ؊,(0LnIm%XƐ&Tk "4$y9n@sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_9f00027c376fe8556cc9996c47f23f78.jpg000066400000000000000000000137641420147000300337170ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? QP)@ )qKLR pZh)إ SҁT.)@HBbSҁN0 pZv)@HKxZ\UXC bn O OJ>P#K->P&PDFmH@mjPm[ivԻhOѶF9@m&ڟm&9@m&ʛm&\BReO.P!+MS+I q ZiZ!ZP"+M+S+I )qKPđCqN J;IS OZ@4-;HCqJ8 v*SO JDCB҅-W( m<-8-R MDDaiiiBrʹ҅{iBԛh OmmJ\3mjPi-.ڐ-8->P"Fڗm.|E(Z]@e*mhm leO(V6J +M+VJR+)V JT\4X+HVerԅ*r*\SמbN J;iLS O ;*i@N V@ O(Z.)iB(hiiB(j@jDG -(Z ZP\3m(Z~]@`ZPJ"# J @Z|3m(Z/8-ReJ%W(m R ODiBhG mmO4@mOr Znڟm&)r ZB`4+%)*RX)M)Rrҵ`4Cx pN)Rh pZP)U!@)إ!.)kDf)@KR P*SӱKhN T! N҅J -HmR N(SU`p #u( J@#y~`%/K :**ʥ(RUkʣf0ʾU*ѳڎ`)4$z/ڛQ*b*T" 0NR+JBdL1dbҵ`4K(^*FO pHC@+D1O ~+D@*SHBN-(I<-8-RQ O K N OFmJSb/N#p U`%<%KTN O9 PkDQX _0zP DZ jլD{Q +'/YSexukⱬ&#/4N\(V'}i{&;e EaAO\/+#J.֗asL anԆu摸788d>A>~h3TL' ˎ4t+?>Q^LSe5bQY.ڨZUޣ,=jRd5jX֘] 8-zʔ#ʮW*KA_*qgޜI@>r R?_ 1 PZ?] ҜV.r S> {gV.r?<*uW )z{8`C9N 6^}N_s-!a!\Q4712Ixo-܁C Υ[ + H r\Hby1rTI1sO#sXO$_5p:)v[0,$b0tf$s<oiv݇cͤX=*avGcW.I-dgx3NqlqI2yN]v~׎{ۉcJH=@)RR# _חrCUζww;FsQ6y_7|Ð?8]ʹ[2?¢LA?."!}ٿ*QwߕsILP?LR6rz(UhC>}4 ߛ1rVn0ҘoN H9nzzy^.SE5{bDĞ9{d.Wn>Q?QީfPP;z4|#\y yr?Zf417ǪE W ,}:=}sx!*I˚QÕC . ƸiV(Bz?4AVz>ag}*AY[YkCi*A}z;^FeH#&mȆ8Hh3O076PM-'ƨMqnIٸTs 92KPcoH2|W= y>z+:W ߑ~FaFWsO yK|t'ӊOO]HsY7YNG5k\E@O\h| 8=8upGD]F: @I<NL{`qO 㰪wcRhR{`ST6$c=1)${ n G#ݏR3V`g#H '5tA$i6zҔBɵ`]I`p@=>N+.xd9'8I''I $OsK=)I׭e9i4\` ;i`8 HlAK! R 1qR0SUPZalQt r0 IJX!=qz0Lj@[8>N wCcҖ=V9BJI:9NU azSՀR6HFv6AȨUgVnޤVMߎ tNp?ZHSJW=( d`SF b9@ ` g9H$<S;eHs &'皨ˠ 2se`:8֡g$M'dO 9;rN `OP$Xc^1኏'<$W dt}O<s6g$c G g0)z,?lRdHҔ$9'$&8Ӱ1+0!99OҞ;Tg=^-~\dS8 q))| ] )|Uv?N-paJ<?Upfl.@&䏏Nh` *䂼?L(R9= Q61*B8=keQ SI&Ru4B \ ԃ P'&gI sjse5TN 8&M z ~#4Aև`$$!LIg ɥ\dNSX*zMEғD(4Òr)]0:TqmfdH   `d~T+ dNX`baaH˜ciXG=6+P䝸xӒ 9$ iݜc9)\ \K3NB0+F(^ccJNZDI>MK"Q1I}F*y& sMϥ+'=)TM,j0K{wpH$5Iiq;)@`qFq<>֐ڨ@)CڣN<` WciA 34sC`Z,sP_nI dSߥn!@9NjB09\g VUtF@)$:OgQI6쀐x8?;RIҡHecOoNx52twPl?!TPQE QE HihS@ BIM`8rO4wފ 896Jwuhg?JAh~$S!#ޙڎvSA ϧGޝ4Jq);v.7htRH:ҝUnR䞟5Ӆ!sxӻ!y<QEsunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_abf356affd7d70d6bec3b3498b572191.jpg000066400000000000000000000134241420147000300342330ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?p)qN @)RN @-<-8-4-<-8-<-0-8-<-8-4-8-<-8-0-(Z-8-F N @R@ R @ R @ Sm @Sl @ SBR쩂R6RR )vUl (V6Q+VRl ]'VSvPc7˫{)(RJiJRR+%) Pbҕd4siiSBӂӂBӂԁhiiihiiih0 JpJ%8-J%F N @BSP!)*m( *`(6P]8JPP8JpJ%.ʜ%8%WKl@]`GKo..t:կ.T]8GSltN+?j%;eW|eV6P_/ڃZ)I*yt:RS1Lul0S1 U•JRW*2J8UijUZUZV" ZP" "j@ RӕihO O O @5 JpJ`ZpZ-8%0-8-<-<%Fڀ<-<%<%0-<-<%8%4-<-8-<-0-<-<-8-4-(Z-8-G J#Fڗm.mjml6ѲI )M)VvSvPb•h0U)QU”MVTehjeJrS,~JR,~*@*T(ڤX%J'L{T@ SU"@*SU"LPHY?ߕ8,?lP2[Wcoʤ oʶс3JxpT @V:9\l(,+?H?I١Hp!pFF1wt`I_1q9L\Ly;q&;9xhH#)LHNFx;br%Ld18SӗVo'jA|M.ہ ;y ܏ΤDAH3圏z=!ug/jUՔ k# BF:*H=n jH ~\8}ɯ#7Ɇ#9i|x>%n>L90j?&խ?x#^:c吏N!ty>wol`vQ(82Ǘi#Zu8#@sZ X:Ź'ic5mc%.}UqM1<JYE ɪjl3?\A؆J/O̟Q2|GBxtjwHGҩI}xżcIrpoUh vgKp~926mΤJzUf3EV y݃@R@:mRnN;-Q@ٿv6 x?Gˌfǹ8UQ #jF ӿ3@Qۇ՘*[,Ԛf!1=?P W >uZ&B to^ة\YySz+dfBK1'n=)Kday>Oր#>f*R9iKWd}(' 횑h0қ,=,UhG3>+DA"&]ވ`KzSҐ3@ c =7jhIYӑ*ޝ "P2wg%',pxQzT$a+JޠL %zzUAȨKF|+ ?CS$PߎWk8Ab)и@NBOFC y_# Rd97ޚcp>J` g9sҀDMY5Hp/-<<ˌdGQ^1I, WZO&X>}sK䝛OlTaI<JW!~.Ny@$0 a^5Ԁ.0ېŐFzӃm=G>6Ch!X8*I i!G ހDJi\`@[=s@~, = j ?&}2*TTq b]3Cu(>`f.1l)~Ϲ ; r$~j>nQiRzsHꀐ))NG~PRuUTzemynTpzRsSNCJ  li1Mhr9>8F6HT2jzu@ |7j:`(ܱD(T,a95=zx)O${&2s T!U2fBjg`zL0>f@Rj6_VG!kf77 PX@zr(9Rn[v2 (10簦{i\"sօ FAB3)Bf4H{px>;u?F|qO"`Hb1v4=ZmtVbğS@fMX8Ac*(#sqqM3@ AcKyjXP`$J?@@AFO&Hh_p2}iJpCޜx/N@ fG<|U -UNvΤ>4(qG%x5j.ހ)yg":( ($ fE($t4d穤w!$&PI'$GzCր \ޒ@ t,Ize Nuho˜)(_qQH:ÌSW =*Qrq)Oր$C(ͣօ(hn IވHh=c$i֜(62XiawALVM@%-%sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_c2d24766b49f3147f5a4137a8db592ac.jpg000066400000000000000000000161241420147000300340110ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?p)qN[֛si,v UOL֤@V}mr5X - ZP4-<-8-<-0-8-[N++(Zklq2K4ʥd@҅ӂaij@Z](Z]ZP(ZPP(ZPJP6P]6PP0JpJ%.ʘ%.e.ʜ%.eXFce(Mke&yuke7eV1|R**Oji*E)(JiJR +%)( ^]þm]B {Xg|.|sW]mSssy P0 <ԙGgc_Io']xnr%Ϩ> xwF4;V6b\Vcמ*o=?:(%m,6"ā0xӥAk@Ҭ|7]hWv?!yaz]-[:l4Z3vrMsk:6CJЍjEk*rORM-Fu:FiNݶR"r?1kV. VkؓQ66cbpSVŚIּ/ȗL+kV5* 2$֪xLuWK7۪' I׏z4_·M$.Ѷ#&SAFjbzSZ:cXc鎣1ҸXZ- *EhQE@ ZUZV@ ZP Z.Bӂp JxJWZpZ%<% BSQpZpJ%8- lBpJpJ(" @"bB1S >NVnEXyׂM\]$Wvgېyi%ЉYI.S]SOfii@Rꔩp Q^~ӀS/j?fih T~P)@Rl?d(RK^~P)qI\rii/n?b-<@R%*(1M"4?X+!4j_YCjs0{j&4j T1I=J=k 8>Jm2s6:yNf*\$<[O`=Cfv/ù,֥YsM` $ yſRk?e>ǹ,֥Yr6CgWl&0?ީtaR rY>WcRfxJRt|taR s]N)s7Kxu>}N'8u5kv-GMF6?,hz3|L=jEzSM(/ާRHq4C"8):tPKrpp5qOU & ģi zXxZ-]T=8H=kjK*W<Ơ=kw=%pJ=i_z@zݏG8J=k_8_/[e(^h ž/GJ$ Q|?O.LL(V?EmAN+_ZpLH)|Y?mznLQ5$g1U\ 'I;cAffpj zu?֑bk3, sJGnJnS:e;c =*;YC仩$d+RG ̘9lGw:㌚V=jkc*$gO-IVGO]~2d5?R_]cV?pMGYg5S:—`WקA7N~Uj^X]|AryYOtρ_]I>Sy^$)w-G(ʧ:%h˱UohϷ 1y6=H ]nf/:w9OZ?`?9=Euf=x՘ɯ0;2;jIfxmaWa5hqxi,Jt~7| cXi89+#0j)#$^Z)yy;.2wMGP}x$ )^jI<`<}in9;73`ب’y< C)8i]* ڐLksz SRgMXln@B *s`sN T"VMn{bV$N H=k6HQRD6Fw6=Q:~ UUl ITD?$42ȩRViQ@T"Lxgiwl >`f.1l)~Ϲ ; r$~j4}Tܣ68!>ST.Ss@PRuUTzemynTpz1)9)'֡iBA449RɜZa# $ªIǵO]:ؠoH0MAnXբ*|{S0R˚xVhrǀ֋'j=ہNS9PUb3!53d=yE3u E5n/+K#az3@{qM(,C fG9Y )L ʄq-;S\Tޚ޾sZ~x #9r\ϙn0i#ݳSP~4!> dF)c`cJ[~su7Ef,I4,4j (QAӎ3n@晟JR *]RƒD&Uh9U>"# 3y~vd$P~`y񞤩9*Z/02U)b3MW&mtT$U9:T@øg<JU@SJS F ((䁌Ph4.$R8rO4w=h=(JrTwP:_ƀvҚrY@ O9a)}U A(t8j'HdezнuxsCtxP2CϽ&_z#!{1FI[8PleI9/N@ $44֛ژ?sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_c36da6818db1ab630c3f87f65170003b.jpg000066400000000000000000000143011420147000300337640ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?)@H pS O N LCBӂӂӂBӂӂiBԁih0 ZpZ-.ڔ-.-(Z-(Zm(J-(J%(Jm(Ze.ʛe(Je(J%8%BeLeAeNeWKleWFʱ_e&ʵeV<+][M)@Ltҕl4@ SJUҔX4Y)HRSJUҔN Hcӂӂ!ӂԁiZxZ%8%0# N R @BSPA)*PJpJe(J%(J%(Je8%M%CeN%C%N K N @R)vP.eXtWˣ˫>](<# ]'WUТQ@U ERTp P J.@N O Eh))( N O O J8 %<% N Rb )jP\,E O E!)*`RX'J#b!8GSb!8GRb.#SRXGOT)(XF})3Sl_4Y)vQp[>ygҬe |Aբ(XCE) QpL)1Vt+f:a5CEbW FPp*8M"JNⰪU4hXMH҅hXEH( Rp j@BiʦpiSK,4 xZxsӂ%8%.a`ZpZ-8%aiii( ,0 xZpJxJ\aii)( -<-aiiiis J`ʹ Q>R=mqF(R-mF9;hlRm!)M)V6v;{S UҔs)TFVS RR%12Jc,gҦXϥ>qT"RTÔRTD~"G8r*T=eڥXs%HڧXEp+SUt/h>BzpJ܃~+H'(.7fsԀ `4Y:ciBGҊ`"G8Pi҃G%SGp4A4H `҃Kړb@isQuV$Q f{K3Fj=uÔ4nR$!j4}GJ#SKTE2>@4B^^W4P<$ (@xP)SߏgWO Nf*\$<[RGu۰P;aVqS,ֹx&}Ԋy<5baRֹQ!dgWQqTR] Stk0ֹu׬+DZ]<}):s>h:a0Es']N)s7Kxu>}L&8y5kv-GMF6?,hz3xJ=iAXbޞ/ǭNm `a}Nxi?/;CE5&q*n1.|u=z}]`OfGV%H kƧh*ܱe'FY"dU[*0>ǚp6`a {Px=is]i֔H=k,]ZQv=i91{j֏0VWǨ RZ_0VWNl^`H+3}zrb `Z_Z6/`MG}\{i0VgG/Gf3K}.>*Lz6Kt6imTdՅ!4f+ q*wT|Tmpfώ]}ꓓ:I SaYuQ=Zo .oNP642SK~* xw1B?,``Ҝii1ߕH*G]+;A?+ʤUoʟ١Hp!pF>s\#tT~Wo;bd/xUy.&`<AG {CSPI熏Ă?:Ďg!G!sjHf\`8*yxx3E; /m}*I9~ b Ҹ/#rO$w%5)}ZJg$!5bk3, sJGnJn ?TΙlNAGfy.I sSuVLgq#qM+5S S?pj$u#𧮿XVPQF2T@ϱ܍[T{ʸG&,Gv3GOvK0+zՇ~TUoʸ!MKq«5.RO9)?.??8j?\^$)w-G(ʧ>%h>ǠGM W~65ڛg#T'TuKA==igD?򞚺z#4̟ɯ5;2;jIqZr3yW;ӳ$JN tj 9qJČ1|I^p; dOJH# h/H(UJ|\wcd|ѐ9jԙsǮ}hM18Z%e`039@-'<Ve|rF Q;$bE;94qcNi#⤖A+߭Vy 'L"#\'flRO'@`0/˷C{RɒP0mnw/A}@vqI+ZmS|A#=EQs}iJDZɲlSA Ā=)TIsMf 8HȁǵJ"PSO dI?JH'=Pe3Rң0D1A"oTpi>l()ʰdqc ʦ&/,Aǧ4 rwJ,Җ*֫+ms' ցIqN; ($ f'>Lb n87 ʖL P ~PN=}n4M|ݪG(j r$aSژF\;° @<tYf׏v6+NzФ(Fs](<# ]'W5jZƫ$mFVnP(Jcu%ƷynAmI\J)T`gî1ްu4o/;6Ѽ3Eu+(II6I=5Coy!]HYO}٭W%Yyz͞`LӂPӂԁi(0 JxJ-8%JSR(JpJ-(J%8%CN @SP!)BT)BP!)*p˫:Q0+~XӄtW˥կ..1e[;exɄǾ^+%}fXjۢ`>{ӌtUiNQqwniEoj@ Z8Fij@ഀ`ZpZ-8-ZpZ-8-F O @BӂqBSQp" N SBST)=SQp O)(VRW NSt]K՟./ڋ[ˠVQڋW˦uog&j.*yt\1 t2c:iDJkGW t t]1f:W zREH"T( JR*Ӹ J EhZxZpZxZ.Bp O J# N Rb (JxJ." N Rb-(ZxZ.! N SA8P\,D#`\,D#P\,Cӄu6xJW ?j%8% ~N.˫)vQp[;(E_/ڃZ)I]!)E34VS RXc*2\v)2UJ dVVUqXUZV" H-HER* J` O J EaiZxZ.-< pZpZ\aSQ# N j@aij@s,Fڎ`)i))s,4-<-8-<-aiiiis R,G JamKmE66Q Fʟm&\@RR죘|b•h0U)QU”Lde*2ZRT>qT"RTÔRTD~"G8r*T=eڥXs%HڧXEp T*x!<%XST{@ O/jx!ڞ#t/h>BpJQ@t{@ R*T:zIJxOj%8%O+ِSRBST)(ȂSԡ)){Q20 JpZ={20jPhȶvڇ"Fڛmhd;i6Ti6~ɐ+Sm+K L0NE0=d ej ^er-XaQ0E3Ej$5a cRSTˊhW *Zi{A1UH/hUAR* hE~P𔂤8%( JxAH 3Xm AKE8kc a IeU[*0>ǚxy.礢n G8KXPZ^h Gb KlkAXxSC)S6֞$/zɔ>` x(-3`H)cN֡ɖ/+'֔]Zɚ*&(Ef}zznl~Ś^e.#֥IPt.< x5n1QA6Jc-\X*9##cldA*83 U ZgDޡi=꼗U^zէ&t*lҊc֫|ZEHe.oNT64"LR !d~TpU@ož%\d0@`M#9AAd7Roʵo~i6{gJ2±TTpGk"m9^M57OOv+MbIg/Wf͑4r;9xhH#)LHNFx;br<ՠ?ԮyRBaPN:٬YػfexAIYݝgL'larY#~Uk<|u$rH]A>U-~upn\qJǠ T~Tlu\$*@)VQP+wCV?8jI "ݶ j`_ݯR 5fWoʸMKq«5.RO9)?.?+Bk?*pՏ_>Ě}]â#ETgDv=jMYu98>&|8ҡ:]R9Gl>ǨǢ?O5'fY؟pI').c!f>AŸRI=9ufr&7û'OMD>YǪWhy霿ɩWVS24@ z5"Q51#sP򘚬]R=5uD!՘XMy9gL0ƙ,K!+qaOͼQ0j?&խ?x#^:c吏N!tygi6OGi|ﱦGPqxe/b*G`\1p.Gn?ּ-#mo{)R bgOŹ-;K 3o -sˏTG.Zl?u7W}f*R9iKWd}(' 횑h0қ,=,UhG3>+DA"&]ވ`KzSҐ3@ c =7jhIYӑ*ޝ "P2wg%',pxQzT$a+JޠL %zzUAȨKF|+ ?CS$PߎWk8Ab)и@'A!Rj'!rJ*J*8 I1O .!9}lҥӀ8?O3aGaNU$F#7O*xFԼu:$'~*n`S߁(J[ Z-ʐZ?'9;41`-1V&ަ'*Y33S$aCdUC)8Q7v 2zBOjbC*_1sP ׭NXҚdMGp riۊc'?JJ US&d&v 4ȣn0q&midq/Zb6hyn)sry q+2)P6j~ sS^=4v9BWҀ# !c$g=fMX8Ac*(#sqqM3@ AcKyjXP`$J? g J'ޓQր$`qFv4/8>Ԑ`?8JڡN<` b%1֢r gi%8 G҃.̖ dԒ"5b=sS33ԕ'?BR%VFFJUE>C,F4|ͳ#?*;ORwJ~B(wqLXVJ iR*ځEQE\1JѓR4ԚJS@'NI'%8NY Q@0ߗ9SWP(Y49#ޢ?vu?8=|Cޟ@ ".bMDi Y S6Zhn H~~Dv4(=?Zku |M4<EXiy<敺{SRRPsunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_cb45fcba865177290c89dc9f41d6ff7a.jpg000066400000000000000000000105601420147000300342470ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?RN-fPS O @ƁN RBӀcR0)j@ -8-H-8-HSPAijP -(Z%8% !K J!N S @mRqmSt._e*ǗKp+eXRl>]]BkˤJSJU4ERR:w)*᎘cT+HV:`U+M+VS QqZpZpZxZБiij@\ӂԁi `J-<%<%  O J# O RD N HST)) %8%L! N SqSQp N Sp JDt\tN#t.:W]/Vt:.*t]ZӼj.*ytyuo򽨸XU+ڏ+ڕ/*ʫW'NbbW4E4Z*a0Z*aP1 u|L1SLt^1SLt\(-<-8-H hZxZxZxZ@4-HNTUi j<%=VTST*@ %<%HBSRȂST))\BST)(0JpJC! N S(X%8GSp ӄu8#+:#\ :x:.q(ڭ?jW D~ԾU[ӄT\v)TU\|.)TU\XQU*+ڋ>U!yT*.(/jbX1S ^բbT# O JUƪԪ"!R*ӕjUZ@5VT*Ԋ4-<%<%H0%HRa)*@F O E%<%JD O JB N!)*p𔀀GNՀtN#\ :x:W\GNՁ:j>ut=ju&S.S;jZnrI{˩{1-Vz&J.AZZnrSSj \Uu?UrE\C*C֧w:OZ{XC֫\jCi ]ykCP<;kkel:suNG51DΔN=iq\5QQ;zӄֹZx.P _8z|=h ~pbN֗(\Zp޲ztz,; G8=rޥÊkRN*yYj-WyTJKV74qP/U^zr煂Zus "Su  t9eoZfoZ`JxZ@H&oZxaޠ$ odwwnqު߽hT7֘o>P:տکVjz}ihcjU?5rnoZk^ޗ s7ۉ棂 ֱrOZT֫W;[=Kh5jǫq+ެ}j R;OU.}iGԽjRc?awXj5ƨN/fǠgwyV?ޣه9?C lzԟ{0=!uuu*ԽH]dz]dzkRAzJ*c[?ާpz9髬/zzk"9[Y_VqW?CB1:%)}LXL}^QrGj}C.5 kZKͪUJ]Pz*ZO1KURjWsUjy*sF)=hAhx"*A% -O=LweS`Z wr`z[;9nިIrIURjInK{s)5lf%i hqq%?yQњu.`4CQQ%>i1|Q@8L}jiL֚f>Bh'}ji3EZN}j4X _h>r޵X4,-}h[z2i3ETsHMIo֦MAV8cNhn IR6>a4zݷRFvjoZCt޵W4Q`'7-L7'֡54zpzx5'NPNd\TO>) KU^R{ӝM@ji3M~isQӳPn 3KQn @uH .j0ԻfZ4&hLHZZZ4&i٨fBi3Fh4RRZZJ3@ i1@PfR5Fh4f S@ 4?4fRv7S3Iy4A4iJ %("ԀTKS- *&Zm@*D@V)L)Sa"*CL4њCE1 ](ۨMK)hۨM44f8pje(cFi\ѺE;u.i ;u2@ ZiM4@4 x4Ep4 4Rm0 J sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_d30c10468b33df9010d185a8fe8f0491.jpg000066400000000000000000000133421420147000300337170ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?j1KZ Z)q@(;S(RN @)@JP  xZP()iih0)vԠQ`0-(Z-(Zf( R N" JN Ee.ʟ˥ NA%N#@#q/@wVt]V|Ӱ<`+yt]\]MMX *oW|aPM)W {SLTX e) U0JW)M)V R)*JiJ.)qK b pSN8-1 -8 xZ` JPV)T)BSӂT:xJp NӰ:˧*q8GLE.#p_˥ЎGE҈Ў"`*|z"TX ~U;˫U/NSi_\Xi|,?&&冕(4y5P`|)E M'Z~E1b0Z FYb# D`(3h* 1S U|L1R)RN(@)RN -=V 8-08-H#a N RZpZGO!i:GOGOՁ8GJW*q=b)DudEOXOXǕOPQH"+=b"J" 9a HUŋz@ _"P|jE,"@"V=EEi}PQS|(($h)EkTdƂ TM l5Dkoj'2*ZoQ543(+("0-8-8-H#UjP ZhZxJxZ%1 RUJxJ%<%DX+%=RT)=RTV*`VX YT)\OXjR,TsYaSb*,5"V*bf`*,52V*b + Lmb*9ӼR_Ry5wȧysC֏Gg}?&+ڎ`3~QRHV*G0J^E;ȫU/G0Q٣fyTyTs ١'G0rE5Q[ALh+M*`2 Vh+h"ghhS€UUUiVR*U`UBR(X*TJT)s%JNT((Jʔs(ՎUTOQ*RT 9H:zaahW) R,u:R,4{@!XEXUh J JGR%ZRXe8rTʕ*OXQ*=RT,DR))sST)( lBRR-lSQ(V6 CZR{UڵBHd +Ua" 52[EtX٫imXڣڕkNWڧ֗bSamRO+ㆦXjSڏnȦT][ojUrM`fX?٫Jq"OXj(٣ۓ슋 JUXh슋LU Hҕ`TDU"XX*~_+u O KD":x R{2% N Kۇ?nhZ])qOۋf]R⟷ ʹm1F(#I&*}d{i Ob͑Ԥdxٲ" Zj'5DIj'J ~8ҬufkS-R$HEHuM}$Uf8 Ycju*eaĴū+K؎XU:jrĵ"HVERkLVV يO HA@%6Tpv7N:7NSnúoඑoG+kxHo$}s s]T)Q}Fj=oUijA\rcE8T੎< h("AiSGx)P$_Y%=._YfJ .jo{2|Ka3Po̥,`>i3PRTsM&4g/M/Qᢦ3 SAQ4֙=gJccG/[q\ե ~dbٿ<⠎.N?WsZ" zbo}.ǭXKc?xAR)ZfuI^}O.]/_.ޱWdFՌ] #/vt*u_W&>G욝isZFJR.ޯt{::ˍ`zԫZY֜' Y=iUOԸVgMZ¹x}UzĢƪߨ| sګQ/KRH+ Lzdo8V ԇP HU;O@\>uߚr T SoCTWL4q}RMRO%O}zr\ts j"! ӚN+tVGwwgqkivF z Uٿ*Y"v\fKYٮ9`is҆gZ1; S!\UI̅v*z*z(ʃSLjxT*[#h'hiZ2G ?ث!6q¡־iS;S??ٔڨ 8x?1 stChYUN=GzKOR]q/5 O~ymt9`Կ"-,~"/G.ܛ52$3^`5je&,F8?RX $u:7# ?έ'*[(ߌGaYK#ROv]žbbS/NqZX},Q<5S[[ft}Ka{ctDˎ♨_YZ3`zs_:Z|Fp`S6q>*n_OA>i۩~"Pq!?@k 1\ y1vY1= ;.?ST\jnSWuܸ~:9Odܧ] hEOG-hc}8FS6|@E4;m#T%կ;mO#p/U\0]:ylR/V8=8wzT%~פxtǶ `ǓUdmݏaKӎ6$c=1)qcrq @cy #4:6ߛ# )==IDAb{qn\tQ`.˨T;fJvT3TY,嘒I&џJ iXPA9)45R>^( M8d=h^`Ps'Ҕ ;@ ևM= axOJ~E7 t>FGzsJց8 E}){Pr{ъ U'U0JǦ)(Ivb@zIQRv%21IEKEtm ^)e})7_Jpc74%ց _?J\d=@LF79hTӌD'V=F .%-RQ@TwA3N#ހw<ҜM@ KE74PE'Z3pJNEP)sA>J 2hA"P.s@ ZJ)s(9 ;y)vґ֓> B1J:ќӂ9CKf4)P=M/ sA6RQ@(ɥM64JKKZZV&.=Ȧ*w@ ]+m}IIhߝDSiҘmJM f)1NHh((@QEQGz2h(()A%tw4P攁3NE 8b(RPhb-&h4{RZ(@Q@sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_de1fe6c0f40e7165355507d0f1748083.jpg000066400000000000000000000125351420147000300336510ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?((RVF)@EqR.CBӂT)*JpJ%<%B O @VRBST)(*G@DUge(JR~gʥPo*#"*x+|"yTSʧyUhENKU**)TyUsʣʠ ~U'Wo@oWg@4&U( RȊ" UBWUq U Z&:S.C5*1TE)s4JjO" LSr$U:ES٩ ={2U oSJeQJV ڇ*U *A/l?fUHQ[S{`eQH"KJ!EQ5 ڭ,5*K^U?bWM)6~ŕR2UҴYXDRQK1a"%BW\RC2JҮ8)q{JPDr&$HGLCVSmG/ USRJ^دb9"0b*F*dS-/l?b(VZ^دb9c"ԫGf4ERkMZ^=ij}mCHܡÄpvC֩rXxsS?\W|8ֵ50w<߳yGwH'=E:Q}*1cǷ( Zu*SSiTJji)@ZPE/l?d)RN i{phpJxZ4j]ar RT!CT{qrN@}\i3PoJ KXFQx,Uox>Bmiz"I e".j~ Y6qP4i KśF;jai*㋱Osãޭ84kSM2)go,U3KSϽqxȟj?F~=Cx*~K% r?\\~#8̤t"k7kޟ\Z+\ M~C֯Ah?jf兩i.V#ָeMqTOʦXzWl.GL"s>>i *??K?G(r.֜.Gڰ.?IOdsi{9rp_T:z1R YYrjξyֹUս{{{w1GhN;? sF|Ap= .#AZ);L_wծU(C)kWI-(*0W?Zr=kN*>R@cH5_5.cތN?s ZuG4:o5%8jC.Y °YaJ%5J5P1}RFahZfpO޳s}Y~m/Xx=jw9* JUWiD}*9,si1 Vs8fO& mwR\P3Y.ު=ғ;BLQ<=괷Z#gTpϩSsJ$m"Sé =Ҹ(Y Nʟ\v3p}+UnaQUda)s tTMSE7Zf0 TWFQXX3ZV'r,^Ă7~U"rlLU7y ;F>gw9vf>4E'L~un-vFxBѰdb:8"Qrvd>\첫Pѕ\e)b@Ojת"5rV6t;WRVV8ۻ:]dAu;?^sß*GLf]B\z&'ӔFHǔʝ :?T%Ôn8Z#c[F*ٔ՟c!? \?T[ۅK+9irv3O]xrQk2Qg\ki߳YW3f?\Xf1%8??ҡ/ -d 8q^<1/4YHv-ek_+%{Uv,nX~ rϫH]FXtT}Aǥzgϓs L~NӎT#)s52'029p>`3@c`߽~)1|TcԚYٻ^?#> q#K "0rzu;ۄ mUJ*P]Y1$OzJ( ((((((((((((((%F(qmX|(QEQEQEf^>gyĸ~U>Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@R gڃ ~tPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPsunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_f6d8fe32ce3e83abf130e91e33456914.jpg000066400000000000000000000144251420147000300340760ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?ri3M&ȱIHM4)jBԆ8040<4048404 ZFZZ$-M-Q RnRn RR 7RR KwR ow KK7%7777o@7請w2̪ȒUMhINUӄl=8=UN@CӃ`d=8=VN@ jiji48044ZZZ-H S Te!zij!z4D^^%/M/Q K;  % mm9zMziz}WI,y깒̠ >eeV) QU_2%[)|ʧRs̥jNP"蒜$"Jp/ )J$($BOzpD%SSL&ZZ-L-M-L-@-Q-QRũũ2jaz4F^^%-M/Q}4D^^%-H^/M/@oK1zBzB1ziz4Nd*H g4U̔%Z) Ẉ̠e22e-eS((˂JwT_2\SHIO%Q\yjij4q婥 .P.+z5>P=Mg IK\Č=F{M->@%g#'FzZ|'/QZ9깖eNL/U̴-9 ޘdNd=%0Oً^yy{1󓗦L%9lSTJ^_ޡ/M/U{Bbzaz={BRziz~^А4F^ZdА&ꈵ&={B]ԛ-ԛA wQF=6]]D۩CT;CS,=' O PObڢp j HaQ`5HUԪi{!CjWqB3L fٓ#=DiZj~^FsQ3Oهlj#G0)?f/h!sM/A=s^\ґL4sjij %>AsiX:YC e#p:=*ΕnzՍ)4??k|kaI( . nk9(-<0Ml@-M-HM4HP\I$bZMi!{@-M-E4*BHM{{Q 攊LS"I\Rb IN&){a(.(MaFڥ%ap4>Վ "UMJGՃێQRʵ摮zsU#]Ewcʠ)->ׯWstr j8zdm“WkO}5>B}+A\#ف޸' Z{Xw#]U>B}+>;r?J48Rԗ .8К}+m+ٞc0JkǏL} z?.Yv9tO)T5(e2bQGҷ0J`YaM6ZKxc>/oo)lՅz/n,o5kg*#/hi<6cRIB*V;c+J N2T})3[Mhe!*Gt^f#M1{Vϥ0Ҫ\/})#[F)ſT%!ɱ?4dVu sma?ݪQD7i f>HlORHP1iC[SMQD:FI6ҴQFnf>FoIM;U"TEqL'bDTSF]֞T@Z9[}_Kh_Cj'5~P7`D?j{U> E),FHh%ؒzVrq#=̇Ly:+0[H4__β'Fǵ0gi#4Ʊh4cbp8#J}:}:0NA=ib7reFۊk!+ӸMB?~u2x~ux[#{ כÖe S"G0 $8mmߏG-'V#IDN>M2sVOApyak(<8岆HI0b& 4$^3o"DeC1Z>Rk)g)bG3v ig'נ׍.7ZxU$j"0~kwgBVVGxI!lsUz#A Ï96?:M+O8?udұ,Jr7'=1wel/Brpch!;)}M:OO F]za}s42~睝#:i=oM-?o :;gP9_ϭWσy@OΚteޘSlvsJO`0}]u_2':=;:Ry?AѾM]3+džt?4(HOhH:Q1fCͤ}Sz|ZE 1Q6;WF$ߟ{U,d1m%Шΐ;I+? ^Lm*3(!ǧ0ڵI<ݴi*&Xg+E#zF+td|UFO%F2m-CZM*^?^4>0Bjx M@skEKc&xE*ݏWK5$l~dFmyL?+hg:7Og:oXIsRiWӢ^s;)C,rOܐ666$;GAgoY_KZ=}Iurr+gi xԱ;)Vtv?ES4\),_@*IO*vyU~G wup3-tKf^AZ%, kS0JVPW>DQ T`Svt>prJVH9HLC7": @&8?ZD;VvI2mSSIjqϥBӸ>HHI'R[bI@>ۏu {PFG]ޜ^%LgqU7`}h9X Km@ŒzTI@NюhydF@nWcpj`9g#@'){T/سdZܨ~blIsP"8~j$YW<֏)`< T{SI҈cq:1J UhWF%911XI$tnzyvVR0RIqJ۳pߵW wHXDaTOsMnsScb Tkm:j LF%U;I4$+CWg'Ji]á֫"#b4 (Zif$Sp j[-"B #'sQXS2&(8$֢SU8 Ǯ D)z1 ŷy2^ X2#j{S7McYgѨm>?t0ϯ@/lTZ$Z|1A ҬACҁ 3M~5! 9OPYp@;|`zT/!b5lD} 84*|:")ޞculT )t@,RmA< nր"`'5hGQJ>Y WBK<hNjH-Ҟ31ߚqڼs@Rz)J<}c)t:\ޙFrI+>~UC*z~>7E@84@Gޥ=( sLVo0N?Svw?1PA89?ARJb#14҆h0'))=w+{Q'ި0$s0_Ҝ)* 9H"Պojx8^hugo-0.92.2/resources/testdata/golden_webp/000077500000000000000000000000001420147000300206455ustar00rootroot00000000000000fuzzy-cirlcle_hu525d1a6cf670e85f5e8f19890241399b_26792_200x0_resize_q75_h2_box_3.webp000066400000000000000000000172501420147000300362210ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/golden_webpRIFFWEBPVP8X ALPHm۰1_#\ GtSũ96{Fب8sÑ$9l3?{;@<+b&$IFnY C$w -ImIdm=_S鶗 ?3xo/Z (eV{οgDIT#QH%W ,n"ʕw]L0$]sάLo2iVd+=3ggĞ˶) r͞9l] ZM!n8RӚ(svf(JNr{l><;WX `ʶ`s}z1:4Y#wь'ger3}<؁2fnLW;}Ùc_St A69;aιrt(YhLٟ龦cg* ބ #M9L-mw;kvgp~̏gJE!7IJ;[tOֶi}kuv1;s:l0I[ΰe$gdawVcFN)l){9yClhC{-n\%p;tTR.n.'"`}űLr"dTe;bS=j }^93<ΫsXmkڄ&(T*$ִK9mgݳ9e88>S4ņ.P-=qeffͣN2uu]o<?~<}fvkGKI#ĄKP PhiY<}#qq=0NWVv*"'Ioɕ\?xvhR RZquͼLϕ;T8yyxLE $\ Z-l˹f6u9{|؞mBEb&׏\G@ $|,жtf<"O% R d8Z!#ZnG03x%exubU ü&&q]DMe/ k$NI֊HLov R0:u4=2|;(@Iޜqh@H?_PV5IdԐ'NgOYJiЙI(BHB+>tp$&g]-^ eW`0c2@I(P@:>vehNd4&G$!+DUҋk},XY{PX*QM3$TAJUyZ߈,tO%$_"hdc9vVt=향T"$!׿D*Afz"mAs>%(( B&ΜnjoQiVPQ>$$!PĊvڱ֝:Fug7mz }Hj(Ymˀ ߠ4R۽{-P>$+(M PȖswNN)t_|B9ȵ#f/FQ?6P)BHc_E%mKQJ/u5h^=lWW`H(Rvv35 s)O@. @Mv}-;++ Hŝqm^$ym?|s_!ZJ-GrSS tsSΞn=}`WݶL&HW_$Ʋ؅_ zI 6oB$9O[ _" @qcKoK~y˳R_=} RE+\/V+xK<ݲc|@A؛_!_-9-OB yANr77+y{ /> FI ({p:d2$Df$ urJ)r0MT> @@+3LsaĽn[NIgU@>! \>ACeq0y-}@!FHxH=kyՓm @d&zkRn&yvQ@(d4!sF'O/;Mopy-DP^Ė #Ir5189n(mt:G?R'DhN38ikW\nq8.Q~ךC$Ƒ޺ЯNZunZAf5z͐huv/;/Njkir:iME4aOڬ=,B%t/FWµ6f:۹?Zvʊt"8pfFbvg3cAWds9$LQ"|S-'eOO7u\>Ι](k:d='uߓ dQhmˮD?B:-#7'mno?s\wcѕ.wsO׭4˴eٻ_➘Elq߻9s^}?H4P(}y69`B_2s<,'Bm|-EqS Pz73{zcڝe~E>]=wOtiRq2,/-X\JY>RZD,vSZZYִe=Ik6zϦ~ZgN*|K9sɞ)BE"ױ@JmpKOgJi.֝l(a;Zm*EWP>vݐC,T`uqz^3In6X<ʟV llYbɱlxn˒YvS,n>U64V( Ul6q瓬Ж9S9O_@چ;s(nZO^8Ssꂕ{uTj߯uu8S8.{kNJMڹ7.RCrdRΰ0!ϫY+ki)|c@ V8)b~N)i-J`۾9ZA,gvm?|8PBqB NiWX{ۡt-haab[-T3PjƘح3)I-tC.C_|Λ p])5;$V p?9ʯC7-;-|g(4pƧaPw- \lROz|{^9v[֭l*ruy'ԔqBuzJ31=~⦔U#@_| d*l{ nعmv϶@uzXJmD>xro=۶˥9$ ,w}Vؔ"_N6}8.kٞ-/46fRvٺWW7x}{{BE ms珻zʢ_1:q|$L\N ~pF$3^y$'sͅрI8\%"{1LB _0kǹ1I_kb:1I !ƙ\I */|LZ1Ih_0!F|jdZ-1IN/.ƂuMbʕ.mFSU+!hJ1QoW5mFT0S[9$ #o诫h Nݯ+c̥1F|ߔ uLn;#`Hv~O/%8K k}8̥:(Q 5/1_-E>߷`Vlw9UZ -tcx={pS8XR"퇭-]Nکn/l@)K^žvﭰigN{{7{s"i-Pᣟ Ҷ{ݳݳun{r>xi])j _(T ݞCﳍݶ\?SfY<3Ы4EjE(*\,-^g <<24v9L+fkP+`_JB]yvsX/ \}w [3 ;LWX+EZB*/[Ԟ9mpZ5ssD*ص=Ӻܵt@K y]E8S=葷؟4|K=2T8)Wsϵ  j+Vrr>Jo3u xZ]7ppay=I:L1嘪 U)+n ,JU2gM?>|/7\.߫Œx=3eZbcJ,M}gc>|N@yP )d MRW9-,m!?y[Ϸkmo_Z@JG l siZnGo<\ޙܗ{9l. %evI#oS>Wh mO$Dxv[+wv׷۽Otwy;tbl푳5ԧNGxo0wCJs{㚞 sc=Ye%8xbfOYN:^ɛ {{.lNylg5i2zl$Wܛr͟_ͶWr-RY{a˹y,l^#?Zu]dZ(]ubywlV;^66- yv֋6iM:80ÿ=bo TkhxjGn}.u.zi`v[v&,I t=ۏ@ VP8 0$*>RI*l D佮u3 woL;Y;}8W_P}?L[XKC/K``J_ڟ/?="7٨$H"=r3f 3)LHx1Pi\85K<3#,g=tȑ>vk+{vUz㓲sK -F+2?6]04;ٺbEW%-%jq~?Tͦ'Qz}QM̗T9`ɞv6nMQтF \RPw}[\8B%m[+sgj '6{as>x+R@4"U\A͚ݧ tx'a1nz {iYBY4vΎ5 @TX6Xz UsA-#(vbUG#q7EYޝ_; +|<8ڔЪ&zM|{;\ Иaăhh==+2ȕy^q;Y T(6i#$|EfiacN{[)P0XpCվ6q-J+E|0??@U)țPxSY~&N:M2]1sp@4R <A@ U&GS٣kPpexKLCd|e+/RyGP1w!$WZ! ^TBכ6!)s~bz<z*S K\yV 2F SU禪H.u.[%gVNIXɎ(ÓCnm8W>)Fv.M#Ɓ!uI\; }>%?4!!E 7 ؿxlPT'qts F^ Ƞk>\f ΛvDVD ks6p`!]B8JE.ͫy&hT+})2 hugo-0.92.2/resources/testdata/gopher-hero8.png000066400000000000000000000320171420147000300214000ustar00rootroot00000000000000PNG  IHDROd?r5gAMA asRGBPLTE}}}|}~}~}~}~~~~;C~@ܸCn"pX-ᔯڗӾ8MyƮcI{#ڬ6=ד,0b;Uyxw!ܹ٠>>jkk'~r]P `vӼt/00yzz#1:eW,λn_o>~^Fct[\\Ǯ#wg5JWRsͭwfIJμ=VeG}Q@8˺sýԳ9[ 5R1tRNS@@0`` P0 pPp`@0 pP@5 IDATxǹec[lH49ﮭt$IK8 @B$-IJs#iMҞIKOoJ\Y=Jm3;yy Pjhm B ~-im]֎Po0hxSe8 RnK\uI]vC%?- ʿVI"J0Հ3m(Tw[~K=}5!S:%dON.nTwSۀ )`jk6Bx{>\.j@OݽCw|ra46M~Gj6|"4R'wL 9nOUnRm@PAS[a 4q#QH4!QZ,:TG4^Ox.ͨ;b>JSYapʋPWQV:V(tu\e=9nՍxzqÛ%q3N}hDa>MnDhsNȎ\x;ci08߮$ItP;ڡ':jCRp_a* ,\}69iN,ܦCJC' s6@@(RXuDa&""Fsa$M y07vn0O@!N~U7 fՃ0`" @!N( qBhek(,/h]8@ t6-Z87HX^L46P!N""fSmx5e ʍa# `wBmxم8渣4A(#ː E|!(e"P &Pp(;;| o0xBqTsz;_<^?), rtIמ5k/Vk죧'_x{~S9L[Gw@Jյv]O> =]\Qzו;[mݷ/Tߩ^; .۫\Tuzf9?oj,8mߎQ:= (%9MƂ'I8m MuੇmؾW}{vxqzWUXD _eI&叇d9_Ǝ; E4qE'4e"!e3 _רZuWb8]<}硫VP̙)rQʦ/,e}=RweJU޻Pk%4\T㲞*t|'9oI Ls/LiONy~n@z )MLc)Rtq@+VbS(\N0(O@Bif nN#?QG #PQ3hZ\ '@es&0E8=!;&< *=qT;oŶ\2a#QTӤ]^O5ǩL_" F'J!q*G.YXiFQ=}=Tx4Oҁ4gaصEa9rNN*ͭǃgfÎQT@LD46N^B޹h +`L2M ~  gɹvt8帹mWɌ; 6U\6u4v;P@uLTK͔P5)D5ɮ# 4SxkOiv/ h PYmkh^~5Jqj 詆Ec9'3#JYp TJhO 'O TyÁtpvp>I/5щaҫ#OzŋC#uĨ˝R%K{ǎxȡ.km@oBy =̋B܇>"RO~iPN'|dk~0wlEx8bL: Lcܝb[ɢ]N>ot?wx4UAaO%[ ed;"me7M3ynF`pulǤuM ~>-}q~' =IJ ;00≲hN?;g4*xʕf'#IO@wl]$y_9h6ʥ+y x'FzꐫpG<䴉D~r睵@=}>QPtqQmOUOmX70ޟ,?]1.T nփ"9<9~琪('NK>'ި" 3Ox=6OM+N-3?޽nq䜂r:}n}h x.N1iШ'("rWCwPGq͍'|Ծ9pP=ׯ rN7'*ew Q9N͓/y^Cny2^TF<~ŅX^,S̔#4y Ņ^{Љxyo D#<('ꇧz9&yTSEs)b5O4ce8~p$MݘE{-R1w*9Z?18}t〻R\GEWe) {ϘD27g:Q<1|vȮ|nޒ\yuT_S&NRvV]a3=jOo0Mnh O?G'sYrA#Lnt!1uS3ҝN :1JǷcCe%dJKy :26YF4\c;fVG {EY}~P;&cI'MCwPup^x{WA3;v, SmG\yWFnʑ ː oGZtS</r|)8i^S/sѣ5OA5IJgu9O7 4MGQQ>""gzP f5 4Ot/ᩴ<4'=i_mcҍOI)Z5穏Dx!d*s|rpWӿuEi;??ĥb!H`5mSY@Y8=OLs-C!C"h>9[AS8md7LLXFX}_)!/F_ΏoA0V1Ӓ-DZ޿\/‰mw7~y~!VF#do68/]9gS3V,?ǧCcXK**~U?wެ^+i2읧m>~Հ-y hZ yK8Ƿ1P!yj:G 8?:& 1yԬ+Oeˏox޿qƗ_R,y<uɵ'䉣`E'Tx %Oa䩞xO!Ob4U<' SuCtuxi` ܎< %8Mb9xPaQ yH}lw4RA GxFIN>'z.ِ' yBӌnI1n y+L<}(6]Pcd$}d,B(yɛ#9ϟ$^1O>IF #,善r}p) `LGiykb"9+lQ\ui:!Nrv} x910f Vqim?wܹzqN Lq/O5MyWbLt([ 2=ʳ뢑(:d YÛ*:۟&Y%5qx3i詄KyZO8+O~/YAESr~H*0"#yO[73Т`HAl *f:0 l67I'jb׸2D , O)Ri"%OK.M/xYF2~ n5-9=;P:"_y  lƅ!2tSOF@+e8^/':!PNG鞝ID >i)xwG஻Ku71wa &e@U;-}=/Ѿg;PN/;F}zN3sٿXwߥ &kjNrK6B vWkKěXe@V: WO{I?S'%u:D|g޼GO?r|zdgbv"Q](j&Ƨ:ӳ'k"Ԍ1W|~g>5ON-1)E#4-XÃ8E,+t(xj|2~jj]rh߽ڕ`NM( W&~'\%\\NrWL/KoiP}#`m<;>, >d)p"8 ww]t)X"P`FO+uXTt#tzjѾyvѲ|>9X@,0ܾ +Z, [T <|N#}b\$/xIDAT{.C 9][ Hey 5+- "7`)훗Rk' )V(XQ/A-\&-u|:iI9g>W ؀|)qڀM 7/% BUɱ+EOd4I_SzfjMX %~'k*PBPӒxJ"Ox)i'O+$$:[@@oUBT]v3"OxP m{Ǒ%+x${<9)p=]G:$<ޕNMJ Ox95,犓 䤸d$9 G\xxRSqAOO%5%_Sr.E ¨;IN/NN copd+-u_V8uw⧥>txӯ#iy1pNw@-tx aPȁSVdqwtvلQ/DӮSb*ܸ;;EV8jƓ-ʺ+sbu0MbTL(ɍs} Ҋ&è{2&v')@ŔeAv8;O<ħ gSj8>?{G$4A "zSNSTӳlS`6D("g?DTocSN'w|S`c Y*6"wSrU$04/2jx7Zaa9+ )V6/arc)oMQs/ p-aX"`9v̉0Oxqt)-XN)r'7NSE3 `i<y(}c͈)sXF[Z1GV[}W|h9L<dC17pV2O%3^ M+ XsW1D GX'Gn=_)2JE ZNiryl&nqy -/`Y"YC uXC djWF]]{0* cNS QHFd)C ETBDTu OĄVm gv?x t4#)T(uxϴ O#a' īdwx*Qm$έ(>x ,Fj,}]lj⓿x 4!8UzirOISŷn.x zpW xxN6nMԥW^ /҆;FtӖggn랦mjNtdžʩ<^4%T\SӦs^i:'l!@ol ޞQ TUXkJPqԻvw8Ku^;vΓw<}s]񰣾y+|Z_t֍;z1L 7q}j_t [qdN^=-]n:ѸY}ol\ ts8n!i@vuSNH}aOu+cMLe~!̮rq7ێ8 3aK?L'U RWC ]vRG[cH4ONe%ڪ`[O^V6|!|PCkO(`5Iv:7 7vz`{7Jy-m[[n<9q*AigكP-t&94Lm^/eb(+c8XmFOGDm46'[F+WslJ6p2շͷcrJC*hR 6^VO_)2A#t̨oaoo61ܚ[l޼iFotrn'r˭d-~ܽoߴ`6lup1z`D}IENDB`hugo-0.92.2/resources/testdata/gradient-circle.png000066400000000000000000000471451420147000300221350ustar00rootroot00000000000000PNG  IHDR  ZgAMA asRGBPLTE%u%t%t$u%u (q$u+)ly2Vڛn `]2z zen(uhIIjM@ttB>TzesϪI"Y,ݽ6:Z.j$N%vpm{|qlvyskphkql|y`rbpm&tme*pz|.Cvi*I^}db4^tu<[{f*6`xgw#gUY,m^0a6;%4c SUy}-c08^1A'LR99@Y\ +oW.k49\"Q;68]nO?,G%uOdDW FATROnvy%fC,E)'rwR9vhr:1gui/i_"kMrktYJ{Z%Nw״==X9;ZujVL`z'eA?Vn=g?0s=3W2]HsQ;G&rǟ4>KRU4!3eSFL{T7[k?xDWK A.pqI#OQeatjiMAh aFoʢ X/hAm.d0+"JBQy6ś޿%ٷ(Ա̥cHTb|^%ܼY.WGJi PDNcKDZ,MCOfLB{*dZHIÙΨ]IGrЫ{]&ӮrlFV{ju8~2{sjj\(`JF|3ۺ[*\)qlѭtiskskrk|/K-V-(tRNSG侴o'qY5TZǪۻ%y9 IDATxյF1y!ER,x]%56hc/`Ǯ؂5{h,QخhE?{3i{ιwfsPZ{.;~XcWZiW_]Bς;W^c,y hlYy` fdE.~0j$.%dM zA=!M n\SX/*KPqnG] QActr(Ǘd-H~kj '\Wy9IPmf=罺G@kW)YZ#ĕUv=CJ`8)WsAՋ.FURb44 p!f$>?kW*)'K\;PAwer:vOK# iyUN/MЎO3UlF>,֌`7cwP?Nݿ7"NUbn圧fX>,ǰÕ }vQHY&%c&aiPS`Sc'Q7Ogrl3JN?k`|hԌK#DuZ9as$tHVg[s¥"{VGz>Ӈr=@2ه,WJNdHfTNcX 1yܙ< l fɳ)g׋$3;W;3ĬmsNQ SD0Ÿ% V/4ݱA?+OlO#Z' :Q_EMXլgN?:YDx,<$ OIYD{H17ΞLVhLsl~_}Gi5>e$"YZϞ{'YK,S`!VR44ݬ*7cћObJs:š;+CnLIֵg/ ^ {=]ÎQLB(˘ag35gųDDmHj@I{4 =vߐdU˯t}3N̮W;LrE!ݨy&Cgh|N*ɾ#f(I}4cR#rY{ؠ`Sg왴]t~'ؙwQX=ݘnžeMYCY݃5~gD Wݓg5,#YNzsNR|/E(Eޕ\tŏV4?= {,jy Wg]#iaJcUX.7IJa*Em3b$ EVX}-FKoWXMZv=ں{8 ׋{njȤ{X+[t~m%Qj=f2C4dXD3a(L%RLejŌ9lX֛oo1%Z-5wKcWULCyTJ]eIJqb|*f'o>om;vM1ITzKca͒ULIcm&Lj+㉇xBx@ag%֛5zQtY(tB3ӅEK!.H欷L{8UiL^xۦ`|;e֭j뉧@_~`B`BDbtU+Nfx3c\*O6+‡S4> X!<4er~8EQpF,R3rL-.l:<$C ,!O>B{ x~%? )戒.ezWaHj#5aO$΃A}zPܯ7LC0iZgԋKDYݞ2~!BC2)-&Jc;USeCZQiL_ӛ×42-U f[#j`(t?i:1c!X`}ZG@O觏f/IGFZ}3X:"UJ?|ç)Yx4__:饷/͑!bJ2PxOo =Q[%&]%{Tgfʱ/mi͔b*Ⱦ{mi6~|7"ܨ7͍7f8^bebt|JƈGwcZlwƌ\(CH3ˍ-#((21FzԞq#ƥ*ѐ_x\'?%F3 SFBگ,^UӬZSn.YRq1,6Uc( -QR<*M-bO`yXȲZ=>:Lګr3&@ #̦؍eB]x+dfi& /2㲻Pf}6U쮔zcMNbQ,s&]x7Y%o! .{hRT.:UJ3*ٕ<Ō_\-f$!M  5%)|\39R\<2PG]u ŔA'N:mWn,܊!B[)*"C6XS̖[#+Yيj&YUFvع9qIsO!1JzL2헛h9CWU59Ԝ˻rv̆YV.\\GYظL!B"@P:0=E~k,)e0_o͔ON/v"*A5ʑkhC"AyvXΆ+!օSe+O97>8dX=~dzg5jFרsNh\I튺FZt,ukX.V49DH?#!cLW|rs.uM Rz9\s/eU% B 79|tC=lFU"f(( 7+5E;\KsnN'DHn)؃c򱜵YDZPBY$%5$R<R'&!vrKr=sS9KWF3,_@m'/zr1ky%˱sMcbLW!>U*ҐZ2γb"y2y6+ص{bqMrLRQÏ3vݴhOd6\Λ-LRߔ.,ӈq 1 098V|4qCͽe߼1{QCjxP?tL_%r9ׇcڮ &Y0xPĚ'=iIFvbh{1`΢Gڎ&' ICN ]AMR*>UltΥ{H1uF4! S&yg4bK48y $Xܥk&ѤDtyK&bQI#FFވ}B#&q>Mc>2qڴf +)Mڐ2F Ǫ:t=) mzZ yrdلD#Ʈy"aX\5 5b96XLPDŽ 91_Uf|NԚpm^%;։Xlq&)6dXYh oX&`S>hH'WGk&,矟GOfL*Fʴe;M/E?vK%Or/( vtV&'2hG`]t`NhzDM/EK\MbmFJ45[R[).wZu6ʎL@4ҖA3w,]hѢe~h-U'mK#>aX® nR_ tqd+1G5͞>&ZQL:2_ҒM/Ele˂:M_mp^4@oN_n{#iw(OKhZzGcFb(2ql嫡ǖ1[#t.ϋ/xqg DCguٟNFigRh˖f-[Xtip|}VGou ҎV ($SkqCv\bjH.*ME1vϖTO% EA9v23"+ŝPN5,_)pgz0v"+eՉZQ/vbR̝ZH Et $ oLU[Dèr$tqRrqy4]Ʋ%Ό=;VL)HxccTNuHѨgJ蔓+JD@J` <(A\UI 4d1>[Fe u`EԂndRX8d*qb*Ζn,]e-8"Zi}XEVX? Ce1)CL Et/.%bΪ@l!(z;N2:$LU. E@ .M jc"IEKJa)ZS)M5V֐6 8LtcLbNNy5@%NebqɱeӉjdXlNrj¨M%īenE2\TA+`;J"uҵnZ+E݃-K O!C Jj@wDE$MlEǐ!lvl@I!CC840Db݈2?qNBҁF),Y2ܲN.­,~jKԔ*)]!ҦO)Z!}J- T]2 T|@ SdJ(" ,bfZ5:4[1_9ҙT/vvڰh45VaVLdHhN$K]$Wͪ!(E3 sme}wԊC"3ҫsi赎ŴѩV8P-5u XUX)%Kkh藔H}(,NRM2Glx(qIX*bOe?XVX՞R)C_]ɞJxcL/KWa'miJF!nK& I jְЂ](%BR%" ao[==Se/͕,#\UQ kV)]jJMV0ϼj%_ ͤ̉Q*\6J՟RzEqY4 //Q_M4PB%'_>}B_JFɒm ZґRW)PR"*bW BQѥS[$Jg*_~icsKFƙِ2XOeiGJDt>jJkm[")?~)or}_NOJO2 /Ӣ UR)"*["34ӌ9ӈD3׫˙RWrKν) M<:'ѿqa3 5Ϭ q%^-2b|ޟϢK>fV5gf2JVrbKES]AI~AɩWˬʭ8U* ; 31(>B5¸Hr/aٸdbL7ffT*,7*"QW/iVխz Ǐ1^My}#3ǨhU#RyU[5ɶetrQN6jܱ=ӈu?q Md|FaO< }0b*~+l[z:h5"e̓FlfeUƔb1(~ЄnAƍ?nquƜkTmm3ftBkوX#2nIIhl/5q]BU0#BeXTʐ#"LdF؈JFd02dii4![!0Rh7^,?M%3F!+T4qc&s 22?!36ͨ6΃ocQJŜkPN,a ŤqvB1@Y#$@]G89FfָH5sZ0tϫ IDATD0[:v ?#jɤpƅM őfx;_d|DZ ?Hճ=Hmj)>aV!62~q,zQqXO64!>YsP;_E *N.EP#Qa9K6rM<{M]9Ahد:c\Zۥۚ D>o}u^l"չfVT.SAp~\~Hb\_l~Xdeҋ:bTW:r<>^ erV0KRlrlۚU:j^[*BmX4bWתxOxq|. /Dx mdVL&$RuR:˳N#RjJr.׏8{ .oǜ WrD FC>nlQkBLů!=E-q oE_ߒ#Ʈ,Xrۏ˷Pt3j=#-[ptr ۦbRXFeN$X>9Er]Kh1^د"BA+_*&hHb_,ݒ_Qf"\0/Qc?E 9 |}rddW6$nIi#d9D%DB18{֮œ^A,(eG{k9QNdYN̬tP/vsu!u557[_n5=5,dG$9(CբnT]Ū8A|rR5nV7`8\9tܪ[jޜT+fSֈ^f `bF-i2U:A+$>Ț4LubZn3f#W(nі/-) _kzAl,<5,:${CuRE"سS[حMZ2JvgWzWJU~9M씉!2xJl)슪 9tcdV<ήr ڎjG=; rlj[Q+JmhjD.r"/$Ab3ʙjhzLnb[I/vV[IG~a|d{qΟunN3xT޵fzvqyHvٮLEx:-A2Ojjc%٨Q5m5gQ'Ze.FVcً 뭻zꃆpVoxA M1f1=oqΟR.dĭJܲ6|]DLںIodufpI2o܂YB8dzEeH+D3md+u8j&/ a] ʤazVцYմH'vphSVD.BsZ>\qv'⺦P8LbXO<YG:L A^Es6Ḳ%"O]@8 ['jf7Ni|=ذan5 3~e D7 vMlXx* [8N#3 1 x_Ӽ4F 7)pP\I2SXH+LL ~ I ==[?7X5 $[8B͝[=δZ`V62_nH626[=Ʀ0^h -5z[z get |q%p,XcAXd]Jcҍjk Նomiˌ u"e Ԩ,,vLĚ-|Zs\;cuF*@W2z) "qAe7u gƽH8oa2i)x񾞨Y&HږU5!Oڏ㤘Z@kadZ^Z5Tyn_-,b[ڰ>`T ^Z|I7/dN3kUϯh31MDžV"b ɊjF5Kv]A7ok~n*nhH SU#g7ˆ01S,E[#:vjԏj₅ L@V=Xu$(}CMFEN0WW)êe 0B}֫Zܰ`r↌c5E,]o?0x`ΆlV9mgtaH%"KWlB]ՎӲ;fDcN =.}|z6$\qs8bbنbҕa*2ClУ[e؞`^2P27|dV,Xeȭu-]}vgVm2]qo}\m~rksLY}G%>Ygf4Uv$~oׄ۳Y=-7u&zt]y9NK[/R\$621Yx3У{姛)SdJ)yq&oJ)~S01rSZ(b=У{'k6;(rf`MaƳ3s12Ku&EYEb)>ܑe=.}ɩQ.dW&"_闊)_fhg:vfnV- 3ѣY5 z>fe FO0[%N"IS|Ix&ؔ)9ǘӓuU0^Gs2_5,gf~ջfbfXyuY1O-Ǧl_vLw#}݄\f4>W@!}rlJ"UŴe8f/cY)9-vҌN$ؔ)hA|7!3_dٕZ,fiųIY'9P˜ ZBm7/w5C[;>'JD*rjYdZp~RĬY> wc {oBh3z)+d#l#Y4Ǹ˟ބܝ%2)&I6.PL[)Η,fhdFjt ';ُN8<5w`G:ԮԢ!^9EfW^c\Y*d!~?ޗi?pusVM紒]˨,Qv2]R"E˝x| hBN}|R̢IrNt",ɚGJ[/ -HMg9r>l:ᄴvi8R׈Y;1N^M4uZXOjjL 9A r:>G Fu>Qݗ2Ilu' E?/''<|f(FAŒk LG&,StaLK2ƗdC.2%KZʥKblSVikvy$ V1 \5w! !82%/[cfZg'i232L,tc)Oo15muHojLv"uQZŴf!յa:Ȯ)v ܑ@edG:vB# c*j۫st⹤hєZlYBŴ_dWnsxHS̚VŮbXETXXLJ]m~w{/e \l0ⳙS̴c.,yxQfV5?j*1J(6-Z1޴iϥkgi?`t=J U5{E+8PaYc=||0&x]z^rJ!J1R-/s)3] D`=cPaYc}Ic>)&jǛz+]IEK`cK[*[2Ӎ ϡ*J_i|\X2*mb%~)g$;H=)3DbR1C4dh=,*bk|圕7z_פOfͺsv,kkDɵ9f,s#+et0T<>]:8 k_׿#5_\5 cW]XD/.@i\ح;%3f=ͱ"Qa˿{ ˽r4/N:r}m,|Nb$L ybJჸ,(r/Pa]c]{\F-uI3^Fj}%WE%וYY#*YչtցF9U2hȮq~9m] U}Ɍb\&[]%b$A$YX٫-:Bٳy}4כ! 4"Uϱ{q\1[aqZ1L*ſv׶Ne,̈́ #\:%wlvS+Rhܺ4f׽ K ZGzYR*F͞-͞]űtz]:[JÊ:Qvifݛ`z< .OQGCqޏ1dY` 3%vU#1;a99YjDŁո<؂1xyz.7eҋNzfce]O]\;fgѢ7=Ӯ:,2˝2*eHU,ζ {?xwT&PJV2L1j;*cݪ1QhԦ?MS5ٓf C.J2UY#xT!y^ $zih@S)cGpIDTXj]/+/^I땄iLU(Z*LKo2E' kߨwxOI"b sd{-dbT#40_W_x 9AYn ^]F+eErk% 2cWRv1Fw6.BƋ/^̂v,Yo[ib .DbRxFbf%60ByY.^.H͋F2,ed= @ IDAT,]Kb:خwR,]:XWJw ]}Jl' ~^(SӴ)XKc_e]WalXMϰؕC«!8x5](˖^<%s .y.ޥz7HՌ!mlȡڗCWx5-/Kj*Ǭ$JE37RXŎ7@4:B.84G!x$fb#>2g F)v]F qTD0^YKd/Z2=Ȯ ًni|] M. P*iG$2XJ1E]ǃ0HD9Js>GyqIv>#0.ṳX,  rNjΦl=xb $MCm] vB;M]-"@"B98'8LuvH~wW7/B4G촏G)B)vNu"O.Qf j]iV)и1k')9v3=3LKnY"U;T`:\/Ԅ]C4M2wkřjÂRc!TK;SHTypl}8vrĝԅ6lXIƂr'_>܋Uwi9&c,^{2c؏c̀jL_oS_۰W$XN3MY| Mj8ܸV;h%e3ua Q& %")1`̞Ym$ĶcǴk}vlmb+l޽-Ǚq"8)>.;8SZ2<3ZW3]*fO0[/n2jz·Jsҫ2tY7AvsL.uH9;Z,6ae{o5ٛ 88(ŲFvc\DW|V،K[ 7fٲ8p{Kz-cΆsbxOaK3Ӗ(0+֖{f6K<1Ǝ ;8tMڧ;[ R[Y_e\+T49YU7Ǟj P=A|{==P\mImYXCo>*&LASV-ua+&fg1Z1t>z(qAOPSjmP ֶ |eז>r7_z3YSI2؀L~M--#|%NlKY' .S9@_ GTl`mQL9צV̗r{n6bA/Czi1:X5UETW.S/rٺT _ ;C;D#":ZU4J,Ԇ'~hqj\&nA^U8W M_dl4.:w]ER]H6 R}( ԡL0X n;ˎgVlUwo1wц:T{|uD!ʦ:r,ҕVJVpg;bWGG(zh!B7t-CutDHя9Muá<^aY݉lbEb{GUEs+Ec&64i"Tވ̪R^@ By+2 h^.@ >B@Ndy|'*;D+">u4 f}娺BsPgP]ga AG+S_wPz,ha 4xAg)"RMHw_]zt"x PJ/`zu#VšnVi ZPttEx4]4ZXM]jjJ;PZ8;G#+4gV]q׵ ik :f$$)*I: 螒wksOŠ,Y׊+=%9T*7iaJ4 Rc(Q:EƊ ^[Ab^tXc::ԍ^VTV=SJ$ZIENDB`hugo-0.92.2/resources/testdata/iss8079.jpg000066400000000000000000003443331420147000300202220ustar00rootroot00000000000000JFIF:ExifMM*5b(2iCittà del Vaticano #nanoblock #vatican #vaticancity2018:05:21 09:27:520232 01002018:05:21 09:27:522018:05:21 09:27:52|Photoshop 3.08BIM`(ZFBMD23000969010000a93800003a4a0000c7580000eea7000096dd0000b9fe0000b9500100977f010041bb0100 \http://ns.adobe.com/xap/1.0/ Città del Vaticano #nanoblock #vatican #vaticancity Adelaide South Australia 20180521 Instagram igphotos C   $$$$$$$$$++++++222228888888888C   ;(!(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88" QPiPQ4!i@1)  T&J!& 0Ch")"0R X4!$TXh`` 8,@4&0CaX 4#M&b1q&$LL@DjPb 4R@@)@ l $*B`D JQؚt 0 !SQ4`bc"IBc F@08iMN ` !CH@0Ebh !И` @ Qbh$Ӣ,4@]4M0!C@P24$0   @cCT0 Q0`R`€ 2#I8I!h$4Q@h(`( "hC@Q @X`A@T!12#N$&00 L&)4jLpԡJ((i!V!$ MiD4 @ ` 0- 10U @ Hb`U& CC[HNdF hbRP PDbb@j4$IH" ƍ+%` MLDL `IĦB j H$'CL R84`! # (bDI:+ ؁ h`@ bb`SA& 4A  4Ě`DFhm4$  @ !e&(iB0hEHY^ "Hbc0b` *Qh@ `F&ʊłih( D@!`J2L@SB@ @Е 0 28*`@h0bQc@(Bn,h` rg@ M5M0@Ch8Ѐ@4@ @  cA :d@&!" X( &HNqJ!! MiI Āb6&hƀ1bHIBV( 4#P `Ch0HK h(610NJ Ԃ )!4C4 J  iզ $0! I2, Bhb0)6@D@bh& r`C@Р41VPC` @ P 1"2! $0MB2$6 &hVF2&@i@& ` P&4 h(ePPDD(H$`` @4&`44YBPdBQ 0@ &"%bRa i T @ӡ8%bD`!("cjH"8n h)PD`@)(!s( 4ƘBN&*M @4FQ0Ĉ"("l&1hTi#P @hV}-7j|21@ d@ & MTb "Qj DF!@!H(  b4 !P0"Bv"`DpYI 4$ /x{ϖJ5/`:$ b@M@"b@ I! bD@Q@Li@BQLR* Ddӳ:It='˟muho2n (LNQh1 i&J 44FA(L D@PMiJ D40! шZ# PDHwwx=&-/r.C~9Q(!1S`@  !P!"h bt&Ha@4 V "D( %!! h*`@i L2r=鳣=xz7ۙ(Q|GaVo<7. ?@i1B1 *4шhQJ$)@ICA$M@@ 3I&&]{N+oV?/E{o5=7Ej^:ro/$0œMR m"CN (B'B`sA#@aDQFQ@JԐH-щj(!v\oYmn,Ngyyu؛yVN~cz1ѯqV)潃m}7G0=w@FAA 9TIȀD*@ *a Iؤ!)\`7bZ1%@@ V'lxO'>Ï;]re_ yO. nLיquYwZ{77~o;~ {uu^.G鞳7:Sv/w!$DMr*-t$0II,IDd)%M\*BA4B@"1Ht9ĬH1@MRV%%1J1/ͯ5g>ӿIC۷zu.u#yOijuG {7j|c;;WGF|3ko_Ϸ-zwO?1z~g?}3f>wQnӼQϏ5~;uE()[D:!HI` CBȩDR8EE0B2&@c "(2L"D))Tc 2MSD$T.Nػp/)JǗFL]<'7W$>Ckyvy.#0<_ao{m8ODh8[uko7r[v9:{Nn ~O<|f{ -FS2y[-Cu]7Gx{]>qgj㗰ݣEy`;}ugÙgs^~Zݤ+ 86F2Q(*ɡ)**j"8L "l '6C  u*&B6"1JA RPtebN=0/M ^j2ᓮ<9mΝ.8u9}u[uR붜t>9Icz9^'hT׽c}x=lSvB`TDH #(KG#z:E8p8hb`  J*%cB @LbkcyO>s]$yy]:sz51]q/W?Ut<,'8^ײơvy,z.myO6te{Ww?V^>pd)P9T 2q0D$ELTP I H&v>^O5.Ki' il3Yl%)yM?66}|]yݞasޗqю<\w+U*yuZ{fn+4&,U =4vz]_ra˿goz"3lc:}Ya{W`lݤ9~/@|/ ;ff0u\o8ouXr8/O}7C};v>y׿W_xY5u2h9OoJw[0L:w79=Gv'W{)~O:z8?Fn$2-hEED#`۲;K+#z3Ѳwco4ik0f5}3n=g'_dzdO9C1ۡkmճ&<]w<̹=G+G dGV;c]lvFl~/U[t}6 G5[Лuy+7#f rnm"DY"h =?ώY^Wykot&z47u{N[iin-7â'T~o?;}V\-VE7jܚL}wE;_+tsuv?=v%z5ᨾm.1ᡨݧ0z-^9ꮻgdp] yF:gus?_O̳=Wn;OշJ,u]&cNɝ:|_V%uty5ZJƎVCg.Eo}W?cηݏurwvle, @`"+&6Qf.DPAa=t?%aazN)j%i[O=óMpnm;~Jy6W-]XV.ÀG=o Sz&n9o?]>c?~e=MuQa:~[^[_%:Ww'YL GYot}3]WS˷r5w W.f<y\/59K;26u Iay~N=*wv2nxaפ /N̍[>tk}u ? _ٞln0 R)`H ,( ZǮ\DĘf\A#ŽY\z3]CcGEd~ݞhzϯwvϓ_i4daz:P+[ʉ^Y?Ov'I}:?ջ8~^]Vr<|q7y_Kro!5_kL'=,x]ϥh6|߳wnÓ<[~1}_9^Oyxi ?08/#8=|#j}ONxyNVae+o] Vx8lk|kMj5~`s}#=F5y>Sv9dߠr;+VbD+n?t_S<>C;גzG'oil=}?פ4w'qlopɸX;Ĩ*Pc1a؜BpVF%B[#1ZZ Ni{n|!s&SqUn9Q{GwMձk:::qvx̵-հۇby+^Ah0{-kNK=~#f?Xsl4n9̫)';=-/kv>yM?~DGeN_w1fbqWf]n>yry쫎.|<ه 9'{A|t; }G]hl_=Vr+ "3(U&5FEV| h17TzV뜗6>Sے}7纟Su:ΛyV^{M+zwFm6uݾWzΝ&M6wmveu8tNg^~nw/3Inǰ[yyUZo5mcպs7Hjnxy^VKGWhŽ7{6)P u,.;x b$5% ! ehM, p!tJuW-yen3ThM->φs]N'&zOm&%]sldopڝ>|'gmѸ/FG7]׷o$9?H3wh}_v*m-~F/*/L^{ޝy_W7-^ X{|,Ө5iyv e=/޷<:>It3&/djsT`$l!$J²r!@"! M]ch6 wu[V2{0y/ncv<w|]܇Mg;ez6njv=oVUu\<29z埨wm&o?m2Telw{$㽃̬14mՙ<,=wYCl:;**K8 %"SJɵhd(uŔ-DJvQp4ȓ`djUĢ6O%lq/I||׭Gaꞗl`r:}'Ro0]vMu]l|_gۛ/>ot:8us':}oN软>N]>}︷3<n齯w~.nKϱsb]wy}x^8[}ǘd}~}Sٕ>so|яkZ4;~nqyrc}WJN`#o()ŵ&UJ%queCBCiSd, Wb! ٌX,#$Ƹmܥ.Cߧ;^eEFN}|5ﱙyysWbgGw.hro >C}0+a{7Ѫob[o(k#~Kawt_ s3|Zx/Az|/v6q_qs/?4t .w=<<8Yp^[.WvL:e#HEdy4Ӝ`"Ӑ*l&ATrU%iDr+ mVʣuʋR4sISj̮REv,ѐ֦-!'R*VKtϛ'hҼ(^[qxZ3jߴ:-agKxˁ[.'^Kak|6q^X]~K|6\q;VxWaz>ek а*Ϻuoڱrg[2~g, 6-07{, fl;A\fJ1ʲ8ytR$XX$H3'̕r(SNȩĝ U5sd- #(YeN.*-^M2!mQ'Fbݍ%C&v7t[ /V]VLq/GU>V[z߯6yjncW-.XZJN0ێ8t:;~ j΂=FafAq,:/OoC1|vnPb.lnjj䑓Tb")dU)^J"U(ű'd'\IpVKYabYLxZUYXMy8mu-m+2u8\%cȲȖuJⰢY(Ŝad ``N/ ]]fߋ/Ys;9ޓn>ts8FNxt7iʾzOpth6yԴ|;/_'ӓWVamerivNc8y;cò4쒲 ЧTY(@VYMє]!IEJ8+Q\):Ԅ1HMĕl#Xa-E%++SLFN;B#"WbڕI¬ƽ˓T/)wN"YNR\Ս¶yr%,mJPd8{+#s,kѺ#7wY=/k_ᗶxM{ mv.7)=mF/cZ-gq^ɟ>#Ǻ):,r 3n5IdێU@[S+, 1DT 鵔Qt^FWjI(Mb4$(Dr Xd8ƉJH] -1jW&FVdQ+,ǜ*IX(4h#&v2W8+YH֠i mx/ph.*l}en/:h pC 0rѹaH(,?JtuŁmwCѵi+ExI;X@&Z@~E3+ aקIRjh6,i{I:'4>ʇ:EKUzҬJPڕ]d[#;NOk(f1ӱ_}P*\C$6ϺW`ó G)0z (+ZG ,\ri<&pe2t[)=݊@h##J[zoh6 pC튚Rdad,״8@5@'\N54\%l&8]^x$ ~Q t@-;AHzDhMMe ! $Uh%3uH h5j3,,tyQ )=Z,@V^՚^h<j tƢC+ݢZS]HQqS[@6c5iذnrXoJTWJ ʺAQ;Zj/˅8kodPL{GO3Nk\551A(H+^Sh3}d@`vWUx/RivܠmhNq۴7NOq$~\wT؇<y"$Rf+&yB,#cNA J&QCTd {a?ⓝz>`Gʛɑ=ò#''4݂ =!I-<IO+ a>ۊgڂfS&c\8~Q* Q nн?Mi,耚XT|NCʣ_ԃI+Ih 08_)(~J2h:^lkkJ->57* S;PkuB YSMXp#Ajt{qMuAQ(`'vF]Gd7q=A\M"R͠@kuwJQ=&r >HS grc٭: 4P66SD)dߦOAhQãe#- rMWlF97Q;R .Q)js:` )ۚ :‰aZRG cg!X-<."`ۑNd*ݐZdw4̀%uH`xCR6Nv w9 EA9> Z`}-*M} @N)lxq5Gyԭ NZfw9:~˲r m' ҺAȖշr\,hjMAu참 N˷+IQpֿM~kR$|Xw:G(d{'&pkکb1 kK8r8Ok=ՔH $Jv/5T9(DŽop8.(pPܧ dai`r{hž! ;jXhׂ\#jo]4Ғ2M0w'}9f*3c)& %<6c_r1vwTEx&tpe XNbisx)nSvyco?Ճp0ijQNJ L,[O EV9R1 _3w KXx wSIDQ4E#u$:U,Hiݲ6 I bJ< ^**Αh<)ñpc\;M 4XM"@[3H~N93yNK H1 $1[ k1V R%-ob~ư7X;&S ; e9P 杀Fi E(p!:VjnGu4{٩t@ ZWjmV2]E~Ѡs,\I<t#g20NHi?O Z8 -pPrTRY#wwMc\B~ZtZwd.m\|FXš+)Ѹ(2tB7Iƻf5h=pK\xF`МOB{ 5[*=ECC(5R@l( ZFdhwXklu!b-@;96dE5cg*סx*!'{evtŭjpLu *4kک2N&d&H}W0]6-#D1L;l.<)ɭ@{2MhoWYE"}""ZV纎7GjZ} eEXAs u]=~ *꾚_E- @w@ekqZt0ZȠ3T1t+=Zy^uuu\#Wjx?~3گk~U={#qVu㯅E|rEf>ghtg9R=\tVTYw>VGsDeUw]wȡ1UZt^@J迏u]a]<_XG*x~< WyZҺ 辞W5lj^Z }5]\"(YW]xG" G!H̪EE{96!1"A 02@PQqBa#`R?T4h5ӦrfZcƛLXo M:<rCus&u-VG̹H;{UvMPv&VFo 7LK4",SȚ<&;n9=q1R 3* a@M9Ifg'tšsfBCm3/`2}L>?2R\m:H4cuC&*]Џȉƽ,L`vmp?2+M'U-eP&PqP&ٟڠ'څVO"``a7qZH jdAK?nf,OE/_$.D*>b>!cf/g='d62p|8ȬIbFuv4_T,1;L,LʣWidӾ?{+*iE |B^(wE7y=rD}:CM1i1f pw m6?>>uh1=2̺xԜC&Ya`\.5?TWCş6zY3:$ U‚Nbӫ VUBq1,ygDZ\Ddaj 3=;52C񡈉\LڠcQ2knٺg(wp 9$K;:̗j&Oi_b3f̹Kxu1J&aWEG6}2UKf0.gq &ø\1Y~ UAp6&OwP1@ÁO0 jmZ,{Xs&\ |6MA¤'øj&?1idfQf{.P MVVeަ@V#c5AFUbc]QƀE !=GF=0i,1M`fT6M|s;1穏3?7!Z4kq Z<& 15?+z#(q6*6eu%&&>r,cj+g5Op0~OY~Zbjv"e &cCLnG1$f؎O(90c15LY|LA)dnxD>q=y隌PrV+rqM.Rcf`,[Sp`1eKX 6f 6ۏQ o~n6>@(L4wU5Zw 4d609r-}+0Cg(0?b ^; Àam ELoFk/c¯ȄE^ PКv@_f91QUhBfপbԄ1+t ǁ>|1S5ztE{!9وGC5Ofm=? ^6 {;sMN(xcx+;:em#*w]J O`Z"r~yb{?LIb#xFvI3ZXy!4Q-Og\QpjD (BW UQщk MEԟC8nj^":LVUvp;5.|2=, Yy)"0@JM6BGb`e&\Dwj2e^f<`(e&;of㍜s7΁ܹuO!ØЄkqh90JE33垳q7R9ef8YVnX̺u*X*aΡ@PzQs r!4ɧRi"j}ˈdb_:K 12PveL6I.i* 0zy3ØXOfUG McɴэߔOCsFb.1ͪ(Sdjx('ν}7/+M]j4%@bɡ BXg>Zĸp|W095fpD 7@gˌ`1]MLP:??&+xc:+z"mxͰ8_&WS8q0&_P-u.FsB_"/ɝq/raseRWޏ++_ο_ _~jH9h}?C!1AQ "2aq#03BR@`br4CP$Spc?:{stܦA@'d,rsAb:׺lsǃз@u%pD gBlAѼ{$a UeZIT2JށqBgE{z#?.l_ h>G1ni_OEO[q+&RBJLd]ZKx+fu[E~ڣs͘/쩲>?򌱟#us:FJ^.'M+msUO2L\|tly_ WÿpM x]6fd"rq>u4/{AU V4m3-<߁鰽BO,`o ixn$ceacTSzv{`Wg g/tZ4fG6R7–lÆsbq#a]f*9d6y6^Han\ZQFiHG,qoݐI?|\vJ5N4kVwT;l9ƚ5& -h,]Zٔ"HŻt"16076NPN聑([F&;;aQNca  XtN0-q ~dk ';Bє8.g5_e6+?n5UݏeI:@Pp+ۚW)Ґ&YtQǚp 5RoP|i#l̺rA]#6÷I3JGBFf x`ʎ:f6TKEDөM,2ѩ26mU1nSuUUG.F袒Gy+TI4Nf. Eʂ 1f_K8RRPeCl ʾ.-MAvaT3e_Dz|[ 2zvBAO.\ѻAkhj\.O3XIVbC;S\,U:nʿSUCZ9qË&4/ϿٵS'd'P6 /rLl$O$B[4U>ɪS5Oh">3t\N363e}?ʙLB0.j1e<ֺׅu<.BG7bT gYLUT5!{OG;>t +S>Vܠ-)fq.#(O9@>Z۪vD/SZEvԸV?cԕsMmsk,t)K42N,ߺd`йC.:KrC:+Uَk`뀸2tUZM:.#r 5_/8de]o}TNzJ ؁}?džpGTh"J} kZ׵=T?)VbgnШzP2+- ҼYUK.Ђ )F꛳ggz*.glOGLXם Z `vY[^2@G+dMy=\?-/~%RR@rO.PnAPT61{&O t~) 4PŽN(>ɃE8&TKrk)I3G2!̸2tQ,uzeFj]Fve4U\h;:N0oe©#dA:6:7plzI$na,A OPʮN2W@LK.B6  $cs ers~5KɷBO7Di k=vo_O6=&4,Z;LoTЦ0U1NqfTkK XmѪx!6v~ 7spF` E]K#sToi`ad_<c$;_MK5Xod߆\W\7٭tNhQ ˝њPI/,d ekSL*ٞt\S4ϭ&?$O BSC9#(ve_uQO=0a222 uKP[_ 4O;l6 y?tpe0h=hP.GU+yp!RULI1wuBgU&\4ceN6&@\guO{JkdS\C \5zdyDE3s}Z㕻\evlE8&Wpo`vT3 uM]jl5\wfhM4*KNez19D ,YFW7Ui(is'R\i)MnWeTZi(a N̲A\9"tr6fnP"{Z}W9O!}g4r_,{&Pt?3j#ne%46wZHtcu,̓GT/6J3@cˏ%Nn,?6/mSioIeh#P+\K&-l͙=S~ȘTDIȄCmmUН?4Ub.. F|Jn6:s?*5'JnTSfR.Ā,8P]lu mL{ cFyǿr`wqKnNN.ˢJ99ŷ*w: 5BWFꮉLr5^gdMb˧D\7*6+$#<H'?[' GOKn|Q^!d~l<nLȦsCâ} >yXJ1/Èลq9~ڏAn'@_!`BM#5ұ]5G:{t@ 0,\FĦ8!X'qߘo$1[O]y<ӚYIA`9!3ᛨI13Kdn8q ^?:G;|*6QdT^O3Sseu{ 90WPTO~g\<6AS+͂46yw>#fe/hI ~3vStzGT 4'TJi왺pQ5͏,"N_ &U`OdomPuLp[n ZNmŗ]&[{7UuO`bβ.¶ya4yJM#uqw\>xu_l'7Q 7U̶maf,:9㔡U;*o0vZ^kg) VriUe(( {A{w? \*bB*)xsH'RI;H'5QJL2n4¸Iu,q`[D9IR8E: .V ;GuvDR6,TS7e1y)ۋvN=(5A5L<7Wq2ii o=|tcO SuRT u#P<ߕ26\*f7S87lQv(sE]< ̲Uq?a;-B #;uIR ( ҵV$cp0iV=ѐ{ aOÈ.zjʝU p&6.3w-sXM3 Zl@.L]?T/ ߼=?f6?!R'[Mq'蝪">prw-Rypg;`0A]4~Mxrc%w*.2bPTee_n8TqYvoM-sM,}dT3ϾRU? O. =\\pfuW>)a17xH4YJjP78r#GCd< UgKO#V#uLv]j |+j?0#e?qbld  <ٴB)sn_P 7R#`uP7*a茯#OD͑FeeP>CPQ3u*7}Mv|+j>0'EQg8ʮ_[Y jlŸ Ga]tH.Ѣ}MPtS0*OeRŹ'c:全f]IØAGuqmuB6'?(  > U?|Tڦ9n^S (0?ڨdks1LGj'pSbsC7QQEIM=U sKWhGɝAk[7B#m9m}nk_9dh.ҧ+S7ar!w@؝oN >FQTK-It'Di!;a2E==QyUq3;dSM~\G@3(c [e,|e (@E#6YT Jd_#P@7 ${9ssG0k0Fꯝʸp<ܐ*w>ac{9dvT073]$*VX㑗'!cCChsk `4pI@<)i]SBrOicZJƻbE}1n n]"F5;@Hk$*Y٦2gnS&.d%|Bl 9N6u{ *HX>H̔ Vnՠ'Tu[rSsp]##ѻVčT^d6th#}C[2CcYo|qY|+]{#`lY9NuYu.#&\Os—c,9X'ulsR16\%m!#(NvCu%FlcPcslA.;qMg*J֦{O*zc{M4gD!PO0khDnAp)-liCLĐo⪒6Lvٙ"УLlp]uKoeY6RF)=g;|.6',*f`Q;|,M hzS#/isjzFeh ᆐx eVfz#uD9Fe}h=&{Xr)-ltq/\VVĮlo4ڞJN7hmgx\bwK& W.(]w&l(f CXpf #)kgx tqN cee9&2Fq mY:3`WIMDj*sK\Zya<CXwDM`BlȣkuTF`~Bn6VxC7q*FFsz,ertY@QNCJq.TۋD~{pvl;|-o;HBG!(ЌÐEUu+Z//)Bi9^[ls|WhNuּ#;h947RFo6QR%Nv\7(^]ݛbLo t&|9SswN * mvȊd F,/~>`\o@ zG<8٤.3333k95^ਗ਼sDw|V'Mn_?/}x#B*|C5(hUE$mlck4]9A>9TӰ|7T>Em{8лP*޿;ou#݀3ET q(|)SSjKW 26l+je\Hgؖ**FIDfi٥V;:eL3]5r5<%qVWtOD|LW+#&ɲG)-/C<3*WݻYF;nM7FVdcŎ!tNTE<Ҹr *5g`(Y?ݤINF~jdFW m)^$S%Dq5aNJ̲yFRGOdG } AIQK2r`wqeT@4?k`ys[==!eajJuKj 5vs5\xQEŒF5Xl`xNHK$#,eM,9n lh捅mI;TT8t$r[M!J19Nk<)͕#"]>'S{A߉RIVBm$&ˊWhVٜZg[([47.Tvr\E :캙%t!7'囂4kZ4ƅ|\ hB0L?kmqM7.!O>.eYpOdf:X*f!7T$!C7UbWF[km_ gҡQ?U46xwM9^/fi8pۯX蟣BmU_9Iz%;dSx@'A;Ȃ7$KlX PUk&ӎdyylˈ,Y~|:7`SGvarNO^fȟSK$9ELҸ5MP-IXODB{sn6_"Dhz((]enΦpaS|Lq4UtB4:7N;>A+x\VœJw ™!{J袎9XFWC/#ifaWyqS4 KsW?er|,>˺srqsB --T9 w-}5\):* og4~j#7adpfO|D凡Ců*+58E*J>T/jdt2nxkc*[f45Eمֿ eo꩞b[֛hᾲ@6(Oe|(Bl /(CoM>E:,Ubk.*fQDb,KMI䜇dTŹtC26_yOc#5(2Kyc:9Zg~G鵳#4'Au /s@ܣF~#MmŢr%Khx\+l5L{7G37Aj6n e{0c!vw~bbIu2&3/͗OEWSxL \.׏Q-,<7qtml-=+N$xCF7+d 6wڞye'eJ ʝS>bJ$= 8U7 Z2<`cӒa;5g0U.|sfۅHسl4|SafW:"CnvT\!"w :h[*kyE3]7tS|2egs>?S1S=M=.{c :eC٩L!'A9nDkˈVBMqw裈A5fr:v4MR彗SMքjbqi愡9ѻ̦86Q1xMՄg8ݥpe裍7(1?q&O>7Bԩ8 F;EC2䤹@5 5)/}BKhP:j_F֍]u,-pʆ6 'gꦊX]uPE#ao@])NkS`ڽ?.*cR2m8oe;ໞno胜3nj"Tc+wD벚Ө5aeI!7\F.$k4}Tp ȓ_*E{cD+̈́P$d{4?,RD؀n/޿׿ULθ,|ϔP\eRuL:mVH!7O`xo,Z.JuǛW O) _x`NRHL({]ζz[0id%pBWM#[{YTe{-S3C BsŖt&! Ҹdx4$rlӺ6jJs*S4u[lAڧ=\qHBbOT(olɽ<9$u\R҅@[+ Ve+)Lܗ0@ƌhI%'ӂ/e#-xafBB#ݲIE;Q24SJi]E'@^Txe,*I*v`Tyr~ jG(3-[ݷsU~2ئןŪ.Si!5xavN 2|eLuRಾ1Ght .$a fkӝŇy;G NL"vry%< VC2d|M0b.aAuO /e)k6(=fl  #<ׁGy&T!0;?i?$Ls+,ST2h#9a4Fg`i T]utMAξ[j]M%SMz{L2quu.LHpEJ$C-ph#]tyrꦤ1ߚ9(c-N+-Qs9Ql![L [*jflӢTX j>#䥋R]i`k3r=MK ~Gq{+_ܷErcuȿY[vkxsMH[Я/"٫F|^J>fG(⌒۟u2tumC̲MRn OU$ϐ5{RSᢶ[zw5g/A35<] X6R)LFYo#݉$.3iC#qWRFY\;gq^4)'eI#c~*Ϸ=j/M|efhg cufR9qBAfiOO3ͪa;5O3 GKX f 3; p H&-TDsTY[9axw\MK -=4q5=)nm},aFycg =Ļ1ܯR߽Z }xF5t ^Q@_ -AuCR d84z`Q'v{I03He' SZ5f6fpӚ i~ʙ)0n ̳8IBlrBqw%Z)S!O#vQюpv)[ᕻ# -Rˍy[ī]ηЮ?u%[MTO'J'?vDKe l~Lv<:g 1x'}ATH+ pkWiDt\! SxB}QdefwUҥWz;DMٺ!%eKa§{*o+3]8  ݑ3H܎ʥ7{M1yTҶ?Q7]*4nsBeM<{z$9[ 3[ꥒ:ff`H8XC\<(F[E{|,mݲ QzLd| Մ[&Ԏi9NG +Ե|~7LcvF 6^n ޜ%h)O)\G6)NE9Yq7r 20Th{7nL`',Tm. m[_k}EFy<-)t"/F必J9l@o[e4YNqD9og{M#Z5!H\54?hiגR(7'uZxlZآ弖̋J5>^AT8he HB~Ҳ \(- BB.s4Mw0lYz"J8yЀ0݆ɵWƸЙ^ܺUwNNxLx&bx5'ygr'| 5B]]Yj}FHGPye-wmf ;[~d!=l#=:nHnmms>ʹ+L4;lmхVUkb s˵:C,mF*>&_-v˭}+y T\u=DN3K~tIT#=e;խsC3JP/,nýUUP75ᙺMw56FE!++ݒ&nIp<D*:X[2tTp6doqT9hvdb|zh呎4 aJ.˪m@Lh!%ײ?YwR?#20;yзYuڧjZ7Xu#멎Y-fnEiOJ9PVʦ 涽IbSI7WuM*FAu 9*)[;/Ϛx\&atJcݓ& 3jѢɭʕ? 9D!+mS*sDT7.q%÷tN!TfRBoEnTp&K>O[Tu,>Y 9![Q +٨Ff au+N[7e)a! ɿ/›P-8K9 b#r/pLWV16P ic)OoǨ9MeWS<6yi9-WZsQ /BFܖg :#>uӒXcow/ , tf[0͠PEK戇U;&J5B7J.S{J;xDg>6CdQ0;1e̘LOiLշR摩9ڠ|Ȳ u|1z) jP,#cAF *+IU%RH6t*OTֲ8j/裄r7LuOlx2 )|2F;%Sw]]]0waNDk!7FE?hƩ$.CU,ɳPΫ3g3Gh,P)ddܞQ*橜EmKXW*姐QŸ {a3wAN~QA\c̃k{]fgTel'T㝎JjJэK-֮).A6hY Qи89h*|W+ouQ7ߖinvZ~|=ՊoY s^hwMΥY_T_qsui&ftoUVC)6U-4P TTA T}[>8*M:)a|t^<]gNvm|M:"-lngk|9d\p@69"B8q3ik[PS?+=qY՟l1=< nN!rf*PLVMa&ڕ,iN)MQ'e,Fjx##|=ïrkEN^pәuy-N^|X~[Vo z5捹aP m+.L-ub5WGǫ } AGWO';{ئ{[3yYpe;4 !Y.\UAjO &t-HrL 0fY̓$S*[.,nc;96!#ԔeCm{J"#Jehp٥ӌR#q_8fW5vS=DtB~$%bL9|Dm j xUKgnU[nJ^*EBez H[8sVcBeܫEUdZZhBrYpsV5WC]0-? "ײU&7[,ěu놪/#{E^s)I"-Lsge\x?EQDeq /+(9ۯTerVbB'+9 $OLu4Ou%,R<>:*8]9de;/#̏ 8 :JܰeGzwZen,U(xMn&zh@0m[W[a5quV‰jZײ^NK}Z(m]`.Qxprl'N'5i$տdf'dCGNbkBIP,Mg2Ux?FўSAR0M3~g-9:+Y]?DS>zc}s{Z-GM# Yo+4a酂+UfC}Unkm񲽗W'EeW6m׷psa^ʳP%e8y 6ni+Ê7C zhF&JHSX^\BYV# ,0)S5[t[667` '<*thQl$m8!(:m:*x~cTЗGuhF~o̟y6ٮPSC>TӚ78=cVJYrBwZ@[^1ȫEnl[WZ~s} -=hvǚ [j^%!_t@joV^ wXw |.r +ouaGBl6orp ^BݾuܰˆbU/uc{jBG۳ au~wZ*T:E2nr^35<~(㍼XƚA 2HES ()\|B6,=k;$E likc*.6?G eŷ*qN7~Hr^Eeræq: mm6W䬽k 2WV 0 n-# y/tmPZaպy-WCtXhu ~b?t?.꣦ Gj=OD;B[ZK[og xܙqthY7fk\焑G(ԌYQ6'4rh9$K T(',ߟ$GfrmrWum/B_wh[p$:ln/}Q,u+L4W;+"yr򵷢j7^}׫V+ VՊZY\[e\ ~H=p 򭗨Yo[j+[rV{WW/c~]q<[r.\&7|xpFZ—Ip¢ˤ4V7@hAUP 9&T@rFwsL2-@V Z(վF'I#bfwt/!].4 m44MD6o\9ꍭuԭ7x-,׹|w V[u~ʺ{, `}uu^e{+V([usko۬ǖ;a|,[-\/kZl\,8Lu 2(EN#&b3 A fP%8)+Yķ \$: ,,򹩝ڏhZOwMdt%TT~K~9+Fܖo^]7՛Pnh@ꯍW}qZ[tl!D~Уn]3jeqe- ?erdG6LNm%FvB &5)Ӿ9IXTu~G<#fs۔GEn\!GMSHp¶6i'Dђ1~AUTVF 1dE*@jQ#`rm{ڄLy+4V;e emWȀ~ﺲ%Keeo߾*7P^+|rBz:G_\X*9KK+NFR+]ec+xNɨMpdp;@yEbnVuE1 R&,*|m=:muZsEl@]oZ+ JD[dmH{=E~+eu~_ aeef. #>Zankݱ玪eZ-py^a\#]_Tuh,ry͐OAQ33sVR5ipݚ*8Lm%ʲ) auV-;-JվWZY6Zlsill^m۹e`_Fh:셻퇺knfF:|E4y(SSI!d~AdtS4eUC<)#\P 23V[ wn@6mJxmeop֟N~pۗw\k:/eeluwen]e*8wZa lF;+7V|P]IG IT,g93~]viϻm/P 5+smemׇl$ ܂ V]{ۻku7$B;-[ou& ^m+#nң ||E椑;1e:w6Wmzl6kVr[ ZѢ6xe潰_۸du[+ խ6Z/o*6+n{m0jDa~,tǕ޽[:um.Ẳrĭe{Y\`M^xVL7nejՖc ++V=.֝V덺wՐ^rNil7VZQ.׷mޱW@_utV[aiZŬ۽3czukw.Vz;wnUve;L4uk`^l-l-nypl-uult@Ur;[!:۸0.ܷzese]jVQm<uk+n[ nWmt[ }@uEZZ+w/Ց=ou 5_rx-U|@捻7{oĜ4[/uWߪnYۺ[o_ -16WD 8~tEհ(Ym^+-l-̀:mtu[asuoa };w_++m_Ֆ]]nWVe~{c쬎ܾۃ=Wi6#N[~6_ku~n[~ub{6V["I_~4{|/[uev>=-ՐVWܵ[ w-;\` #|N!` l,w?BBZd;[+-q"m߷zVwnnm۽t譅Lm[ ulF[wetB[} wV}anL"VdmemUu -[ܽ[Y][ o޾nD'~zFul/low*{{w8iˢU]lG-߾~尿Զ `Q8d{U- :woO|b@c~^e|-/ܷ@w43V~[o|oܶ m8۫ЭdѾ v-oUԲ][N-^W\Gҿ'!1A Qaq0@`Pp !J??7]i]cيsOKJ0JXkZd*¯\;Cfsq iQ_cJGPo*&8/4?dIFۡ}+-2wYtlyic(#QLhG+" Hr! TIlg['Qys]x4f-DM|jTi:iWt/oefw Ul۬m;[>S^V ;3G# zLM*JO~0pmIZJS %+ɬ0c5P pwk zI|#X_B0IL< WBA!Tu3O"oViǎ$)be aeĒ'i}6h-TJLP7pԖlx_1Zn^CKfjy$ќӋp#Q4/>@Z;_`a4 c-{7bdgR ^Qm3$tҒBS4XVg "|mm(l pgL3@%0VZIv1T@*(U4E>e=F#؍6X[ĖƉ6rӤ1VH;F|ChOH֫t(ifL J 8 o%SD #=0ݓ mM $ SSɱV*h +5JCtˊ2 @IH\HjM:Z䧥TBF4OD4i \ѻ2Cla1)gkP#x~hCxaT` 2үk"z2eW-P܀Q\"t;A>}>߄G@ZMZgZXNj$VKlj\uEP &UˋPLQvw)b":l3lxiu B|ffV/fcSPjĩDU( u+ MNfQMp {_]t04T*@Nu-. =,<_bO|KGzS\,$ύ%p'FZe 5_T -FwLD:cK)j׭E 9%as06? 2񔙩i^4*>B5(p>{B N5hDlcSgF;g} *_.Itb?ZberӡoZ՛kѷePeXI#n6(s*wgIq{T9XDŽ50/46وC؆fM6NcQBcՄ[c0FcQBMI}):X6}fG)_E_LGI񧇟fPm qJT15(p G"e!*rFNm$n!0Y:QQn;Ls ݢZ.\ߕMK(Xo-nȒdSGk㻛2$l!ݳ4L:bqQ"q2 a6%Par!I`h ?˯~dB_O!}ң+ Z4MtS^Q!E>Ö 5H4) ]GRNOCȯ@HdJğ}e/КE`U BBM{ }B%V~}E$?ve =o$}U_iKxb`uR>lrS~8Hb˃ǢQ!~l }B. ٵɴ%hh !# JiG2@Ae8_gN@O$л4g0r}*"+m#MG|6 ET EP 5dn|D@HalDkOecM;R/c軙5WiAILiDlr:iXQt\"BvJ[L3=>쬑!4]CxYyBO9¼eP*Mz\ r9BV9a=`kJ-9֤iʏK +5L<(6jSDC6?S AmЀ9'7N95AMCճm,X>eʎ` j{Af*6Bk+`9[a\(jH=\WFەsn„:M es3ԤWUbOmOb=`LRbe 蝂*;#2żq.q*XcHl1lnZ,HoMqCr; p R(=A 4Fkȣ 1K] pd'⏄OȩA-Yc1@BMUPe! Hט/0.% kū %*LdV(9B:5&HDe`8B:7Qih &a 92\tv!<"*;sWFI&"JunID)v7Z&@>| p&i3 tjV bR8q}w E# @`i 2FD#v0MG)Fb ]5c_+&h J97^s|G6DDF=ggF&4싸oαTu„&4U`d!hmQ pL6ьC}T94i_):+kN5+qHѢ.V.UZ2 .^~$$~j62FCRrp - ,=>' pI|TH*c$gBDT]Xϫ?\- f|c ziJV%RpaZSݦh[|lH紵Uț`@zFJ`$pT5x=%5F-kMۓEWڄ{V )w2cێx/LR++aX(f pJ":B3±4і NC 6شݶؤL unX"BDaHr&dw[m=c4ZWk*2׍ "=.{1261`zoF']Bgn(`ejCW;Q^S-^ؖm"+bmq-#3LRl^Fu*USDϏl -~fyUU%eX5(j LYI LlDpx3zlsZfeO1hi ?.6l6ii= ȹu BD1`cF@Y}T) I"Pm !{c.> R U Ѝʱ@L=_!Κ-L! ޛH,Eƀd< ЈӜ爍i Ȋ !#lDpeЦ-:%r &SHOalES?Bitŵy' I|<$4 MGBcF^&5qT MǶk^i} JW@Yy n$zTR b-=Z"fdtJp5*6[E`6}P#]#ͷ#^` U|G32r=Lg14 Ո8>iP1CКpI|z4oWjȪ?V Bs 42FCbػm=[/kD􅋸r%k)$qIE!Μh~98g$B4\ܭdADQ&h}6pXRE3d6CTN xW*snQJoJ6o{75nb/FcKUtL }ނGs:{b" =|Or3M\>C$|ЃXhtE(k(Qƶ%jCXb.J'"6jڕl|.)64B6 n#'ǡu-3=QHA0-؛AS#Vh fvI[ NEEMm{𬴉Pb0 >F6UaH{:7Dᓡ+ H(5x?ҫOs1KHwu>]Xx4FՀafL`MOF8Ƒ14LFϬأ9R=KV1@FͰp;AbcE@A<a6YVC+IL{ s7550o4bJЮce'#bi1M|J1vFQ3uRµG8Dt]aZMz&mFq 75}wQgz RCfh57ۢz UC#đp>-H&a棯&\BtmF4ĝIh}DkU$8qpYōl3 [Pq΋Ѩ IE6iaX"4+lP'+B!~! 6ˣ&C|gB-GqOq)$|5t4N{}S=qlaP'!.޿HzYw&7d ~fU\ XBqYK{x7bfUQj bȑPB텃 }/KHSTr:-&v=1GuF#\ 8?MZl&Vۍ=D z' h҉9>"Ѧ-ۈLV (hM>|S|dGXk]Q a;5s#Q2?A(^Q^Lxt RlTZ bca i^pCl7Q"ؗl`Jw cH& ׅڛ[Bs6^HTڤh!&M*'SC{1&1pHNlK)zi,@h.(Ir`LW#[Q0HOhרL%»Xb4. Bh *9L:ka#Yףwg\JtK6 ٤/[_n Q]DACm>ѱڇI>P͕ L."; Mc.k ҕꍵJ6ÆvwM=s}pM-9Ĵ O&9ua&eq?THjzZ-97b(⤽6-)|P."mJ"NgYƬqlAuPI{*:^3|cRI4;q%6=䆄3ב[(qŵN퉤+5;SIFVvQA>!J MTsQ8*QMVmstcz"U8З=N I 9Peb6O7J)mp1@!HR-##i m%m |4DnjsSTn:V iIf8p1¬j=}+Hm%WlhNcCU:].FscfDjNTHiOa 鑾۬=A#QSɦ~T:wG^Y|Ds6-4CCvhZ%WP=l$ X1:p*FbO~6s&\C-!ZBlQJm-MDRP#J W)1&ŅD%9)i鷨J$lߣfSERP+EL;J\/,Z{֍.  X~B+d(F?5C\4m :"t06ش7$Zcfܔ36 |6Y(F5~ѿtw oDev x #kmHn`Ij[8/. !-Ÿ_@(@ i &#썱 9C^#iӾz8!V&7Z3deGˤ5Z6]+Bil~^MP46({Ƣt}ita3*4lhGCe56R= .8xkqؿ9hYH6: ?XRކ%.)/MC^2`$8;(_iiJl;px~cw3D?Y-cSefz49h 6(Hn67!h m8ܯ*=IQ_2&VhlЩtT7;n押(Hä, EzfqI#ѯVaYOZ`B6xm 7?oeF ;=%oF%'&9`ہ"+YsoCzFcj 5DfBNp(Im MKGTVCiX[h#mFݘR)M'"i7vqlSe!ĢfGn#CCoHEi ocXEh?EO✬EL'оN{1hu~$oՌ` Z%tNmlnSWGtLG|h^= ѡP16w]x:kjm ؿD>!+ %ލt:ݍZtDrJօ^c"D 8ڄJ4]f9A\D3hxhoz&=pƍCF!v+ES -lt8vIёM2߬lYtE?F8mѸJ 8(eu#[5zLzpӣwCPzѨCw8\8FʍB +\4| BoN iX%8huq5ѿJ(LLBz$Cp`-$7EN Q;F;Ch= 4#5Lnhn"oX!DoQx94ln 5~$xB6HBiGp-$!h?^ZxN5͊-i]JKAR ?~8J΍:2̈́ #m #|(T'E~[!Ba~t`j?b_s~DZitm?Aǰ!@߉ <6oCJ6Z7[0,p/BNŷ藥1*W3 Gp NKa_2iBa'FE|Úg-9EbIzO%88\W g87HLZ/6/JN 'ΔNpbb FD7skґ !`kbݜwc!]xc_V$֍AXCCPBl[gG,)axH0t OG<!bt=O27p;h^XQZ=ѝz3!=kC!"MbG5}/LBJWlI}Ci6O }zaYױ?CI Dp1-a[؞b%Gc3qh ::db OgPE«BtSOFʍ Ml?5 I= 6_X??sM4tfbmpQUe?/^TbIcG beR*W}CpC๏q6-#BKW56s20fHئ6(mBahA47+]1Z AݙQ R/I8oJJ,;ØQhb-O.?bZBTM4=Z@DlqOBJžeEV}~>a;Ɏΐa-I@="}2Zã]>H(PMhiyVHNץ煤EаN cѶ+XPy"+DY2e^ ='E\TLF1zJ7  ShZ6 CBܚHGFȹhL( :F{ŦǞ=)?>p`cb8FFce!Mv8tfjsr|umIzYFƽo:f'͛ &-Ƹ=pᶄpjc kB}7p/M"pœ| ;FƢAʂIs-hCeHwe# 54FR5Ο3E?ߘIҥ0OF ѶT|dMaNOb "' pD2>#U2P>[_+ ѷ44=")1qѥ ѷHVH(#%齅zbVR %#Ež7|+-&1a$קDZ DeHsUXJC..Ua)¡ABcWH8 gld0kZXMElc醰Ь8+͵=?*!&\3mWOQR8tTZ*TaO~IHEojm24(H.E(=hMlB#a1A68w M.W_cYEtCk  G2SƑ[Ջش~ GGdNptxS/+[Hmwe A*&B(CNфk |V[he!k찷b BQ̡tjCh)Ѣhž'=0Rp |4uDzLLb:Ip>PbocpM C ӘM4'44D'4=|5Xth(:Lk[^ B a؜b ž?Lkܣ:s,-R] gÞ zɄ6R5Lx$sFJRk(eT6p -bxma(8(6EΛh 9 8F&lnPV\ 7OOIE0=ML}d&wX6 wbPqܼ(=RKƅ#N !/Tx 4(:L MaOG!$6 GxIӣ VLO#]OScdlA+Q*1 K 8\I'J"b|aϊe" }pQC(8&<(;"Q2oD!Fʆc~ 5 tap/ /F$J ac1.!1AQa q0@`Pp ?!>I!+&mdMKG [G6RY%c_9V?C<=xn&/#J6qїGtI[%bk)}D-`G؜\k# rM}7FcЍ./'ޱ'5fGoGhCtFһ}`n?4@utkʊhteku~}Q9q>~ӏLɎAvl ]\~R-0kyq^8!;OU$Ej8KqfB4 r.HYz-dv?S+!b6W&c}Q Mx{SQk+wFK9K";Zp?aB#|>)rzӓDpaL#m^=%;Nb)<.v .)tW|j;ط,4ԇ_j TJybj^ L83Gڎǣ=Eݭ/Qw1ؾЎ-t=zޖu_EIJB{eDBWʮWfz{z.Tb/7Cz_EqEN_FKb&ɶ;7S%ZƣXژt(+I=} krjjc,rHzĞ|n(se?qSVv}+Zn[B#!p.sK&(ypy#|l&SW,⎉—pE~p_F+bzL,#1W/AjnN l}_2huOFwL TV2.Y CKI$1s4Y1E쥺}I!gI&,zz*,H!c7;Zd+ն.q`]3DRqK|q+(جwoDCRgtv'tc qzHCx@gt·o1_EbFp^ i"xlV+7;)*K/W *Av2c(Sm>*͔526wl;^KXjaF_k=Sc]9j˯z5}:d"]:cSr6V^Lu.fFԴPհw2'lO)}g&pg+ ,pfi)E?]5,>z3nO9qkw3i.W 'Z6[ix.Eȟzcś RvXM2% 5ݦЋTnDo-Q89[,!J)t\]^rҕr!\R}FF-ND%X}5uMT xfG[$q,"88T6"şKw#j$= cM.m";icmf ǒǃV`E< 7~'T}|#{؂qD>k)؆*iIt7"Z[Xgރ#f!e&(Yd+ c(\g&dOCi/z% wڹߺtXE#e$ĎHr7q.'t|tA{-6Qޘ6D ȶR Sqjˏ#J5f]Rk5dLj4ژ"I; S|ZDQ[\/k􄆸ٌ4WUi,zF̓(z~kBz;TB+&3kU-X,5>DOH1Hi'֦ͩBdv@b0U'r"ΉC*&\.yRzx#[R*')rq(0nj%a*2ro,ո6ոxG&Qm/C+[!>d) ҄LMg]O+U @k }I'k1e4_qJM9'.Cgڞ&.%3HY]6=5-R\##C5ed*z 䆡ܱ`n=IZ/̸R*X'tMU :>[;_enfzAT"PJ3]j'ք'O4sРˏaC| n.7}6F]8~xgMoHc]źcGgMo>K=EEʹeM< }<Qf V,N‹xLG+MI71Ba %.wz)̌FQG>ɞRMJS1'"%0ӕ:S!KRwl!Iv+ ̈́%_'Mкl^[EjP"#uFY_Cl_+f6C6[?o$Y-k5Wi l^\dlT4aΎ̛, m腘Eڽ=I//$Ddz5||rWD YqN_ki:*NL F6R M ,:-JUSO`WBN})'HGe JhZ??17Vc<57vX~D[9;"3:cN.@MVcs~ 6&&﹡eo4P-v"JycJx=heNМ͎O#nBnAl_9Q9HFÐth 8B/2# (ȅF9O`L;[z+΢-fЧ+{t ER>M7럭*k+JC"pcpii _,&`/qv6&ۉUݒ=Jk } ӫTm@"Dh4^bq|R`n5$c.I)4'< mP:G-!RJ*ZZDոJbbRe4*`{z#NCpwzl(WOg।ڍxK>47&*OB-#yo/Ix(fm=2m%eF!MC/GikKΩM89S+zwX5,O܌_y▤ж)DgG/qR&&9ޏ5Y' CrEnO' U[imbe!?1ru;#з,ROFq Y%.l$wTp%tgSip%KfBDhmK&dĥ?s}+F\v]a"/] ytKiHC8Rt|+ AmoeXa;㰃MEgNȚ<%{tDM8 TG~σR8=Q"Jad~Y{ޒNL!M(b(9`Ax!\za.ǥY.bm"qu{tʸ={:WZ=қl&XIz% EM L&ɸG 1H[ r[f Âz$-'8o5Kλ%نBn]bz}K`&1Q"K`Av!)؊OCq2~TKĘBP5w}qK-\:| mxȒ.HtވTh}b= _mr9}6ۗfB&`!>bex&$/V42XQG6/!÷n ؏HU}ܻ%5w5 ġOq K5촪HcD'4VͯrS+ޭ݋EߨO,0nr' %\)zw2wgcH}䁋P)ɍ_R<K!r0^xj1GK΋(J U|A {!Աq$n7n2B(^\"5̐I]NS!fOaxT7(&Ņ tMYҰ3qe/7$p nj| Չ͒506~NZ_dD bh[uܝ}#C 2[fcN/iܐSo"n/'L-К]ƃKηW^ tlZ ckr婫jkIܓAbT~ӧ+KL$ML@ç/SJ_vOdDYrgL6掅i RBqb#l3RZ%%!'7D;VQ?At']d&F!QTG ˋ/rSHe7O܅{!aSО߃#|+\$?ޑDHz]ר@ĝñINr6ɕM=`K>MDBQr'&t)mÅ{3DO#;;OmM5N8B#.F;FHC#~'-l7(}]G6>dTSO$uIw'\4Ň1!LH{%G&ib~Fّ.q5 dsdShf!vwwx dž&)\5!8؅kS߱'cory֜~ȝ!z:X\f `R.RO-k6'q: ZH(-e2Lxړ. t#/~/T1{ C_Dnl6 gd{}ȇU9KPYH&58:4U;U.zfF~T ؖ dk)I$|8dl#ޛ-WFw/Yml/NԓR:$;89%wNN ]55YpmgĵuXz ^D?J"(BX [y*KUFNsNlo["bX$[Ȼ4{Aw/UF8>/jBu.~wkO߹;1?Oa]+[ۭ6kq _C#DaW -.FOW$6r4%g9!ӣ08ɺ0܁ yBُth' smGc0*5b腾PxԱA.5Ğbj%l=|Jf$Tg;61?Bh]o?AOMuuv~8DPG9|-q#OG ]б✜ȇJrFqZ_qRl4C߱o_"?8jn1saV?G1CN0&I?O辦.-z_wnZ;PƓ˴ Dm˅Eʢti;HXz8#} } WvAbH'z2 [Ga¿ҍsD4T`OnD럡yXry âAb"t d6ðмޏanƇ$hGatHkN);/;:ʼn~SD*V} T#qZ$ϿYC55=OT:/K<6XnsnF,r*[vG?9u]!@#6:NԕF; v[ iILq_tM-OC#BczKH+ҶjR;]zIQȻHtH:#*|rO.c ;Aߧ'F}.4>+™;Far:Ǔc <5EvjjR$G:malzrq}]QT\j<6mӶD*3?4%HR:~wbboHZj1UQ1:F'@n9T_sdn?'ŏTSr Ov NYd&n d CVw6܁kސ} :Ip&pR+ ؝QTNoH<9Gz51p)؊'F>'qTzt^1e(`j;8+ ,df.%=E#^ĎB0YG"$-ˏ^ŎG*N>:dUnD2caw; [Dj1n I6^GߢHnÁ|l/%ȝ%b\+"4H$KrYVKt6&ɬO[ꎆ%; ȤFZ;?:>PMѫ8"HIzVf ܇"AUwD Q$>:'i:2:[&oTh\iH j>K:*1UեXU\m_GcI{.C΢7dc#A:pA=B8D莇^R~z"tL ڏ>:PqF.ڰ#} sЅXtt}MZꞵ6<ȏJt]y}tM~>Һ"K..E YORߥ4zgkAQ>E]PGKD#AJz TiOI bI+TG]1IۭZ&L7;tG~Iޮ>}}ы/dHTBz#1>>~>us՚OЏGgB#d~C YO?i?K"!1 A0Qaq@P >ų3do }9=͇f<ϙ>|C{? >/y'뗾d~?χW"f^{?ώo^q|O#y'ϾG'F}ܼy=_[p`A>y'Y:π{fpt<㯆}=Lg_?_pϘi{uy?t_w s 7ϟr9'8,/sݿ8 Ys~OSW.s>ߎ'{Ov|7~/>kuc>ϗN /"zxo?yc$wϷg>>uǝp]mcSoEI\q=8ar߻<O|w{y~>޷YŸVxp_,~3g2޲%~^>x ?5Ϩ>..{Ǘx/>o3߄[s۰kז&oۮNs0y-qs%/&"zmί8η6^[{윟?rs?`?W9=w/8߾:?|ym3埾}sܻeXyl`_Ϸ>_~^_g{'>gyݿ|ݼw{~ݎq ?> >{Ͻ ?#ۿx2o{w$^9:{?l9>G\<~|{zώo~S_R^|>Z}]r|y+&|_xl׿n?m/߆q gr'O<|N7/;뇯?gO}_'roCY{Ϸ'Q=~|/K9ٳ'~χ{Ͽ-GԽ|7矋8xߖ~~_\?8;^?-I~'gy-^yvN~?<{:|7|~x e.y{luǞ[㿘[{~g_uÃ6m6ߩͽ/9?eqvu -՜o6s /ς}~[gӏ}p{Ǽ\_?(,C_w~99,W{痽w'Ox,?'s7g%yo|!xW/8z{Ⱦ~^C_~)my'?>MGS>u{~>[oÿñuտߙO]sYs^?w~ #/-x~]ȷpřԟ|3N\ż/y9߮]Yx9~ 7fdyǜ/6? 2SՊf ٰ)f嗖N:9gxxߖɹn#IɄ(:+!% x)>^>[yg/ Ǐ8_ WjɄ`Sy"o\ydaǟ?xy_OxAH)chUG4N;x:d?Xb}rO''' ?L-ф Ql M:Et'gl&& gmߗ{|^] !uR'{6]i%/9gp]5LL40o}KG;vK5N| s~'aF#v6v9V6toc>[ g s/Yu&WJc#ID q g-'!j1/.xXs{Y>C;?h;$e/ic䕧 t-9P6 Ile?/;~gȳ[>:U}"E)}:ňapy&2DI8Ż^q@i1` Z#5AVR`w#na))$,yr,88N?~LgggşXGh@@c%\fs G^ŗ)ӿ a_s?V~8ͳ62r3lqg)?`h ,{Vcb%x~"BjWLd5PY1dd@G˖Y'g9sqg9Y2o0_RL?ayΖE,E'S (1F, ?Xe⟮=e?-qϙ&1$Ҙpe'.ԮEeĮQ$8j΋?duAe~&9fo/>o>6637ye d6Yqodz'&+ϪS0uyhP[I;4ha'+،7L?dס*&JZFDa16V4g+ ,fD9 埫ދ8Ì>sl38ĝlΙYfŐEɮ9_o[,R9s%[/02z_P,ÿMZBfsG\8!sN8"g_J/ }.g:;}oo,xO݂q,iǐav߫\dY!g$؏Gl\5ЛxY4\+%=3y Rp!MqĂɒU AX5@"tnRyDlp/x7}adoYf /8 \ cf_x:^埫#}MϹ<^ugݖAy%S}8,/0ݤ/%y2Kr[k<|tl1 8i .y8bELd DtVtA&KH9Y3GwMYV; 돾m} p#ˠ GIK'}['kuf=Af˽Z YXx mWL2F-h5XhK-?SAfE)XݐG-#7V堆2G]웙}`Ju8trŨ:Na݃PeX^ہ x; o'E C8^2:dNԱeH@z!WS@>xwCm Lsè4պylYqg"|Оo{m<38տWav;#.hǝ !&;.29Y mx޾ժ &6w*[d5KV[+4(6@UOa:yo,.zJ>~& `F]ug{NaŇ ym_ۡ߆[̵lpdϽٶ}qjƿ&#,m_s/~xnCǾJ<= :u`wxo_hcs*h,a6qbɛnI@ͲPLpl]xӌ޽YV\ Zxz [n۽cǜnC˯pK ZA~qnjsb|F޻l7p}Arn C] pp0,(m:;Ե{vdemKvJe!S,l[ǽIqvöŜ ytm 6ߒO8ݼ{'*fD7I^Œx%u>8A@o&I6#;X+a'sOmz8Y6C!:B s$A[xm>][~z0,H~m mɒOV%_yOϗK=Iw.Hg1\x0RĜ0} RD(P |62LF@giZ1W p6.P;?WJ̰p2cg385uk¿W\ຳ~yߍ2~ }ɖvYz1L 9wMdN#}3grl)l/3kuZHe) F7vɎ ?l ϐY<&``~9dxsx;t/lHF$ù2id}[1ZH}[MݛɥEg]qA 5aa(X&>Τ[Ԃbׂѐ! zobw| o "Wamk!~E.Y㿗sضY_~?_p`MXGpY![D!p;1:12# #v Ne`0$|;EF t, Ǭ0}- q/0{pZ!7\b9gkXZ:8πNL*㇡nlϼ'Om 8|3t@Y> 叧@cA(Zl*=m6uShsA~R&1TR 1gx6=8:t Mʄ+_aLt,Ơ@0bB|"B IYj |Xk[1@Xiw^2D:n(ĕX3^!pvZ{4:'{#ounwnNxCuw~>_ͳ4M+LySvQ` )=jCbm2Y+l{_aGӥFXn1JBf[0GitOͱT Q8;ME4h|%{6,7Nj(K `  X ܛ/Ctr["ɗ jS9oRt\6#Pl`[$@: Kv.Y~={/8 ]<$IDؘBek+[6Kwα6d"ov"bFl$h ڐϢt nJIcmK!t/$!c̮4IzǢt#ay1^~QE`u0j BF NZqVj01hF!lHYpQՠX *^~Jwϩ Qcl)aޯ=y ^9ߧ~Џ-dbJaLD<{RY($Njp;O=XXD gwK+S,P <Kvg NɎB κF|V >"jE LGdLF鉶hGL'R%3Q-s͂m:uN\L&/ÂĻܜ΋1ޣP'Hv<8;B4Yx+o-DVy@̓ydmaEᅷw,8No.%bfd -Дť\2{vf݌3D0Ԁkhpvr1ڤl A mޟѰG<CƐm܁~p-!߲tuay9?J7s~?W^L싏/x_ ]Pɾbj O.]sOM<g`0N \/]xOFKm !p9Aъ  +s)2+F2% PfpZ&\ǂtx萚Mɢ @Aߢ#\g}<;m0prHkʰo4-NaOXԨ-b&.z&ngD= 7.K!A䀬k}cPhڊ z:K|GIMJi+Z;Qg^v`F Mk4ptM饽s:\n-'pyBEğlYM @Dn&3TIYC5ƯUCrRw0Ø]rlgW>k/~Dޗ%[nx (i<|дR&< 3Գ(2K*V9k S6BZd3@4,9Jt| (*DQD%ubZJ0=qCXMsҫ] #. Ś̕qS!h7}Qvj~_35nۆ 8?V[NqA G|K*"wbsn:x)r7km CL Y >ցqK'w)΅2rV'2L4+hDPqm$5P͜[ 첅Ιx<gDUwl6)UpHN 1U!$CϢO{ :v(aUӽ Xyw!Q:A!-NZrm,-Z拈>Ζcx#>L;֎v'~u4&xcAO]F3\*c8N؍v'~[đ龙AwF6/kݢ9̰Aȵj. HN)S:4M8Vpw!exyv3@`uCjLm've,2?i03uؕzMobu];Rbw8߂GſsP<$<()y$EZߛauawpVioA #/Fy4+@7Xh-F"Q'i/.wv.}yP\7D aqB\8>9)NolAw@io$F;Jrѡ6Jtw!﹚z-%k1]َKqivy`eN` s)ÙbfT6TAĪ`YPN2r!E0xJ*bM>) sJ rCn⺼g^# # 0ͬ7\zJ9Q[.J`%o,b$ Z9*dx/O3x&vX,`C 3mY\p:QǨSӉЉ=5xmgX%A WQ^rp;K D`*uIER#FX Bp9} Ҁ{tֹ"9$PfLnrJ\c֭7"R&2wL=< ;b/ tAqo Й vk=nBYfLAY^W5 DˢYU3:YCpuki^ӌ G#\}oma>H`(֣6VAh1DKJ JԆK&!\ ۻ+>.vp٭SNkᗙDˌPEnCXa@py}b90. %Z,J&%^Lҷ;u?}lBqHa PZҍЀcg4K$7@kfvYVOR] 𐠠$61^>*"Bk193LƇ(5NsK,ATy QHf:ec $M͍T!p3FSP- /!K!'1ZMiSl=ŋ6Z#ݐFutesPL,z;7y5 ڞnȟ ?쌔! ^Ps8hdɤ}> \v:AgrڶSUzM4$J(\ sA3@a 7쌓*5lZ,i ʀR8uƚ7F;7j0=8R"Y3Gσ\؛i&^ C"e X(:hJf7-V#zuuc`HʠD  Mo4tw#km1FpJ"턆rQ7歆-p訾pd^ _rn? zEQnQb$7NM "MRV;({Kw|) KhH0t =I.+a9[+ 8\DąQ `}yF*,X:H$k`,;8 /0Otо7V|QAP̠84h)xa%D*5 nI W~aI! ~f`d2]]@p|FppTRHlNT>ҞW^ ./[bE$R cQj ٧dZE';2q0 Xyث70J`e8 QV'RMWiBD D&Kol>W3tx㢦z6@.x P;gh3(%Tokq°w#cp;"eO\6xnar@-O 8APHvN#3)36!kTR(e෾: ]$e20,} oF= ]eJtR Ty 4)yfoC⾖Y閟p}%9~6 eS) xoK&&:[C%4ިI !<%xxU+84`X3*Pu]``HJYP P)#*)n:Q`>ɽС&Bs#B< үxq#L =z ZQ1|}-4b <&<Z5*CM6K%h&*Q8ᛘ'MoPjmv/8 j|k4}:FI뿝{ـ\kީؕjsal.x@Bz74KJ2N!܅픵bkun @ uAV 4!LK°GJ:@($Dfl Jf=PH|L!'[(Aƈ\FtUe$!hUϩ OeVE|PIS9-ֲd0*N4[0jï:᎗D#<luoĔw$,Vϗ1]GFWIgI"X"v$'-oq"MDwffW c;wY TR")Kshdkۀp렁h0 S!:89(rUf 0$M>6' 0مvh%2jd`@!Dc@U]j[1_#2l^XG '؅htҺ!Kܡ(S Oh+fzN Csls bjn""̍k2GQ68;5v$@/$s3W SN3-wLt,UDtq>T*0V3M/FP,ŶIOI֥b0a!ZdY C^:.&)ځP<\$M.́JaSL5,$xhHwL#4X L*m0ك k"&Z bH,3Tb}—ԅ3yT-ےl)aP}ũxkaU!]5";8`Jc3dE 1o2@1ݼF!E~;90%(lv,;32F2clt P.v-GyJl0iF]aS,OQL؆f }9#L8c!{e;=Zt5hTY%.'&]4Mig_lYXk/OhdN p1hSYA!YYz@A5CJœ NJBg :F.(y<4 14;C(K64bQa :[d6F8 (j  X Xh:2`l랾ɘ`Y!'gePEbG `(4J(&e"'buQϲ]]6sg%gr[AQCLwݜfRjtauv$$g w0 j9hRf5g027:ocSL}H:?c) @zEG9D`lb7q.%~/f h`VyJESW "lz'iq2] k@OwvC`) vLߴu7o 2,M><͡,G20H!g- m''+} :ݔ`z3; S-עp ~ژB*[Or]g:tvB]V렼Nkq֮aó- М#v)M`)L0WMf^Bj@P@ GbhN^wqg4ĝP.a{^zd4:@0i1$2iو@vGEt ga~g* v:vd1FD],RAF9=$:~7z]䲇ȇz,ݳIYh.om- v^#4asG=iяlmPv֍4u.i3o=v]/5(,up:t7PE !};ղ6$1Ӟ C|Aя/lCރ6 r$NaE`Y/gi|v){=,Cf^7d#I:3HR-0m2L]v1%왭֙7E]S::Mٕ46eՠ]zB =4tZ`ve;Bzz-`0 C@.i'KZ %ѵt׮[ۆ]q 8>7c ce3ig^[,(;uQY Q%Fib1tjW Ɲ]h&EѐiadJwˬ۹ѻ~zD"X6 gAɮ׫cOgNoYhԩV X]F'MaK4=ºАcoXۃ=kvҨo!zЛBI k^-_7рh*0TMۖ):[ {#B`Nmu#HL ],8 Y]۶^nE#Xs z.Hz꺔 vz!eelBe' 7}ӴUNXcngeؚ J]-^Rf(轩Мrz㦲9aúF]˴P$$#7zՑ^.]ξ^{utlP#" 4Z4ذ3` Lt.B 5F'iX>u8=Sa7bbaǂ4A5^jko1FAԌXdžԴV.M, @xxiA) mK^-uLk ok׵]O@Ц~-V WK#=Qbf %.j%&#!A4PدFbEbv@ ۾A=4`?i}ZHЧ@zۢrPe3z#mMȒI-l-FkKDpufqaR# 76l ݓ n8hA e l;6\ݖxj3W " tJgWٜфt1XCXɖ*WkNL|̱v1 VIGѝz@zz!6(CwI1{~ܩhn@' ^ڛ{"&dWLu=uu0I5m*Jc'pR % qİ:Eݲy++};~,_Rge94ݰw=b;GP}fJ`GlR#F="}`X:X+ûFΤ0vNa4m玚˲gdbǨoD W> V"Ga"'}5dYwXZm;:lҗNmB[C}WV`lFvw% kc^6lt4OE짂\ػ |Dا-$]\7=$辖S0,#GPk.G1%0GruX@m1It5Ń}}Q"@!6>cH.l}#mY:M# 4 1icW'BGvK!fZ:HWҭGYz @wkAa#-X^8 $zt"Ž.t: !{7K{h ݻ)am/t>wŻ /p]c!dLltBXɮz۹˽]Q"]u =7}B"aIE}mޅY 7٦ xH/e͜)4""c`` 4`NYh 6X1&s[wt#`"/ {m q^=}.(Lx w]Dt?oެvбZ,:o$#c`Ǵ.iYvE0t3l)M!.×Vw}>z[ӻF$:>ˊF'}jL0^]$H ׌Ww#Au3z1cdz@~BxdXc HɂxA3bRΪCuD#Z{H [d (}F7P`ݎ@8;=;ۏ+!)cP$:]0`d 6&\Ld֛OV. V AE[na:t==/\!2g| q7V,4x5uccu,CoK!p1 ;;{4Xjtά;-4IkY0gN/Eې|F6:mY`,_Gd l}Ԙ+ ho\,سH?H Iܗ[zo9#Xhh8E!sq1%T SU4\zY7,q#D 6>5 ܔeD{cz;RAbiZTG&VccJqi'a owd$dՇCt18MmR"wdoEKz 8BIbP:@u"\-ݮ/X6͝Q] +V`wvv+>sAooֳk..ƒx#JGw6]qH6w>h 墀Mov t/Pa쇛.#_ I'E|wdbcܽw{er蓬z,Nh94>!]=kS^~ILeAu7rFz,:6^A,{ B/d:-~7uu & MA$$hޗge_GLM{S?De hI@Y#NO[ L{u3tl"Q/{ckdF6ǒA)i}JŃf5Hr':0H͟Y#Ա2ۮ&L7t؃ =w  p^czhCBJ_EԪbA0mWrpxIKbIYOHC^f TՌ0v7oӨ38 sK~*fDݏcO`W$}H:9H`.2mVoV^3啥B|!73[2׉`VÑR3{"%+T؍L=锝]ջ{:+&3]߄ )-Yz>k({lu,fe^ǻ0`il;tY/Butc3R ePtZ 4Z#g,`zOvpX\Ki(l{XF`˱ Cu]B!%qLJ>Jw8Qpޭ}!ԧXh GvlԿkᩃ0"nkL_=[;ܱ=B:[ix{dRݞ禖PB~jzK}f0C+^k =@LD4k,v6om d 1:2Qa鰵z=LaE{dB1L/dv"au?S" pjA=[zn^X0@p,-^6,SCYէ.',Ν/SH5BMbKz.B{g,>@}/x5}5Ռ< 9ǖ[#YLĞ@Øz@je߶2  ?vg[j_|t'DDg̗ʞCb4a =̇dCn^Í l?SZClȤR3LlK {c2ՏOEn `~^}p# " bdD!Բ Z]k}:?!ȧ4YlcO]-v'V`Jzr fl++2ycndu壄/d[EX}BMZP٬#X`hޖBszz;OՏ$G7BI}HCpxu ktdس6?Fj0{^ZnE<,韢ٺ4nt!f_b ntpyregwˮ^>콴u[:{ԏ8wY Wtp!(.yfB4ِ̏t{, X'!1AQ aq0@`Pp G/޵_y}?G4$ P):xnR?P>;Exv?ao0Ve^,NM¢qaL! 1Ј t5 F?-3*T[v&ąsxD?9f)"j-1OR&nXT)J.?6,=@,2}"Ĵ4C-Z76iTҦG# .&ne<}CV!rA%n;/0QK{![h$&+Bz,>c3ʵƦ|/; ,YӌBሬm1"Z.yCT Fl4hES P+pb<-Ukڊa0ٜZcRֵzߍ5J%G VLؕ W/*tƦ" ik BQra[g8fC#W1xYoayp2̃gF}`-*߅֥y>{:KҪS@[0YŎc1VƘ@l츿yntyjV7 #dvѼK1$FBK*/m#qH}0&PV7"z7̈́] >j]r}V^]0}D@LtAO;Js@,BzmxMa* R3"uJ}48JՕC!# t>o m^c$p Ө=үOm'm,vF-%B9𾣦dL6]VoHvWEW]^E46龘io#d {ܢmAGV $qb]LA 6MɽTau^ oѲ[0" ."3'7hbT0ѝbĪ3/1, x[ɦ±3)8Y)4;^ͿN 7+fYzU-6f %qQd"h,?6tEq7!` mXkMbEXI{ h" Ք:)A(4]nHD p z wNN0o)ɬ#,+Dbpˬ0FBSyJ3y5+@ѮN7#$Bv)PKS`@ E P4qV4cx 0+>'~D&e* ,I .10ȍ:o* .@V*mq+ 7%w*7!(W d&"4B +nYv"0܁,%aUe#"/9H``,@"eާ@;LlwCKA+ƴg“j.*C^B@r2`m9 ۅhb)QH{MR/@p?CSQU`Ġ}N+a +FEf*R~i8$Aq_´bY RvU&@Һ/3C1Bk `zbX.)724;0 MV^Xs)o[4ɰMkqwlҷ8)Y:,`hK&*+0V$+Py Y7(XD}\ ]>eR!փ$7)7Y) \'| "3d ,FYtJ4d%l`,R@j`+-P)se"Up0О C- )Ee Fg`4D!6qP0l.$BƭJ`5bKոime;ɡ6!;d wEMbzOj1/J7"Z@ 17CIpFѳaҥY.kN@lhJV\ybY`f7Faq(($mL"*g(Ӥ7%tT}But =u(@˔噶 򴤐s5&vyFaOOfbl|3&ӋF# FZȲ1vsr+rb`@<@sTr҄G 舞a<GRf$1G݅@.$XBMHO*JPkh`cbZ ]H =!?b5{ZRq\ň0H6 =M C(76g=PLE?ƕ,V,# So}(b L!لF8AMTNÂ얄T+#*T/L9)+5@7NRb-b, d"; &zTP FtAdpd錱€u] D$()Tae (\7x #)C:'lvXu]@K{=1vsʗ 4`Ch-I" rSnBA(o\mBP0zs[b{Z>= &P&1qkY(J ؍…b{>3T IX b170wE"UJ` MM%4(`uS5ŧPAbm0YJ:4Q}L[.d\^a6/MF)Clb6P%{=X]QHBf ++XȆeYUU BSKt =0o4|aƲ4C ,Y@c $}0-q V}KJiՅ!kR--_%VQ̉sf!2RҖVRSwD7 *ԾXB>q!wqrjoalihJ鴜K &V 1k)L%ql<ͩ׫Jb $z )1J wvPd",v$dҘ#̹s.Qb |@*=9 =oˎSa*bCJWSRWajEqj f6ḩc|c5/=f%fm ŵ(x C,YOCr}$Ye6,1UkJ#U+aNX1 Ny1{u>Z2(P*~wǀ%PB^g0ky SUy`VsLŔFp\;j$7o+cY s)fea!.aá 9bn'(w(&` RFⶀ9"޾,lo1xʂX\ !}p (0{qJ&h"J X5;`;@)wp`z k`6n+)/f[L3]+,zS-LBbQ,GR'3 (qё-#@XUs~X⢀l4"7b$ LR B(ivʋ-D8>rXJ JME"@ѐRc1-/yie.( n&T VгR| EљQ*#sEo@"WnWbt1(hb& DfU|DE@\a8$|ȱX@&Art%>r# %Tf Ie(E8@"( hʊS.2^К@s-„WF= !I.b5t`Wqd/%# HޖeDڜd;<-%\UDnM rP;2iUyKaXJT)n@.uJ=>ii`jr bH\;Qu#nlP+(z}F`L`ֈH;ۍǭ +!X$7fȵD-l,3gl]ŀK,*FCNU!53sWlPHF$`plV1Y`m2"-/`JlʮODp8h 0R2a/"%4Šgnd3p[`@n{#OE2RD!@0y%-&Drb]3[7 {ucc1bX Yk3ĺ23qHZRPcAqlS @HxBJ) $-1N !x$HG z*ġx_, N-Ukd1]VJi;LjχYa vn4|`Xj%o@A Ը#0 c z-N*`1cD3ͲsAPķVKj'wuҩm]GڝV+fZ0-lʢh R¶H2xlY`Bˍq,ˆio0ql!M0bdAJpآ ; g+pY;<Oq\;K/=.,=>LR>xؘ-sӕ5M.1.+ 5xn6@o b H@\B3&4THR64)) 1@d@0&%Bj+|96g tL ]@%s * u K`h0rA^U6s\McQ3VJ牍nQk]8n!2#X&R_#Ca 0krV &鈜 K"%)$ (:`Z *T$@R)wX%0@& qBm`!% c@V.Z(S-d<>kl -i nY:}11Գh@d|pn$A}әfGfiiȫ@kJmX7K ˫ P*+LJYi!P-p%XcJ )ɼ#ea Jn_r"@ج50#"@A!q V Xļ*] B1BPA lc-(d|M> "Qf}ͣm !F7T+m .1u ۠܊ nTP28$wH c;ˬAʤhn4 P )s<Vo+E,T dUdq bSe K1l 3AyiMrH K vmmnB Z6V-6,B%A."`RQMq|\}G*10g-pLZ6] p-M\` M4>@"Av +Xl!{KҍE4ô8jQL f\+UbJVPsldZ@*( ]2Br m>;_2+-n-1v !%-dQ\ e"U LɈ, Un?#Zu1df=#g,j fgAR;2.#V,ְ-GI_Kril.cA\r0ۓe8eBxN-p[|!p1GJ{yCL^0kq7,g pm1{y ɋQ /h69z& . BpHJ4T';@6]U]Gd&9{e9O 2UZA:Yl|ER.E(}Jvm@Um,t0ز|ܧ^or_r!+0 D{zC m6 a f׾]SRc͎Q1-%KM+)xR` #%-T3iӹ=*5š[XB.uB@>Q RR5}jmOjbKX+6bQScVvDZ%- epG$6DmXѥǸB[eޢCrOx)-Z -cԾdW0)1v+7A ܑ3(Tb/-[=O/hE7L$gyr`8#z64[+,R*Hn4: r=❐8U_jܫ¾'[J5:+W=^ s/  KLfFQF>bBn:v# /P/h8Pbj@Em-\B~ `P!g5QsPZ%-%(%@1H&.u4O7r}Kɣ%h[M,„*V`&L$ e-\U-(vʱ!}{ ǡBVD]$2Z-e epp7TMNS2Lc3VLڋn2iNC;6XYg35p  T+!.Y!\ X-RE-fUq)-F()kP.EUw|J@0qTU  [MH@ј7Ds-6mzjmA:&wr.핔m/(+xq"ƠWxeL";0 +s[~^(bmၙ܏h3l-_ jJ7Q qs !`E-Pt#)`> ^U8ـ;@і+0{Lfv'd6>E9%^!R r+FGx +K *fIXI-BjwĂs`rP܊.S D^v]Nd{G08=OH`GfZSv/ +rơWP;%*}q2#!+FZToxS6 wpZ`LXLѾW7'1\ f% C@_ z* ufvo+YJ6*')b[CJ`C4;A4$a ; [NEKvI| |:"}[EܹG't½w;15T!ox x7Hh_1R 6.[U*C|W2-Tjgti (1J(Y|wZE݆Qvs-G@evywЖr$=;0௨TnA%rJ.|AcS%OO2KveY^ыlB(AAELOh%e{ zߎ/dlL0B!]/$yQ ?%iFTA`t0DsJ/p8&eʹo-#Ҏad+9KdZ.IQxa? rFT}#O>ŕbԨN*aufxl 1^о"DOHCRFQayF*Ȑ"ƴh-xld8^qһՊGk#\qKNUnelsW ؖF v3P9eҴ$qz䧉SF!T>x3;H_tTȦrE.2^D9jm#|z °x#xц3= >-|Eq +ĸvClUl{̧hy=w`Єv4+xjE1+@6"gv/oNu^ѕ=B|tGOAM*5\ ^8>˄{npA%Hu1,[}ӱ26F/jOlSlWqނG^,ԩQ f N@\u+]ܱ`Fk=-sQ{ބ8/7S|N\}nؖ5/Whv2i'Pc*`:"s툇|Ks-2=ch;!.5*V/WO\ dVBV2ⲘAᄾ}}h]@i1 -Q:v\\D9 a=Bؼs}cu(=4PZݥw ݄GV aRuN' pH2?#*^Y+TC,s0:ִ/Qr@ٲkxWzSO4zЄFn>LwT蜥/N .&_,Hؙqv(B;A9v*Q7_p%ER5\KiN%ğg\Z}/[Zu&eKa%>AX^v^Kһ@c[/+LpZ\_Ll9T ؋._1ؙ˗OH +% gyR1R֗hK}A4]˂JXDbzBYJִaB>A]Bb>z\eJ#/gJ9ExTR#.|BW^4ZV11ZR:Ңrh%H_.J|^L%O^,#ry P%@Ɨ@CC/hޗ5+4ޤz\Ri~%Zҏ%j|%/ԹR#SܢZT_ %D u-%´ D/n>\\V+:$ks1_*/B}O/lh:'zQ@tJx/U1Įkz[JJ¼1/ƽ/2:H1SK_ZS?}K4n!iܽo/Lbܱ]Cʁ+KB!1x?c{ҥ< *^+Jz &3-E0\P Vue@#+|o\:@*2/\k_KYqy/K}t5TT04̿#_GŇ*㝧:xߕrO @Q3[.\W:4+C3dt4Z ngIWq&/O4<_stez./K+/[KuCJė?^?C +J.z73s:\<O_ԉ¿Wh__e%J<_:G[+6_iPkZV?/?J+̿ŏ'4x%S+'z\uυ?eCJ>-!1AQaq 0`@Pp?}EsqUB}Pt1JMřC`k_*3PN?|P}JF3,4uA : D)2ؖZhAXD}H#Ĩբ'p/YLVB?}L;ԴhZa7H2[gXO+f^T0)=a_s:iw}puu<;'$>9OVV:ct8$t5.nr913VoN''؁ W0a .v(\O V6⼗pKn/ s͝p:~FoQj5 QrZR`pմk*^]ŸgߜXG(< )Xkbg˫Wi/:!qǴ(Iv5Moǹ3Yi56ЃTcYi9A7|Fq+n/. ֣\zGBu#׆ ԫ1Y`01?~!ѴeUH Z۔ֻ,>E-_yg?0j:޳\gS0](҄(r-s݅»NĬ(4'?sj.!W 3!LmeN+<k E^?KdCc:@1YBv1 X?oueӘ{L1SѢ!ɈbB5 o}!5 )M{F>䉄ֵ%1kڣs }&%,cxUS|ݔ^3Q"& s ků}E:!>Or]_ITԤ_HhX9{ĥ)T!W6;UF~v|fec/iZk}~LgDr)%wE#AUoHv>aU}\eSHݳzT؁m] u-]U^ WU`cw+I^Re*xRTzMF4'ZQiޘJ+FYƐdn_sv>ZT"[|Q̮_pz<<ԨOV a]i|sƋPR< Sq+H(u:LxS[nVrk;~W8çivYK f1eg:UaskJ]h&Q uBv.tUّ)*mߎL5cA~dnmC /K:oȣw-\B(`XUV%v`^\ 0J =@uj~R' d;/ ^8RIthԯJ91 r;HYY}K57-RFƘ}:B5PvP;D(e3Xе`58dP 7߼xwT+Xl4p`k*kjFec9=:EVZ{Ƭ@prˮ&4ư-fC+s.ViJs<9qܺ\\1?3#"LKg3Uf VJ9֍˽jK._:>&jX f5s;7w{ sfU&eԥtƭ Vl yĨ*6߁lj_hSG$aEjw|ޯ7\2c,?3,q&N;˽:1w}.pyJǧW Ks A2][ M_hT&efg^ @yW#3nWi4GnmXsX_s X/gV5x`󿃗S0o13Ƿm q6AjHx4O [0i!Vr2F?>Ћ,Rg<\zBoڢ|-1uDl= `f}z4O^~1 Eyr(Ko fqEcsxE勍>bVNQ4t֧鯴_BçiyS;5?$OW}<|xr#U;?σx;3GX>`>Ro fwxqׇ<;m#;p:t ۼ8wҟPvx@eزn˔5;Yg1@{^_"Y+wO'ZOxh= |9h*([:DiJJ:<=yO,N= 3S ͈`4wFqd\"F~i D"к =%)luS WO `Tcj/PmIj'lH)m97TRwӍusfRmup_@@`FΓ3|; nm|*#@Z!+Xم Yf"˚M[E5~ 0n / W&I%d$ctѧr 6=7sV (2qU)hy5㮞 sr@)q-W@ YUO/-Cl֘Ak+n _3godY=xؽ)*8\(P,cfwpCYcRrRsfϊc3?xЋv*<:~Z~n`3TtE8ptkN]]2# Do\:qVy5u-ǪVڠıutq2kD7_V)d[v2,ޜ^?SGS%&@Tқ]6ħQæN=σ?AN2ƚ7i1}Yޠۃ*թiVW[@nH~y#2x/X PaP˷8 YR;J^P5 GѾ*5޴3J?3Kg[ǤTdf.߄xB˭s1[ lm:^.SEސȗq`X.8@j=OpF,ㅂg@+Y91֫06+ e 诩\8n-ɪH}fbѹȖ/`_VKczv8.zc k8EW \L< ncy -clp~cο*CYs{<5hY +S+^8g7Ml&KUR1R֜pyd:ʴA]f0NH(+\UCh9I-Rj3(FG.cL=o8ћeOs{q'Jti_ 7T"螾'B1r^_zst׻TΓ\ph9Vlۀ?15Ը~`* 9 qqE o )Q0[J>&80\rf0ػy?KQΕxyL: j\imBô@{i>ze߂3e4[ ӬuyՕepf( *gn6K'>,}GG5{KѶڥY)pP[)[ƏKݘ=8>_>S.;Y3~9{s8t/dY+9o zھ@z\}G!`lu(4JAwOh?,A4UGXօS r.^6rJė\G.Tak؀0rj/ 5}k4}ats.U'B`w^P'3Ld7M\7ׇ(nOIJB 5CrT~8tӃ!uKaFa+E_(M6MFكiors̅b%t+bL {*$ 7/7t6nӼHnā֏F<+afLzbZqg?=!t5w*:L)kW#UIQ9J\=O5[zFG|" .0 U٭St]u)+-ƷQsZ YfxߋGu*9*)7e -*:4#If'|vEMDM4T^1uDzW̸8YDvEnztЋ#頗}aix~` :h 1bgBYMz|r{PLV<6)Jqir94m)Ucc8ssF}x}&*XfSj Cy zh_jcxOl3Τyf:W" sDU5hFգ| Ӈ^8!Aϟ? Xmb-CtP~cs)j^qR #* %qk2]L۩n+EPO> V7HF/kpF2܍o+L||V <8bk޹VzQ R:";iWrX9lri+b=ԃh^+ܛyvkݍ {ƉT)ZJsk~fxͦ<r2r]f5ƕcH6%E8 ӁY%qa/@Zm AQ"U{sG%Ʀ k2Y w=rtVcHYZA* bꪜ) m6sf˨r7&~&GzM?π56a b7AɃ#@|9}0ubٖow,@xT=Dp`0wNGEy3>xU4S/ݨTQ$G&|uԨgM8l6#yR 10y.YeE*Fڧ#:[k*^(sW9xsƫKYx[R /LͯT_" ykrt֢"lLuX=p}UB5%8h 7=jnb&6tü,Cr/~'>wW5m=(YS-4}o =}86+FGJVQ3㟘nnƸj.҇SB-guSe.y,9dYk~* +^Je+&*2V )].jRe̚+y|c`9,ō/D*?qoSkᧃt]&S0@bo h`hL71u{h+>,kQ=*8%WY:eB6 󃨫NXgRjkL#l|K4/Fω#zYWiuنqLa V1TC5kDo+@4j(ٜF )lB5b4 Ljpfxi ,ʦeWZ".BT.-_yiB`)t(<*нhˮ%H.]/} ŬѹkUu)=fág(gԀ3s=^b-yTy A<$_@< yRxg3n.¾z5ܙ5]u.6yGZ'?v]̼11]`uG#/YYYaؼ\˽iZi˂WC%qkXfes򙈧Za}}ٓ5E7Z1M+%P4=> kUieYtayv3 rF"<sn5I͖_y- 7^ y[Q+6э1Rv\sOmߔv?o:hw0Z9&7Y9V}x))H*vڤy6 5Z-kq5yf94#^Nrץ}ϲhvY.OIo[5?COkMkOy3f;i>t="W94F}7I)8wyJW@/܆mh#[3*z0 ©.ƻzL jN}LNa\6F^ aL]p'./ς50eM)+IG! i< =xR2Yleŧ*cO0̲R@(ήFx80+_14j ۀǃ8t|ޛzť ZA"ѲuhYJmq.;Vj1b,p-n&&˜mLݹk>d3ٍvky?&m|ߞ ߤ2+=G~~?aLl`zs_6r\֊iM:g ٌ(o]JiwA0;Gccn׬uyHvx36[3KiQ9L8f484lxKP}/`7bd(U*PzQ3G.hYuS9t5ێ]P.A–UB q5vnzƦtDuKMD 85 〃n۳v@]؛G(*I te(1yWU4GJp 2>&tdLǭk3_YM?:&}I'i u̽ӮckҊް/!i1LUe24ea'\vJ< V*EC2y-K;w& y3kTjQx`54ɒoEκXQ-Ƙ}Yuqg5)t /2QL0PyV"eZbAYhvmXyg & _4G<75T*& _@ׯn&k`` NWv6]A:v>xUhKS3?d4y׿_+Z&Ceߝo:l4&r3sG?? `mKS va } @ J ~4jOud4jtihb @Q[s]l;sj<p]Dy] /vck# Qzk>py]f+ FY3L||*8%}=|pa8|ȣ1:;7*jErÀ9:"LE34zd82ߝ93PnCJ:VmB y$XL'Y9vW͍ 4oyGj+a;Tp:rT=څ[џL\?ykϽ_.}^I1l'M'i;F51BqɅ\Η0eW-lCΓ#vk7s_֯4 Ss([j6}?wb״WsgDVP 9zpؘg)/̰1VǷA ]"Em+M^ru{C)jEpoKwI=\Bb6*u]09d4wUMsu %E኶ź<<淟'f)-CSzVdF  iQ}Q揜K1 2@v@-J]M(o2_dMM6 \gfZrizc_y֟gInT=94l1XEkx4t zOhfӟLwmWPqƔb֭`z$87j_\@ u/OY@Zn=&]9zo?{ߔX٘O0|_}rd^m3GYZzO&?֙ۂP< H-quYjLr}'I;~ uF|13Ohc<&s,?. a6P(l@@aAyЄ=` #褣32=Z4A3s4fs}&.,  Vd)vriXBRUzO'$X˕wNFs~(-9^fmc IhCjt^cM0=;OQuںKw؎Z©3wysue׭"6wE-+Fܦ&M|]l &10=1u%|# O)ۿ}Y9Un gpڱ]C{Ŗna,"b YG,@@L6y8jcOSRk:oNT46.Л¯lΓQ|J:8h1ܛD)nWu k qsZ;MV vQ``|Mk1eYyw;ƃly,FkҶ3lp޺1=)֢{Ncmf9=u%{3/>e:^-.L9]=/4͏X&j@ s=k)6hF/f|>ץmnʛ_8ƒ9l<_uu~"r}Ö_OnKf>"b6{F x٨yGx/\|LjyB:lG ^N|˕&3Ǽ :5o0,kxi9O>”jmϞ.j4v׏XnSGysff<[c2o0-!G?GG̎A[ƄͺG`徻Om}K&<sk+7Ytk,qavo7|˟yR6&&߉znO|޳ q?~=;n=хkې5ޛ\g~v3Ka>ϦhJt^B7߹U[U=r=e};9<^|3Oe7f pWP. Ӗ&&ObN8_-]OS 42F0p<@[c.Q,U{6^)Gm\+Yk/hh2!(3(t2GB\B7icɘY^s#ԗct2e}K]yCtϗ9vY/ח 3_24gY}®Os|u7ݦ ߴC4;rn-{/_.W?;ߦ4|_V O1^ϱq&Pk#:i1/',TMOxz$+v㙓DĹ/>6*!sr$fAzԾ]%f[w3lr'eܡ^}t V@PW)B3f^w\ލ{0;0uCLYO&e:z:Z^`~N&䘧muF̞|0_F+ i);U2Q.Ε gm!<ޯ\Oi|EmYhH$611T[hGq7KXfC9GSd5n\.6:̮'jg(6j)z9d30rCmyqi}"6!J4'ɱ9ƽ#S]:G3XS~RׇK"S kx83nM@Va=߼m^{zGK(e2yMSS}3 a{q۴hWgL)4Z?r5y/J#4s25MV]%9frlS|kDkKs3#߭%12u+U]'Z*aV bnrad5C7Q*ŷ56 5)u0Y/0X:u'M)]#5S+E#:['>K336z(#Ft7ՙ>&quuV>ӯ0'q&H'Ľ~?MP%x*["rωlHRAioc44ɗγ,iϣILzWKq}:/A|l˶`&DzghZc=9a|ͭe-" K{rWoNyfBjk0IUg W& ՞qu{MS\Dw& -e5“w殚#mI04 5+Wtnjؘi/YKG6Vᙯ:PMnVɤktqCdqŌ)*76yXtPFSn ʘ}cX>@ |B٠}Ʈ@V@,;&G{PNTX|B\$qG4lW)>ysTÑ9}'XxT\$ߣ*)^OBᗿ82ߥMdJZ&t5:xso)֏g6)6]?ɗ_BlSs Gl.x{STqM~S03h<ɀ]`|b,y 1 I]ta]'Y}r0;ACO69Oe=pXe3X%|Νޙz:MkL3:kHys93f8C54kGh ^vZ9Lc;A43k5șyhr OHmK߼JwCzfk&} )`N }3f,5jHyCϙצ6w0-8Z+="fძz~ ohn~1= i5{lͳ˯MH L?4]l6}@|33,4*?v0~<澚v9M^MNpюIKMH_jv:3>P̆99MiӔy8j/8ZyQ93g.J6y&T{:Ud y\*gk>4>1xqVyLt9Vą[j} F35Φ\t?nӜxYL+oXi}&Ь Nq>|ͦiItpӓ?Gi3wly>?Ku:ٯѕsEV5{3551k˙sTۿgK =)WaG- _x^vG1%.W*3b蔓ZۆQ08NQ-bej&&V8s75N}=gsfn߆6Nx*h3Fk4c̟sG?10 5K58gYӬ־IifsQ՜WsI[iͻaVB*ոF>3zs|}"J8nAԜ.Yb(i7q؛9_z™CVb 3zˤG'>X9([pӷz|?'ϟnM]oN |\o64grbosRMm4a˔ԸC:Hk:o-7gf\kXwat25MC 319vݸjһMNӜm~V64:pna,La:/w fR>yf,{^.)كRrsYMm17ht8m.-z@Ъe |pێwins>=on:h͸63N:Fm>}pϤԎw;{5;&yysS8|~'h$3隇YSYާ3xf+u&S9{i홬ɧ?5}bR|:DEv`~#O͗?9k:Cq(6=#۫׏X\x ,8?6l6 mtSYoQgԆ8k55!II85 iy}!vu8i5 L&hv|ɮz^(e5?aє/'!A+IT4#ѾFSw>3YF׶Ki钮oUxtxm6jx6qo56MIњMI4 zrͻMx}Ч7?q߼su>ߩ SYy!5򚿢ߡLfq(g`m~SUBۙz WYrӉZBӓ Ҧ?8[?hێ.foomF}phO93i4gֹ4M|kc>7ik>ɤNY~8H[KϤϿ}8k~ l3YC*ǁ13sx~m<5&I aњMfO׆5&' m6M}fO2?^9ρNO/YKϑ׋x󺛗ydo2zk7kj߃O烯;ԚL$dpG<7o7xi65\˜׃5 ̙:Ӥjͺt&p69gi9xvῃ jMc4p~MkI׋׃|6M&7 aO69pk׆ qoZ>CO4j&t{Mf4o׆wzi |o7~i4 &iu#_ Y Giƿ/oin7^'cvjpi8s?mi2oW ~ GgC~GjW~~N<7jxo+J1 È~3_C~??][ُ|@~hugo-0.92.2/resources/testdata/sub/000077500000000000000000000000001420147000300171515ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/sub/gohugoio2.png000066400000000000000000002202361420147000300215660ustar00rootroot00000000000000PNG  IHDRQKiTXtXML:com.adobe.xmp -CDgAMA asRGBPLTE F~( Gҙ ֞ Ж ԛ ͒٣ ܦ ީ @ {1u+ yˏɌ7LRؠ ptDF~i izLwnaGYx^ .$'@>DӢ :SZd#6ɸ%9E ˳1Ҧ%Σ¹-LTp0CO{L͜%7@ϯPѫ,8:/:(1"l& ˩zNp\cD9%KI, ÚѸǣZbTi5ê-BƉ" )'wtrg@]ٹApPZ{k?fX=~fr>vnHt5{٫ m{IrƠl`߾yDֲݳcjbZ .byYÄ $@W&*m>d, Ȑ vơHDßا2X߿x)sQNWȷu/kϱzvDۮs̚qc5TTSZ;87MƢ=Ի IDATx{lն]NHn U,PD "ˎ4+D.fD@ Ml$@Jz&ww1oc9|յFYOKEקqcGLv c ,6ʱM'M6:is=m6C26<1FكFm¸ fk5{f{d#m i%[{XjC+ֶV.P8PD @X<1a0-4>K(D`8iCI>’B#- $rI-$AXAXAX@KSr)R 񦬭@PCض?q'B8*E4BhDRN*q-3atzB8IKO4 !- C G:_ !a"h B( `,Bx12H0%PD2j-cPs8z"oc) G>HqG30hpfB[ 3:qFcJhP躣Cڔk1l鎲J\` B`p(jD%%Ap4'P!$N%B: *GRBHu0pF]>rVRM̌R !t2uQ;(P +Y14" 2!FV C_&f'!!&:h2ތi '( Y$$A+>a Jh2/0B5ΨEz!!:Jb^ƀX6\)N ܨE qGiZf˸J($G 5Ajt$ ҴBB2LnI*%t)>"TbZ? aD5B'/c1t2m@8GH!B3*p4#JuFqI:Ky!hj_Q(+c/:`kvY0!!IDD MJg8J()۴LPp~™$5:S#7y4%OEmf?nV ?DHj"B< ]!MAZp0ʐ^1a0Ly$tFC!)O8?e!N<\I[B(J膄7JΨNce%C8g-:I[FQgƄ;tyJHt)PS92epdFAF!xcP \˚O<)!I ֆH [#\gGDsk&:he6Sn})ӻ kOYZCp6"8;ҮQa|q^ZkhcZ!!\FBBWnsuz[azGS!UZ!=(!si5(d@8PwZܐЋdž%R'Z! KNp ӹ'| (m(ӯ#~j4ڸde&iT̸07 8+ )O "&ꌺuzFH[y27J["!BnWƺgЮQÃh@a{Lry gy7{̨XwĐF5 =LQݎ5{|%ԕzJ贍("8`s{-O( -L6f!,CRnZ)W;K싶BxS TQόpw1d~;Ղ CF%"F™S Ɇz,J-~^4BCjtAFW'e&ᓶFH t|܉r*a "9.c#+#/W FA;YFۑa!CVo6c'd(6"Jy{vH3؆za2hF-:}z[mu0tB~lXpe[O-3l/:Fss1m3ɍ# 0?1+gy-ӛvY)Ot~HrSB˔42Ag'ġu{ĉg8ms{yCv;oRz&1:+km>Ꮦyʛtde6waaVo!\.3jA,"em';bӝnFcY2aVY!0 NXBL`2Cp1-Fu=L6B222٣eR"_:|XdqGfgS4+"8M7ԷBxnZL$ROՉp(s[LjCl(7lʰmx!|4pH ^j.fG/=gtTJ-$ORMx{GӍnfA}n7aacg2y{zN=L3"S-2rS2+oVOw+7CD;bWV9lftꜩd;"捒‡C^ D)R82 ̄qۍe 01YP '9vH[ݰ&u+ӟ;"L㎵HYD̎ؠC~ ۱(2J3OЦȬQW!|*2M9)/NVwO{FrS|'KNxGLwJy62e MDȔ鹈pp?bVr3/%ʼn%BiEp =ʄi3ϟ;yh cr 5fg :j3Sۘ{wXڹ݆t˔j/o+7UH-= -׌5Sef[&9cH;kFG f#S^ ;֢R|zo3شNe a:&--㍖QDɼdfYX0Qgš^qHZP!41!QTP[B49兺5AO>I'<X[lcGˌiX $61MʑɆz~7/'Y'Ey˟fK6@‚il&Fݮ!ENu"°D8'>b-4-PNfeƥk$7NBH;k61Q4֫Oxe[d}+7iZ'F-wLݞ?PG2Z֜f?7+hNّ5^ Ӈe\&y E[mK1 Rw0b"<0qJh{5BIe#BIU' O NX{ԏ 3-Dq›NS8=;p:MΟnJF #9z Nс3x'[f?v;&Vow83݉?|w_4ROCYFmIE3`ݼcn¤,?k"(nkԛ-be3'T6QmH'#<ʍa'gPV^ YsFQ/"ȌX ;9JȔ- :<:iLg'fBB 댲(7QwSTtN孉?39 ύnsuz~SлMЮQ~ZC`"(9;Жg&yݶ5o@(Ke 2muZ edZ!e*3ey$"}htlv[ER}3g23A}n06 -Xh{F#zJ헉+n85hHȍ\Og09'Ixn n'ZV%Fș$)3¡~rB8'j?&6Zfx>)P :$pv k|TV&huJc-ᓶBxde^Ft;#s-k^f)2wsL[.$,/y;›Po`F顠F©f9̸_O0In UBv;ւ9;RsF>Bg"QvSFpa [!y2^M̸mkΛ8/wHH[LybR,"6!88M v3ǂAŋc+7WVG=U¬Ԩ6ʌX  z[ӱ:}Fm$IcBNS 1([%0)/Z 9$+45Pu.9<3G Gotf P :hv$JT+90V%`z3mtT0Z&<u2s ጵ NHH Ԍp̴i߰Ɍ-,ƍn)›Y&)WBNvSݼNzWGJFgOq> wO$|4_gXE!-\"l-D!\3-Fu4 G2ccL_4}Q,?1AD>(!U|r9lyk 5B}м͖B8G]wqFgDBv!0Ýt Fi~{D=#lרqG9l?Z6X  mNushpNp*h]GP_쟘na$aQO}p_pPԌ>_2X=V!;Xf@ae0c2HvF~ 2> 曱杆pmv}[=YBFSim{-`2R ?-cud^h!eQ%$g6 fC}-򧂆 nb7S9a(FKx^f7pS%dvR)!1M6oOaw17[ V!2P` aFGf$δ>$eH>5c>1;kQoE0AcopTO\I-аD8=A0p:{LXN l)6[S`f{?H8HXmp:GӱO|w/? {IH!3݉閑NLtˬ3 0'e e:}$& z]Ny8\(B!.GƍHv)H|ܗQ^S\!dBB}ILrӝyGԻP'?-#P{eq'hyk@|CL oG6Q# ;~A.7*#…d \pyJ mKwZk1[%'^ CӟgˬQaC⋄4"Zn G,ALFh(\8pAD(pX/浍% m[vW1M:􏟠QCgղVIH趍fu>wLx aX-sCS`2 $aRbHR| Xvm4EZlٿݙ|;uw`[Kksm5u{F0;900=a2߂NEe7%AaS>`MV;AOy`XhλLqb͚bB7 QXPo63mttdCpD<-v2SB0g.4BPCP cDwOv?Db&ϋ9!η0%< ;Slb e؆X̜茌:}dG} !Ɍ:Op[ BpvHd}B2(DχPP8uG>yK ajY^ܮi)?H _gy˗ O 'n>8;r2x8~"&6J?13:Rp Q A (\^ O(Gk-?v,s2-cAƈZ/\IEl1 sDKd?Ar^ :)?-3q(O:Gy2lh ;d- 9dFKQϕ'숵GeBX UjT`XQL%k%ԷmӆX@Tpgm ,!2^b)P e"!0sO0ިƛF9wtR%ftp2C- Aa pSfa5w[j A [d$te fY2Ǡ 站Л6Jtpb*"9dƚCI70YI82ߘCr6/Os2 @tE:8_ D u!-mys/wsa,g`bׂ^^z6${#ihѩ;dp2#րq鑿>BeB!T(d̨*Da{XP*3#%%jng ayIe- C0%WHpY構} M'녞İר 5:TI(;ddTopfՉ'5e&$temnrE1&D1R J8o o*a۶ d,aiü*ȓs-Q%/a $^ s>S  ڼMn?1cͫs0e92A02n'71i \$ApGRxd:mNÝJ a=arS:5 [ Nq{k4 ¡9LԨUYxf4H8:<7)ӱǹYqm:7X%֖WΨporGU~TĄ2cmDt 1Òia f4 BwܐŔ©LvH},$ dޠm-O̲B8 q[֘dBc $zJH (a;/S, _ς|İT$. S\!V^y2r5 (/lneZQq7DN]!Jh2n\:W_Ypҍ* JJ`L o錖XG_`X)#$D,s\zbՆ&ʩۜ?:?t{D=;Zftt;/Pw4U`zFd2 Ǔ-Pp"Bٵ2X庣 /6tH!fŐ[1-E6m=r”댮2 7+)m @J!NL K!uI_ϨE "D!ttPkਰg?~nu[ze\ #FOL&xO$0Xl$!@K*b],czR O:vLx+GKG0'ZNxNCbaxOˠC$f_}GŠQ{nr(3m':9tSpuHHFÈp;ӂGO}"1bMwfƆ%U`UbFY~ڌJHPң2sQ kSa" $'P_ 8,(no@ylH';F*$T2fp4 gmӽ=+508 -cqG"U1+mVF=۠PxedTai ` 2|%v|3vAvI A/"LMXn'Ѓy^ީdh@B8= DŽϽw0Z1-CeVYWeQyaߚ*P m#X^R3u0_x0jcSӕ+pPha r: b>v!*L?1~<,wQBu69| cSȱ#"@]#2k+W!ڬ1$DXx o:X ; t2?u_cZXpb^)] >pvubTظ gONy:=|b3bt˰M!BDAL4"dГf'N FFC%n; %B7*G 33hsMd`65崚+#=lK*/)TRK%p()Jn&Z|g8Ruf_?e#O̞͆'z+ Q [\5U 1!(nG(MaZò aJ4dMbkaD9;vmqϲn E%܎ n'NT:-kx'61:vNX!ĎXg>g;[b ҁ@!"•ZS!%D ATxPƄ:RZV !9Uf[86a!;2oBO"-\HO"Z  aF3\j=&ٯ0xtBH8Mp}VZ%L{ZQ ;I%<_X,[Bئ8 K!X,ln0i&)5wYOAV [!qQB@P[PŸ4矝t\u&'3UWq=32 '{NC; jw3ffeC`50 }T@(0!pIH!( ݆ۇܪM8,â'̯zv Ga0(|szq?<+a` {u-~:|X%N]oe0K(LypM:WUݜ >=ix)bzC f9w$xTG9! .a2Wℰyiw aaP R <Ӡ4Q@h:XV4EWI&}ѻ[޽' V-)D!tx *. u-§!1ZZ oNz:2xH'82H^BPꠠPhg>H%\2~I8u)F•4 wBTpPlThֈ1|&ŰEQ^:2eYsZ(f !Nt>`~}z~_M …ovZ _tSaI[ 2(B[,dJ)D%|@*3h2(|hT3"FɑGG#XE;:klA%˴/j=djDͻzۯ(l{@ oSRx-hL aD{kCYvUSk$MN؏WS2(,YK@G05RoŒ{Cj27EeVFŰ $| *a= Ծ{"(n@!OLB 9d}1`JG lKfk bDR=sC•+ 7R/)VAPx@86 j؂f`eYWB5!t*Zi+5{+J 0" D&\sC8p\UJ8g㰌/> hBF5{Apbr*!!fJG'E'H?KtD8efg#tBUDr)U5W5$S3;%oK PPjgg: :>S /f ^@r|@~uEH)ѩAV+|(gh!KEA{BQ _ΨA j @HH<:t(Aϔ5^DŽY=)~oJWZw4O RA!F!h!fHY-=4AwR5d2j),b{ؙL%I! 2du }}FTj!'1D%H A y&kPŚ@A֌BAJ RtPR&FB@<  bmB ?=deZC#B A%ٵ²⅐dFKVm)8l ,)|0   <̚+|,.F/ƜC{|3 BBh( ]QDPxH H"UB6R` \lL%0R莮Ze R8  - R!Pp)t V@MF}Ҷ%Wl!4/8WtU`X c,3(_& |zBM!"5ApxD0$P "NaC|de ZA1%|oP#ht|pCJJJިQB`qْe]6SGf !|3ZfTAIR`CSõ)S*}A)1aMy !`dFPسcsRsBY 㧏)D NHE%ԞF3:*4:h CuP .d?e pSRhB%B%339;zG.*wK+TK-1;UP˝{p))+:ha 90>N( LAxX |0Dž0\=oQÇ?YxBQ-"h1D%QZ_u|QAcC  DU"(Q+@"Jh8\K*!R&Pɞ&fpСG-[7Ωo^͹+bT r3Ph0d76DOayi!4B:}J" U%.pH#hw3 fBHHNCh@$0 xX>@ ՋPH|N @! ZvD"C@!x@܄ %Ψ2}08~B>*90 %⪮vCصy}w1a7zZ9 0LKayi B1R$e2ހp [B:[3B2Pcx.!Rhgu}pXBG=oT"!D^ŇB2(|=qy:hHlo!(*ėj A 7:*GިZ7ڷo_BPQ d,䰙aJqh ;z5v Wu<9 aYJ 2Z(JW=fpY@uP *;yw^u*s@"& x—^B_p2Ay3tEéR pB*` %LvPQHk/͠aCuo4G $at-sʾw"` hDx?!rxJx0<,/kH ~g)7mI2I=ZQEugCT J= =wx!D/D)o pAyœG&fVV9E-$[N7'D5,e * q衻vlrAaAdv;Q4kw7=_t2!$2!mTZ z/%:UPƄ!(TpO"^ Jb2ʈ`:Bwrb\ ؙ¤77Je|E=)WmLLAxc)p|D}7s;䢾Z!kZ Z@zŹ:r?_đA w"0Y 1J B`/r2`:7QPϹy@%.PQ؉P772 +R(7knЉPR`u|I[H+S^eẄ+B uGz ڢa@bmX,`='4, .EZ ^O첮. ;@@%GX %oUP( ht)@ ?v?x?I1Ga"&ljaW(ZW|9/2CŰw CnLJ{.}K@=b:0x*~D I.qpGO& %a%BH(*A~w9 :M /GX ATX0R33[ſgTBH*S 6XO:L,Fg` wBHPS!aDPYvJQ`zxRx/o,`տQI@(Hƺ |LipHW Wk_KAǂ?aC wXTDk2#.4D!;! ٸ~eMzjNoQٲVECBIAJX!pa\{\gpcbP'*,+\oIDT;(APrաp0BC& W^ Ea0.]x$%!D ~5b(Psjk@aBǛ "(.i`0\). 2K`A߁BeTJ`/ă %:p%b2K i!?A  ugÀBF c6er.宁 E"T 9M21-W%7i}OXZ Km ʚo*&\ Ow }*! "8^zT-]CBˤPF6 C }`R!&5@?گFR:Nq+g <:_3҈3T6f@p5r$pMaR w wX D۶va1 F#T qׂ?ieG^BʛIP \~4N3L̀?TF(tpXs?sw ɤ4hP1@+aW#ReHX a{D\~kRS*ka!;OTmۊsP Z6~ @A Q +R% pZBP0(N-JXѷBSحd)lvPX&Wv+=zxa!!Dt{5gG.K@H0HSh-@,k:vHA%KRrFk^z+J_%BE!TbLJL%RE!(\A;FL),J c ޗ5v:X˜ÌY} >G [)|^VB_]J(_jo>ş@cy/G_׋ዃiJ5̀R)̎V20>x ¢0a*94ȷL)~u\4 Gd@肨?=(0b ͩmeEC`Y/6xW^.) "bz2ԸI%P1P]DžägK&G堐BMa_SkA-y -  `[JwDpoBwETΨTBiZ2. IDATAD9ju"ˤ?J"2"[J&k:$a(}CP%h '('(tp+F p2R4䰘9MPe QL+V<"JBwBM@{rm m{xZ(;q*+Fg/i) w\hp)Pj%B̘pBG Iw :aa !\#[eAJ\ ]PT̋/P댎$=%Zb IܺE~{oRjw+ /D @DZQfvGB8QBA!NɡQ!J𧢞5BN KQoT]&˄CL En B-BP xF\=ZĐpdBH!DQB/)% zEii %LLTffHLBG M\ؽV:Q Y4-P!BJ!OacN-T *,U1X厢 =sfߙJUe-o7?3H+/",[Z(jĮ5.Չ\JhK b5KaD s9a,>Rd "wjf@xF3 !"$5*!÷PQዯJ8p P+a\V W*wtJ쨡hkE?3U?œJ9]B ]I 5!T+@P a+ n?.tFsAM.kj)+ ~6ʠXElW@+J ӈ/CB YVZط異wqH*U^@x~}7!,$A` AhCAX4FfA`(@O\R*醤`"*YHb8oyj!B`XCoO cgDسgFT~m 'vֵ,&trF[L a Q'|Euu9pHD`)Ѳ~# |B\oMBH! Ζi>apd0Vk0F a!͐$] Q&+#!쑀~Baa1Hiʫuoz.-(uC!̂P]J@z&E_/˄b( D@~_}M?*84zQ+@i29*Q\JHBb7ZYҹg0lX!5R폖U$;"a axK&5]xd~4"-+úEJe@xwD nK[,B\رc_u!/|ÓBWm4QL8WuLФdw@uzŵaC,$^S7ڣ`)+VSˮ !l1%\Ψ") )Y(R%PTHx J(·B%-~Cqz _|ťOQv)#Ye~ЬWq @;I&RRQg|A!aE |_:J +ai䃰/P\kk tpO. Q JOTB&s}[VP(F]2;aVD\J+ ; ZXꖹa<1 Ena'-NT鏖ů,5}-aŽ@r+'wh1-u@""eCÙ3?J@X+^m-R(.\~I!AP"c69Me} hZ@ A 0|? z EXkׯO@I_ +S%|AAfD= A ~ j:6*eTbf-!Tj>%3Iam6nRyE˟#u9BT-AoTr(5̡sń:"^|WdHHTPx7J vJ-5"#9zÇRvɉ6Bn a #F$ $,i[F e$?$PY^wT!~}<}Ys]!h9{\T_&\׋?*BPB-hnFyRoVK % uM_'N$\ן+)CKPBw`PC%ZB鏮Щ"ImDBP2>Q( G@w%^UY B~Pv;}vFup* ` EovQɄgtO~t!Lukm.wS9h%*!xtp/`J(=gT(" ~u!AA#^oїP T ?UB4:/KL)(,^ 5/ Tȏ:Q2, w(uiJ PM.;J &!bXV!~8 GO{鈂}+ܨ$APBB%25 K<0xDLuGB?<BY,HNj`Fe-!ȡL6G PB! #)J3 &!2* UjpDPsk)yD sA7O OT&!L1a)ٓœ˙!?KV\MAx#BC ?;j$Z D!LA(🀠g0ƻCzDF&#15$ P?2 {J!G^ ÞA(]&ma{P4K5g֘J)[`j/)(aeZ_Tد %D!%25*(,@!#(Ur@Aٳ, \-̂0250蕉W _==W_Ѓ#B{Y!<$ rz !E)%t8((hWe |CiF•Zʠp ha^%d08gEomna>/ڳcϘ*/1 LAhC0#̈́lBe WI%tbBEIBV Uv4?]?j4̎0iSz" !NPX5钂I͂.n ]'g)]˯\3J0DV]@‚њdLJ)D4C[厲JؐPB*h5vs*}({ a*`P'| vp lY&;4C ?I+A sCؐVK$pQ,0;wn1TJ+͒:ѥvSBTL"RXa7\_Zz"0(!\1!w$g«9GPr)˄g/)~YJ* %x񎙚KonJQrBpR ᎞(L ۖB  { ̆}j/?(%TN)1!Cab`/ANպYJfedHi4I`7j`QvnjgRJZ&ѕr)\+jwl@'awϵӣ²(VL oB, _J,aajOKL Y1!\@[ DU7 G MCx+^VBr4a/p*p#zWjZHt0; ϠoH%ӣi{济1%Qdb|&O-; 1!l_0z?8H1Y kkRG)tmOr?WNZ櫆$T~(aLkoI!|WK*X"*X'yBY)y ӛNWݛ aQ'(%&ӣ?xuM 4fM]vὐPQs)6wGSZ`zgWNLyhrG ̗KIݨP(!,j)45_ Cw4U9Ya?;AњB'|6 vu*#+zP%7h憰P%<M$f[ؘʈGzKj.%!)Wݸtҍ+KUP •05Hr-4˂Mv2pY[[^uCXnٸ'WޯB* Agj9̬22)kre3J渣C%l ^0@!jvfQ-UgQ#01獞H<<)Z ;t0.]&l[*i%d)L*W?zՄ͆ϞPBNJXVkrB|h &V?Tr-P*b_̨~V^7 B8ʼnĠs29vԫ+LB ,IjkYX2=z6wLS ~ɑJH5Hkr)P[%DwTQ8sԈj9᎞`0AVI=P燄A;^IܤS(İ@SMV52a{B!Rg}ý3(bx2Uo0i UvmZCK,O$g^$ %~镊BN6BXxDbdۘx?ޓrŽQ!Jj3($>#LEr/{ j0gcBA''В2Iܔ(EeIQF᧑ T)!&J8 X_Pߚ&A ɠLmL\rvbؘS Sq '?rY"b:H/r=s@$_/ۅ_kr@ Awj:?B*j6AtH/s䙄t'aEp@AQ*LBx{NueF9F&0k|e.TQd٤7OndR3vQ9Z!-K-ZVU2헲X%.Ѯ/)diޢJ8ܘjOA%@w̤ң|4 UT['1 ;!ǦƦx5̳&b>qٗx0']*BԙԨ@c{4B1#w123FtK?tQ  ^Y'>y >KCB;:v̋_P0 0JrY M~X(>Vy@Q`gv=[R+ J wy Q KX6&ِReL[浅¨ Df zAa׫0Hů~*/ |ֽ_.BPx{R PfG?*q⍾e0]'Q<"oLa03鍲(me"BtPb)T1#~.*!Rh3{= %SYwy}%}CPalgR`fYhCf', ݖ 9jBBZ'%,j%vURX?ҰQ g[ _/-{cpJO%JhxB障"HY1!E?&/̝Y޽# %̚!Vw/^ /skdBYY6R\JFoבކ+=)0,?ZbB@ vQ!(- yI4_ W':Z!!ϋ3FvJX͇ЋmEC)L[7PKq/XHa&{T NV2!R=]*5LԿel p0!SVfAX]3BXgOoN%ww(T mL(!\qtj!aX^7׺=GWW`nbxQ?K)]&)+7ot `+‹2'ZaRx Ʉq;y}!$zh:͡QvP <t+%JfCXF ϗV B O/1(2*-jf+aqQ ; V<d \Z.n5 9sOH!\!!]fAXh]TBJT 2B\Y*U UcxB E` <eEܮ VDB{SB3|X@UbFeGA+]t7\;"+]WSzk%dP a(pPJ~뵷j_T`1*_ fA0_HS;p-J8hPS)Oac& l#8+vTBAxC^EG+f _Kpkgeec-:! !"XQ-(w49)+3jޝzxdGef(vhv=w0!WW[:uukfIaeд2GƄ'O/Gm>%-*9s1mN1(*;f> ax2Z MQ+K! <_-;QlWICB JX>̙"wRµĄ {NP?/Tv x XLQ鍂nIת'{֤惰BKPxi@I˸=dSu,?ڴBӷ높@L[3[6A*#1"7.v͂9`̌\)8J%e>BYecáHߧp A>Z tb=2$./Q_}K 5\_[~ABce_iN41#AU$dG[C ԉO p2vs0L%͙'nr IDAT5PGŽ9R :w"Z7j!AB{Diզe0Zה"h&K !eA} L0"McG!*G34]Ū4U v ^@ςP#xL^ !p!z(a~oEE ԐAa2* . AO>yrcM߇ӎv@&(XV» /WFKj&)Z?FAXgx^/(>ucp$ۅ744~A]OGA 8/D%D>·k .Vy>J U\ngEE>  q. .]2-B^e(5 C?Sj~bc %P0\!>?x$:'(C5DpcVH5\"0*?Va!j^ ~_IBbki֚x9h_;W#LnT~!o_ /ճ߁~|֗>d̻ ~JҵjAW !233X dptFú!vI)=ey@!$P!O1\ WXpnчfX([5J->AqxVb(e3JPx%Dg~:(C Iu\_)DK@kU KF `5\j%{"@*BVML }1 F%Z'F =84~f)9?:Ec!`Ӱ32<#z@\CcH!<$>aP ?֞Z) ʇ$QA-`{$9U(+/XT1CxZ ~.G7JA@SN@R؞@hR7= <C0. 8X/Ez ?<\C!ucAMQ ?RR kaAXXV' uG^P1'QR $ > _KC&7p. pw @6*0 ąZ*b+03825[F 7j33aT蹤(Ah`w#8vE}} q\>=EBɢ­Z Q !pZ1d`p=h I̘93NzL&&K!|[+p)P (7zC<AܲQ#qVBpBQq趖@-;þR p7p}gaEEC'ۣ?NZgfB!`Đ PxvP,/l 0dCWF97;*jzw0 F-\ zOqEK(ᦺMA̾}JG"ZF 5_B oN(LxauF!|AAP~]K :| 6mJ7QV'4BMz;~amݭ"J.DU:sF03RIxE 7Ejk)_pҴo#8"Kh&?cXL:ի[= d:Ix .}(ݒD)6 CF1G=Uzok~l5+|#* D@~~)9ܠHD[Zai 4 R٣'Y;wݹ(qJ`70!_mT8QN30Q k.٥І) wAFݷra. iZ?9 qi[ X@pJWk!|vo+^&XB 7i- )7 5gB}xHx(5yzTc}A/AćP aK[oH|W pQ$f?W ǏO>.)AbQ'cD)  wKз[ :[p?(9; w ڼ aQ. ҎJϏ;"9DCBƛAZcaodCsDs?=u:zՈ!z[%ֳr} g?VB(/o vÒ)X (;c0&) R %D _Jw .pF_KCdS J 6X%|CJ-ȟBp)D@`;w&A N(?NèYnb:79a!',:+X](wL(ߴ؀+X]^EcAN *3/i!ACmk[ 9 BXgv w+k%F;x\ABG/rJ /I_:"nR8ܠ J E.`P.GW5O`h= _T7.ذe9T(u- f ad CoRե~:g d,^g~AAӌ`߉`:?Oj?uj\\@>Iܕv(-D!ś6*jR"JG)ߋ;;Ψ/!/\$ UP3(.@ ƃ+?MyKKP@pC;%b8l+5"AaRB؆\>ܤ }QKPHA-[iLwn?G ;&$W~JPxC@$[_{5AkCQPc) " ;vPMnO>w$DdF ;,j D#p}.uR3UZ(0q1\2TR݉i7D8h8=D\JҙDЁ` JTYH5Io"AS`fÞGB(\E 5@A}B ;!qiu S6L^҆@'TD;u$Ϡ'EeR%d횲?v,qǢ=74`wZ(PxZ`5ȡP-]Tq) .%ܼ?c9)s@Y'?Fany߭2jZ N_6]aR .t5|͖A&%v|ǯ{KFT nȥ8}  $צŚ,@ зC3\ >zLRY$UƨO%Ked*oEW_tB_ 5@Pm,h,Sװvv'ue5N~;I1\ #/Š/u 0 uۯ>MsDb?'kCֱ_+!Kjb>@ ?P2bsb SPM>Z<#6 hݻgYei1aK*V#0iOYX.²]Q( wPi*\l@!PS=G(* xPB|{/kߞy`g?oބpf&=eQ@!@D3AXUEoU@ R Ιf7oxgzCA߇^;aO%W^"Ж—!-( | һRAz~|F@& 3 Q()D;RBb[r3QcyˠY3fxj|5< Ap0 xơSg\|;WKIHF`N[N~WuJ o!!hv Bx^܎f/k3E 庈!M'? ƹT -j07uI𥳐% S"p'{ 'jG"((ÈfzGj8N/Z !0,X *+*P5A(-zxiZ A & #C + f6R4tGf,t2LTA2 &D2 $(BS:8`[-EA`Ks ~ip6x;nC:(1V!8?L#;x_ ^,8uܭ[f*zn4L@yf0an8WO@zJטz+  ^ArU?ZMaJ(pK/IC'EvF; yRf(!a*09L><8g#ӑD̬@-]m& [V@(:+t )18 (D%!!8UPQTA1JpDM!*GHqu62h0BJ wl2!EՇP`8~G  18L0BR kA ׊r|2Əʌz5YĠUPn@Z8U DPg08 Fv%Z47dT#U#܋A aRA/~66)`H~d0 ^=@  2:XHQF3 B H pyN7BV*Z㾍{K!anq~8:Κ%1HTg5ef1) ϯfNPeeAs'4JH"Y#&PQ)n n?_udʎG0ew0{7&}'G^;WaH_b P>v)tbA NiحAPgF $FUaUO +%F7(0H*AeF5D KEK6ITlvAy:0 ~e?) &$en ˎ0x!Ő_$PR XBQPBq IDATpDP9>l$ %pQBz"(Bp1H AG*1#(k!-sA*`YoECJ?˖A`PgfN$LgD#5R.. ^"1{Y * t'0OAE/xaPn($y;=Z?!۩DܮS'K4Bwp%_ n#QңaGR#8RZ7AP B"BȋI G *(E':?tnD]Fe9`/7M!2(,< t l;}a /,8;_-&J ir =o %*'(Gij#$ *%ޭeЉ!ԏeHA gDtpdڵJ 7 xl%! Ʋ̌iW9tp~̂XI!̯f^T)H9RQy{$%xTWVeѮ]= y Cn2Fi^^Uz/cQwSJV |$WX"|\ wCge"~Va|Y ZVԊ{uV1 2!9:QڵQ wo 1 |^Q;1(!ffP  7D'kIO&Z2"# GV(v6XI^.n0mLwyiԞۖƆn-  ۈA _:(32(vdpp%\LQJTB !(! ƃRn;)sANr4n8H%*`pVBkk1;#B" ]CB2hG/BN^fjcMv1PQYS3hIOVbgcG{6󇆋^n&P jQ2eƁۧLa ,R4cPJuƕD^}0O2u} yiNeGtC$?h3 !! FpOmUJv߭R2R]`{__Ja('poY#!ңV~` #E*! $Yd$menqmE7#{^ssKKKSSSIxC?onn Oi!R0بG9E26qg1\˄Zwh_ k3j]׽ L_%DQɎx?W:3 brdfBHJHBN^л4XY `:iv1%BB5:QX(dGI EIniqd+(#R8υ05~3%#U@4x7%ൡUD>!"!7Dݎ {w; A RK?"g ʌ5 dP()4 kɌ ^F[P9Yvi^6ܩWq*5Do? dnTSr vsy 1(Pt  PlʄbP7룎j/.6pĐtϔ !eF .umppH qx?MX_^B(e g)4J(BFupO׏HP|AbuӘVjXpuZC-̔5!]mot$Q)]Gb4U]$]?2!o _P?L<arl,"Sғ(nL'X14j EB]72HFT ƌpP}{%j!6)G~ˤ (_#DuZƄA (Hb(lTA+2ޮқ H!!cEiSw$YŅP'T K24sT ƥ0REE)@`;4Gx`@p5]E% AIa}_qf6 P Kt~B4t~9 Bp?'/ "ŪF(‘uP Bohp7!1O947"J!+"s1kW .3*M (|ݒzta),JM ,PDG /Ka2ruxgB ^eʨ*'c7X *Mdfڽ@-*'ݨBBH)$?Y&ݨcF됐)aSBE!1  QjsIU MvHhw;|T5p0v^f. [ cF:PD2>g9tGcf%p{b#)CoL70dIPe+('sPw^wy-| F{ QɌKTosB3@!22$#3j%$ R Q. N iͺ{[#Q& :ȦӘC6zEKjE݌s<&s0!3I n+S+5ËzGcax5^h$7zUzx_2WxBC ȼofn~I}A%Trp ߻EKGџagvyKQft` \材Hh"pjXIh /zVXͺgȮ%F]!։O } yEAJi8%9*,prWZw,B~3'KnӶyo4PLxBÜ[L?we3 "dGLaI@yQ&ڋAu;vǏrq!!Jk%^@0\ņ̵eͤ! .F8te6RXOZJ#K fnߓQBaCEYܶdR.['BG܍؏L#.?~ Չ:!@ BA2PN*ԯJxn6 `VZI8U2zҨưjZ7 H50RX̛>;=WHteD ÓF0RH+x((18fMl2eX(&M#rҨǃi)d]"!2 7)0.BeIe`^t5  hǭ76PC9[&[$ȗta+bڞ4 !\"ؔNIеI5CwEJ"“AՐC{ڛ^wx>2_{_y'ߊڝ۬o{1˨!(^ҋN6J@A. Գ[  F~Dhh+a%U ]E;(̴Qv FҜ.D D}劌W hyEl9W "4\~aT *d4(#. H%d'l[z !H:xCOh $=B.brЯv2ByרFhz'7ʤWBBfFm7l#BkXDPF"sc5j =#+ r'!b;N%[̌v'WXK&OK9ȓ&`nHވ:~r z0 p‰ $U%곓QӶyFF.Etp(^Do%-Gp^2jcF;bDhm"h,CfT'xB24` ߏEaj;K #p\EA9P)H{ј^ڎz{.eA 6Rj45@s_di2AO2Vl\h ww9pA)q#yup%z!B8Se>ȮnOȤP*!p|Y*3j0c!ˌ1B8aV9 $E0`52Rp !H8 -0`7\# KD}0aÂ<^t`.#\8^KeHЌQXnC~i==L,pJo%RGI q1<q2eyGU^U1RA1]vV[c@,9^0X5^/PdPr:8g1E a8q\;q e+(pH_&11,¤ [EZ@cxablb^w㶯TMJ ⳌS(DTJ%8~t;bMN2ǍNenC@2u*,"Jq!0ja ixzN%xgBq#U5J znERI";bXh /̎a\ -K%j6E!tP,J XPHB($$pc`8'?rcgҴ_p-1l]Z -*+1<(Eh|BEH!Bý `pp*bp*Q8JȀQmNWY3J27E3$G0%D!\(LAT"(9Cљ'y#Ad |!-,dNB!tdF={ F0 YҤcBf{:L {ZRۑgwE`o)r!(0KnοwoDPT7PoKΠQ=A3t̨=gui-ANDhe,3 # ;'K W VI s &rxe{ H %%ړFZJ;=3XR>M"hV:hP&D_,@Dgj!2H %z#.P儵=D^#8t@nRPpH NTg V ZeBA 8o fC5X{ 3AS0B6o BK fkߪPWŒnކ].2H |u+W3>-_p9@f.E 35 :PdP8SÆI5_fɡdigq :Q#hbP8Qob)_oxA KW] BxB^N ϸÆ;u0A܋觓԰]Ahaڨ+{P}%J~FwE4 hB`P#D'_ kEޑ@ɡO? p\Nf2yQ>Ѣa=H _8zk4^w(sk)'A b&PA8v*NG򵼓͜QժjBIw;bp[cZPf5k0 5 VUT l"š@pSXGc8oxZBP(ބ~CsGD:Qw=+<~ >1Cb˜~!4ř=iL CzC#4mȊ1xJ=BzIyt! |A}~@p!;vPI 64"6@ 7 JH!AǢ%Ǔ9OI )4BC`]骤H)G"xs-CPĆw0x 3I’^|qV1LoiK.TZE-+ ܋VT"⥝d\|H% H jwQAE࣏"z3Z"(ɡp| >;6p($[BVKV6 7!CA 2)D1R8s/lirDqoQE1,L _,i24iP(5Ax"lS4Ad0T (0XCCO \f.4 > tK/V *od@TBhڎ4fp͂A$&F kjG ?CUYdcAx %D  ǠA(=ВJ @v%7!Ϡ1‰Fyɡ.PsE’n8a) ZA (`] $o!N( ɠ  ,PbO!O*7Bz.|><|!U o/^^ͫChH4Z7*7*DV=6蠖ABP!ppUwaI i~f2(bADCjxw &BeЮ !ðClo߸W/P'.zP53x4͠xa0dP_1XLDPB t h;<31H _$\ 'zF, ަex:Ű` SуbRoG?$X,!g.b10 ,jͼÛP10TPϺu:,1pёBXO:4|r?dpAPF ;A a5cnP!F!H nHJ?ZC ]T3[`X5 )/HBh Ԝ.\)669n޼YR/Aᚍ #55 RBqfP4HN{ a04dT0OaPAdJ%lq^0(ɧ:uw·Og0 T =ς?E#X&aY]ڑdžp ptr 2ǀc28,T g9[>Q2B< DD_UNtQ`RbZ> >=Vb8I6J 5"(F`P!XI gS.;' CєXApЫQn0#E } /S14f2),*'(X(8% k?MR(Z?$p+8o _^0A1X úڕ]ٓ=#/ %Fku O()TZ5IP(ÍTBD l4^2l@dC0&Ǔ ذ0 T 3I <XKZ RXҠ?+(BO KAc*}ջu|-B%`c6֕](?#Bx1*I| \dDp"gSP OCsƀ>ܼYJfeHFPi:A ) NU8Ċ{>!,%vuRFT3HBCh(ӧ_:RX,`OJ(MZxz׻8vmE:Cx2:( 3p`[J!4J !?!ehE1|f!(-|1Ft]_#e0CG Cs6K<589tDB~HbB |8O{y&t"SM 3Ch>_‹3Plٙ]ږw)  0F [AljrXV=i1K~MB($ |8T2`#?Ɠؐ0RhQhşP9{1'S(J Q0Bp1ͩ ~lh^ }%b="s!Qᰩ {);wIwB5JX22B] :E O*03/g!  AAzX71Q zňy&Yb":lB2)`аzڔFN?}fEOtBԨ ~ OuU i@@D{ e>a--ܥ>IRJ C r: wuږqOj? !PF;{ԄY. {Rl8B") f`2vh8@a~Q ;tQDtHr(OP !)aA@wDwaKZPR᡼""( Q!8)KxQ(W%Cw}ϼ dq8Y H"n0h9ETvg1 A% "[jA {MғSBh(8M-nYBPD[Z4B',L7C!%;w~noުP/F n!HNtƛoV ] ^t8Q*ČQU !2T=4 5DUA(T:{Ԫue0W b124I 2$.V43ɞ:mI"r 9'֣LŁy])Tc!^r SI }j|`JƴPʐ/[g#4 .]$a'juu:G(O גg,W#dJHe _JěB>040 ul(CC[6>5Rn V9Nڀ`ab܉2eJOCCuW i״b)`ja'.Δ)Dž" @ +g@RE AnEɉ !Q h24^ 1H"H=N4/LiHda%&JEh^ln7"ADpK-0)0IR M񺩑` ߘ/Ο8d&}3B84ljj1B5%Z]ne T^DB 0_(Q+8i Q }Aq<RMYbI*1S*(uP B2- !4ܢ(4Rq 2p:LD=j{:&NyȬb׾t| Y p5njVhV#3 *#:pRftBcrMΓ'J /+4l$T%ʠ MhNel4Ieb8R QcG %`; +p8m:E]?5O7 |70IO~0Fy}? }>}4 6Yzho9XZx (ᮭ[ADO5T UdGWXc%dndNԪ Z!`΄9ق* e@( u3-ԣƛdGyM ڿ'ީ),\ Ђp`g_h}Dd%M]'sDSSInaT'g+ D O"+GBhň`luFb&E-DjʊAljv@^4{R+s] BDo8:,qe:GZNBz-l}8 M&ϴ>í<;Bż, )AaG}48)o7:tK{Q:+_~UX&-Gf+B(3 Rd9QBp:lTdZBR hEOzLT (qwfoH  :X-f(bpcQs0Yd)(B(dOK#/*V Ē0ƚQQlpEY( ʴPw ♡P&eu ( 8*ģϟgfcm}^A,SJsp?3%D]0eI%Unt0 TENoxRIa@ LF/z;A^oRpk>-1ˆ @`HJ}= 'aRY+(~JE̐Zí\DcV1ZE[-s >`B .Wh :*(03-:b-ϜYDSKYTR&X ޓ`KcQ*ʰuq C+Y0ZvBv3)GDB¤LOFܻw/ފľ'I((,BHb4x־gBHj%BXY92"\Ž(a.LxJXNJux~)ϊ= ]د:_/ͱڽFI lC!$+ROAy\W%(xQOdQp b|Y5T)sgT?k q3g}zPPٹY ̶)S;?\4VB*D2?U!NBh2BBRŠ4% };ZW~~d# ɐj7&B&<ۙ+uY[9Pۿ4\ ёRU0SEΑT &=C!6*?yVdg9BRt)1w7Oj Óa(;sd`oJy!kjH{uEBk\2]de=KLH\4,++V+ I! <̦r gBjΧpļ9[@ C]T:ZBTfdY֏UZZ!(.!0 A><7yH9Jw-l–tMTўF!"DGS3](!@XP]]Ўn\3D)I++x ,NBh2 VoߏϼΙ{-JvpweCt|hO2(̨q4a0|Pq}1a]D %Pɤ7rJs^wZ8&,uR7Ѩ?ѡ)5Ht0BOcZрBx;AFfd>*",yU)?x ^*6=Rv-b};Aп1EF~4\B!j JaO@FGW ':Z]h.>/KbE!QDo eR !ISķHbFDŽ+W¡0ƄSmZAa'nMy}CWGm )\j:Aa aOWJ8{\PF{ Pxa& **Nh3RĘP: TNb#oPKj+PbI!3,Ֆ-:)#h[L0 ڍ U1XTto!C= AtїiV'!/Rst6q ώ^' žP)${^ub 4EbGi H)tظWo+o !{^JL.23ed%J ynv$ ]%D7W=CBjb$-t0YhЏz;A/swQV2> @ÃMi-zLP I I3ZW'8ʍQńuJ}B3Ie;ƃBo R ,5 &f +L~bj:,%$Ŕ0)"<A =%z,/:]BG |An BZ߸1(xc;߸YƓPb}W4Mfk:O~YV!!%tRNAEEu:a]EhlIbCh1,t(&fO>Õ0Y OsI/mJ8sÿ~#et();ɹ *} tg8E{r^׼K@}[:_;R}qÁ5#=-G\ PSWVeaj"`CYv ܨaU ( DBuB;S3 BɟV{`WT% ҎL޹'Rx//ҽ|,i;.3!% ~ɖ“6X'B!O{/RP=of|W 1k=++vx>gc~jhPLXTE@!dCԄ*FNuvJ3VS< hRVd 75!| D!5H9Zro9;jɹ%NeٺFR“q(jQL;CfaU\ ٓtpBFI T(fQºXbFnMgrVćnM(Ȇ pAnFmx2F Tů]BM6&!cQK7 tT}_7&snLaFhw^px8O! QL( 4\P@QU.Ca!s!) ){߉Q !KRƽ-@Lq|gh\n›|D%d *7`E JS)#2Wœ5!#*! J0&ݹoIeUB!Lۨ|T@S*LB6& 7 {8O7۷3rB$?VT$)#9$y<B}2Ąn[c Z _Qy.\8;j8Y5嗁USBuTb&ᑌ=<Ω3A3@"Ztp㖴5o ̒9w3IW'd\iƓ_1,?33…xx.NBd/D?* AbQ!&*a]ꭰ5{(lR|8;+a+- 4ǷJH$nITo fТ0~)BmIvNlEs̨9؏fwZ%P(.Z^j&A&f,ei!d/j%)1\ aS"Т0B1'86ZӔ0SvTݞ(sfi1 “`P HQ6?_6*d&ܰ=Ҽ,՞{!7Oaq-x]ݙ+*OAö0LO?Nɐn5ntH%s<5gML*a]Bnj/WBy, %=)ض{AK2bB6 + >'R{B~Op(p&~;3hC (ܦJ ,ͣE; r5vwb .?%S 4+\ IDAT)pV!=bӨղ&h2<3غ}B6_]Pqh+p3)WXEfS FBu"^jl~FӕnK 5U#oL0vʷF<@--=PP(iTq(?<pE( w *d&݂ Ia !`DCiǕMTB5cPYSU CJ_eG U*oK:UYoʗ ![%j-Yn7&0p5}V{SBVOsv(ܧz /ieYH(w*_ձǾpGKm/‹3ћAaH!C033_aB SPk2aa((+av-D3a5n-T['f<% odFw&1 PBlo&w.!Fss33 Q,P*Iڻgd@E oa ʌ;]% 68,$lJD?z)!xQJ !%T ʜ 0lrbFfG+2Ąeuhߤ]PWJ rY.ضf2t'w;3;Q#.* 㐴׻P/l: }5'?>}yYC:PVfnuh|4?zVBPJC^:EƄgJXf<V0]v%406֡DҲp:nt-lvk0Ǚ)o;|>32AXX1aS A^8(ѿŅ(dgh5b'Sn{eFݕ*X曗ԏ7: MfBW !CnJ>Ы>lZLy f.p>1&Ċ&㩻>J⽣|~.!CvTꥤs hɻGxS^h1\忬C!Sjx2eELdE B5f/ ՜hgx ;za0 )!dntRQYxĴLjh{;Ѻ: !^&LFҕ4SiB}w:\$c7)L@XR_h_yY)ts3q)nDOh:p}33CdnjCfʎrLp`ʘj̖63\gCX؞B*QЇ۬ߧMuB̅_p[F,mrpF@CBXcvcf& cKڃZ"853*PѥKu~ Sڗ&%w,v4qkzoo.;F"YTh!(̥^Bp89*GL DuWPW4!MJxGQ-R(9/sZ>GS!bL3$SF[LJ } 3*a]Y?uJXʖh.aN t\2T0Զ$ܨg!VavI'vz ).I9f4 EH SB)Nj4.]2iee ݅0uuu%|V®3 dp#c-i:ao73 {0:h{w@#q -njǛvR:f4Z |//Q) ;M1;juس ;C$ftdX߶ f'./R F̘֙ou Oe0hG3Zˌ&!4J͠ubkVLh]ϕ'plS`+ oߞpw] %flfv̔jG!ax9,/?$?ԤZ Q8pgqI铼?LRPJ /2iѬHKxd;Z6`@ڪkРDqb¼n>Op:_ɛ{Yh;! w8t>«CmV U(0|I*E,;^Ϯ~=׏ y^J#cBoLh.zKM"H g;f=gvL5~yДbvC$h($ġ}5wCpzCb=\aoފƴp`;񗒣IAaD m3 aPMpPRfmv^fGs9gtLU ܥFԘ0aEƎs~Ί'7$޶hj(:~уr>Zkv:DN||ߛau\.<}EP[e VB7*!JhzGۖ$T/OuBO֑_+y3v;;Sb})nM^ro$wKqkҧDIW/~yG ̚/-Y[:ZY9-X0󌙺1:&,#%t |ˎẑuB6W#t뚴:& )ad[tksG^OLޮZ*1x|ɯ|NUpfF,6?0Px4emIJahikrZ]l!L3e[go BM8P'n'b}JffBa^>oat䠧2|37'!\Ln Ł2dbOT^&-=!OUvtݺlzxKI̸R #(8v:SRwQ𞚄9{RϨI;mw๣;*iD(lnȰv4<3Teң7YJ8q+!g9.i^Ƅo1!/„Z s*CEcfvSEmy2zGDNSEbŒ`w^{İ6- 3(1W Gր%2.;VZKR&fT>ƌ/ul aJKmR2F,-x+Զ +gy;܍.ޫ2k ~f71yf[x[RA7WpBV<&\%&,˲7͒J7JhRV0mXEKRf$)G+2ƔQ(pV[yQEI|,a 0Wg[Tayao VJPMΞ-`?nu uBHczhmqb¢ H{, l2,b>% Bx-ZLl)&5!Sph󇗄k5Z ly2k;Kt?Cʣh SBXo1--0;*7Ƞ-n\AOpmV ?2!j%oтpvr>)CXm͸&Xצܠ=lՎ&t7/!%$G.t!-90M өn K3>(ySOs EGQšߜ?(Aowp_yT0 .HaӫeM S&'0ݍ]&Qʋ?zUFK gń!),JZ=T%|]ܘj &$tn6[QLḐA(a4۝1^;s8g|޽xܽGԿVӁ RB23@V(!\QcYe VhqZ }LW{ם cG%$+ MZF,QB~) Rkaljq6YhBy~44{%t_]W,0!#_ +7(EvffҥcA)̜ˮ )1x:!ы_ec)!eҜ}M?6p5J8B'Wف1EeQ(vgz NUi|-b%·Tc}^<7JᏜV|m[3Ao3 !$ +! )f%[;Đ?NYo+aQBGۮ@!,G?'9v.neb p%oU-\/l)_GOue&4 r]+)vT?<;!CJG0\W!4 Z>^Kw Lp}0ƣ,K PBdLəM_(eG/WG ++ݮ5$B");JĘ\w:fւuk3@Y =.jfRi{ƌA}; ##*:u VQD@ |hAu[OԊ|X8|pkkk'qG_ta[.a܍& Q ˩.'i!{킰M\cJFNE cP8_J q+_B׏Ҟ^iG+;^|7ʋL kx !`$ll/=TS!a`LxC^QBo^ǂVOvBXZ-!zpE<$]k:JB9d7 {?T3XV(5H%,'fcºĶ5;C*İUµȡCpй3?>ȇeaـ,W{mg06&=*BߍJ â%M~^S3sX~|p!lX-7JeztOA!IR@v Dik)1aNr"ך a]gw~ylٳ_ yD5;gU't稭Dl[ o8) 7F s/sO!pOЍf\PɑT?/fzXM mT3NQh!lyӣCBBQJI /[%fƒbǎ*%L,ZӛBE%JɎ]aHsAZIh!TKB$6vDž(nS=dm[j# ?2{pt7˜g:fl!Sk 0B@QrJL.EWbP(SX~U Ąy "XB6% )Tydw"[`d]`F>QҖ* i}6)< :2xZ> 3ಥT`j1,&>?։\nW~jb  o (xmhr1eB SZ3"oPt93) oHpvc˷YT n{H B{z30uP08GDh!t&9P&KO#Gk7l!B֘V%nt|* !7#)|Vҕ κdަ=_b ~Xr1_jZD1ĆҜ0׍pڜ IDATRz0I =l9߿%>X#7 .xO^ |jexom= ?pkk1oC=Fhf=9Wψ4 #ZJ| 0bm#j( o(l NsOjX0םq\鏸 dp B& CG啧}OKsn iWzB5_f@33ҏRz0\ RcK 9P`Ѻ2g'ZE))jdvm-!Xp}u5Rbw*_kXBꫠ@pjW]H("xS΃5#0*hG3=htlO{|=X)DAG}~pA3NDCFBjޗa&w&Gx!!g̟Ϥp>(!ҕDaP ˱\hJd:{D$dp튵nh#p/KjeK^3S`{ Y5 %bAO?Ɠ%}ꞎRÀ "d سC7}_7ɜ B,S ;J5 GۃZeii.J.1c~pRW2 ?@H)ӨD%1!\[+E M3>÷Ű3օҜ=|ͭ R08hI`E5]-9-zcz5Xҷ;J (U%92{ uw˜Do GB6F ͩۚN9D>b&'W /.P1cB|P `GYڞPX<,1=Sg(2ȝhp #aZ|Aq^Tbx^ړm*3XZ%Dgo 3 )'_7mza{Ή>Ŝh3a'uBüݛm~ o eq}\/0P]/x7(!ra+|tǏ=z&[Ѿ}GMFd erԻ?AB(!, J #E HIa9ဤh%ZWF U-'JO-1$QذA6'E1 I͒8D3 Ϊ+ZS)I3(^ ۨ~YOwbx÷~  )^6Fм[s{~-Gng17N%O0 j(֣ y]y9kIH#Xj̏}ULh|AqO˃TP0xXW`)KWհ oUp01hj֋0;Qǟ;ANW윅AOۺ^ ZkaHAN>jS_ju7,:36]!1a,9|)*&$!-br) t8C_+xXYbZc# 0ҷW 'Zʣ&"i2;b;]rی?x/25 )$5D1 T e+Vh+OCZ`o-ذA> 6.x*'_K:z 8F k@QCAp|KNI &}"NK)W4o]Xeዧ1a#*}*Sv >\DM}|*AkqL6]kloe$$$)bB!Fx rk'4,r1lPB A wxG?W` Ws +viI͌Q \ZpiP M|cCq4484{F-]pD 0WB}e㟫@h&pwԘ- 51 BɏLYxC-E  ~j%N.dًT޻'QmßW|30 S v 9j޻I Jj6!:rR&GXO./b$ TIeːFl"\ W] La> Jo{ wl4hBȚL!IBpnFTJF 1tr9@ϷBA M ߔ.e qE8p++C #1 go;%8Om^t눴!K%+1l!:F+l=g'`h>!W?ѳf ϳ;F>7j B%Q%~4)ss7E'X(/MN W'í[-* = )0+*$>XI2 礑]mɄ { 8FB@iŠ])#Jg14rF` "V}S<+~ԇ D(Z"DaQM ql9G7C3>}= 2L@&*j."Be8냁>ۖ/HST#rH>z0d ɄAk8D B* ?=c "{' _`?ο(1gЛ&k~y@U$F@Ƒ(L<ƍ2c CaPUhI* 9ZWdX"yIGn" Gt*٨{A؋L_&& A`NH;/~%BdCo}JwM&/=0M#AYa91*AS F!`JESxbM}o hfNkK֙5GU.:FrF**]Dqc!C>BHjAqል!"F AIG Wj ĕ?# B1:"$^pjAۄ7QyFMA1X"+Ya#6`H$ CgԒEo$XtoǾ}s私yۈ`f7L8"&b7C~4i̟^?FDDŃuG @ 0\x]]d pNKş ob-FA(" ?He(RA 8 eY" ^1 Za!DP2QXo <]9:Ѡ&7- A2x*@LB͸ᯐ_`1%ry<~T|pc3BUFp1Z(!舐QƐ 89" \qj%sh(&P.".G"wI'M>)(?7Ʃ(ބb&Ճ`A`lbaP6PP-w'JpW? ŒthC d/#0X;xGn*R(npDQB՘q=NX" A* ] 9#e`xρ/Y*FPH@}odid8," Ż@ ո @n`15H&\iPLxAb=8:J 󃃬B`MCšAp8v&_Ah*G'ϼ+}"'vGǠ$K# [PꆖK(CsBα~Bqh#1&DJ@>:7əB7!5~I:_:M=bM$2!$ ,p\|p;߾(ͲdX J9"B ShpAARl0"Pbl z ` я!C{b|ҋmm@b7:_Y %913zo0 7B>f Lll (p6AGCᤪ ùI$q#!H/2 "?< \#?f3 ahH\".\TH"{q@@D8< j4~Med5xE( j4dGyp!F 80@!мH8u\&5F!MOCUBa6;*y\dbMF&KtU}"d]tS17iՄ*E lBZ A-G(EW" wq Zq\TK{ZV}P( / o[Fقv( \ jh ^w1.ż/~KK,8ڳ{wV{0Z: Hg ܙyW"X2(|})0$ r8I*Hah8wYQxY 9gfFn33p&\T(= x,׉2^|,SHr*5a#/p6 *i:D w66OүA'\4+KKK+C= uB8oHK?sio 3 փ;3#ki@?tDK bf꭫ "p|M.O)...i5wWU) WHʀ0V,/F /YF:dFރ]. ., 6,|em{cӋ)vi8 `էU-׸?gQSp[ ܙhMc8v)Ab(! 2cUWgpbp%ńH!nC _Fަ GV4qQB= AAT|!аA7`p܍vG1B ?ʮBb aab_kki(^(*g &!ol\}dFه.ݶ /㾬0^!x-AS L!8.\ .[\rXu\(2(A^O@. o_aZ ji-a)XBpanX x˂ሒ`;ԯ=ż0Q5`D|_0Ҧ=L#fWDxy2!PxMIi* iNэ$v͵) ЃxᏫ 3tg g\" RUbPTjA 2|ZȟFж`x7!xV#RtaP@DɆH]!.SDNG`Q`СĘtl#~0.P>|㓇 ԟ Lt6&$ʠ^G Ń1~-[i95!bMh%˗vY Ze9Ʉ{WUከP/ e;.ঊP# j` A+a73. 6D"+ r]9,)A`v ޹7mz/Ŵ&U" tk p+5f؄oi` 9VQa7,"Ն6䔔Uȥ!3KՄN 'DѠpX!12l b,5!Bx\P#1JttԈD`8[d" -1!ݻ#m[ $=d ګ/W3П1xf Xl@[f3" i :iaM *]n\dخ1tQhpFMhjB%beBH ( /( : *jMŅZXrMț%KXz<)A"";}( Fc4`N 5 MZg֟(BLDu7Q&Ԡ`"ά(a*"d¶9C Sh0dqNx (Ό j0D *5؃H9Fp%l@8"/X T8d DDpjj !U)$p7 M0bb]1p>Gz &3臐 Amk>ݶ9?sN!h̄bGF4=:g9RUH&$ Ba7e^_o,Y"p0pJGń&D Ʌlšhq[f& FJ cyqoax.@pxHdKAgKvM9($Їa|~dd}KBapӏ>궍9:o \`h`HHɖbQIDATuMa%¾>( CF " ۯ"x#gɅ*"r.ZE"<(DM8P*G  )bq~g  A~M"BP8 . zSS%% %l?p-}$pXT%9`°n^{lRmkaE^3Z;&!!d^̸'g [V) '[ A Js)lsL؎DxlQ(Yg UT0"H+BoUi#@r?,C. CIR %0d& /NHT lI<ħ%݊ii Esg0B^/p 3+ ~m/C1Eܡ5. ,TF-#Bu(C?B ې9"0lgvۄkin HĢAVABc˄Z_6kHue N9Ѓb&diq!nX"% ]%'(uX(FDF z! 4G}ɚs~ /I兇zF) ÌQe7; *W >UBL\jP!8!`ٳe@aij$ !7v"6E!WķX#&SF)G0kӎ(ZB_}?9gHz^_3zyLh)Ë 0^KBslD2d iw[wE{bY*HC2a4(}* A@0qDU~!*Bdia`",- {Mx!z\S N֔ܧ<"qS4_.ZOB4Q|>N`*n~__&{je0qaB'җ> E!YL(3.иr!RA_ фYIFk@``xddAah G\"~m~A/ohba9%HL&Ѓ 2i&`Zd ):ɿ S+[#]y'`WD|( re^.G}}}`J8_} 3oB:(9}W1^%8"T \vw L!v\Ā ă_OsEH((8z #~d#a?cАLҹj̔L)qHh"DEzưu UىѭxE<u04@?KcbO ,toy!v49z-R-I=i@t>ʞd#4f$/ZB/s- qT p%!"h/[\N* eBaꭒ6aM $Ph°AtTp"B d"rwȂġ 8a1!$dolBهÝ-Ý P6X٩),Gb')̆F}slOt0/e2)%ɩC*|Q"PF!wfoD_%;ex@  m/]MM8k10\|t\W (sWs CDCD!ldpU'xTYtE8QΝQPD!2 jlSѦzV!n: bbTűD`5{Qlɦ#̠DŽ̫oլ)ssg](Q w(ČPB*ic:~oטF"FL=h0gy](Uu@a]Oc63BaQK!y0Sa%BC@o X>Q,/5 BD&O4qMX___Q@ˍbVܙ'>S4ϒ`a*=r_i2R;贈e 3^2!e(PLs: ݰvj6 /Z8hWh,X REH^P\DT2 ChUG fYa"2aU=X& :@4aqNC;};U+̡,[A/Ck^"Ck>Jœ2"t5pL5a/.!P{i1au'Sx :; OiلA!=&$ 9% ɅbB`jT R6␘"f`Z",M)T"U * rWۊo-ueCf )UcBnp{vNeWL+  O l((&<0ۮ5.}ݖmT*-QCG!AmL(bX4e^W.dz2T@zCZZ@m d˜+ %87ǚ10veOkY-]G_%?p:*e!&Ҁ"ʜd(_ufB"Pj!u)X]DH$nV ۶8%g0]l'iLx'a/6ET}rͅ ҄Hb1CPeFBKo_Z w:LSH&RH}&De>2kq;&u>B",LG3&*BfP)63iCԷ˨В!zAJEa6 @Q TR2}%!F01dė<}ɋ_Do9zoBR+Z BXH *s_`+et*zOrQ u6V)E!)p>ʩ%B96MhcX#° #$"D R JG1-*Z-\>rq`ad7@? aT_>s Dw'O~|O}G|?-z!DbgW /QYL9}u|;pj RxRǙBBPehBPmT #fڃk1 O155a1eV.Q,h@"tѠ[5}դ L*o]#b#8LIs`QxHP @ٗy<-?zۚ7%F bKƄ~1!an!קMH JːlMD(0(Bo6zeM\5RE(|]'|K}d1a͡"P(@_E* H`b^ZO L՗qk⋷Ses~mᡠ LsָB CA5&E䖄ΐ - Ձ#Z3)L0>NÄkK|_~Z2&FC CCB&1>;J"t(fH+rNJ>~gUEEȡLHEa-eڃvs4XZmƒteBas2aM sȹ !#R s0n BE=tId(nNnn}3Ӹ k.kky8 6 q!!3(xR?m{PSJF@dI[Y̠p?BIF912s[_UaT6 V'rfX(=fk;[T܎y(HD asVQ9FaΟ%D #]{ "|yBKƄVMfBpZ 04%Q9q焪9zce1^xVUUM)<䦣P1/!%'j$8A"|8,]8,NIi˸ĨZ*^kj2ŠB2`saa~>˹5d6GA&\g_jg^v<`3hЅTN ̔0j#, 9 ("<]J 6uVo4<$<\ Mhy͒5JĠE`ިC`S}D2j'AnT4oo8$Y$'fµ/y:}3B($> 3ܒ*tR̰ /p^.󮨐dծit=X\70ŤSyS`ї0OÖ́kNsǘh([U:J3ؗy`WL5!ks 2-+~DADAM 4"hM4 O 4($L?1QAFƪFĨFā  (B((B: h77ADPI}AA4PIQ_9@b[![lJlH FĨFā ",B(,B:     Dh8  }It}QFA.dlhdh* Vā[ l* l(-A  ,@(@: 3~DiADitA:@N@NDW+9dhvDfDlZ"Fª âl(l*  h  O 6)A^DFxmZò"M6u. ( 'ShN; k#] ȕȐt2-3"@ͅPͅ+a@6 #`6!6PD}[iAbD)tK)A ]IA>, QBmTl]\ĈdH* vDlHQJTB6P#a,+aK4K 4K }6DDbDM,P,W,khmK}րmE,DqnF8ă%dH%dIaXVDaa[XF斴fYEl ZQ[NfӥVӄ)#i(K)BD)d% ZFvK)vRdq,>D;R4lZ)ie:c,C#K)ie%:K(̈%vDZ[eQQYEk3#R3"K(͉,Q[eV¥,BR)e7Mg6)<btSeؠ ا;6)btQNMtlS8b1ŢdIlSFd:&Fl)[F›&l*lQ lhl ndI[ԭ75X75P7]UMYMXaMTTn7]BT$)𩹫4*c74uGJT4tL{'bꎔS!b莐NGC)e;CD43itSt3)tRy0(NXW}ЭfyZ3.Kqhj)u'jiF§iFQIܽJ'q ;pzbSzRcSzF:@'ztSF{Y7ɜCGtQgtvEStuG{)غ:cv.ڧbƩujvjv.kb b[}6&u 9ͳ,?.kx1f!`^yu3Xg bjNӬhSzօ^;mgzu,YNSz[S^Y%k%[ ϲ0Oez빤r3<I\L|,8*kKC*ƎۤC*wRmil}Ӫ:ܵNVGKC+"ɩYu-u0&e\}cS63gfmXcKdhj-ezmj t5 $rիy_?ʼnneK;9mS;քLUuz*Yfy+jbsj8*bskbԞF*by% w\畸gb[5ݗU6툯yĠ9xO|Č<&a&soM;Ecn]ӭr7T=ڷ">cڅߥ},~^Nwi(.Y G?qoN! ?\ǓFa㗉;cόYp|l:G.?^'z%E3Ŝ5sL#Yڭ[ofVW`s ;r/ [rMu8sc(jD{+D/kc6L<쵬&nmI#%ҋk1f)HFMf!3݄aM`I&֮tx`iCAk U]i/6`>_b"rC&p smc#n^2{Z%!n79-l`hT돋?[鴰ٱ@_BS]Ʊd8@p:^ܾo|0t=ݗq47F+ߗ֎m ΤFmE^~} ;)p49BH~ <8#/l0Zh8AxR{-{t3u`ųA,n?Sůk/g:6Z^wS}ok57#v]@o5OOi=D[%pu?뺛RG'^?^~O0K;{D9"i`1o|ywFYZxtxaS8Qm6xlcqxsg]3}`ǏLd fi=n8aye) $?~*3͟D[va crG[OWg`%l ̪8Jny+E A)r< HrAB\${悸`;d~ 1r3AxIX ŘV=wf:_ۜxTaY9̛p(LlM{׸ qayu-ԋQq)lx 4mBi!cYI&")d&hFہ_(-_ 0J9(I\h\5 WAdd)Eg g%Q7 q'!ſct0tGa{}Q˓O1"~(a{\ai xg6䀝b0]`A|QkI20171027?083852Pbjorn.erik.pedersen@gmail.comZ Benalmádena_ AndalucíadESeSpain8BIM           Adobed!a1AQ"2qRS#BCb%34QA1!#a2Bbr ?h- FĨ‚ !* h  P>+~DADAM 4"hM4 O 4($L?1QAFƪFĨFā  (B((B: h77ADPI}AA4PIQ_9@b[![lJlH FĨFā ",B(,B:     Dh8  }It}QFA.dlhdh* Vā[ l* l(-A  ,@(@: 3~DiADitA:@N@NDW+9dhvDfDlZ"Fª âl(l*  h  O 6)A^DFxmZò"M6u. ( 'ShN; k#] ȕȐt2-3"@ͅPͅ+a@6 #`6!6PD}[iAbD)tK)A ]IA>, QBmTl]\ĈdH* vDlHQJTB6P#a,+aK4K 4K }6DDbDM,P,W,khmK}րmE,DqnF8ă%dH%dIaXVDaa[XF斴fYEl ZQ[NfӥVӄ)#i(K)BD)d% ZFvK)vRdq,>D;R4lZ)ie:c,C#K)ie%:K(̈%vDZ[eQQYEk3#R3"K(͉,Q[eV¥,BR)e7Mg6)<btSeؠ ا;6)btQNMtlS8b1ŢdIlSFd:&Fl)[F›&l*lQ lhl ndI[ԭ75X75P7]UMYMXaMTTn7]BT$)𩹫4*c74uGJT4tL{'bꎔS!b莐NGC)e;CD43itSt3)tRy0(NXW}ЭfyZ3.Kqhj)u'jiF§iFQIܽJ'q ;pzbSzRcSzF:@'ztSF{Y7ɜCGtQgtvEStuG{)غ:cv.ڧbƩujvjv.kb b[}6&u 9ͳ,?.kx1f!`^yu3Xg bjNӬhSzօ^;mgzu,YNSz[S^Y%k%[ ϲ0Oez빤r3<I\L|,8*kKC*ƎۤC*wRmil}Ӫ:ܵNVGKC+"ɩYu-u0&e\}cS63gfmXcKdhj-ezmj t5 $rիy_?ʼnneK;9mS;քLUuz*Yfy+jbsj8*bskbԞF*by% w\畸gb[5ݗU6툯yĠ9xO|Č<&a&soM;Ecn]ӭr7T=ڷ">cڅߥ},~^Nwi(.Y G?qoN! ?\ǓFa㗉;cόYp|l:G.?^'z%E3Ŝ5sL#Yڭ[ofVW`s ;r/ [rMu8sc(jD{+D/kc6L<쵬&nmI#%ҋk1f)HFMf!3݄aM`I&֮tx`iCAk U]i/6`>_b"rC&p smc#n^2{Z%!n79-l`hT돋?[鴰ٱ@_BS]Ʊd8@p:^ܾo|0t=ݗq47F+ߗ֎m ΤFmE^~} ;)p49BH~ <8#/l0Zh8AxR{-{t3u`ųA,n?Sůk/g:6Z^wS}ok57#v]@o5OOi=D[%pu?뺛RG'^?^~O0K;{D9"i`1o|ywFYZxtxaS8Qm6xlcqxsg]3}`ǏLd fi=n8aye) $?~*3͟D[va crG[OWg`%l ̪8Jny+E A)r< HrAB\${悸`;d~ 1r3AxIX ŘV=wf:_ۜxTaY9̛p(LlM{׸ qayu-ԋQq)lx 4mBi!cYI&")d&hFہ_(-_ 0J9(I\h\5 WAdd)Eg g%Q7 q'!ſct0tGa{}Q˓O1"~(a{\ai xg6䀝b0]`A|QkIELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km[ehttp://ns.adobe.com/xap/1.0/ bjorn.erik.pedersen@gmail.com Malaga Torremolinos 160/10 500/10 28/10 28/10 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 centerX = 0.317495, centerY = 0.539287, radius = 0.037149, sourceState = sourceAutoComputed, sourceX = 0.437723, sourceY = 0.539840, spotType = heal, opacity = 0.1753 centerX = 0.319353, centerY = 0.539993, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.262521, sourceY = 0.539993, spotType = heal, opacity = 0.1753 centerX = 0.315717, centerY = 0.542001, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.258712, sourceY = 0.542001, spotType = heal, opacity = 0.3316 centerX = 0.311387, centerY = 0.538226, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.248336, sourceY = 0.555915, spotType = heal, opacity = 0.3316 centerX = 0.312516, centerY = 0.541311, radius = 0.045786, sourceState = sourceAutoComputed, sourceX = 0.460210, sourceY = 0.541864, spotType = heal, opacity = 0.3316 centerX = 0.978481, centerY = 0.252986, radius = 0.027387, sourceState = sourceAutoComputed, sourceX = 0.894010, sourceY = 0.252433, spotType = heal, opacity = 0.3316 centerX = 0.974345, centerY = 0.252157, radius = 0.027387, sourceState = sourceAutoComputed, sourceX = 0.889874, sourceY = 0.251604, spotType = heal, opacity = 0.3316 centerX = 0.975887, centerY = 0.251968, radius = 0.036587, sourceState = sourceAutoComputed, sourceX = 0.900226, sourceY = 0.251968, spotType = heal, opacity = 0.3316 centerX = 0.596090, centerY = 0.159539, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.657413, sourceY = 0.192430, spotType = heal, opacity = 0.3316 centerX = 0.857023, centerY = 0.075264, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.785508, sourceY = 0.074711, spotType = heal, opacity = 0.3316 centerX = 0.936523, centerY = 0.223695, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.874509, sourceY = 0.204900, spotType = heal, opacity = 0.3316 centerX = 0.050101, centerY = 0.345555, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.114879, sourceY = 0.315151, spotType = heal, opacity = 0.3316 centerX = 0.055633, centerY = 0.343137, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.129739, sourceY = 0.278460, spotType = heal, opacity = 0.3316        qAdobed2!1AQa"2q#BRb3SrC$4cs!1QAaBR"bq2C# ?7iq[@m(@m  h(P`,`P.0YE cqqB(XBc , P.0; .; @ \ P \ v;.; ap.;@@ w8p;  Á8 w@xp; aa L! 00@@ L L v&0;=iq[@@mZ iE hEQB` XE qPYE (X   \`\`P.2Apq\`P;  ppB@ \ vp@@ , L \ \ v;a @ v;r&; 8ap] @ Á0 @@@@H&&!H A0S aa_Aiq[@@@m(@[Bh (A`PXE q (X (X,P(X, #P*pBupp\ v...8$ appB pHUB&; Qp\ N*apB;p'pCN;aap 9 @@ 8aaac@ Giq[@@@VЪ"  T XU @@A`  ccBX,!c a, pqe$  @@@ \ \ P.;$a@ v \ \ v&&.av B&&; ÅB IQ8J@8@ B!H p @@- `uKiq[@[B(-[@V@mQm *.0 +@@J(X,B–02"BX` .2(A`P; ,  qqpppp@@`v;.;a0;@@ L v&&&RaaqHT)!@haxV)0 @`L L L!Da?Oip %(-P P% PX@@@@Ae, P qA` (YE h,  qB@`\`\`,`\wBv=P.@@@`P^(XpqpXP;h aax@@ L L!*aaaRĂ2@J@@% L v0 Y1J@%`v0&+110?UipP [@Vm % h,"(@@A`+@@J= >!,` 0X,QBXA`\`\` (X, `\`PXE `\!Uq\ \a B@.0  #qpp v;@ vaQH&&;(B 0Z) @8@d* @ L``B [ipP P +@J((),PAa,YB A{@A` YE .0X,  A`\`\a ,  (AdUTpYQpB@X;EAJ(YcP@X`\$ Ô7B@@ v;@`L v DüA @J; )aa BI) @%`B I( B0&0 _ip+@@@ !(  XB PA` X, c(X`,a,)BAa,  aBAqq,dP.2  cpP&8$  @@}v.;ahv;;u @ L9H&!(8H! R)J@%!D @%:@8@@$V)0&?hb8-P%BXC (A` X,PA` X, AaH,  A` (X`P Bd B B|@ ಄@A{@`P.0(X,a " L!T@!] "aa @!HA) H&!HShR@0 @%`L`!Xq1h8[J- !Z (a`PYB   A`0 0 0XB X`,L"2qd,c .> PQq   %$ (A \` ..;hp@ \ v0;"{B8! a0 0@ H @ % hR)!D"`L Vl8m(A` YB a` YB A` PaH,A`<`\` .0X,(,B2(X )  YQ.008,Eü $ B a..a L v@E @.&.:8a ?'($Pd @% !Hp O H @8BI)t8iB@(`0(X,T X , 0X,! Aa,  , PH(YB  ,`\`,`\`P(XBAB(d/x,ApJ.2"W$H@ v p;p\ waa~ N N p'4@&i&{‰pi4N) % JBORNEB?z8!P 0 P 0X,Paa,)0X,@XA` X, Aa- X , B@`,` (X$ QB0.8$aaPX/$, \ PB.7B8' \<@ v;t\ wᎰ''?'4N p d@%,aDӀ H IA) 8@%<@% B $Tz P@ZP@@aa,) ,  X .[@ae, aA`\`,` OX, BA`,~(H, (QpqBA (H pBB@E A7Pp pwAE9Ba ..a 8D8Wp'pGCN4OirP8Z4B)@ qJ@&R(L<@JX,h X ,˜XB Ae/H, P  A~X,  qP0> P.]@X`\w@X@`, P.0X, B" QBwp\> waxS8Ea1Bu\6xppBR@ i @<8XiITM9f)J@% ily@zsP0X,X ,Paa -BX (A` 09B A/X, ` (X - X.2 P@@Z X(X (X'@BPN@ʤ c" !/pxmk@ \!+p(YQBv #u%)\ L>&6p^80R)4COÁ ;Ȭ-* "H4fi ?'+{<8ӐLi̧p{@x & 8 @8`zsPa`0T0X ,(,` X}P@X, 0IE X@A PǼ  q !BN.  wwx@;@a?aB E(HS!N* \?@9GaH(@8} ^+~>;8pN<1ri!f4KĀpiii̤i pp<@ae, a` ʤ^ܠ0 (,hX , @a ,` X$  AzЅ@ PH  , PIQB$J(IJOB  (A < nPH $  vx{yE8'X v/4@m\a4@;Ӂ @& Á ?i0ix ,d, X, @,06cA )AdR" $ YB  " Ǭ aaL$!aEXxU "ԂB.)xqpHa @x0 @8@$a % BX( @̧R)2SR)<<@urh4P@ hh D `h@ 0?E@a`h@@oJ_HXR, H ,xˆ ,XAdS -,<-0a (]䰂XbzAaH/.`0XA` ?,0(X, y  aL ȍO@A PO4 A  aB`P.0.;; B+c1p0 @% H(%$2`Fe" ,c6HX ŀV,trj F$_@ QEXhCUūE4 _Xjm ^Y 0kF,0ņ䲌/h .jAa -Ԃa|@Ad(X C % @`@@Z ay@@@`@ao`0_az@A X,PzoH a(XB YŋX"cXŎ,\`v0K ;,qXq ʼn H`YHSX̬,Xb+3+%V,fV,` biͰzBF j5 4U(abƁzWXƁ{E-ZIhDX mL, /,0;@ab0 0XbG8 ,X ,, $ņX`mXV ,X`HXX,0ab -"  X0YFm ", "0"K(ŔaLYD, a1a(Ŕab0eX,-H,YEqRRQ)qhq)Be;c;YN,cIe;lK)EEZЕ) Ie XXbJI`( ER,)%̤Y@R,+S2X `ߔYODl `hō0"ƪ<@/`5HQ@ōō a*ũa 4 XXao%ņX/, ~QeX((Y-h(ŔX)p)q(Eai, , (_YD, K(w(ņ%OiF-h︋$QYD, a"҈,YFKR QAbֈ,YF,,,,, e2YD, Ab\b\b\b\b\bv1e.1e.1e;YKZcS\d,cRc&1e!X,+%%be Y,+P( Ŕ̬Y@%bf$YLŔ8)1hV-ZōUbUZ4UVƪc@o%,5cU_,hS@" -Z(CUVze4 DX , il %4 AbՠXY,/X %av(Eam%[ŔA/Q-ha (E" iDYKYF%A>FXeHĖQ(E$ab YDkFZQ(EX,Ab֌,YDEAb0eX,YDK(eY, Q)BŔAb֗/,,,cR)q)q֝ZSZ\bv1e;Z҅֓,bBYBV,-hJIe XY@WYBVK( Ŕbe3+%̬Y@V,edYCYOUm[*Ŕ,ZU[ōh,"Ɗe4 S@hSE_SEXZEH(,(~e_kF,-Qy,U)_YFYFWYFK((>kDK(EA" 0Zфx$YF, Q)ťX,YDQ, Q)B,{EI, SENZф֌$(}KF)BƊ0#EHD4Q(Ɗ h (F0/D4QAcEI4abҔ,ZA%,R)q()BŔŔŔb\bv1kN,,4$+%e;,-ibLbYBV,+P(JeXY@VK( Ŕ̯S2eX(JE Uktʟx)X*E4 %R,e4 SEASUA֍Sǘ~kFSUH$YM}䵢 .kF,dPhQEH 5Ne4 J,%A" eI-hEa$ %a$F, xSf[)pJ," [(҈,YFZф(PYE-h}IkMgKMBI ~$I 4dFI4eBF0$4Q$4Rhѓ 2Adѓ 2AcKD4dƌXd.H( $4eBƌ1+hʅ\cFWѕh2eNMcK4eƊv2ircE;1dє4Rc\1"VMBhȕ&D\X@V4S2h+J( ƊJ DhTwʑkM YM )ӷ,iťSQv)Oj'Qe4Z~7h)h)ƖS۔hM>!YMkN,hIS-4E/Ɗ0S&$h(F)(94Qq &$Z1NM-dhJ)Ɠ+)xV228N-M% QKEEY4Η-IɄY<$ɢ/I4Q,#FH$2A#FH$h.H$h&H$ira$ђ 2K$M $4dƌXђ4d\cK 2ƌѕ4eq\cF]h˱\eїc&ƌɥ˱Bhc2cFD2cK"4dH$ѐ"6#K"4h2#F@eѐa.ag,ȗEU>eSmrhkMuE4TiU&(堧&h)ߤih8M4SAHcE5ZDAO)MkOcFZ }ExFѢ _-&h)bM94Q^6-(-F1JMB4QqiƊ1NMB4BZ54b\&)E8ђˤʄIa..i)xqSa#EI4dIɊw$13kO).MRM5 3a&$M A$EhɄ4dPirAcFH( $4dɣ*4 $4d hPc2ƌ1*6eqfWBƌYveqv1.6e.6eɳ.6v2mpckc&V6a mpIhف"6`H#i"6`i"6a Dl2#iaLa5,]3f]3"]%?!D>.J"I-8MV4iѢZlXіi4SEHMKM(іLiɢ[kF b bM-4ZqShK)4bhANMh?4QqZ}hLIRHwF1J4d?2BhƊ1N4QKEÍP&S@ihI Z\#IZ]L-J\eeBv2Jxѓ 2A$ђ &$i4 :\iraftL,\Y4\D(-Y4R(ƌY4Q-(XEh &,h &Xђ4Ph irAcFT,hc\2hc&*h2Vv2ir̨XmLkZ6e֍ukZ6e֓kZM]i6ѳk i6aKI0%d #0I#f`fci"6al0ͥ8dffy'T?=צ֛*)q&ɢ4SUKIFl&-FjMPF-U>Ѣ*IƗ-oh $MFh#KEh?Ɗ5AZhMa#EM4Q-4Uh h oZ,dD4QadKDMAd&ܣE-E(4RFˤ4dƌY4dɥɅKM.H,ΚɅ6MeBɣ&M.Vh˱.HdFY4d.HђMFirAcFH,\Y4d.H 4d.T 4d\ѕ4 $ٕM.Vѳ*\lɵ̬\]Y6e6e֍tmr6t\mMiZMmpk"O1p$I06` a"<2#0<4l30ǘeac3fn9<7'.+Q~br/-is)UIkMUzFjI"jM@ZhYMTFhiiYMmZh&06)cFMG4S@ZhhZjM`Ecq)Eo&&"1(hYEi4RZ $DihEZҁ%e-X)YUc 4SO=f=: O_Pר2% (؅Ӯsy/<~Z.L&&2@IɁ&3&$Z $KhNh4dh$ђirhZ4dKM $䀍@Iʁ&$$ђMTI̔\FHF+&+&̬mrMY6]2mrٕtlˣfV6tyL5535I5LQ:gj8:O1pB$m''`0<3b` yym0 ˴622c5ٞ 6'6"tns3q͉m?+] lZЛu%6SZUjD)Ɨ-I,irsMF("M1).LFE4XіM-FɥAxѓ$#FZ(ţE,hYJ2YD YF$e֖i,ZӷJ[ŭ8 e?/>ޗ}kV:_QtPi}] i>ӎ|xViJ.QNTXoGOWǩ~I~{ XQkji§Rv0{?9O>|=h$Ě\h 4L 4[IMB4@IR@I$$ɣ$$ѕirQ+\䄚\kirM.TII*$lʃ\dٗ^M mmrk^Mxم\,y^Mu\,cXtϘ[a.&|Ʋ섞ae3-&Rl6S%ei6mPk@ZM3&6d 1pɌba1&i|6i12c,sfx3c7&3sbx1flO-(FoB3mD=66Sa3kMkMP䵦d{e6F%5SKZhx)֚)e5[Ie4XPd~E4FQ-)1kD QSAƖI'h4\RiK}ŔQkF$%B-hKZX%e:kMa%]O=IW&;ky(i?I5ҙ|T2`+7 .Ȍ.\q}[xSӅB}V%TfU>Po">^IE2hɥZ3M--(2YKxђF"MFH4 DirFTI$$AKirBgK:k%&$-3^M.]q2@4Pdѕ\n$ddD\ˤd;k+&.l˯&.)IMvRe&LvRM6.2mD ڳ&6kLFڦemS3RM3/jɵll_10͚n:Mea%_YFKZ0,VZ@m0K(ÁQ^'.V(-;/AZ@K(Abeq줲;E;9,epΪ2i,WOmT3Rtڛ=0i88'yWXSQQp;lw5uPh+9><23g&> QU`~Bߡ+Ei-hIkDIkFf֔<-W卻u_b9,,KZ K(ihI)4A)CFiiAFH0Md 5I:)AM[ɥM-ї&%y4[鬭o3by5ΚM-:ftS&LƊvBME.S:JL)2hd&vRLy6((mGZ6 la&fDi G2i62cj1 mL]Li4͜FMS2j9dF'"t6J|Jj iJ d;&&j*"Z ?9)m䡨JiW% ּU;V[+E kơE@ j+E1\m cQhS1\w!@Mu?;9^Vh%J!\EbkF+kMaQo2Zq,xZDS~-L^4]w6 ZO"gctqj{?<9rro`=si~Q|Oak躍kzR؟{QE( fy>!?\gZ-OEQ%4DQ Z $|kJ*֋$^(ֈVZq Z fmiEi-r\i, ZaK\&mrBLY1VKZ.,^',qd弔u1CEjIKf5]j2REAWh5^d!%5^bƯ̔JR;5~d!bz05#-kdZh5^dZ5ijyjK2-/⤵Ϣ Vm+>Yx^;q|?wEu 7>*^78ޠWu+=*wO_.:{=.YD߬5_`~ P)FEEE2CR;ȴcP;ȴ_i ^d~&fڎ%3-~'ns3-GDxw&mp<͘N<͘w͘wKL;%!^few$*2Bh&mWͱ0LķM̹KusNS- 2a6l[90mLIX:Mi%樢kN/-KKn"[v X[uy%8XM7Xo3M-^n,Zj8mG͵f,P;5'R:D1yS\JĈ}<'N>|rʇ޹F5ST5t=:֝qzD<O>+M?^HRp?u"N^ > +z{+NS#'<=?&r~>OOSāF~O _V_M'9{Ci/h15(6Co<SS]G5rH{#~mCQN~|\#O#Xl<9x>&jußK;wN|/S9r%CBTJTGTw=.@rH2ս[mZT"M.\98_JA8*=6CyӚOǜ\>Վp˭O8ʣ*U͕]’O`H3 <>Bom'puFJSm!(!<~PGRWQ^k?IMG=#Rv|&/ZJjʐJkRJS甔5d1%) )HkJC_i)TkA~8\O3JW:fGkT"@# =6koY~ю}iqo^zQ7NJ@Dy^ 3~P}ƪO"ᦉӨfxx.jzܧZ5&;)E7fe0"ae0CQeDEaky'texJ9̸L=t̸r')p)qlg794ͧ/6Lq樖Xb][i/ V<5זVxԯ,Cqyjj<Α87[ Un8w#Q[W_n3P2< v+* øPAdR@ J ǸׯTV3fcG,(`wm^UƧGTҬ9؃q-wxq]O%mB %WQ##=g((Z:pF9rt׌:GWzL]UZmQن >6 &lP2$1L-/Yj/3~~NY{({Qqjݪ/ҟtԏOO]R 5^ӵ n:6pnO ;|R~u>ۏUB[pNm1?-Ǎ4>znz֕cor"|pKѥt*Ҭkgz\%Q>f2ҍo.̘S38[1Y2cW~e1&K=۟KCCG:G\09O{Z3˩=ӫze!ĩJ}K*OQE| ?QϗGwywgZ- jPpC'fi筴ZXliMU|?(֦ͦafeYQ/g>Xo9sFU9."~9}u/eQ&Vky2_&K!=RamFߜ[!L[!=מa/8U=Q&=@ D8n$ǩmbx5_G1]̘h|WG̘U0=G̘U&!'UL)P&z5D=@w QPpC^;市39j ƿ338t13<"kykOH38t13<[0CWLY gCULy313'ey.sW3<\JpPS,YrУiHx~O/){i *yKKO|N˝=?8&|ܼזx;qoY>G_>Ks)cyM}W tuHtr'qg^k]EQ 2Rөc c:^pԞ}Yy}>TPI$s幟Gs}.qȹ#G9^?/VB&UR c옧B7WMU:*/agD ofz1GՏ&bg_i'jyd{D4RH.z'!O&Wpڃ'Q)<U_]ei<=Yg]V_j9VO昞'L-8/di赸!gɖ OO&WpCՓO%VCgkpi8z?yyRVz!c3ZKLqeW'-nz?y&[pcfz2rOfz2Ǭ'&]#4_Xbz2)8F]#4_X}e9CUz?>їX 8OF]c6_V}e9CUJ}'.R}Fy-'-W]HzS5 .sҟg9 pӟgר>]9} '}rsϳ4vfx|OivbxKχ'ԡZ>ϧ/>2ZvHOz]J8ЊLq~+=W.YR4ݙ`}BO|3u9"|Ʀ3zyxz=zzvtr Ckg3üwSsӚ>ꏧ'I17@_qOt:X#juq{}.PpZ y|MVH/α^.^ω 6&ㄽ:\Qtҗ˯47~=)z#/W4)vVDz}o[ӯzx~R˫ËWN/OO s=\|ƾT\Lә* /^V66po&͟gQ%CFPTّK9 Y>>VttƵ%6/ vytOJ} [F3Λ ~Sk|~Ѩב>czZ5UkJ-Pl~>B0'PN=0WBmcүV>=7VޝZhV:pD9xC[I+ѿP`xo>rzƛ_@: :}= SxR='Pjڇdҁ]@$LJ|}j=7KP(!C#ǧ]9R9mmVu^Ԫ 5j``Ia:q1\kׄ͢L\α.2WIvnv[^s8<}Zȫu$oM~{EԭUVq7-D/ϲO^yYx#W+ZypǓϷ#ҵءXz<>n}j\h54Zf:5ߕoL];}?W;9^$]xW>CvPRȆ3}C뉶TlN>UP V%CHrT=AH Fy>S#_@Ԥ֓8#?3> ;G+Y`MJ`r8{SNH$\n{|%_J)x>uO@pv>S '%[ob_{w:s>~}w4>ԧ긚ʊ]hPL^WbX~lŹz /7kHVZE]r x>^HHS.y}Sdk:EE6b>`.ݯzN_7"c}ڏ}:TB%6|Ou}4[nD!#n-gtGTOM1S>V̓x}ڏuV:m73>ۏuߔS>]ZLO.k)}'TvIc>G+[U b5H3/isQz۲ngmǼG/};2ײvt}t_ݺiu3J+-L_~\LO:>gXO+оF8F}tG׏?ݰ_V F?x~ԁ#ISc"m<>qt9/=&T <|t G/zTH7ښ'b񷗭Δn?iiFdS{}'t:c+Ǐ\ӏOOw߿qhUM\|#=^]^q9|Oח).ސ~\8\~u^zܮ<g<}xZh_k*S-F=QOmז':^?g|}_z5=B5@,WFgqkkuՂz?9~_ǤWPg=M;1jhݽ;_K#_ǧ?<R:*v' |ʭ/܏{:6T|OH'r=~<ܾ;r(6ө# U5Q$k?)ߏ~<3~I?W4mf NC"'+G_Q );GZnYҁS>̀'݇)_ߗkq'HqrS짦KTUn@7.#`j =7?1>#Kl6^bۇ$vR@YM.RQlƐck66S%RDEE[]&ǟ>vh/kn<mEXb]+[ m~R m"›J X-MQr`(zH ੷E F2lznPKast ,vSQ7_R(_Y%U(7İ[IpdW=q%(隟[kX\4/Le2 ^~rQc(*ïwT"$nrTzAT,SkHí7jPzCLw$}L|tLQmI-*R6NH?蚑 u *w@k8|N%zg;Ө>,9>~(j5)P*p#a3I?~Zm}\Wpy݇a5"S/tꞞ]]:=7"y[SZz\.dwn(;U\,0ldyF$t?ziϰ 뵹=E,Vװ1j P9 ڙơ' ExXZ~:-­/a[ff;rּj@i(O"X.VP)2'eQNVȲw~ E[= i}1F2b-V5ic`//5hizF{q3ݽj[IzZm[7bBߙɁ;s {FTPo*,a/OPj,rbK\;#*hFjzAHN50;7=^fxDZSZikraB}Ѧz5IVMIǘGڲ૾TbrR|MzUڕGRPCkx>2s5.~&7~[%4?U{L+42.N=Ox p~s.rn:o*VU9BG"T>Ǵ?^jתʌ]|JaEôx^!:cWY:*uEF[Hg>=.\#ֿO&C؄jGB8,(n5>}'6hQY~=ӗ.Ru<^Whe}[\:V*BE [{_@zy¨Pε(ud_S3_1}?hi 2dפP =x)}nofU,I `H>gSOtlLwWdu4NO2 $o|D<zGm:=M>w4us䚡ϬSnj[Q{5N᢬IާO7x؇Ʃ]2uj*YvjfVSDv|N3?UƦhMu7;G<|?wޟKE*zcz0.t`@mwDQp[tț ޺u!* E"P|Ko=ͫ ޓd [T$sT8}V!ڄ*hF(Wo*@GJ>]4:QAa+Xމvw2OK6ɕbڰ_7Z*QZiSH}bTZJVɳćEUJܨc`Ou"jq~P5J+En6TpdC}=V &V5 y"u*X+0`r߮3oy`%CԪj|cFZ04k H/ :r0KJ] ?P )i.AC^>A"uLBO=Tba'/R J;FI%nM[ X97rk;%F֊j&y)b^mYkaߑ:yޗzALv,@/+_tԙ{u X=\lGn9qzL%^yyz}j}g [y'GuYeer6?ˣ暿5JGӟRs1o1bx|g N 7^q~󝣋=O5T?WNB5 䝘\75\5DAOrvZXf[\RdC:7V',R+snnI?KgV=@/9Y{4~jtm=FRñxr GV1VB,ZFې<}X];+iF |deFu5Y8Y81ו[Zw .'0W?c3EZqV!ו+oQ> D;m#ÜZsmOA`eYI.N<(j/H;ub NbjGL^ɨ}52@{-&SMed ˙pz2ԥWRjihܙ+ά؞P: 恟d!:oU7-s{PvĠTi9޻|P|O{= WT3!եV*m)7Ӯ/l-\o}ȭRss i|P0<_*('*6EEFԝ5BBi:8VsM㐔x)j]6="Gn7(7cM 6$^+2l8}IiSD)r?v & 4t54 @[<% #5lJk[{wx*{ST{2 cwX2J4Gms#ad~6R@5Ht}P;<{mQS`O.R-0` YO/*lo4s@RNGe_Ơis{@ JPP:Xs6$-j@Y6jRےdPU"Jkkc̙,IQtZ:tvΛWNqsy5keâoqr1N(N O3Ӈ&R 9az5d14ﱹڎM6۱2rìjjYc˘Gg˽R11^y򺳮h.I 9 Ei L*i$j!s~v4h91߬$w@{>!S|(;Kei)-lO8UaqXhFE-iKS\cw|YH=8ݻJiAFɷN#,A2֚%{ Ԙ:ǼazthHJ1;8j}=+r} %)PJ~WvP݇+ZJ |"NhuȸS~KzFD*jG?S%JaL髵jWYѭJm(?/oHj&?uj9?mR,z =.$RWT7sk|(iiEjF;Y곭JqӥK"s6MtZjf*Pij-AM~@$SіWAMf6 OɌ]uZ=+QSGK Q&b:Q /K=KSzզ4fYo~@3Q́EFu9@Β8U`{Ǹ,ʠ*Q 2LW±UJ;ELyohMYx0>m h5He13@r\@y5T,+Mk۸Vv8$GYF0(z|ףFXVpP~re %6U9v6L)w{ALn-ONRot2+SEJأx}7ӛ%F@W8h2oUs(Z {VLkE룪ALT#6 ؃S0;?5K"ݤf~_)@զtG26>G( Gmn%-SRj>DmjV(Lv5,`9 P̼ug_ۘAo}UoETnIkߜ[Uf{`nB gMK ôt*TEI2D9;(=Ѷ]y:4+\rKiO==JAG6?ia㙦Hw: D(<ܟ"Qu ccrdz\wvt5⧸ʬ ok%Pq#V# [9' w}WˬJ`_GPBUkM2т̀@:j IM*ÖC}( ȫ^ܘjCvf=4 n{j_ O}V9ToO9| ήA?IRΝv@zbZSjYЙoN׽"ir2$cf@\#dG'9H+H/eO(ɖK5 頢7rp9TcU. 6Lp-&3{NL>JoPV¡^)rFv; HZfdQ1',˱ y.@@QQs"gyxP R&]]"rizccM#ɨt#ѥњx5BQi&kiڍR eM/KiONR9-iRE۽S"V\˴Q.Wsͪ,H^*(P)+sGeh騫K::vxkӦ+)JovPn?YQtɤ4J^ٙ,~L޵pk)R+\?2A^Fz 9^تEK2w5 [AGCPE}YSTAQoVӲ2 u[nDQDDYzDA)$XUkvUC__uյʭf-mEE2󕸵-:fvdČxVS"A)Pҝ ^R+Q>;H6ckU9GӧMh Jd\2u4)h+dz L)d~7ZiP..Vw*5>p70<:ƒL{oQy9%TG7 ҽ,~VcT|nBTAM mRI*+lwKlo(ū~k2lj q_UV \_-XCajy*Ң5hŋHTrI[[x긬(ZÖ=zju4੢B)kuPֶT D%jTeP`;^%IoPmJVXiF#I!*A;b9(X.bA|o֘SUi vn630+zZsr-v#)m 6Kٱm,KoIYgY*5cPEXs1*vbVWT-33-b~v^ Iױ5#3yfBjU fЖ(} 7!^zt[TDwWD`KP.5&mc6'8)J %9/9{o+Jnԏ&Vl̎FiL~x8N" ɌuYOQ9،B(gYq]-њ.ʟUP7V?U1u*ZFZ y"s[ގu5 bC@'\I3KMihm;X4 MP:LFCdZj6,*n-T{"j gX31Q1t2w/\܏-kE>%KªX߸;Lw^ua+o ȄN6U!]B_e;Q ZlrT ٢x nծ7j6]ŀK6~jkVAr"$kz -$n " (SlLnx^*T[0(WPI'V?A3nsOFsr^A,Q[A8@MP6ב^J["U]UB^Q@#s+:a رi6B&Fطuj{ʷ^PMV gZL{-ɵJԂUT ڍUʱս7=R}=b%M ]V6Eĵm,fb0er=߻cZzA[N+M iҵTMIRjMQ*?XPBԀժFA+u*3R_K&nKq{I_u>EFUoCn*e4t15NnێpeOTutҦ:\!lWzOOM4 i@7aoםX,ܑ~{JҚ-suyuf$S-`PzcH~vQS`jW`-f[ ®9T6TKW z\ۜOMAkE@Qhs]hW=5ahUIT7O#Z_H-FۜM}E@@x" @@,HzčE`ڬv3+SV^B62ZW̦j: 4>tgfnBѢHe iCQv=!H-C{32V&ROrl?)-irC1,drDq{=GӞ Z3-qoJf!|Xe򗆄1S"L5j]U{A%-`T_kY`X Gj\S{ [ q9֮^aBx#Q*eϼE ߠJjlOx"1Q\8?r䚘gJGMV7%}[u (e3Kmkjd[ Fn|n iѾ}dWT "\xHí` [!ΫT!eeS@R*GSR[l2:\@?C2MЫ>^aItM^-̙u5l(~(R6&\dw5j7X$KGR2/S{s2[ΩӪ9:VG"7=yf91$daR@'x k+ehZlv0MNûlyWe ^QA}--%U̢׮qͰ7W)N*㜀kcqVO䲛#{WQp.vTiJuZ4H.w0^a=[[0DT73(q$5 p $CӚ"k0b}|3bzHvO½= śXF Q,*u$;\U XH &X.*IaNmxZT~gdMxa`@8UɑD!Lf*sc Gd/ -itV@w٦hg6s&!rqE5aO+ ؞QXUٓ6&Tvb}5?/8& M609#Xu&}![k?nCnV yhխ{o$>N!P6eݷLbnzJz@Y ,Ս%0E-ui$[xq);Ef{G6AsR {VJqn`9ܑ`>҂Wk1fbd0 B *ZLVQ(5p7!Wro (Z5KqP6b[H9f6qLXXrfyP]q!-Ak:NJt!\B("MDR[.+'\~RX:ٹ x\]m:@6!Oޕ `tEStSTRzF1%\5kyW5g[`Ve 0 oњ3[CjNj;(۰]t"[Jj( MD`Ijʥ kPS#ıJx*ך\MSTT6a-X4:}a\#Rf:F{c~<:@4^v7H u0#TdMޕ%fMPç)KXT A8x(@-^A =47nMo UTs')K۔XT$EȧU.ͤa"c{Y:/&ԨbhUn9㜀TR <|vzk-O){QV߹߼(2H (T[bf(7`9ʎ|Ù*<*]Z+amZ s&Bބvds24+Qā M /l&0\[``hW,J+oRRTR0/-4JiNulFĂ9J o&ñr8K Zk Ԫ5Yk KI^vIkOuLP},m6=/Ӻ0Z׾ZiXT9_CR-bOV*d&jֆ"=d.qrX%&jvb,qm:R +S{)iկQv/~RtpS)BΛ|-x03\`m#mow"bKERەy5^/y\ G(KM$ANrs[P꾑P OZSCQMd*SUم!\sM{/n%ZQlK5/?Żӛ(;:@Ω[yfH 6<ŷfNaB發MC ;NC-$ `TTjVR4* 옐2 FJf6\QTcƩH A|8-^"jRZt2#wZeBe[ҫQNKEwۙ%\#dK?DDBܱ]~ jw7[}H0W+6lIskIWYp5l.YrO[^VXҪ_D\n`]Vj dP [x5:UUo q綗RXSXkW5΅OkH\SR[Sح۔(H:B@t0:+ FغGv6@Zj ,mdP\XQ';@Y;]nЛs0mB9@ƵEg\(Sfa!V_j~NMꕳύ ZK>UV<,LmHoAZAu ケZjdQP(̫5rHnpWTY{n XPƟ izLPU+֑m8:-1lߔӢLYI ^7Qia$v8j5 Ew =K_tkI-DU<%3QΩ,.K,lFU?EG~%Sf# ݿ)P8)$Tf&۬#Q5̂{?_}q+W4Jfj+](6^PQ~!p*mm1xLwX[H+}Rfz_MTcq@3]?QIjB[2gZ 6%AlIKQ ܮO:^5S }& fJE.(kh XpWߜ0+tNm]ME핟}9}MyliZ}bwoa&5RRQsa(w P9[M9f + sG֥ J=?wxF&N%#đIߕGm9@b1=z!tt:@?hh@t: em BL tvqrw Ɂ/#/bts+ndw ?a*0BT6˼rXx`lihss"ժF9XkK`IaVF`uk uBhX} {s<¾MR#jhwݻLM ]~kLk; K ΂v&T㔶 !bZ**e]: X{ve {%C 0CzP݀)*[&AOL^-N"cS&W^!;»xE5+U!G!PQrۤ&[<{PQb[*r BԽ9rmB1>I@@*8m ,%D'{¸akHs̢EG]M@G+}IѤPj-R)[4|,3@_( z[F΋P}=jWл/U)dv$+Q[:;UL4Qb)wjckRMǛf KS[TTɪVw!.?A,ԉ*Uj \{ߜQiR;Sz|BMbG@T)z(wzCj*rַɨ̽FGN/o5~2oFWzvKs%[䝞M7- p{W?,vyu^OAh6R߇|וToۤ2M>OSPn@+ێ*)#w_u.|ܕxMӪ.m!5'\-!<,̄EפDTdP J1%&crj.oHJԢrXU :IEבFJl,CTLm 5eEJ `D -*Zo8\͂{ߵ" cD`pq \FOHv:`w=uvt+w8c`wO08xr??"Bc+'PE07a(U=6< KCtVa{{B[YA MVnuN*{~ =a+򋐽Z \ txhHrHn"gSPŹj6Icb7Cr/ ӈiչ]9@9 Gp9y@,I6%`9S6MO@=E[`fyKOP!"6=KsQ3Q pm݂Ju~$2~JӦoʫU);zO@Ԋ.&jMl^`X`9bdSBApF*vvHpT3aD$}6Kmk*1Q*{PEwVGb}gS5t\骾qMW鵺TiT}A7iu2PivΊ~r%IkLYGj W :>"}|UTpU[RqM"iVTL؊"6J81͗v$<֬ZAvAUED;YE*~c#%%*ڮ4MflimM=\=FPMFh&aD=@ Ev4rn$WV*i!`6 /Y֭*|T<Ko0Sy}ЦYHQX_:bosN?!4ĺ*<(5ZVn.5 FwZi~́GmFE6O,RuXSϼ|(z)lf<jѷH\^ۈVliG@p&#ۗ":ؑߥ?$6m)!b- Qrld(J &/n " JwʍNÖwňӯ8ңglX HIu ״&ِ~$]I.V s عۺ" JlXZoq!۩$NȮ'ŠHЄy@|Hij%XVdZʤ@ F͍&FJ#Op YO+y pf>U|'HUߙhAP67=`lo(vLVvm)}ii- MJ}+m iЎqWdhYNYB,ݶ*/ G3x 9 %3$ Pkʕ!ISQmVb݋Obf5UXNN 7DQoE-FPTV;=Z`2LAgհ=@ o"PYZP؟=>)]ѫgpwyZd,@njL:Cۈ7Z]*?徹rRԨ[NY'b}vSAް-)P֊UNSIp:rh骓Ι-,T) }+OD}Z+5liGQ@Kc(CFj4VlyK|TMR [{hRVO(a) Rl\Y nW\H. @D>茧 ~=JޔBE/ol QʮUO6 0vXGQUժp7=}Pʅ-=P2jk5Ŀ3]j=*IAkf~{" yF5MMscX3TG80 pZelvFImѦa]u4od]SS;ö5ii\*Tp>r;!n2кMf-E.u 󰖒ؽ E Keb6vr 1b67+Qi(VԐj GjRFQU\_Kcwyx:(x%+ Jd>'F !O6 (]yQ4:ZAH ȦUE%[Q*p tn#BKZmO UtQȫL);uß73*)q֥M@[򥳭@Kn Wbו›} ԃjj ?bbۥ-+VO?QR 2$&ElޟQE,%,~PS#zbŰ /J8[)rjdh !r2no-֏ UVDz2{QEt-Bjʰ98݋۟EMYDL?i^ 3*6(8=ժfbGܐ%*n2O5 bLʊ7l:moh? Tr/,x'6x(D"%CQ KǼ@B{*R۪P('nf(boȋ[BAo*$ܯ\`uȁU9iTv;BFW<f܉ H%ź.%VnyB:9ۮѩkZ׵2W)!Q.pD9"㔡ܟlڎ*Io{򁌃Q ֓*[@hD,~c6>|-kbn2`KS[UDU*eQl[UE䇑48iRmM\yNpՏ}$ 﩯jcek*!'u`.eԥ75!STʼn2+_&ѩJ}FXR/]>+1o0kaÝx#˩J5=7ҩҵ,"&}b@J: )[fz"W@ɞ+QJ/lCT* 3[*T6*j#-kL~PҟWQ:g$q:iƜ@*xekG8fx} Vg4RzP˳'[KXi6r-q ~r̤hk5 i֓N@Gk%4EL@܉GjUi SZ߽>l(>I?k@!r{%TܕQaTfWuz5TqQVQiӚ*S"ĭ*Hn)ʘj]UEeZYAE0 TiiښZ:H8P_ʅ ~?hh UlO[dh+4RP.ȨܥCj4 2ZfSďJoN芔V "yk+Рk& oٌ.K(Qe5BZ4\(?4}R55;*6_BvrdmmWnZ #QGMBT[S:Ҭ|:/xѣM:G>@oJzom MdӑEH, T/9>Υ&KF"¢vѐQT,>Nݎ!*Ҧ馨lG r>7YPPyQb7=̮8Y-SJG#BUe*Rw/66[ZECj5Z&pt/d*e7ЭO[az /gjw4'牼wriaH8U4R!$+iiu ZQ[?(F .XLQo-*Tiبiԏ,|GU5SMi"<32 Q*A`-ne.tVOGOׅEact:*QiUh}"ѣo{GQ[niQZ 5Gu#z&]JPÕ9-^m:jj%JZjPqCuLQ5 uf6kʼnFH;ީnX c|M~S$TH}'ZT=ESni-ۚdq6j&ÇPOq E)wZcsHYTĬ)K^H4}[w)d.\$(bt̀:,yj_t!خ$礃" `~+t%ZmTdr@|-kX~qJKq9_R3" ] \3xU ^1Kl7cRġ;.iA` ݱ Gnp!lEfI?(WH:TH@WN}+iN9}XPyX}oS8u*ߚeosxe?̇l:xnrSw;!▔ck}w},jQεZQw\EƁ**Z=;W;[^E89OM]$~R՞WTHedh5:iM߹`~qP/y[VjSCٜ KEE[7>Nur?95_BkzQZiP+Rԋ/eo/%Oħ=Aj=6,Zj٤8t/HjWr)bm/kQq!J[Ij ?8]Ea|jOA~쫗*i)TLP@"jlPӨ)geHSJtuȰ7r2i(ĭ*f;ۑ05SSZTWuLvo#gze5ڋos %zuLB髕ÕPG 4Y¿ڏX'躦NEp?sER3 PF2jE_P9ڮ$[ToWOSĭGKtH P|ȸy.-)j)FS@iZ*>E|E@9UbTEM70"ƪ = i-iX,DYOU%J0&\Eǔi4?Θ7QP@5[V3TAj;Ŷi,+h%m!57%-M--Vm= Y]U3wɵUON`Wlk;zmPYX2 ]JzkH_QpA)8r)M ^ZOk!e.j:]=[ƺۗޡ+5tE͛Pž셥SRfh SԻ!,-F*RW< ,lQQr$oEIE[PSTFB,4UuNW{EjRLЩPOE-:?D4^ʕX#=6)-_O_Pi;7FSQno`bxByKoWG--5TLEfQRin-Ԗ GJҠ*諵@DmvSF_JhӬGQ*W J 2o!~.ӐV;a| dOH\*T=Oaɀ̊::lj1ff'~w+*L΂iTkܢV@.h^ۆHA\#hT,i;Sv悡u~| MHV:-fs<ԇ*x!LӦޢUlQȇR/-i@Ѭ\G$Zq,  pj7kiSț//U)ONVWFZ\)v*H6h-TZ)Rz5 Tc@-Jdd(-M@f g@Zß3}{ E+"-"t:@zEZ",BE N [= jʌ;l:5*2cɼi$NUO~RzȬv[_,9Ef\ra#m8`NP:$ FNSZgpfZ%V2%EO̘*I1ƗqS,q^i:hRU]mᝬzc2КgQtP\SZT-JLr+ša|9mNuөH)!i[SԊt:Ujtϸj*GsͤP+j}V9rD./!S7AN(Q(`q6` ۣji_jkjuh U_UZiOZlpQkӪ;lK5"At)j!:6M2UjW9y)+fhZ`Yj-{EKD~"u@XϤ#SҿZ.Ts%-4BhzW7,2m(bKTmk//tzcS%>#RE|zA&Ae2IEzOZRj " *QJob~ =jl)wSQXdrM= j=FG7+Y#sȓqcU j4RЁ܃ T91UoӬF/Mwm~״ M*R"wT4Sž%+``WTc6`\sSoNDBOܩ6̌G%ĔEm=UKlʕ6"*Hۃx *j6\AH%Ў c`UB s>7ŸK QMPd8\X5RE@*w#/)xeyJKȮ۴sxB$Ю&ڤvɖ7pLJ/NGu6~vWknN?1pTКdq5:]bM}-""5s\7\ j~N'PE־R4i, ᚗ* ~6ZfU2~mY2(?3%<ѸJ,E~_]Jd MGKٟ^Xƀ??%^8@>ZG2x楪>'JI+_LhuWO? aQLXiFPuEB؂|^T3& xʎJL«e' gN|IS0 bTj]*&OznMl͌T)ׯQoUPjn$k,q zAjWI$ ן¬HEցU\Vze֦WJu,*y1@SM_K]Ɓ$YTOQT{V}AңU-e?3+%[~QHKrU(MC) \bs&XSk nY_M@CkzrQi}kFŪ%j5&,g7i.S9~Qe>P2xe:PQ CѣYXTBìjV%{Iyly)RN ckA_FtZmh9ު*(*wnCQ(5K6m,);#Wʢ JRVONC֚:JIm-ͪGKTk^R8gWk ]P[j4NJi`~VeZR!m1 XHmznOz|JezqT ]KR*5Q֣oQһPҝC8  AQQT AF(qk;}JUP~$:2-a&[w4ZsTzsE9z3OLM*&TkE+-WG RVX.*WU*=T ~5-gԥSMxU)Z@Y[Mֆ+h^UKD|]Hl Uߕ[CO[-%$,j ;n,Q=%]Z(zX V?(755:ZR4 R}ă5-Ik-&eUJon۹0F᬴8ԫM8;.h2*&H] *,xk~E}AG]KQF*=@@~:R(tҔո{7g[XN +j*Se{AQlZs_I-ApzA2 M3k=L)#q=>3=OA) K.-*ۭ}W)jj5.AEݻUw" SҧlB'Pv;FSJLڍUPB*Y66&د^;S&BI5idWxj)9UJk]Ÿ*ڕP@Fﱴg-:^4Hǰ FJ*DA2 PPtx6PO`-5 ) M`ErEӿ+*Jt.WcFցM5tA$ eKz-%1 'ԥV .mpJ+l•S}B\NGljŏH%57,~}dVQE\s' YseM#R@<(C/;"kZc~f®!ׁ$t:fR;SEF@򜯻L*VnC6Z;LLP@bHm5\bаDw V;_a-َLO.@¶NB?:_㦭Pfy,>LN> zY['cϙ&vqeWs/7)u==B!/P{h}KwmUBSZa[ lTAMI`ykU=4RG*U]_ oeΨKWMi(E;]^j16HmYe*H)QvjIzD@΀ =U&$էMUJr֭Y\`HiV/VeYb =/b^/i0#HکEed=I *TvN8[_֥Hh0E ) HZBƫ$Fgzf{ܓ2ZIa%=TT$A^1+~DADAM 4"hM4 O 4($L?1QAFƪFĨFā  (B((B: h77ADPI}AA4PIQ_9@b[![lJlH FĨFā ",B(,B:     Dh8  }It}QFA.dlhdh* Vā[ l* l(-A  ,@(@: 3~DiADitA:@N@NDW+9dhvDfDlZ"Fª âl(l*  h  O 6)A^DFxmZò"M6u. ( 'ShN; k#] ȕȐt2-3"@ͅPͅ+a@6 #`6!6PD}[iAbD)tK)A ]IA>, QBmTl]\ĈdH* vDlHQJTB6P#a,+aK4K 4K }6DDbDM,P,W,khmK}րmE,DqnF8ă%dH%dIaXVDaa[XF斴fYEl ZQ[NfӥVӄ)#i(K)BD)d% ZFvK)vRdq,>D;R4lZ)ie:c,C#K)ie%:K(̈%vDZ[eQQYEk3#R3"K(͉,Q[eV¥,BR)e7Mg6)<btSeؠ ا;6)btQNMtlS8b1ŢdIlSFd:&Fl)[F›&l*lQ lhl ndI[ԭ75X75P7]UMYMXaMTTn7]BT$)𩹫4*c74uGJT4tL{'bꎔS!b莐NGC)e;CD43itSt3)tRy0(NXW}ЭfyZ3.Kqhj)u'jiF§iFQIܽJ'q ;pzbSzRcSzF:@'ztSF{Y7ɜCGtQgtvEStuG{)غ:cv.ڧbƩujvjv.kb b[}6&u 9ͳ,?.kx1f!`^yu3Xg bjNӬhSzօ^;mgzu,YNSz[S^Y%k%[ ϲ0Oez빤r3<I\L|,8*kKC*ƎۤC*wRmil}Ӫ:ܵNVGKC+"ɩYu-u0&e\}cS63gfmXcKdhj-ezmj t5 $rիy_?ʼnneK;9mS;քLUuz*Yfy+jbsj8*bskbԞF*by% w\畸gb[5ݗU6툯yĠ9xO|Č<&a&soM;Ecn]ӭr7T=ڷ">cڅߥ},~^Nwi(.Y G?qoN! ?\ǓFa㗉;cόYp|l:G.?^'z%E3Ŝ5sL#Yڭ[ofVW`s ;r/ [rMu8sc(jD{+D/kc6L<쵬&nmI#%ҋk1f)HFMf!3݄aM`I&֮tx`iCAk U]i/6`>_b"rC&p smc#n^2{Z%!n79-l`hT돋?[鴰ٱ@_BS]Ʊd8@p:^ܾo|0t=ݗq47F+ߗ֎m ΤFmE^~} ;)p49BH~ <8#/l0Zh8AxR{-{t3u`ųA,n?Sůk/g:6Z^wS}ok57#v]@o5OOi=D[%pu?뺛RG'^?^~O0K;{D9"i`1o|ywFYZxtxaS8Qm6xlcqxsg]3}`ǏLd fi=n8aye) $?~*3͟D[va crG[OWg`%l ̪8Jny+E A)r< HrAB\${悸`;d~ 1r3AxIX ŘV=wf:_ۜxTaY9̛p(LlM{׸ qayu-ԋQq)lx 4mBi!cYI&")d&hFہ_(-_ 0J9(I\h\5 WAdd)Eg g%Q7 q'!ſct0tGa{}Q˓O1"~(a{\ai xg6䀝b0]`A|QkI20171027?083852Pbjorn.erik.pedersen@gmail.comZ Benalmádena_ AndalucíadESeSpain8BIM           Adobed!a1AQ"2qRS#BCb%34QA1!#a2Bbr ?h- FĨ‚ !* h  P>+~DADAM 4"hM4 O 4($L?1QAFƪFĨFā  (B((B: h77ADPI}AA4PIQ_9@b[![lJlH FĨFā ",B(,B:     Dh8  }It}QFA.dlhdh* Vā[ l* l(-A  ,@(@: 3~DiADitA:@N@NDW+9dhvDfDlZ"Fª âl(l*  h  O 6)A^DFxmZò"M6u. ( 'ShN; k#] ȕȐt2-3"@ͅPͅ+a@6 #`6!6PD}[iAbD)tK)A ]IA>, QBmTl]\ĈdH* vDlHQJTB6P#a,+aK4K 4K }6DDbDM,P,W,khmK}րmE,DqnF8ă%dH%dIaXVDaa[XF斴fYEl ZQ[NfӥVӄ)#i(K)BD)d% ZFvK)vRdq,>D;R4lZ)ie:c,C#K)ie%:K(̈%vDZ[eQQYEk3#R3"K(͉,Q[eV¥,BR)e7Mg6)<btSeؠ ا;6)btQNMtlS8b1ŢdIlSFd:&Fl)[F›&l*lQ lhl ndI[ԭ75X75P7]UMYMXaMTTn7]BT$)𩹫4*c74uGJT4tL{'bꎔS!b莐NGC)e;CD43itSt3)tRy0(NXW}ЭfyZ3.Kqhj)u'jiF§iFQIܽJ'q ;pzbSzRcSzF:@'ztSF{Y7ɜCGtQgtvEStuG{)غ:cv.ڧbƩujvjv.kb b[}6&u 9ͳ,?.kx1f!`^yu3Xg bjNӬhSzօ^;mgzu,YNSz[S^Y%k%[ ϲ0Oez빤r3<I\L|,8*kKC*ƎۤC*wRmil}Ӫ:ܵNVGKC+"ɩYu-u0&e\}cS63gfmXcKdhj-ezmj t5 $rիy_?ʼnneK;9mS;քLUuz*Yfy+jbsj8*bskbԞF*by% w\畸gb[5ݗU6툯yĠ9xO|Č<&a&soM;Ecn]ӭr7T=ڷ">cڅߥ},~^Nwi(.Y G?qoN! ?\ǓFa㗉;cόYp|l:G.?^'z%E3Ŝ5sL#Yڭ[ofVW`s ;r/ [rMu8sc(jD{+D/kc6L<쵬&nmI#%ҋk1f)HFMf!3݄aM`I&֮tx`iCAk U]i/6`>_b"rC&p smc#n^2{Z%!n79-l`hT돋?[鴰ٱ@_BS]Ʊd8@p:^ܾo|0t=ݗq47F+ߗ֎m ΤFmE^~} ;)p49BH~ <8#/l0Zh8AxR{-{t3u`ųA,n?Sůk/g:6Z^wS}ok57#v]@o5OOi=D[%pu?뺛RG'^?^~O0K;{D9"i`1o|ywFYZxtxaS8Qm6xlcqxsg]3}`ǏLd fi=n8aye) $?~*3͟D[va crG[OWg`%l ̪8Jny+E A)r< HrAB\${悸`;d~ 1r3AxIX ŘV=wf:_ۜxTaY9̛p(LlM{׸ qayu-ԋQq)lx 4mBi!cYI&")d&hFہ_(-_ 0J9(I\h\5 WAdd)Eg g%Q7 q'!ſct0tGa{}Q˓O1"~(a{\ai xg6䀝b0]`A|QkIELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km[ehttp://ns.adobe.com/xap/1.0/ bjorn.erik.pedersen@gmail.com Malaga Torremolinos 160/10 500/10 28/10 28/10 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 0, 0 255, 255 centerX = 0.317495, centerY = 0.539287, radius = 0.037149, sourceState = sourceAutoComputed, sourceX = 0.437723, sourceY = 0.539840, spotType = heal, opacity = 0.1753 centerX = 0.319353, centerY = 0.539993, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.262521, sourceY = 0.539993, spotType = heal, opacity = 0.1753 centerX = 0.315717, centerY = 0.542001, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.258712, sourceY = 0.542001, spotType = heal, opacity = 0.3316 centerX = 0.311387, centerY = 0.538226, radius = 0.027476, sourceState = sourceAutoComputed, sourceX = 0.248336, sourceY = 0.555915, spotType = heal, opacity = 0.3316 centerX = 0.312516, centerY = 0.541311, radius = 0.045786, sourceState = sourceAutoComputed, sourceX = 0.460210, sourceY = 0.541864, spotType = heal, opacity = 0.3316 centerX = 0.978481, centerY = 0.252986, radius = 0.027387, sourceState = sourceAutoComputed, sourceX = 0.894010, sourceY = 0.252433, spotType = heal, opacity = 0.3316 centerX = 0.974345, centerY = 0.252157, radius = 0.027387, sourceState = sourceAutoComputed, sourceX = 0.889874, sourceY = 0.251604, spotType = heal, opacity = 0.3316 centerX = 0.975887, centerY = 0.251968, radius = 0.036587, sourceState = sourceAutoComputed, sourceX = 0.900226, sourceY = 0.251968, spotType = heal, opacity = 0.3316 centerX = 0.596090, centerY = 0.159539, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.657413, sourceY = 0.192430, spotType = heal, opacity = 0.3316 centerX = 0.857023, centerY = 0.075264, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.785508, sourceY = 0.074711, spotType = heal, opacity = 0.3316 centerX = 0.936523, centerY = 0.223695, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.874509, sourceY = 0.204900, spotType = heal, opacity = 0.3316 centerX = 0.050101, centerY = 0.345555, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.114879, sourceY = 0.315151, spotType = heal, opacity = 0.3316 centerX = 0.055633, centerY = 0.343137, radius = 0.030369, sourceState = sourceAutoComputed, sourceX = 0.129739, sourceY = 0.278460, spotType = heal, opacity = 0.3316        qAdobed2!1AQa"2q#BRb3SrC$4cs!1QAaBR"bq2C# ?7iq[@m(@m  h(P`,`P.0YE cqqB(XBc , P.0; .; @ \ P \ v;.; ap.;@@ w8p;  Á8 w@xp; aa L! 00@@ L L v&0;=iq[@@mZ iE hEQB` XE qPYE (X   \`\`P.2Apq\`P;  ppB@ \ vp@@ , L \ \ v;a @ v;r&; 8ap] @ Á0 @@@@H&&!H A0S aa_Aiq[@@@m(@[Bh (A`PXE q (X (X,P(X, #P*pBupp\ v...8$ appB pHUB&; Qp\ N*apB;p'pCN;aap 9 @@ 8aaac@ Giq[@@@VЪ"  T XU @@A`  ccBX,!c a, pqe$  @@@ \ \ P.;$a@ v \ \ v&&.av B&&; ÅB IQ8J@8@ B!H p @@- `uKiq[@[B(-[@V@mQm *.0 +@@J(X,B–02"BX` .2(A`P; ,  qqpppp@@`v;.;a0;@@ L v&&&RaaqHT)!@haxV)0 @`L L L!Da?Oip %(-P P% PX@@@@Ae, P qA` (YE h,  qB@`\`\`,`\wBv=P.@@@`P^(XpqpXP;h aax@@ L L!*aaaRĂ2@J@@% L v0 Y1J@%`v0&+110?UipP [@Vm % h,"(@@A`+@@J= >!,` 0X,QBXA`\`\` (X, `\`PXE `\!Uq\ \a B@.0  #qpp v;@ vaQH&&;(B 0Z) @8@d* @ L``B [ipP P +@J((),PAa,YB A{@A` YE .0X,  A`\`\a ,  (AdUTpYQpB@X;EAJ(YcP@X`\$ Ô7B@@ v;@`L v DüA @J; )aa BI) @%`B I( B0&0 _ip+@@@ !(  XB PA` X, c(X`,a,)BAa,  aBAqq,dP.2  cpP&8$  @@}v.;ahv;;u @ L9H&!(8H! R)J@%!D @%:@8@@$V)0&?hb8-P%BXC (A` X,PA` X, AaH,  A` (X`P Bd B B|@ ಄@A{@`P.0(X,a " L!T@!] "aa @!HA) H&!HShR@0 @%`L`!Xq1h8[J- !Z (a`PYB   A`0 0 0XB X`,L"2qd,c .> PQq   %$ (A \` ..;hp@ \ v0;"{B8! a0 0@ H @ % hR)!D"`L Vl8m(A` YB a` YB A` PaH,A`<`\` .0X,(,B2(X )  YQ.008,Eü $ B a..a L v@E @.&.:8a ?'($Pd @% !Hp O H @8BI)t8iB@(`0(X,T X , 0X,! Aa,  , PH(YB  ,`\`,`\`P(XBAB(d/x,ApJ.2"W$H@ v p;p\ waa~ N N p'4@&i&{‰pi4N) % JBORNEB?z8!P 0 P 0X,Paa,)0X,@XA` X, Aa- X , B@`,` (X$ QB0.8$aaPX/$, \ PB.7B8' \<@ v;t\ wᎰ''?'4N p d@%,aDӀ H IA) 8@%<@% B $Tz P@ZP@@aa,) ,  X .[@ae, aA`\`,` OX, BA`,~(H, (QpqBA (H pBB@E A7Pp pwAE9Ba ..a 8D8Wp'pGCN4OirP8Z4B)@ qJ@&R(L<@JX,h X ,˜XB Ae/H, P  A~X,  qP0> P.]@X`\w@X@`, P.0X, B" QBwp\> waxS8Ea1Bu\6xppBR@ i @<8XiITM9f)J@% ily@zsP0X,X ,Paa -BX (A` 09B A/X, ` (X - X.2 P@@Z X(X (X'@BPN@ʤ c" !/pxmk@ \!+p(YQBv #u%)\ L>&6p^80R)4COÁ ;Ȭ-* "H4fi ?'+{<8ӐLi̧p{@x & 8 @8`zsPa`0T0X ,(,` X}P@X, 0IE X@A PǼ  q !BN.  wwx@;@a?aB E(HS!N* \?@9GaH(@8} ^+~>;8pN<1ri!f4KĀpiii̤i pp<@ae, a` ʤ^ܠ0 (,hX , @a ,` X$  AzЅ@ PH  , PIQB$J(IJOB  (A < nPH $  vx{yE8'X v/4@m\a4@;Ӂ @& Á ?i0ix ,d, X, @,06cA )AdR" $ YB  " Ǭ aaL$!aEXxU "ԂB.)xqpHa @x0 @8@$a % BX( @̧R)2SR)<<@urh4P@ hh D `h@ 0?E@a`h@@oJ_HXR, H ,xˆ ,XAdS -,<-0a (]䰂XbzAaH/.`0XA` ?,0(X, y  aL ȍO@A PO4 A  aB`P.0.;; B+c1p0 @% H(%$2`Fe" ,c6HX ŀV,trj F$_@ QEXhCUūE4 _Xjm ^Y 0kF,0ņ䲌/h .jAa -Ԃa|@Ad(X C % @`@@Z ay@@@`@ao`0_az@A X,PzoH a(XB YŋX"cXŎ,\`v0K ;,qXq ʼn H`YHSX̬,Xb+3+%V,fV,` biͰzBF j5 4U(abƁzWXƁ{E-ZIhDX mL, /,0;@ab0 0XbG8 ,X ,, $ņX`mXV ,X`HXX,0ab -"  X0YFm ", "0"K(ŔaLYD, a1a(Ŕab0eX,-H,YEqRRQ)qhq)Be;c;YN,cIe;lK)EEZЕ) Ie XXbJI`( ER,)%̤Y@R,+S2X `ߔYODl `hō0"ƪ<@/`5HQ@ōō a*ũa 4 XXao%ņX/, ~QeX((Y-h(ŔX)p)q(Eai, , (_YD, K(w(ņ%OiF-h︋$QYD, a"҈,YFKR QAbֈ,YF,,,,, e2YD, Ab\b\b\b\b\bv1e.1e.1e;YKZcS\d,cRc&1e!X,+%%be Y,+P( Ŕ̬Y@%bf$YLŔ8)1hV-ZōUbUZ4UVƪc@o%,5cU_,hS@" -Z(CUVze4 DX , il %4 AbՠXY,/X %av(Eam%[ŔA/Q-ha (E" iDYKYF%A>FXeHĖQ(E$ab YDkFZQ(EX,Ab֌,YDEAb0eX,YDK(eY, Q)BŔAb֗/,,,cR)q)q֝ZSZ\bv1e;Z҅֓,bBYBV,-hJIe XY@WYBVK( Ŕbe3+%̬Y@V,edYCYOUm[*Ŕ,ZU[ōh,"Ɗe4 S@hSE_SEXZEH(,(~e_kF,-Qy,U)_YFYFWYFK((>kDK(EA" 0Zфx$YF, Q)ťX,YDQ, Q)B,{EI, SENZф֌$(}KF)BƊ0#EHD4Q(Ɗ h (F0/D4QAcEI4abҔ,ZA%,R)q()BŔŔŔb\bv1kN,,4$+%e;,-ibLbYBV,+P(JeXY@VK( Ŕ̯S2eX(JE Uktʟx)X*E4 %R,e4 SEASUA֍Sǘ~kFSUH$YM}䵢 .kF,dPhQEH 5Ne4 J,%A" eI-hEa$ %a$F, xSf[)pJ," [(҈,YFZф(PYE-h}IkMgKMBI ~$I 4dFI4eBF0$4Q$4Rhѓ 2Adѓ 2AcKD4dƌXd.H( $4eBƌ1+hʅ\cFWѕh2eNMcK4eƊv2ircE;1dє4Rc\1"VMBhȕ&D\X@V4S2h+J( ƊJ DhTwʑkM YM )ӷ,iťSQv)Oj'Qe4Z~7h)h)ƖS۔hM>!YMkN,hIS-4E/Ɗ0S&$h(F)(94Qq &$Z1NM-dhJ)Ɠ+)xV228N-M% QKEEY4Η-IɄY<$ɢ/I4Q,#FH$2A#FH$h.H$h&H$ira$ђ 2K$M $4dƌXђ4d\cK 2ƌѕ4eq\cF]h˱\eїc&ƌɥ˱Bhc2cFD2cK"4dH$ѐ"6#K"4h2#F@eѐa.ag,ȗEU>eSmrhkMuE4TiU&(堧&h)ߤih8M4SAHcE5ZDAO)MkOcFZ }ExFѢ _-&h)bM94Q^6-(-F1JMB4QqiƊ1NMB4BZ54b\&)E8ђˤʄIa..i)xqSa#EI4dIɊw$13kO).MRM5 3a&$M A$EhɄ4dPirAcFH( $4dɣ*4 $4d hPc2ƌ1*6eqfWBƌYveqv1.6e.6eɳ.6v2mpckc&V6a mpIhف"6`H#i"6`i"6a Dl2#iaLa5,]3f]3"]%?!D>.J"I-8MV4iѢZlXіi4SEHMKM(іLiɢ[kF b bM-4ZqShK)4bhANMh?4QqZ}hLIRHwF1J4d?2BhƊ1N4QKEÍP&S@ihI Z\#IZ]L-J\eeBv2Jxѓ 2A$ђ &$i4 :\iraftL,\Y4\D(-Y4R(ƌY4Q-(XEh &,h &Xђ4Ph irAcFT,hc\2hc&*h2Vv2ir̨XmLkZ6e֍ukZ6e֓kZM]i6ѳk i6aKI0%d #0I#f`fci"6al0ͥ8dffy'T?=צ֛*)q&ɢ4SUKIFl&-FjMPF-U>Ѣ*IƗ-oh $MFh#KEh?Ɗ5AZhMa#EM4Q-4Uh h oZ,dD4QadKDMAd&ܣE-E(4RFˤ4dƌY4dɥɅKM.H,ΚɅ6MeBɣ&M.Vh˱.HdFY4d.HђMFirAcFH,\Y4d.H 4d.T 4d\ѕ4 $ٕM.Vѳ*\lɵ̬\]Y6e6e֍tmr6t\mMiZMmpk"O1p$I06` a"<2#0<4l30ǘeac3fn9<7'.+Q~br/-is)UIkMUzFjI"jM@ZhYMTFhiiYMmZh&06)cFMG4S@ZhhZjM`Ecq)Eo&&"1(hYEi4RZ $DihEZҁ%e-X)YUc 4SO=f=: O_Pר2% (؅Ӯsy/<~Z.L&&2@IɁ&3&$Z $KhNh4dh$ђirhZ4dKM $䀍@Iʁ&$$ђMTI̔\FHF+&+&̬mrMY6]2mrٕtlˣfV6tyL5535I5LQ:gj8:O1pB$m''`0<3b` yym0 ˴622c5ٞ 6'6"tns3q͉m?+] lZЛu%6SZUjD)Ɨ-I,irsMF("M1).LFE4XіM-FɥAxѓ$#FZ(ţE,hYJ2YD YF$e֖i,ZӷJ[ŭ8 e?/>ޗ}kV:_QtPi}] i>ӎ|xViJ.QNTXoGOWǩ~I~{ XQkji§Rv0{?9O>|=h$Ě\h 4L 4[IMB4@IR@I$$ɣ$$ѕirQ+\䄚\kirM.TII*$lʃ\dٗ^M mmrk^Mxم\,y^Mu\,cXtϘ[a.&|Ʋ섞ae3-&Rl6S%ei6mPk@ZM3&6d 1pɌba1&i|6i12c,sfx3c7&3sbx1flO-(FoB3mD=66Sa3kMkMP䵦d{e6F%5SKZhx)֚)e5[Ie4XPd~E4FQ-)1kD QSAƖI'h4\RiK}ŔQkF$%B-hKZX%e:kMa%]O=IW&;ky(i?I5ҙ|T2`+7 .Ȍ.\q}[xSӅB}V%TfU>Po">^IE2hɥZ3M--(2YKxђF"MFH4 DirFTI$$AKirBgK:k%&$-3^M.]q2@4Pdѕ\n$ddD\ˤd;k+&.l˯&.)IMvRe&LvRM6.2mD ڳ&6kLFڦemS3RM3/jɵll_10͚n:Mea%_YFKZ0,VZ@m0K(ÁQ^'.V(-;/AZ@K(Abeq줲;E;9,epΪ2i,WOmT3Rtڛ=0i88'yWXSQQp;lw5uPh+9><23g&> QU`~Bߡ+Ei-hIkDIkFf֔<-W卻u_b9,,KZ K(ihI)4A)CFiiAFH0Md 5I:)AM[ɥM-ї&%y4[鬭o3by5ΚM-:ftS&LƊvBME.S:JL)2hd&vRLy6((mGZ6 la&fDi G2i62cj1 mL]Li4͜FMS2j9dF'"t6J|Jj iJ d;&&j*"Z ?9)m䡨JiW% ּU;V[+E kơE@ j+E1\m cQhS1\w!@Mu?;9^Vh%J!\EbkF+kMaQo2Zq,xZDS~-L^4]w6 ZO"gctqj{?<9rro`=si~Q|Oak躍kzR؟{QE( fy>!?\gZ-OEQ%4DQ Z $|kJ*֋$^(ֈVZq Z fmiEi-r\i, ZaK\&mrBLY1VKZ.,^',qd弔u1CEjIKf5]j2REAWh5^d!%5^bƯ̔JR;5~d!bz05#-kdZh5^dZ5ijyjK2-/⤵Ϣ Vm+>Yx^;q|?wEu 7>*^78ޠWu+=*wO_.:{=.YD߬5_`~ P)FEEE2CR;ȴcP;ȴ_i ^d~&fڎ%3-~'ns3-GDxw&mp<͘N<͘w͘wKL;%!^few$*2Bh&mWͱ0LķM̹KusNS- 2a6l[90mLIX:Mi%樢kN/-KKn"[v X[uy%8XM7Xo3M-^n,Zj8mG͵f,P;5'R:D1yS\JĈ}<'N>|rʇ޹F5ST5t=:֝qzD<O>+M?^HRp?u"N^ > +z{+NS#'<=?&r~>OOSāF~O _V_M'9{Ci/h15(6Co<SS]G5rH{#~mCQN~|\#O#Xl<9x>&jußK;wN|/S9r%CBTJTGTw=.@rH2ս[mZT"M.\98_JA8*=6CyӚOǜ\>Վp˭O8ʣ*U͕]’O`H3 <>Bom'puFJSm!(!<~PGRWQ^k?IMG=#Rv|&/ZJjʐJkRJS甔5d1%) )HkJC_i)TkA~8\O3JW:fGkT"@# =6koY~ю}iqo^zQ7NJ@Dy^ 3~P}ƪO"ᦉӨfxx.jzܧZ5&;)E7fe0"ae0CQeDEaky'texJ9̸L=t̸r')p)qlg794ͧ/6Lq樖Xb][i/ V<5זVxԯ,Cqyjj<Α87[ Un8w#Q[W_n3P2< v+* øPAdR@ J ǸׯTV3fcG,(`wm^UƧGTҬ9؃q-wxq]O%mB %WQ##=g((Z:pF9rt׌:GWzL]UZmQن >6 &lP2$1L-/Yj/3~~NY{({Qqjݪ/ҟtԏOO]R 5^ӵ n:6pnO ;|R~u>ۏUB[pNm1?-Ǎ4>znz֕cor"|pKѥt*Ҭkgz\%Q>f2ҍo.̘S38[1Y2cW~e1&K=۟KCCG:G\09O{Z3˩=ӫze!ĩJ}K*OQE| ?QϗGwywgZ- jPpC'fi筴ZXliMU|?(֦ͦafeYQ/g>Xo9sFU9."~9}u/eQ&Vky2_&K!=RamFߜ[!L[!=מa/8U=Q&=@ D8n$ǩmbx5_G1]̘h|WG̘U0=G̘U&!'UL)P&z5D=@w QPpC^;市39j ƿ338t13<"kykOH38t13<[0CWLY gCULy313'ey.sW3<\JpPS,YrУiHx~O/){i *yKKO|N˝=?8&|ܼזx;qoY>G_>Ks)cyM}W tuHtr'qg^k]EQ 2Rөc c:^pԞ}Yy}>TPI$s幟Gs}.qȹ#G9^?/VB&UR c옧B7WMU:*/agD ofz1GՏ&bg_i'jyd{D4RH.z'!O&Wpڃ'Q)<U_]ei<=Yg]V_j9VO昞'L-8/di赸!gɖ OO&WpCՓO%VCgkpi8z?yyRVz!c3ZKLqeW'-nz?y&[pcfz2rOfz2Ǭ'&]#4_Xbz2)8F]#4_X}e9CUz?>їX 8OF]c6_V}e9CUJ}'.R}Fy-'-W]HzS5 .sҟg9 pӟgר>]9} '}rsϳ4vfx|OivbxKχ'ԡZ>ϧ/>2ZvHOz]J8ЊLq~+=W.YR4ݙ`}BO|3u9"|Ʀ3zyxz=zzvtr Ckg3üwSsӚ>ꏧ'I17@_qOt:X#juq{}.PpZ y|MVH/α^.^ω 6&ㄽ:\Qtҗ˯47~=)z#/W4)vVDz}o[ӯzx~R˫ËWN/OO s=\|ƾT\Lә* /^V66po&͟gQ%CFPTّK9 Y>>VttƵ%6/ vytOJ} [F3Λ ~Sk|~Ѩב>czZ5UkJ-Pl~>B0'PN=0WBmcүV>=7VޝZhV:pD9xC[I+ѿP`xo>rzƛ_@: :}= SxR='Pjڇdҁ]@$LJ|}j=7KP(!C#ǧ]9R9mmVu^Ԫ 5j``Ia:q1\kׄ͢L\α.2WIvnv[^s8<}Zȫu$oM~{EԭUVq7-D/ϲO^yYx#W+ZypǓϷ#ҵءXz<>n}j\h54Zf:5ߕoL];}?W;9^$]xW>CvPRȆ3}C뉶TlN>UP V%CHrT=AH Fy>S#_@Ԥ֓8#?3> ;G+Y`MJ`r8{SNH$\n{|%_J)x>uO@pv>S '%[ob_{w:s>~}w4>ԧ긚ʊ]hPL^WbX~lŹz /7kHVZE]r x>^HHS.y}Sdk:EE6b>`.ݯzN_7"c}ڏ}:TB%6|Ou}4[nD!#n-gtGTOM1S>V̓x}ڏuV:m73>ۏuߔS>]ZLO.k)}'TvIc>G+[U b5H3/isQz۲ngmǼG/};2ײvt}t_ݺiu3J+-L_~\LO:>gXO+оF8F}tG׏?ݰ_V F?x~ԁ#ISc"m<>qt9/=&T <|t G/zTH7ښ'b񷗭Δn?iiFdS{}'t:c+Ǐ\ӏOOw߿qhUM\|#=^]^q9|Oח).ސ~\8\~u^zܮ<g<}xZh_k*S-F=QOmז':^?g|}_z5=B5@,WFgqkkuՂz?9~_ǤWPg=M;1jhݽ;_K#_ǧ?<R:*v' |ʭ/܏{:6T|OH'r=~<ܾ;r(6ө# U5Q$k?)ߏ~<3~I?W4mf NC"'+G_Q );GZnYҁS>̀'݇)_ߗkq'HqrS짦KTUn@7.#`j =7?1>#Kl6^bۇ$vR@YM.RQlƐck66S%RDEE[]&ǟ>vh/kn<mEXb]+[ m~R m"›J X-MQr`(zH ੷E F2lznPKast ,vSQ7_R(_Y%U(7İ[IpdW=q%(隟[kX\4/Le2 ^~rQc(*ïwT"$nrTzAT,SkHí7jPzCLw$}L|tLQmI-*R6NH?蚑 u *w@k8|N%zg;Ө>,9>~(j5)P*p#a3I?~Zm}\Wpy݇a5"S/tꞞ]]:=7"y[SZz\.dwn(;U\,0ldyF$t?ziϰ 뵹=E,Vװ1j P9 ڙơ' ExXZ~:-­/a[ff;rּj@i(O"X.VP)2'eQNVȲw~ E[= i}1F2b-V5ic`//5hizF{q3ݽj[IzZm[7bBߙɁ;s {FTPo*,a/OPj,rbK\;#*hFjzAHN50;7=^fxDZSZikraB}Ѧz5IVMIǘGڲ૾TbrR|MzUڕGRPCkx>2s5.~&7~[%4?U{L+42.N=Ox p~s.rn:o*VU9BG"T>Ǵ?^jתʌ]|JaEôx^!:cWY:*uEF[Hg>=.\#ֿO&C؄jGB8,(n5>}'6hQY~=ӗ.Ru<^Whe}[\:V*BE [{_@zy¨Pε(ud_S3_1}?hi 2dפP =x)}nofU,I `H>gSOtlLwWdu4NO2 $o|D<zGm:=M>w4us䚡ϬSnj[Q{5N᢬IާO7x؇Ʃ]2uj*YvjfVSDv|N3?UƦhMu7;G<|?wޟKE*zcz0.t`@mwDQp[tț ޺u!* E"P|Ko=ͫ ޓd [T$sT8}V!ڄ*hF(Wo*@GJ>]4:QAa+Xމvw2OK6ɕbڰ_7Z*QZiSH}bTZJVɳćEUJܨc`Ou"jq~P5J+En6TpdC}=V &V5 y"u*X+0`r߮3oy`%CԪj|cFZ04k H/ :r0KJ] ?P )i.AC^>A"uLBO=Tba'/R J;FI%nM[ X97rk;%F֊j&y)b^mYkaߑ:yޗzALv,@/+_tԙ{u X=\lGn9qzL%^yyz}j}g [y'GuYeer6?ˣ暿5JGӟRs1o1bx|g N 7^q~󝣋=O5T?WNB5 䝘\75\5DAOrvZXf[\RdC:7V',R+snnI?KgV=@/9Y{4~jtm=FRñxr GV1VB,ZFې<}X];+iF |deFu5Y8Y81ו[Zw .'0W?c3EZqV!ו+oQ> D;m#ÜZsmOA`eYI.N<(j/H;ub NbjGL^ɨ}52@{-&SMed ˙pz2ԥWRjihܙ+ά؞P: 恟d!:oU7-s{PvĠTi9޻|P|O{= WT3!եV*m)7Ӯ/l-\o}ȭRss i|P0<_*('*6EEFԝ5BBi:8VsM㐔x)j]6="Gn7(7cM 6$^+2l8}IiSD)r?v & 4t54 @[<% #5lJk[{wx*{ST{2 cwX2J4Gms#ad~6R@5Ht}P;<{mQS`O.R-0` YO/*lo4s@RNGe_Ơis{@ JPP:Xs6$-j@Y6jRےdPU"Jkkc̙,IQtZ:tvΛWNqsy5keâoqr1N(N O3Ӈ&R 9az5d14ﱹڎM6۱2rìjjYc˘Gg˽R11^y򺳮h.I 9 Ei L*i$j!s~v4h91߬$w@{>!S|(;Kei)-lO8UaqXhFE-iKS\cw|YH=8ݻJiAFɷN#,A2֚%{ Ԙ:ǼazthHJ1;8j}=+r} %)PJ~WvP݇+ZJ |"NhuȸS~KzFD*jG?S%JaL髵jWYѭJm(?/oHj&?uj9?mR,z =.$RWT7sk|(iiEjF;Y곭JqӥK"s6MtZjf*Pij-AM~@$SіWAMf6 OɌ]uZ=+QSGK Q&b:Q /K=KSzզ4fYo~@3Q́EFu9@Β8U`{Ǹ,ʠ*Q 2LW±UJ;ELyohMYx0>m h5He13@r\@y5T,+Mk۸Vv8$GYF0(z|ףFXVpP~re %6U9v6L)w{ALn-ONRot2+SEJأx}7ӛ%F@W8h2oUs(Z {VLkE룪ALT#6 ؃S0;?5K"ݤf~_)@զtG26>G( Gmn%-SRj>DmjV(Lv5,`9 P̼ug_ۘAo}UoETnIkߜ[Uf{`nB gMK ôt*TEI2D9;(=Ѷ]y:4+\rKiO==JAG6?ia㙦Hw: D(<ܟ"Qu ccrdz\wvt5⧸ʬ ok%Pq#V# [9' w}WˬJ`_GPBUkM2т̀@:j IM*ÖC}( ȫ^ܘjCvf=4 n{j_ O}V9ToO9| ήA?IRΝv@zbZSjYЙoN׽"ir2$cf@\#dG'9H+H/eO(ɖK5 頢7rp9TcU. 6Lp-&3{NL>JoPV¡^)rFv; HZfdQ1',˱ y.@@QQs"gyxP R&]]"rizccM#ɨt#ѥњx5BQi&kiڍR eM/KiONR9-iRE۽S"V\˴Q.Wsͪ,H^*(P)+sGeh騫K::vxkӦ+)JovPn?YQtɤ4J^ٙ,~L޵pk)R+\?2A^Fz 9^تEK2w5 [AGCPE}YSTAQoVӲ2 u[nDQDDYzDA)$XUkvUC__uյʭf-mEE2󕸵-:fvdČxVS"A)Pҝ ^R+Q>;H6ckU9GӧMh Jd\2u4)h+dz L)d~7ZiP..Vw*5>p70<:ƒL{oQy9%TG7 ҽ,~VcT|nBTAM mRI*+lwKlo(ū~k2lj q_UV \_-XCajy*Ң5hŋHTrI[[x긬(ZÖ=zju4੢B)kuPֶT D%jTeP`;^%IoPmJVXiF#I!*A;b9(X.bA|o֘SUi vn630+zZsr-v#)m 6Kٱm,KoIYgY*5cPEXs1*vbVWT-33-b~v^ Iױ5#3yfBjU fЖ(} 7!^zt[TDwWD`KP.5&mc6'8)J %9/9{o+Jnԏ&Vl̎FiL~x8N" ɌuYOQ9،B(gYq]-њ.ʟUP7V?U1u*ZFZ y"s[ގu5 bC@'\I3KMihm;X4 MP:LFCdZj6,*n-T{"j gX31Q1t2w/\܏-kE>%KªX߸;Lw^ua+o ȄN6U!]B_e;Q ZlrT ٢x nծ7j6]ŀK6~jkVAr"$kz -$n " (SlLnx^*T[0(WPI'V?A3nsOFsr^A,Q[A8@MP6ב^J["U]UB^Q@#s+:a رi6B&Fطuj{ʷ^PMV gZL{-ɵJԂUT ڍUʱս7=R}=b%M ]V6Eĵm,fb0er=߻cZzA[N+M iҵTMIRjMQ*?XPBԀժFA+u*3R_K&nKq{I_u>EFUoCn*e4t15NnێpeOTutҦ:\!lWzOOM4 i@7aoםX,ܑ~{JҚ-suyuf$S-`PzcH~vQS`jW`-f[ ®9T6TKW z\ۜOMAkE@Qhs]hW=5ahUIT7O#Z_H-FۜM}E@@x" @@,HzčE`ڬv3+SV^B62ZW̦j: 4>tgfnBѢHe iCQv=!H-C{32V&ROrl?)-irC1,drDq{=GӞ Z3-qoJf!|Xe򗆄1S"L5j]U{A%-`T_kY`X Gj\S{ [ q9֮^aBx#Q*eϼE ߠJjlOx"1Q\8?r䚘gJGMV7%}[u (e3Kmkjd[ Fn|n iѾ}dWT "\xHí` [!ΫT!eeS@R*GSR[l2:\@?C2MЫ>^aItM^-̙u5l(~(R6&\dw5j7X$KGR2/S{s2[ΩӪ9:VG"7=yf91$daR@'x k+ehZlv0MNûlyWe ^QA}--%U̢׮qͰ7W)N*㜀kcqVO䲛#{WQp.vTiJuZ4H.w0^a=[[0DT73(q$5 p $CӚ"k0b}|3bzHvO½= śXF Q,*u$;\U XH &X.*IaNmxZT~gdMxa`@8UɑD!Lf*sc Gd/ -itV@w٦hg6s&!rqE5aO+ ؞QXUٓ6&Tvb}5?/8& M609#Xu&}![k?nCnV yhխ{o$>N!P6eݷLbnzJz@Y ,Ս%0E-ui$[xq);Ef{G6AsR {VJqn`9ܑ`>҂Wk1fbd0 B *ZLVQ(5p7!Wro (Z5KqP6b[H9f6qLXXrfyP]q!-Ak:NJt!\B("MDR[.+'\~RX:ٹ x\]m:@6!Oޕ `tEStSTRzF1%\5kyW5g[`Ve 0 oњ3[CjNj;(۰]t"[Jj( MD`Ijʥ kPS#ıJx*ך\MSTT6a-X4:}a\#Rf:F{c~<:@4^v7H u0#TdMޕ%fMPç)KXT A8x(@-^A =47nMo UTs')K۔XT$EȧU.ͤa"c{Y:/&ԨbhUn9㜀TR <|vzk-O){QV߹߼(2H (T[bf(7`9ʎ|Ù*<*]Z+amZ s&Bބvds24+Qā M /l&0\[``hW,J+oRRTR0/-4JiNulFĂ9J o&ñr8K Zk Ԫ5Yk KI^vIkOuLP},m6=/Ӻ0Z׾ZiXT9_CR-bOV*d&jֆ"=d.qrX%&jvb,qm:R +S{)iկQv/~RtpS)BΛ|-x03\`m#mow"bKERەy5^/y\ G(KM$ANrs[P꾑P OZSCQMd*SUم!\sM{/n%ZQlK5/?Żӛ(;:@Ω[yfH 6<ŷfNaB發MC ;NC-$ `TTjVR4* 옐2 FJf6\QTcƩH A|8-^"jRZt2#wZeBe[ҫQNKEwۙ%\#dK?DDBܱ]~ jw7[}H0W+6lIskIWYp5l.YrO[^VXҪ_D\n`]Vj dP [x5:UUo q綗RXSXkW5΅OkH\SR[Sح۔(H:B@t0:+ FغGv6@Zj ,mdP\XQ';@Y;]nЛs0mB9@ƵEg\(Sfa!V_j~NMꕳύ ZK>UV<,LmHoAZAu ケZjdQP(̫5rHnpWTY{n XPƟ izLPU+֑m8:-1lߔӢLYI ^7Qia$v8j5 Ew =K_tkI-DU<%3QΩ,.K,lFU?EG~%Sf# ݿ)P8)$Tf&۬#Q5̂{?_}q+W4Jfj+](6^PQ~!p*mm1xLwX[H+}Rfz_MTcq@3]?QIjB[2gZ 6%AlIKQ ܮO:^5S }& fJE.(kh XpWߜ0+tNm]ME핟}9}MyliZ}bwoa&5RRQsa(w P9[M9f + sG֥ J=?wxF&N%#đIߕGm9@b1=z!tt:@?hh@t: em BL tvqrw Ɂ/#/bts+ndw ?a*0BT6˼rXx`lihss"ժF9XkK`IaVF`uk uBhX} {s<¾MR#jhwݻLM ]~kLk; K ΂v&T㔶 !bZ**e]: X{ve {%C 0CzP݀)*[&AOL^-N"cS&W^!;»xE5+U!G!PQrۤ&[<{PQb[*r BԽ9rmB1>I@@*8m ,%D'{¸akHs̢EG]M@G+}IѤPj-R)[4|,3@_( z[F΋P}=jWл/U)dv$+Q[:;UL4Qb)wjckRMǛf KS[TTɪVw!.?A,ԉ*Uj \{ߜQiR;Sz|BMbG@T)z(wzCj*rַɨ̽FGN/o5~2oFWzvKs%[䝞M7- p{W?,vyu^OAh6R߇|וToۤ2M>OSPn@+ێ*)#w_u.|ܕxMӪ.m!5'\-!<,̄EפDTdP J1%&crj.oHJԢrXU :IEבFJl,CTLm 5eEJ `D -*Zo8\͂{ߵ" cD`pq \FOHv:`w=uvt+w8c`wO08xr??"Bc+'PE07a(U=6< KCtVa{{B[YA MVnuN*{~ =a+򋐽Z \ txhHrHn"gSPŹj6Icb7Cr/ ӈiչ]9@9 Gp9y@,I6%`9S6MO@=E[`fyKOP!"6=KsQ3Q pm݂Ju~$2~JӦoʫU);zO@Ԋ.&jMl^`X`9bdSBApF*vvHpT3aD$}6Kmk*1Q*{PEwVGb}gS5t\骾qMW鵺TiT}A7iu2PivΊ~r%IkLYGj W :>"}|UTpU[RqM"iVTL؊"6J81͗v$<֬ZAvAUED;YE*~c#%%*ڮ4MflimM=\=FPMFh&aD=@ Ev4rn$WV*i!`6 /Y֭*|T<Ko0Sy}ЦYHQX_:bosN?!4ĺ*<(5ZVn.5 FwZi~́GmFE6O,RuXSϼ|(z)lf<jѷH\^ۈVliG@p&#ۗ":ؑߥ?$6m)!b- Qrld(J &/n " JwʍNÖwňӯ8ңglX HIu ״&ِ~$]I.V s عۺ" JlXZoq!۩$NȮ'ŠHЄy@|Hij%XVdZʤ@ F͍&FJ#Op YO+y pf>U|'HUߙhAP67=`lo(vLVvm)}ii- MJ}+m iЎqWdhYNYB,ݶ*/ G3x 9 %3$ Pkʕ!ISQmVb݋Obf5UXNN 7DQoE-FPTV;=Z`2LAgհ=@ o"PYZP؟=>)]ѫgpwyZd,@njL:Cۈ7Z]*?徹rRԨ[NY'b}vSAް-)P֊UNSIp:rh骓Ι-,T) }+OD}Z+5liGQ@Kc(CFj4VlyK|TMR [{hRVO(a) Rl\Y nW\H. @D>茧 ~=JޔBE/ol QʮUO6 0vXGQUժp7=}Pʅ-=P2jk5Ŀ3]j=*IAkf~{" yF5MMscX3TG80 pZelvFImѦa]u4od]SS;ö5ii\*Tp>r;!n2кMf-E.u 󰖒ؽ E Keb6vr 1b67+Qi(VԐj GjRFQU\_Kcwyx:(x%+ Jd>'F !O6 (]yQ4:ZAH ȦUE%[Q*p tn#BKZmO UtQȫL);uß73*)q֥M@[򥳭@Kn Wbו›} ԃjj ?bbۥ-+VO?QR 2$&ElޟQE,%,~PS#zbŰ /J8[)rjdh !r2no-֏ UVDz2{QEt-Bjʰ98݋۟EMYDL?i^ 3*6(8=ժfbGܐ%*n2O5 bLʊ7l:moh? Tr/,x'6x(D"%CQ KǼ@B{*R۪P('nf(boȋ[BAo*$ܯ\`uȁU9iTv;BFW<f܉ H%ź.%VnyB:9ۮѩkZ׵2W)!Q.pD9"㔡ܟlڎ*Io{򁌃Q ֓*[@hD,~c6>|-kbn2`KS[UDU*eQl[UE䇑48iRmM\yNpՏ}$ 﩯jcek*!'u`.eԥ75!STʼn2+_&ѩJ}FXR/]>+1o0kaÝx#˩J5=7ҩҵ,"&}b@J: )[fz"W@ɞ+QJ/lCT* 3[*T6*j#-kL~PҟWQ:g$q:iƜ@*xekG8fx} Vg4RzP˳'[KXi6r-q ~r̤hk5 i֓N@Gk%4EL@܉GjUi SZ߽>l(>I?k@!r{%TܕQaTfWuz5TqQVQiӚ*S"ĭ*Hn)ʘj]UEeZYAE0 TiiښZ:H8P_ʅ ~?hh UlO[dh+4RP.ȨܥCj4 2ZfSďJoN芔V "yk+Рk& oٌ.K(Qe5BZ4\(?4}R55;*6_BvrdmmWnZ #QGMBT[S:Ҭ|:/xѣM:G>@oJzom MdӑEH, T/9>Υ&KF"¢vѐQT,>Nݎ!*Ҧ馨lG r>7YPPyQb7=̮8Y-SJG#BUe*Rw/66[ZECj5Z&pt/d*e7ЭO[az /gjw4'牼wriaH8U4R!$+iiu ZQ[?(F .XLQo-*Tiبiԏ,|GU5SMi"<32 Q*A`-ne.tVOGOׅEact:*QiUh}"ѣo{GQ[niQZ 5Gu#z&]JPÕ9-^m:jj%JZjPqCuLQ5 uf6kʼnFH;ީnX c|M~S$TH}'ZT=ESni-ۚdq6j&ÇPOq E)wZcsHYTĬ)K^H4}[w)d.\$(bt̀:,yj_t!خ$礃" `~+t%ZmTdr@|-kX~qJKq9_R3" ] \3xU ^1Kl7cRġ;.iA` ݱ Gnp!lEfI?(WH:TH@WN}+iN9}XPyX}oS8u*ߚeosxe?̇l:xnrSw;!▔ck}w},jQεZQw\EƁ**Z=;W;[^E89OM]$~R՞WTHedh5:iM߹`~qP/y[VjSCٜ KEE[7>Nur?95_BkzQZiP+Rԋ/eo/%Oħ=Aj=6,Zj٤8t/HjWr)bm/kQq!J[Ij ?8]Ea|jOA~쫗*i)TLP@"jlPӨ)geHSJtuȰ7r2i(ĭ*f;ۑ05SSZTWuLvo#gze5ڋos %zuLB髕ÕPG 4Y¿ڏX'躦NEp?sER3 PF2jE_P9ڮ$[ToWOSĭGKtH P|ȸy.-)j)FS@iZ*>E|E@9UbTEM70"ƪ = i-iX,DYOU%J0&\Eǔi4?Θ7QP@5[V3TAj;Ŷi,+h%m!57%-M--Vm= Y]U3wɵUON`Wlk;zmPYX2 ]JzkH_QpA)8r)M ^ZOk!e.j:]=[ƺۗޡ+5tE͛Pž셥SRfh SԻ!,-F*RW< ,lQQr$oEIE[PSTFB,4UuNW{EjRLЩPOE-:?D4^ʕX#=6)-_O_Pi;7FSQno`bxByKoWG--5TLEfQRin-Ԗ GJҠ*諵@DmvSF_JhӬGQ*W J 2o!~.ӐV;a| dOH\*T=Oaɀ̊::lj1ff'~w+*L΂iTkܢV@.h^ۆHA\#hT,i;Sv悡u~| MHV:-fs<ԇ*x!LӦޢUlQȇR/-i@Ѭ\G$Zq,  pj7kiSț//U)ONVWFZ\)v*H6h-TZ)Rz5 Tc@-Jdd(-M@f g@Zß3}{ E+"-"t:@zEZ",BE N [= jʌ;l:5*2cɼi$NUO~RzȬv[_,9Ef\ra#m8`NP:$ FNSZgpfZ%V2%EO̘*I1ƗqS,q^i:hRU]mᝬzc2КgQtP\SZT-JLr+ša|9mNuөH)!i[SԊt:Ujtϸj*GsͤP+j}V9rD./!S7AN(Q(`q6` ۣji_jkjuh U_UZiOZlpQkӪ;lK5"At)j!:6M2UjW9y)+fhZ`Yj-{EKD~"u@XϤ#SҿZ.Ts%-4BhzW7,2m(bKTmk//tzcS%>#RE|zA&Ae2IEzOZRj " *QJob~ =jl)wSQXdrM= j=FG7+Y#sȓqcU j4RЁ܃ T91UoӬF/Mwm~״ M*R"wT4Sž%+``WTc6`\sSoNDBOܩ6̌G%ĔEm=UKlʕ6"*Hۃx *j6\AH%Ў c`UB s>7ŸK QMPd8\X5RE@*w#/)xeyJKȮ۴sxB$Ю&ڤvɖ7pLJ/NGu6~vWknN?1pTКdq5:]bM}-""5s\7\ j~N'PE־R4i, ᚗ* ~6ZfU2~mY2(?3%<ѸJ,E~_]Jd MGKٟ^Xƀ??%^8@>ZG2x楪>'JI+_LhuWO? aQLXiFPuEB؂|^T3& xʎJL«e' gN|IS0 bTj]*&OznMl͌T)ׯQoUPjn$k,q zAjWI$ ן¬HEցU\Vze֦WJu,*y1@SM_K]Ɓ$YTOQT{V}AңU-e?3+%[~QHKrU(MC) \bs&XSk nY_M@CkzrQi}kFŪ%j5&,g7i.S9~Qe>P2xe:PQ CѣYXTBìjV%{Iyly)RN ckA_FtZmh9ު*(*wnCQ(5K6m,);#Wʢ JRVONC֚:JIm-ͪGKTk^R8gWk ]P[j4NJi`~VeZR!m1 XHmznOz|JezqT ]KR*5Q֣oQһPҝC8  AQQT AF(qk;}JUP~$:2-a&[w4ZsTzsE9z3OLM*&TkE+-WG RVX.*WU*=T ~5-gԥSMxU)Z@Y[Mֆ+h^UKD|]Hl Uߕ[CO[-%$,j ;n,Q=%]Z(zX V?(755:ZR4 R}ă5-Ik-&eUJon۹0F᬴8ԫM8;.h2*&H] *,xk~E}AG]KQF*=@@~:R(tҔո{7g[XN +j*Se{AQlZs_I-ApzA2 M3k=L)#q=>3=OA) K.-*ۭ}W)jj5.AEݻUw" SҧlB'Pv;FSJLڍUPB*Y66&د^;S&BI5idWxj)9UJk]Ÿ*ڕP@Fﱴg-:^4Hǰ FJ*DA2 PPtx6PO`-5 ) M`ErEӿ+*Jt.WcFցM5tA$ eKz-%1 'ԥV .mpJ+l•S}B\NGljŏH%57,~}dVQE\s' YseM#R@<(C/;"kZc~f®!ׁ$t:fR;SEF@򜯻L*VnC6Z;LLP@bHm5\bаDw V;_a-َLO.@¶NB?:_㦭Pfy,>LN> zY['cϙ&vqeWs/7)u==B!/P{h}KwmUBSZa[ lTAMI`ykU=4RG*U]_ oeΨKWMi(E;]^j16HmYe*H)QvjIzD@΀ =U&$էMUJr֭Y\`HiV/VeYb =/b^/i0#HکEed=I *TvN8[_֥Hh0E ) HZBƫ$Fgzf{ܓ2ZIa%=TT$A^11Wɭ$ԋ9k9j%;9r`D2βkB ѬW;ZZj> F[[d^(C2f?|E=qDh ?аsil%TG~I#`U.eo @, ^r%$KF/nuhOߌ;t/Vo $wDnݢ(yTa迆Zzߋk& 1媣 ]PZBoVR3u[{ɾev(ɮ@MO~#\ wu 'xRˌG~Uឈ~|H^G Ziͨ y{^6{jJd퇖ܾ` `l |`.*ϯCoVBLօ*y׻@ ,q4UT!ɤGYsK ](#򄚂fz%MMgSA{YhD;@:/lOD*e^/@xƊ2?^9%)pPU_]=at)j %f<u˗l`կbχ<'+=7+nw- D$ȡ'3řMZ~TL(@|{}îٚ@!؜Uxb A.)9#s7S!V;IUw-q砪.1A'k}yeۍ-)E" n[Kb4{PNşhSpQw~-Jƭ~^35zrG}N.ɾ^);S}B KjOQS#eZY61}JsS}n&A^Q?$@zbhc8%:q16߀7a #/#?W6婿!R,\^XXV^EC+'@8Ժsg`(pƏ(m|[&yOQmeBĞ,5c$L|h=k;7FIyℎx}g2Z88ˤ?yK]+T322Sʻ%ವ"illE6a"jmWT*d,2f/+V0`we*„2TlbYԴ;GXQ)9I]J.m/d,ۂzP!H\Zt -S[9F_+9X53v]!G/1y< :kVK/R į?t9}s~bR [uo~wLQ߶v{eYg# AxB|@ X(#5*D\#t*i䞓ܣ}_yV 4]Q%`SdՉ*LQ~2;G"Cxڟ|5d'rx8e""5~Oހ. +C,Sx>LPڤ+gT N|K4妋mj$'Qwfb6B-OC{C(2< #FP_qğAԘӨOι0ͤ %IdV Crx"z#ԘeEmw!Zii?}6>pβZOIDA荮}Gz4sV+~yߨi`ѩǡ;m)˷Jvq!{xW&AJ=8d9(%heKdv,5OG׭%k%AGP쁖ӃWk%[enUYt zV+)PY([[JGXyMfX{:N&"TNGL ٟD G]/sb {*~KD00PD9}PPF43Vُ<#F G3k8aAN[9~Ocg\֑Zm)]:x"b,ń(Eqo &$fz(0w5IaCjSMP_ۉ31/-  Tɛe{zb#h/rF4\Xl`s2D mCg@WdLa/km>(@V"I[?W~ƥ$ Vՠ.FR~c).Nq5nyTȟs .LSfVL dl ?pIWϹq]1yI>9HgUX`"3ta*kEg踧3]t~1NȈLSh69j_7v 2[ .oNr{hʨzB%5?sem .>=:tLk_;cn ozv' }e {ו;RẒ(D5BB4HpZz5OciA,jS4ސV,6ax@p}h q; vr dW-yh#!Wrq_,~AZџM,g8LBF#o8'7^xHtUI^xic +b0 `)LPM]_Jt$|i|:I0:8W5f +c z Z=SWY  zZiͽco-ܑXMůXQ%͞<8% _)QSU]I^[ALN &ֿoQS"*\4ieq޿,"oYպѴrKf051 }F {kOzeR[ SE*;W\{YEܢĠ]u%+`xu6n3{ΠJyu!8lwd?lݘqĪ$ߚݗz w 1y'(|:O9)ž8}u 9Qxd{Coyl 7 +=\VIX04<58]V^A<[+ZeeG EF 4,XVVO< Ȯ[\)?Vh@y4][:eZ,2N[V|Gx}M{8$/!7.1ݚįU6^ܿM'39'}--][CEx0ۑ#,ڨjYOW6PwԞMD?cĈ5vP1eo&N SDeȉ'Mݩ]u7Ji6K)‹۵c0kRѐG  FdJ}x[K)%6w=~=kET"W)p#| OFXNv\L9&l (UIk$O jw:T^W@ؚ ȱ^?+ G֋aѓvf[+]FAơ_n̕8nlB𑫱FU_>>koڻ}b 0[nRzֺ%p P;f|O!S.K-˓y#I߽XŚcPf{qS@lDO])*n"GK$F~_£JC_ŀ6B sD(Uo˶S|q״tU=*} r+S=Vs<1"%kRAwט3RY{90w<z4}G Ǯ8BZu+:0@I'|Dq%YX_[* Z`n,uzN[p2 gfAa'jZ2%Hi[ƥ*4;ko/`/c>Ʉ~J:JD,%fZsḇ"VwQI6pB<9spWzxCp,kJyRs{: [w:T\ ` Iv*gbj}ϳ0B9VwK~d`6`(Go7aAlq^cMW%*Z5>hcƪp1.k-~F5 _s // }yq1x>$U[7lj`!-_lU눮<:BXӛ,[q?dV- ^46|sB3BzM0,L_mmB䪏fΓlc! B- WY4H`aLƟy9-Vf0Y'a=ٰ  iϟ,n$aYA*#{¤`5aKg}qƉu"PIPSp#bQC*Bot䥯[B'YIOQOBK|ʅfwRÈvju6#gth۶T{H+lhh‡1NȜ:z2,K:Ƕ&n_zƾwzūӦޠ  Mk(8wXqږ,O{h"_xۑ41;m.cwN)w 8r(ycĕNY{``qYLY$]yg!~׿]<_uitQh G=`q1l [̥ =%8s_%(J$xR290[B:-:[گ^2lyڽ@ydlaX\0j<֩fk\ Y1K)oCB%D{ϱg yjDZz1+ux[j0H.6uQ8\&ѳ?5)qx𭦍QPzA">jYe(>IBKd Nw$@4 7xk1oz(s)__N0>A* }te8ôo6"ˢv4^D^`!!;{Ҝ=TzOY\wac)+}AF *n`HKZ8BFN SicEJ _dG͉@#@q;X-鞇âJ5Ebְ Cc坬_+oٺǜJD̬Ppi>pExAƄ lL TBi&Q1H2MuvH+#UG ZMr֣aifޟs$wOyA:7"{s%`xOe3ml^8@P-VF[9 Z`@G}H"@ibh[@r@ \;vUZ&W>Ovhrj>tY4 o,N7Sx|f͏k<QܑEϡc'h'/w޶ IU(߅b+yl*bf$/#bc%F8P w7Py?ҷ>1snr;LOB~pmN14>9[DV[W[k0R,[0=( RO^kKY|q3:D@Ö <]kQ 7 M`ぇ ݼTRދZ?V7F0 MB…@3|cxI50Cr>jh@sc 1`*N,RM,$h!ra~t$=^.\O]0cٜ,uTQCZأħEO$ļ\>vAfβukJ2HxrQ)m|ZsJgŊM1)ϥ ;?>8FoZ($ mD7Q&R.XoʜpJB5uKK* Rq.T͟"W#K:#Wnzs+KL1#'{%T֚I_E0Kt$X+OE(&d{ӯ Cjl(c>CDP>/Ht DQf9;2 VZh%'J­ Ʒ3ݢq;Y#!n֋=\h.e$x6#k)ȕ&s,~.\aj_9eӌHFDdPY+iGDտ>H4)wuM^ TϘ{!QgX_teы\(<8?\,<&ޅE^NiUypt m ˭v %*=;u|)эH8L#pr\NBB`g?uM.l) 1@sc>vL޾G {)]%nK`hL 7cX7>]Rb$JLL2os gX M\K: kV*sۅ C6ad{-s};RFQ%XLbr=,?#cټ@'ʼny~6+.]Ս\±+p&Q8`%F0MxBTW~JvYEdMnQZ?kEJ|ƄGa9pbX_|%2#pSКHDh*E+ۀ_1?dz[~n2靱KhN@:[^ Όď,g^!ɓ`apU\EԹGV[=F\NuSRntNmWͥbcLCg0dBv9N%N" 5&h^y_m 0;>YOǢt=\;LЇm… fUd'X8?_ ;t!:q7>ӏ [ʎS_M…c8pR3_\+%eDg-.q&ޘHaqnzرff? ,(cs[чa?C7.EB,f7A+Y}9FQFX_wAZ_=y,9QdqU}c/_}Reڨ{ZA"`]o<%}[:=Ҽ&b! E=SEN3E7^ЁoC vNN}l+3B U!ȟΪV826< M 71^ۿl9ʑLS4s?W:MEr4umWJ)E-Y ̋ CG(9.gm6"|*E`]2pcÆZe$3Y:g6R3'{;4C%T#a8hꆬ# NpDX3!,8G ~F1uMd"TjQ{P/05# Ĺ} yleF; `ޤ%Tv(攽 2%#@â( ~oSX҃,nigGñ sqJD}F4uZ߻Ytd^+@RނTχ^QhMbv;ln1M dVAתBͩ[X=cr?qY39w-Bҁq_!=Hb]cwg| p5x) gq]y& P3t?C dXUF+te&_eF 2T'חm/xP|L\CWB tl!m}&f]'p–$Ѐ7eB|I y}?G?_XKV&{pTdf<с9y|RO^xʜWӧ1-H;-0 j|!f˂D}>">;?u(x3D'"6ZoX3%;G=E|'Y']e*:,QaCgxS7wwD(cnMvz|A@[SOT#$Lt<G6?BucҊ4\X Re<[yA,#ڤ>Iݷ=ާzoT Q{$po45^\,U\L_Њl8 ݃ W#Zb^9IJڷ }B֣a >l ^W$n:vGEq.t{ oD@@2m#O$GlYfSğ3*q!. "}A0>"{IN 5waDkIu#&7ۥRc(&bq4Tƍ0AgAmr>sH(m\uMxtj(]01+[@&^mR&]`=axTBJOj1Ż)#r)5uG=X.{B%LyfңzL5'@0& $wl &l O;5ʰq?7uxC©AKQT [oՀ}.Y6K_I=ic,p Hu6Ĕec@~'qөgC:,0g%Z 0 4YM F5bdN~1A#maՏKz "u AY.Ft1w)*^4r[3 ) I;!jں(Zx9+5.x*ji0 xZ"\ '*v~ `-.PlJ{&%:NlcsoY @UW[wf j Sa4s:;cR;Ua8ի4MRP;_a]EE&BVn@ܿE"sh.#3&{)MOxAh}po@@:arEN(L,:Jo G( F ,[xbFaPT'b4ʚfީ胚M\mD`E\ T@?4>Lƅ'>o&у"'`;j>spwcnU/}2>40.ό_i!?FhX=h$ތ]^&"RQB#=~xej_wй[[r-Ղ@MfW@h=s2)`XTc_K5? 0C5"I<ם7W-Z;;n1Il{ʞFuk }z}0k![%|S* `QP~u@Gv:H/L1lVXNMt5F ?`31u iya>ǺXX%2;7QFaܹCEk!Tf ]cFƲh>CA|%khTkp3uaY] ȬC :Pڝ;Vķd~(z-?zpIA'prT$[6N_1~݄q8["qe\1AшD8ven Tg|xm88)2[6!Ճإ?u\~Lk'Jxy'XC2/6 U]czj=@eȹ{xfjy_~zV!FLD]F̦h>]'ڴ2]]LLdJgֵ1.UPjv1p|&nGtTs ]*%ER$uӿn2o[bUv#d5ef[n)me I<\&-掵K4Țxs6m~9^a''W!8U-0Cp뿼 f(:U("7|>ZKlKr汇 qh >xIhF숾厤u]tc ?1BBc f"zRQq }xL;px 3@g*Fq%m5L0dSԩd xXԟЋ.?֛n̓L 1Sw -1|XCe "8s均@8muE%g\i4֒s QK8%;Mdh` &e&2q2ð;53)/=Kjv087,.6Z fA# W~Xi\ł,zFΣU Qςť7r[{p>q@9+{Y7%y&-]%Rm]686G7\xع5( ?N | oN2ocAY4/3.Uݺ["QDYXF^diáWjLP '_Fe߆&4vZo nB6^ }\0;dLKlD>_&#j~IX/<^-Pt> JhPC=gdt%JNP-ih!Mљܙ%?^;x M&_E--⫆Wg)e#=X!D4,pQW ;۹neϠ)qH]$TWv#ꀨxм*1OGf9o3ʢ曚ޯd L?{s37u?&3A`D~ޞ=VɱjHwx`g*}oF uhbOv7VQSrq0FWZGTdW S y/ =ʹߜV?+(Z]I +qL>R_!p[a Ma%3 vGWnX_Eʲ*ܾ(kOeI)DՙSވkICB(?pc2fwe o`B8Y9XřÂDs:q͋U7m%pr?,֗6[{Uǩ.8b94r3zv%[OxSD!,<޼šnY3WQ=\$>9)'3HJo+Hc-dJ쓩$Fn JX%TR e;Լa uq7 ^k[~=8}CL@jtL 1 (i>nבW(Ŵ%Xat2m Ζ~Zk$ |}Rz- 5jltlYVm%Лl~H-s(q`r- [՝_uzHoL/ۂu,N}Xd(KϔQyԵk_j&ظR-&vNI+n%bz8P\9g.qR-8/_&e>쭵\Wi eHſ"ZO"N9J-% $di @==5Sߺk6zYY2#JSL-lIB,/,3 >^׎h.d(fX~6\B3jbLBc9T_o@3 (lbƭ[cQk_;pu"qwOS2+ݙ8EUAưɼ^>c :{TqS xe'ȷEDFXŤb0_p )9]dL?E/3 !\tx<>eڇq\}ވqh{mּb~}V i&^ɍ'~dԭY bzo`>E0V˻6(8꾵8j<v1pv#?h6j{U}`mJmeB}3\>0@oR|1UTXm\UL4 rM~A 4}PvZI%51£i NuRհX)d#Ĺ/naTx wL>f?]Z*dNY@%BuE@˂gtg萄Q2hp+Odq{jR^jM*SR*1, 8)w1ƲzpCCoDi:Lzo)qжF2h\Up_2Pjnc+K\3x-xNAƍ?8'C?p,֬:tGA"Nvxm_{|%*MgKy@#pg=iWתv9D)WX r`DZdN<͡lrKX_ >y}#9+m~C G!=O8`4y9u(5lh4)f: .UJtL)*x3+${M=#{{*[4=`vxA!eH) >Iqj vRhB^eQIeXKB?I->pm$‹4,PSZ$TJ GIt?&J^ ]t5 ;Xf[Z.p=&i 9s0)pSEЊPB;+w4SDqdGaOP`HФ KAi&yl%ć 5Q]eC&f{,=ϚA\"~nG5LBd0D^+?raBEMˉ݇ȿ$-sqij_,cgX@CZ`zi+$3+l%ZQYeKء߿/DGbr{O*$nr*̝<..Au?wPڀygz`$21dz σ^vQfp'3PvIu$ 0ہ1 ?H`Mk"STa9gLEx$*;p/lw PJ'AC_e5AS%4l3c9{(#i/\.NGG7@4uLZ3d;^]*6'5Oio!\vIï!*ym%eR_@^LgR:6\!ę.5<gA;ibS%\zG`\(|ڶB a0n\i|gGfpܤ 1$ZYޅ\hNs"[OAGe *llyC X,͒T|}UGiPJg9l»BIWe. u4ri>6Hxr#me(ȮlŠwhjٴ-nMQ3cZ IW<6&y?IpN ^KJ6na]`$ TXRlj:9Bfd`]K&w]gm,-U<<| 7y6jey6&~[=vw5>Rh/ L* he¾w4I.U.+Co>1\x$S0 L(دŜ(Qu[DѠ꫇9@52Me֖OrqF%wz]mT<{Yw#GR-8b.k4j<"#Rx}-wElq;=gtt5R͸L^^.)q!. xL)yCQn_2[5"j@pXѻW L<] Fk& ̿:BgE2llWR"mm![q> _jnaÞl8N=w^ٶ>{cH2+9mӠ'a70E_V}>@a^atvqh3֘6'3yu͐ZtƟ5%W0& .{osg(_>h6GÉ I D'U\c w&Dڬɦ*J:XkdadZ!fԋmgivf\'i)!Tct%sg v(k VnKT>:f~5 $) ,BdC6iBCb{v؎ BVrV{BkWP]Hzty)FDW|66X࡬ =/ME6h;>jxz׉U=m<&я֋Xozd3Fem?aCJU=39.DZt\jN@\gbo^\ಪ 4eȠ^;hTʆ|zR@X)*bwpz|95{FrY8۬3?h{ݑ~aА\%UQs/q c@4RTY|I++^c[s>x GRW+@Ai9'hgq26ڵGI> xckڽv@qb4UZb4EQS^v;VKsL YfԽV=mvF F+@ݯnj"=I0O2y=D.<&PgLBLֲ}}^W0T[tz.9㈛#b{JiW[Ս5drzxxG/UJ jsJwHӛr=\\^+u'W=-= Jbp fqb?BXE(}=+CN|C龫u\o:/5~{`& !sfR dt|Hk, !;.jmM >SU̕D>e:9,+Gٲ#S~׶7߿jYxS"Qv42:o|_FwI8Go%ǓhtnǼ=ci>n;c02G6;0Տ݀4S|RxǡRdsZ eݛϮ kh:5woܛff)BX@;in9ϱK axB#k@!D 43#,3*` (_YjR;r|0U14Wqv܄ ‡O+g"K`Õ&SB~) /t "Sc :rB/~ҕd)C;ws&U`¦-h]I| ZSbpGD{;^:l"H+a+WPAYj3C~*CTKZ@ǩqu7 Ur3 e[!a a@"\ObJӼ{ ˤ.xQYae.`[L~5䝜R<{ƫգ=~vz^՛4qgM4cEt[]D-~n.Zyw~-?(tS&urdZ40UMG!<QUiAaxSD/dmNMvc"FK:"r 0,yԘ8^ylW&ƖggN9[C)ߕkCQnCnkS7=X~ٌlPߒ78)U߾Nvv@]R#No,wQuVE 14jm0˘EEa&29\L>oc`ijO;5!F[kI\en`|Ek^tWZ>M1arX=9CV,'mE3sMbb,5?:I6Rs`_ע pm@(n{n[B9PWTb~ |p􂘩pX{1>gWΖV$, D_}mѧ ,=gC]CubME>f_qHN7PR(Fu7fBeEܢ݅g5>8vkO0ng|[&pfa=Va8ӎ5P5lm9sgɭ@!lW{,n.qR8dp:DYv+$x^Apd\C o sެQ/ FCs j`#ovi< FQ;i6u>ln~Bq)a8# ҟINPO`] Yh-7 5eyJ(YuMĨ=}j2W:J϶,L̖}^By!Bj1Lbvnj Y 2DAd-$ul0=nnOy?Z{Q c΁'G':qG%vZ\e5ddPgcPN २fQT݆Fkh^zy,཰l7TZS5~C2pԷ)rh!Y otmLǽL&qZiVGLK8(U/U pX[wzk}.J^.<2.@}oz V+{8h<0o8$ϤOՊ QNF%>?߈ ~^Hn}Kd8}9ݗ9[}P[f@YI}W:C4>?En@D+Lm(_MG>_gb0 bD$ 㮰/1y }ͭߪbǞ=P-:*>JP >l1~D R佇|e:~]ֽ *VC蹾YiVG:+[!ϴ!%^)p.ރ*,)]M<ru 4}8Ch!F.lݝ e,l9GktkiNO3B\ J(չ=aq_g N,{{Kg0{l-1h e囈h'mPU+W=ݦdE( (WZ7j!WƒB.)M:] (s?Gݑ!fGwys|(O+6oc׈D{Ow?@sR~si^j6歬FdS?SuDnߌ3FF9 ~*yہ W\BXp3`(ڋp6yϬ-Dy#ޡ+Q݆-P +l5+>TUB`&afH jɈ]R1x۬O]~:>~!oԄ1#$/<`),>3\avU"7BlhCl_%"MȊfCK"HsdpQ0E.qݼYQR"8 VnE/~ }p:W%2l`{BهX@! (,rfYdn%ލ!F/5qg Ёir?%v5M#Ȼ&3gWWOQ %Z^4a+<{ߧ/KK+յ?x|mQ5̡IU:S&(NGk [gaYy+Hafr"@QkxI7) Q썺aקh.ۯ3/<ب]8n7G&L{\ O\1ИNKaaZQRqiTc ]n$ "hp_!.\J/,*D2 8H?@%͂>lH ]63py9@ű(XHZ5>T%tҵ);R 4%{!v!,Tn9wM;X]RɽKTBۃA uP{c:*f&.Fe< VѸLݹ󭎺w1,dXk0TM{`4=yXkhۛ/|LVe[-Y@,pw7ntծuka|o1}GxchJn+KޛR'ꔧc$B9u7KJ?1=x{qsF4$L80Ew`Cm?7Ѵ6QH4Fˎa& кoyemiV\zqT=Z_H^_ix`~ri4W3 |I=Lt }#RW0im5s\e7m|eH[z.LīZtG oI/淡+P]J?|m7[> 3d?TnҥY e>d}54T>{\QVxi ^/5~!Tm:LWP=~`אּsKA?*=Vj֡H/qGǤw?#ƶ#"7αSdgBEK Hq0ԊtsPCeSQb:=+|$qzWcHhK:ߝ+7pr^x ڛv&˅Na3 Yd~ !<|xna䲓6s`$_c;MnIB+~:P opzguxb"VNeHGW0;^o?i=\y'Z -\|H{ҏ œgnjJ1?`^y ,G "4۬'ccZ1kZyIc"컺C c:+<$%{c,MVn[W?;پk߸gߦr!2%9.7!T( uw(L)T2hFY:M\C57GUecp2bNRC-.* SVF^4Uvl@8dn,WE@Ƙ&/x&&M-iV/R+f߳:n/&Pv|+BlQ\'柉È `w޼#.Y II zpsŤd,3TYi*酣`=v$%HҐ V4ڔhݢM-(2˷%:=U{gJ9Lܜ`'jl*e`k"Y;sgUi`{%0ba>g4>,'-7v'|ZG-)H X/)-QEd'3ϮD2c]*ޝ}0\.*=ɤtdrO"eLp$k.j'?AUӝLtOB׬frA}+L-yE%3 6_2htJ/orBT|4d؛\6g1ӒGu\̓3UwOutn(t COԭЛ2Rgp-AJeȁb.龃3ZK^(?:K Z9ykPLZ"F}#4#Q~Xj$|guc)]yD ܀vc)VElnSjb!Tjm t!kh;G tن;@-nTi;Kn=Ew,h._Yʂ'fI4ZVr8ցcBҩ?RGHC>'kލ6f+c<[vK~pi>NƱΰ&]$q^RZlPYΪcRf5*+d9LJ7c闵 N%sm훹i[]j1dhA9x& S;M;]a-PhnT4{GQߵsmZB[hѾ|hOOY@?aRaG]RhϚ_jZD˞O& NRXerL °Yaɰzؑiz?^wbBtF͙Vs  xZp?_>\U'V\QU!|Wiz@~|hO'i?lG9a0GzbiZK=ڪ S|C-J2cy6hv? x@Gϧ5:TPv˳ n@L,4`-e1ȳBa_EνO?>A9. 4q?/lbyL\Dr 7V%l˰Q,UUeL& lTɝ G#uW1|J%u}@/x@YBs Y{0/ fH ]u䐕hqrdQ]Y{ ЕrbܰsY'mOH~⒂>(8^'Mf< d7a0u4^̠ m.UoC<Lgi!\:="SeWF,#ŃŰ \c~/@K!|/ /O.ް\_ ߬,isX{%6S4 98Eԥץ`E{uh>3OqḡO#"xߥkmhT3?AQq4&cB1qbvGLY' 9N 4#F0Q[N;PFz~#$"v 3n.9?̶wEs̋wnIZnNOD0Y f[GlT $pRMɨ5@EkAq<5r( ]L3p<7H!VWv1xz A&ʝ(6n*CS65&kR*_|Na[_zKU,9hYZEg] UoP:ǘKpW`au|O1sK"[7DLkr-'1~lX2 `R)je#&+˸nmtgr`Z*-ey4Npq!TiМL$<);psZcXFzng﵃Hz .Lhuabp9~@ζ(m ׋-Qb DgG/\TQ[Ѡ$"R]A2&,rMkoGm q)i鼫jbk88y=mҚa%;v`&޲Sp,8Y&&2?(:3>) աXջo pH Xy*l[kR95'LBX%ltw'$xy*.g!4~rG麀y KtZB=f%!P3,J1jZ-=0ؠmyEK+;QZF$ HG(O$Tw=愌AJoeT`\&|q6+`b{5(-~ЕRKxL ] ơMQlmͧIDX"4J1>O8 ܫbQH"NP uUP,bzfDg<8\Wz~!!oz '9^!Z(0B)E}ȯ&z g‚qɡЏ@jM:=͒48-,|Q`J=9eUHD!;IX3njbC]s1e9y) C]('u› ~@thJ0NpX_|JZ$`jo=6BA RGz6}_`tJ(/)C0+ DԠ-hWC:Dx3GKf繶tJiR/fCIJۀB)@]^Ϛ qQk*0k{Z"&HP[H8$PShb?i|WyA#zQ]kѨ־ԘLh.P5.u-D$#2r߶9LHo*/pނ"Ts*O:9] 䍊8%}T=fσV}Dۨrd j0B~WP^b.[γsxp,}Jj!1+~Ki긍vߗ~YJ(f!"3 a7@G. 'U3ۻI36[f/Hq;:A¶f}j7n\##-Ie'e9DVݎ5f \"n55jk'!in΂a o#E\4IL mNpSOl-mu>f-96")B@l lGozZ&DL^r*_ѧ&XsoiZA"g{(_^?AUπ+[*7%8$#>p6 yP}U˝hš;ϡy3 n^s5Zg{Cv##1f> u[֧L+O!Q"ɊU^4?ʸHazKϱ=f"jҪ`b}MRd["(֠A^j&čW#cbHyphiOF]ݓM9+cFx0 `u06 76vab5YyKFˢ&dɖzh۱D 'ػy&6AC]`34CcaT?_a申cW-հK!m6B{nօ8BIO# kʯ*r+-6Nj@ gE[R;vM 7k.q,k<)u Xq}R7==ßqs-wW}y?S]e|elʊ'^@eC]Z*λ}y^ѠL} &׮U❓A*T&N.;r(`O$cZHݕn1J/i Rx߲)(]@5YSo:sǎ>KS"hA^֙W-3{:Uh˫Z2A&| P**h+pidÍ<=k}+hnN. mW xq2 XQh:Aܲm5IPYQE_By^\kY{Qc ׊9 Ա'2FS8 VqȺ.v?ئo1QyҭC u~`d;|=!gg D~2Y2f|v3dѢ蝵 g =%6&kSqQr^L:rHgh#{aZPd`ٹHL7$n}w*7ekϸ;CЎL{TxF+Im5~Hq7 5첥暖(M0 q.oglCVVǭt5&$,Cv؄['.dTfRyʙDLJuJ(^4hHw"[$znk51׆иxiIخ18~:V*(IjX "@.E!=gpΞ$p0J*b1f\E|!{h@gl屬ٖ~\,dCؘ#Mz̔Y@j fCO; nlkmdJl(c"FE` )0!fq2áu0V6 }8GLbZW{cq,-vű%#mY#pb"tMy4M#!aഖNhBMaІ! Q*ů0{pgD$]T swgQoȥYfU$q Cˎ_gC6S2'+~q)WKՅ1}ƛkR{wP1Iȭ\kGom5[hG 5Eyѝ"gΌ5ve?ʜ xP~9=_ȿ e+[QaXޣKQeHpUݚet_!IX+|oҼK#Þ/@ʎ\*rNð5eZ`r 4#-1tQrQANKNS4>T`feAؼ5W .Tc3&#r+牽؛` nxt|7Q~aԋ6x)XH|oMғV &a|JS#!:Ą [t{Jp$?NB.][Q׍[ho ߚF'kNxTLYόJDC-3Yq0lIxIΘ z8DHI: ʯrW!"S4rH!hqA Y,Fw[c<8x#=͕% 7}a#p A]0a1HcpmR0TF,nkT}`8غM /6A2Jc(t>8d &xHKv3v7VX$_!q ;r8K#>AՋ,~͎cWtA HvWigOB.uo6R26 )<9ی: p/U0fB21dG&芁Qh}mˮQɰBKGL5h[-/Mb&/(lJZ$;ӊYy*౤t5¨AZ~T ?ZqsX{E)hBL7cOyx~'倩o#trl8a]hq#]ĽշG7p[,bt..Đ%L`_RNHsg e\_샢ٟߝ3r,ZE! ± i3eR_tWJ p*2bK~ khюr]2Ic4Iu"|ƃ[7.i3˺(.]<_W$ZuQkmEa祧X-HU'h?P܇- ԥ'%u`jHECaq 3*4TG%QcUQ*[65;fۗ?-dP{irߊ ܌D,OOxb^AC=,0Rf'ciH,7ZLJ.a$* HU˞lB,cNs;N/0wR,8/=ԧxZԪ?fbKE5UgFL\Y00Ti]uЉ=DZOՌA[Yc.S^Mb\q矯Z;Z*ɼI FvI%7RD:M5U@/oTa¢gžAغk-DlKDn]Y=%)vɓM7.ʟc^WV@{( ׶YJYW q.ݎ̿"N""ѿ5Xf" AM>5zQL:<:?v'smōj2Mz}؏eF=PlhD}$6}('osFArǭ gX*j!T)tkoAs.q̗HڄN~I` ~joN@s;^:)& Sl!2MOWf] :%\!06V,53`giRDMc@0fĨ|9ܢ8ѥk͋842Ga݆Ey_#.)b̬lzr C@ax]u, iÖU5;zD+u}dR9*<CvL@ᘥj"c"#f8#nۖ6A9nfDA oDH0q^9>/m09g ͮR?<|lUE|nsYEUTbtq7AIraD['ǡP^ .L— 'A7\>Jpcu(&_U6c 6^u[͑:<`t3ԁ Xʟ"Y('eq;J )&/:j>z ˆ-*(^+CX")o\REO"A5.D~qJEe !8#6tBpݷ$PC0hES ŽR+_{:֪amqTC-}'Dn3v|!f:yU C;:w/:jO CXBXH5ŤeSz-+!^Wًjh"r8#׽z*9ϵTSkjZ|{rHi%ZtQx9,ZXHk0' I|*, -vd2~&^['B M @ 9>6`^fDwled1y UK^Z XUQ9X~l1Cӊ./_{3@Qlb3L9*PF[nV5o^Q# ^e,еcLڳ;Mz[nQ՞KBb,fe(Hy yWQ\"-Ow hDK/רeX\ k'FVDe X j5Wݲ2kU:M: Sz\x(?Ci Z g?< 'LJ(KP٘NO XUfh[\[=)D>n0Ч#3Bq<~ōP r-cŇ("ͤH(&&u41dhoyuwm- H1CZ+ZKI8vT(Kntܭ4Z /ns REU{UAL6ͰD/%lp8ݱpȟNAeǖи'#LhauTMj2o 9.4o<}:7\_%B3tI7Qͺۤ/O`-$W/\FIYgmR¹ Y>~?tnQRI?F41d4ȑONj X)mZX`痚DY3G¹U1Z/k^t ;o@RA kx; TYČSid 7ֻb=9`:r8S( ҘGD-: I})J6Хp5;H~%w$Ud܀4bIV@=Hiڊ2[Z5cp^j)R ]Mo/& oE\K߭:s*U6tӌY!yOH(>Q[_鍏Oid,EQ,0ʧ"YelFK?z`> %7?PO?0ybju^l+_O'[.^S/0Nf F!aYkd'2#rI !?"/LJ/5Pp<'F-ga s+K</"d67.chv҇)ś-bcUrXR*d׹A)8>oEصg"*vtx\'}$Ra&b*,&8i-G.[k\l{vEPG3$4S'nHRSj6G-tPR4i8rT,2]״G}7h>bdY+,Bs[xVA-wn@ɭ?Q=`i5kJ9S.4P`9>ʫV~H5OiAFFѤe,QKP|iN.;ilEä*%m %!=kWQ2+fxkm+M+ D:;SӼb{,s\-z_D8ᴛ[YYd5Iv7žVˑ}@{ivg6WeXYy[}txć:GSMyT01e]BփRth}Љ\s<=('~npLB6sO ŰX%~~N Bz-AdYMq,N6^)lWO| $of9 3'GDͩv=g#|̚:?% jCEVP^9Q1\6Zed)\jA ŕ<+t:k$㾄>v_Ƒ {yai'R6(drlM-_|vt@ˋkWX1xq-BqC#|yazE^PƪӰ6Tv]Ê ~tY]{EK|IEӅnJ 42fybt8B`ҁ(wR{{~(b|QJkْ`y@H'Wcwڮ Lm@,2D1㻴Ne p1u1&{]m6F̡C릝P7OkrY2,96?2)7}yE)| $S [;QK r\v,ERnZ8KeVc"'rŁ :ԗlvQ#;v0JJ7>I侂h~=WVuO\ݷ>Ptz 9j&ag4:?&zd<7WzƗe rymzv)^0.<*G2 YEN^x2 6Mgs}*1~_{ubh |cwx[O > =x#0بP=M~-^ ^lH[x{=8<>n0=Rw>ְaAi2DrLGrޠFaW\(syQD) sΠYLS5q5pdP$<] wqZ>35U\e{CGԊаVDeȅDI׊#T@l:g271gKEt KL 36B2`d!Nz^ƇS/ZA3K`v7~Aڅi 5d17I0r{9#72t{\W+N8> E>,O6Ho0O+V6 @1ǤTi)h]sGHu:kYaXPq ܗb` D[1u|SxZ'Ö̐:,B.jX]M7OA_p̫Q%y> =1~A@sqN WMpawG>ΗF%1xV uF BuJJ(ĥ|2-L%pVk:vgٔ9d]% 0o|vp$drndfާ@!AUv|}+ܧ so3Oi: CgR)use `D&"{f)O{S@ fU-ً.p@l߱ad x a7Z[c{2嶡i3:ָ y\ \"t[BH$@iFm!/$$q10iErlZ  2 |/h'Ttk5R$?Sy@p>ԙtZb8#J[^.k4Cه .ٽw/bV- ~,I$ٷgX;xMfU1Ku8rV VFTM] ,KV&)Gjͤcv.4!ftcGh]in);i 4y,_GīZ峱LR8xEȅYӬ/Vō"H0,uZ޾O / ;6|]vX I8h=cCnvQ)?w eв;vOdQש`^ % e|vO5Ck{9GO*좢4]ϐ웩Iԓ d}^Ƃ]/[s~!kH|q]D)bQB$eeGد{41q/O "syw<@ib'碑ƿ'_ޭ%/Wqq;e jJRLUVW]\;~h:IdxEžI$V 2,oE,:1D:]^_BY^ՅuKnTň#ăd8sV#o6EV#{nṯ#2> ~Q4N^U0r#r.0Z: `?mH%MqRa1as#1|GLI9yb.*hUVNTZ[opy9Rؑ6ޡb2E,A0/һ١{,ϼķ 礪\/ B/2q~&7>r'[7N*VN0C 2C|75_@+jtόyd+@XJUlZ#߰*{}$2S qh vrFP9h5)r 'ZnL(^5<(K3m{5T` oCK|*WXgTFH`%جʋKj pSnGo;l!917{va fo8&u! Xz_yxLn|e16u^M}Hخۢ6~~ )x:?D<)Id*.?Vn8^ ʲCrvK]zbb]z=LR$8WMrC'])®uJ=ry;DGl%ug) nUwmQW]PDPʩ:DA:.W;#,YhxÃygḾuN%vɍ رbJ61&t$O |֡/KCCal=|ﴆL% :X:m֜ڿ?EƬLkӵK[Gj~bT4,Yu$YIt9[k3@:i0ꩇ*0;1-<AqoQ?u!EUyW׍~TRp!)ty6h mM j̚데8]aB> B)NpN*z扵؎@c*ʢ.m.D#C'g[:̆}cԣN9w^xABp} Omr-h7jfSfqA=H57$֧;x TB3Y[NƟ5$"Нu)x8GK.XEF$)XŽ Ko1{U2HUp)`Tt!,tCA:熯9nΓ}+3D|בYO}*ppa|N7!ujQl4;7^Bn~xa@BWaBhIKǰ"ќT\&IZ{WKTb[1QC_2N3q^(vn&RňY5-]8Zu0PXs8VAav֎1>+u8-d^.*'k^a yiuSVa7FWQM\PB<|i"Dtf'Pͤa|V14wI|Z*{XöKo],籔1.'S]IhZim:Yq?6Uj^5WQOcSKIgfm{nauūWHl]C֐T\+W%@7'*L<]\S9) [.\Ky Y5FNRE2Utg#*ǎW(ڠ`OЩ&tE"նfmI |vSێ>b. \!KظNl@c`GȃmkC@x+\%DlcjCttZ7v%V<mGz_rw+605ُjdVby1&ӫnWzug2@v:Wu 7 zjQ>8 +/=[qE\VcuH&SԈ46n0Cl% ONѾrKi\31\t/)+[.@wyoVϪY9%up".N6JRVZaQ=[3j{*HB( 'H_a1?hK0m /=b5IQdwAb&D_fELD՗@e#,-ˎ\S %'%MmF ǩm>Iw,R8'YYL ;/'wH9Ӂӎ_$DXIa3⺟!˲G˿(E3Dl~Icj+kr3=}M,zԌȳ7>m

    F&~Axgj٣Ä@6ry|]e*"]%hw4x&MM1:`MV6)ăPsDo`+wf \?M ]kVP}pWZ3y/Qf4p,]t Xg,pDč}UM^H츨 h9 *ʧ8/ޗxX0\=2fEb.f8P"{nK`Q9wN@P$'sJnݺL ZB;To'ghǸ='1zה@%b3w [֫iNM[iө_jrgUGs/oZZ\r8Ip}^V}OjhXemu~Hzrgd[9Wu}GʚLj䂬 Ôm;S!{(#3w_ue?ܨ˸d[ qzuzՒVs1Q.ن VDh͘!*Ef*)ܞͭZ߻o/i!0cM1P-HTᙂ:,[]rlؿ7V-I] CR`ZxP4e_d*7/Maj&`H3ϗ[ULQ/"Szm`]mBl+EO=li(r8 Q#j%3It>-YԨo.16%/$lccI_J\imF~m m\qWFDAZ[ڃĥMIﬓ0\iD$Aދ72q+G~7Ӛvq*=і2Sq}䮽BҍSDc і3#W&KC@@0g :6Mmh&d2hb~7$1?$ u 73k,;6ʙSpY;ap>yޚCPD mr(HV|O2nfR(v\_SJrhA[Zص  )"-i?Pu `  NBގ>Ճݸޫ -$7ЅC [0 a$&17#©>i `kHM{7-HaOp Aͬ:uEkcO=:RwIpNJse2;hF t~;=`b8pycCPr31VYiW\|?_&Lj[㘊$_c>tNs;L )- g)8/8`)㼵D&ʣxx>`12#?{ 3,矣)9q/} 2:c#aj,ZfG/c*0AO"mL.ʞ#KٯD.wJ!$m-A:'͒;[@>e'(Z1FkYӔHhB+{T8_Ht_76r70,^6Q䳪<x4Iwd@ 9IP~v12S|VqPrin'ѧc" ~FVS4d|38,7e{(?>;u !M.FhD*_e.ǭ42EO=$b <ٚ$|^F1l?Dm3ˡ)Z[E6jE 'THnƿs/M`{ܝ f q_ ~׸Eo?wSSfHrvՕ NtP8^0Ir1;{>a!kk7CvqGNE4 [)omL #xL\[[h">(VkFD!U&w vL$䱉 x܎4Z0'ӗ nb ųV~C,t`E) )^8CpLb <Wu CmT)=}D,o=P@Y'P;8?eDyJS餡pvr-SKS{6%4&^g-d^*Y`td>ؾ!6W1/X@>=ZfuXso+th@P\ d%kG 2f&jtcDՉ'Z]s*D[z6Siv,8x 1/ >\[.9JEԜGů:/D(ZhO򓞅W╲D ÙZ[;t?{L^ Enb#K.HlMXM>6Efmr<&eϩΥzx䱃NrZ;+h ?{kfF!MjG\M'(?NDyg13%7Uɯy*4!>JMļ]>'ǜ0 2z($^'mE\`& 5hhFv Ism# $EkɥϕNXT:s66@Ε¯:G(X2,FuMcIzkxۭB5/N:xrC}) |,Xo'UPDhk#Ѣ#xg`t;<$N+;$C ${#Ztc.8˅oJM`缎0F!L;&U> GPꩪ0$0,i.@bf%jH.| RN&,ӏxpKj (tҢJ2sF6Gq\v+?w{߸2jC4l2[W؟Li+v0Xֈ"eubʠH@#Lw]9ͩ8gFwG6 \:@zL𢟄{۵?یsLWӪZB%~dEa Sn`(RyJ_>\OROY "|ގ1yUz.<l<m 0T{F:{W=$'*LՙZ]G^ZI _ODՂ4[;rJ )O5dx\t }ur|Bh .oˈnw 1"?^+shFS"#+hs` [ygCo~$AH0nm ݗ0p=@ $a*gxLB'Bs/s΋pFp)_Ԍ[Rae0>_gX9IE!)e^ƄTh_oh`ZBH( /J.gLMA#E}fVB(ah>)xF%,aE/J|a'ֆJ r I55FBqyT P7P W¥+q0hoߛf1XVzz+O@@qBtn}CC^)zST@n{B(҇BHf6br}ʾ{MQO4Dž`]4A[dW-Z"'ҲlWӬ[́q{Ab)p5: bDžZx|"(]嬣O /lok:41։Ȟ=OôsualyV.YC@KJ#u/-l6H,Ud ?]x5 dCiᇊ VpX ? %ɳ/X[ <"BȐeڼ}"D w2=1)T ('Y{!4`9Wn p?I,Xzu-Ք~$m=sz.K CЛ! y,|.J'e8,ð)dTBW>ɺ"ؕbZ{Pq _NFfsgNN"FG<LL520HqUBr1 Rˌz\}l}awPqO麒 f)_OJêWnIoʚZ&/:-9 oW%a||೩ܿ\ˎ¢lVj[ېE{| _NQOz:1(d_. [&g@;0b!L;O/|Lh4÷IOAETڻuʒE(TՃzv1p/.x$uKǡ"#3a?,C-V4;3Dh~lcΑbcׅ](;4oHT/%ړ84)(Ց@#_VAǾ~K!eA5yՙ!@:CYS {xר3c{LA :\Ҽ(NVFo|N#hOg!-F` ];PYG Ms*uY^&|ੀUk Rc70puD; Xe<I,\M^<ݟM^o*J]2j:X e=KNVKE83LX*Ub&j?:7Ԇ^[chBmk:zhz%"8.jeiZ#Fm齰>o|fcKdoTC'}⁥C3?Y,4 o8FJ HG>2,⧦G3KdSc5AJeqqXfr7oD3hVƌ+pvz`C{Ue{[)=!A#^XM-v XORk16&~RZ(CHMĵ=V }A@O!mu|NlTMqmQR!2F5Gk-աZKjp{;٩;GsGQ> mŸԫ8 *c+ID%ƻ4" HZdGUr]\$yiaWd5` a+Ĺ!R#O@OʐJV+X/x&=aG;#W H@ 1( l߆`ESK +@2u+@M-%$enXFt'bbwsO鶀_h}*VDf5sJ5aK/[5vTwq{{ԗҢX"S7 Ti!@q&;zZd͙WLؘ`ڜ1櫂K`Cxd& Rq"e|6+C9={WGH7t爱zNҾ1e'fa\׆R /X!=Cdn w*YhT̗ VE}˵!Rf$>ҢYoƂNIPPl p[L7:l{wrAXMBLcE1.fh}{@dh\w(hzKD6N- A_a6 ڮP(nc"pK$_MmQzB.Kgi,8o1ZtAc#<#:!wZj m mdO^Qк0MWb ]KJD9 > _z{D(!_l3wa bC *siE >\eú7sYĐ2[~!-YPj e2.ҟ q+^lqNJ3(;N`sA@N7[+~ܲ$r@C& Y>j%:7u1njg|ٸ7UWNi5SG $^ԟJƂ7IZLjl>Q][xdbH/͢ #R<@"? z:ANI \i@INs^8:gS߻}-U_̳EVXnvɋFmLَD f <"jWG7c=m,Dr#"52~7ztͅCDP詌5h V 6Ӊj BtÐuӰmvybsG ]'UEHx[%NFgOaon܍Fxȫk7FZptW[M)UǨ Ѭ(njc#/`ZoX! tƯodjQwMEs%1^Rwt@A#*Y"uoTτl@sb1nU5!I?v 2''uWLCbKi**ǽ^O(瓻s+)GDOhg*f[&,4䇴d#Ys-e0nϗH8(s|k _{0qk\~==KP&PRF2a~#V@E oF!ae@2q/ݒpYn+j{6ew  ?R"p'_U cjh)Fn}//l@B >spUf]`ys=&KMކs0-7;bGDe'xoˬ ]_.3`:P)ݜf䜀(;Β`>K`g6yZd衢u U?5 i~ &)-?!%NґQBs ߖ>}@6\ n:ف7FpD]4]6-9t;n@Iy WԐ&)'e1.xjZ'p'ڰQJ N8H 4?MQ@-"(4U-+u#QD BtTs6}W͜$\}5Rd8?뤫; ;t8#,ut+S}i0eQl*Gq18O€rT)`Ťy7XP>?e#!ݔpz\JF1unhYk\`BVC\nq P@0Y4)PN`Zܖu,wĐ~ LTyj˯Fo:*nv]d &P/֙˜M\ˡ96nkigŝz@|nh&ޮˤ9ݤDk,^/u͍ѽ (YH"ppD L,7a Kٳa6Y1:;ZN(I6IAZY1-cLoa pbOXyZX=Z꤭9F=^I&gG$3]Iַ}!CA/FN"`SKY-ºMTX'vS;='^c`}!0Z.'Skb+=m]fG#l׿q҆vP@ Q[ALLH/F FIq1Y,-? L2[TTAWO,PWnx2RP^7YFo!OGw ǚ29,I;wū1&Z͚_L^4WƑU* е>Ζ .wA`T].H*\9|rQ[&py>lе<>H #iRpRP87^ Aʮ|x=vܚZpH[TigI(&e6;M [?y4GTv 3\,EhUᬽ"]4:r#nls &Y 0 { addends := strings.Join(targetPathAddends, "_") name = addends + "_" + name } targetFilename := filepath.Join(workDir, name) out, err := helpers.OpenFileForWriting(spec.Fs.Source, targetFilename) c.Assert(err, qt.IsNil) _, err = io.Copy(out, src) out.Close() src.Close() c.Assert(err, qt.IsNil) factory := newTargetPaths("/a") r, err := spec.New(ResourceSourceDescriptor{Fs: spec.Fs.Source, TargetPaths: factory, LazyPublish: true, RelTargetFilename: name, SourceFilename: targetFilename}) c.Assert(err, qt.IsNil) c.Assert(r, qt.Not(qt.IsNil)) return r.(resource.ContentResource) } func assertImageFile(c *qt.C, fs afero.Fs, filename string, width, height int) { filename = filepath.Clean(filename) f, err := fs.Open(filename) c.Assert(err, qt.IsNil) defer f.Close() config, _, err := image.DecodeConfig(f) c.Assert(err, qt.IsNil) c.Assert(config.Width, qt.Equals, width) c.Assert(config.Height, qt.Equals, height) } func assertFileCache(c *qt.C, fs afero.Fs, filename string, width, height int) { assertImageFile(c, fs, filepath.Clean(filename), width, height) } func writeSource(t testing.TB, fs *hugofs.Fs, filename, content string) { writeToFs(t, fs.Source, filename, content) } func writeToFs(t testing.TB, fs afero.Fs, filename, content string) { if err := afero.WriteFile(fs, filepath.FromSlash(filename), []byte(content), 0755); err != nil { t.Fatalf("Failed to write file: %s", err) } } hugo-0.92.2/resources/transform.go000066400000000000000000000376461420147000300171310ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "bytes" "fmt" "image" "io" "path" "strings" "sync" "github.com/gohugoio/hugo/common/paths" "github.com/pkg/errors" "github.com/gohugoio/hugo/resources/images/exif" "github.com/spf13/afero" bp "github.com/gohugoio/hugo/bufferpool" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/resources/internal" "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/media" ) var ( _ resource.ContentResource = (*resourceAdapter)(nil) _ resource.ReadSeekCloserResource = (*resourceAdapter)(nil) _ resource.Resource = (*resourceAdapter)(nil) _ resource.Source = (*resourceAdapter)(nil) _ resource.Identifier = (*resourceAdapter)(nil) _ resource.ResourceMetaProvider = (*resourceAdapter)(nil) ) // These are transformations that need special support in Hugo that may not // be available when building the theme/site so we write the transformation // result to disk and reuse if needed for these, // TODO(bep) it's a little fragile having these constants redefined here. var transformationsToCacheOnDisk = map[string]bool{ "postcss": true, "tocss": true, "tocss-dart": true, } func newResourceAdapter(spec *Spec, lazyPublish bool, target transformableResource) *resourceAdapter { var po *publishOnce if lazyPublish { po = &publishOnce{} } return &resourceAdapter{ resourceTransformations: &resourceTransformations{}, resourceAdapterInner: &resourceAdapterInner{ spec: spec, publishOnce: po, target: target, }, } } // ResourceTransformation is the interface that a resource transformation step // needs to implement. type ResourceTransformation interface { Key() internal.ResourceTransformationKey Transform(ctx *ResourceTransformationCtx) error } type ResourceTransformationCtx struct { // The content to transform. From io.Reader // The target of content transformation. // The current implementation requires that r is written to w // even if no transformation is performed. To io.Writer // This is the relative path to the original source. Unix styled slashes. SourcePath string // This is the relative target path to the resource. Unix styled slashes. InPath string // The relative target path to the transformed resource. Unix styled slashes. OutPath string // The input media type InMediaType media.Type // The media type of the transformed resource. OutMediaType media.Type // Data data can be set on the transformed Resource. Not that this need // to be simple types, as it needs to be serialized to JSON and back. Data map[string]interface{} // This is used to publish additional artifacts, e.g. source maps. // We may improve this. OpenResourcePublisher func(relTargetPath string) (io.WriteCloser, error) } // AddOutPathIdentifier transforming InPath to OutPath adding an identifier, // eg '.min' before any extension. func (ctx *ResourceTransformationCtx) AddOutPathIdentifier(identifier string) { ctx.OutPath = ctx.addPathIdentifier(ctx.InPath, identifier) } // PublishSourceMap writes the content to the target folder of the main resource // with the ".map" extension added. func (ctx *ResourceTransformationCtx) PublishSourceMap(content string) error { target := ctx.OutPath + ".map" f, err := ctx.OpenResourcePublisher(target) if err != nil { return err } defer f.Close() _, err = f.Write([]byte(content)) return err } // ReplaceOutPathExtension transforming InPath to OutPath replacing the file // extension, e.g. ".scss" func (ctx *ResourceTransformationCtx) ReplaceOutPathExtension(newExt string) { dir, file := path.Split(ctx.InPath) base, _ := paths.PathAndExt(file) ctx.OutPath = path.Join(dir, (base + newExt)) } func (ctx *ResourceTransformationCtx) addPathIdentifier(inPath, identifier string) string { dir, file := path.Split(inPath) base, ext := paths.PathAndExt(file) return path.Join(dir, (base + identifier + ext)) } type publishOnce struct { publisherInit sync.Once publisherErr error } type resourceAdapter struct { commonResource *resourceTransformations *resourceAdapterInner } func (r *resourceAdapter) Content() (interface{}, error) { r.init(false, true) if r.transformationsErr != nil { return nil, r.transformationsErr } return r.target.Content() } func (r *resourceAdapter) Err() error { return nil } func (r *resourceAdapter) Data() interface{} { r.init(false, false) return r.target.Data() } func (r *resourceAdapter) Fill(spec string) (resource.Image, error) { return r.getImageOps().Fill(spec) } func (r *resourceAdapter) Fit(spec string) (resource.Image, error) { return r.getImageOps().Fit(spec) } func (r *resourceAdapter) Filter(filters ...interface{}) (resource.Image, error) { return r.getImageOps().Filter(filters...) } func (r *resourceAdapter) Height() int { return r.getImageOps().Height() } func (r *resourceAdapter) Exif() *exif.Exif { return r.getImageOps().Exif() } func (r *resourceAdapter) Key() string { r.init(false, false) return r.target.(resource.Identifier).Key() } func (r *resourceAdapter) MediaType() media.Type { r.init(false, false) return r.target.MediaType() } func (r *resourceAdapter) Name() string { r.init(false, false) return r.target.Name() } func (r *resourceAdapter) Params() maps.Params { r.init(false, false) return r.target.Params() } func (r *resourceAdapter) Permalink() string { r.init(true, false) return r.target.Permalink() } func (r *resourceAdapter) Publish() error { r.init(false, false) return r.target.Publish() } func (r *resourceAdapter) ReadSeekCloser() (hugio.ReadSeekCloser, error) { r.init(false, false) return r.target.ReadSeekCloser() } func (r *resourceAdapter) RelPermalink() string { r.init(true, false) return r.target.RelPermalink() } func (r *resourceAdapter) Resize(spec string) (resource.Image, error) { return r.getImageOps().Resize(spec) } func (r *resourceAdapter) ResourceType() string { r.init(false, false) return r.target.ResourceType() } func (r *resourceAdapter) String() string { return r.Name() } func (r *resourceAdapter) Title() string { r.init(false, false) return r.target.Title() } func (r resourceAdapter) Transform(t ...ResourceTransformation) (ResourceTransformer, error) { r.resourceTransformations = &resourceTransformations{ transformations: append(r.transformations, t...), } r.resourceAdapterInner = &resourceAdapterInner{ spec: r.spec, publishOnce: &publishOnce{}, target: r.target, } return &r, nil } func (r *resourceAdapter) Width() int { return r.getImageOps().Width() } func (r *resourceAdapter) DecodeImage() (image.Image, error) { return r.getImageOps().DecodeImage() } func (r *resourceAdapter) getImageOps() resource.ImageOps { img, ok := r.target.(resource.ImageOps) if !ok { panic(fmt.Sprintf("%T is not an image", r.target)) } r.init(false, false) return img } func (r *resourceAdapter) getMetaAssigner() metaAssigner { return r.target } func (r *resourceAdapter) getSpec() *Spec { return r.spec } func (r *resourceAdapter) publish() { if r.publishOnce == nil { return } r.publisherInit.Do(func() { r.publisherErr = r.target.Publish() if r.publisherErr != nil { r.spec.Logger.Errorf("Failed to publish Resource: %s", r.publisherErr) } }) } func (r *resourceAdapter) TransformationKey() string { // Files with a suffix will be stored in cache (both on disk and in memory) // partitioned by their suffix. var key string for _, tr := range r.transformations { key = key + "_" + tr.Key().Value() } base := ResourceCacheKey(r.target.Key()) return r.spec.ResourceCache.cleanKey(base) + "_" + helpers.MD5String(key) } func (r *resourceAdapter) transform(publish, setContent bool) error { cache := r.spec.ResourceCache key := r.TransformationKey() cached, found := cache.get(key) if found { r.resourceAdapterInner = cached.(*resourceAdapterInner) return nil } // Acquire a write lock for the named transformation. cache.nlocker.Lock(key) // Check the cache again. cached, found = cache.get(key) if found { r.resourceAdapterInner = cached.(*resourceAdapterInner) cache.nlocker.Unlock(key) return nil } defer cache.nlocker.Unlock(key) defer cache.set(key, r.resourceAdapterInner) b1 := bp.GetBuffer() b2 := bp.GetBuffer() defer bp.PutBuffer(b1) defer bp.PutBuffer(b2) tctx := &ResourceTransformationCtx{ Data: make(map[string]interface{}), OpenResourcePublisher: r.target.openPublishFileForWriting, } tctx.InMediaType = r.target.MediaType() tctx.OutMediaType = r.target.MediaType() startCtx := *tctx updates := &transformationUpdate{startCtx: startCtx} var contentrc hugio.ReadSeekCloser contentrc, err := contentReadSeekerCloser(r.target) if err != nil { return err } defer contentrc.Close() tctx.From = contentrc tctx.To = b1 tctx.InPath = r.target.TargetPath() tctx.SourcePath = tctx.InPath counter := 0 writeToFileCache := false var transformedContentr io.Reader for i, tr := range r.transformations { if i != 0 { tctx.InMediaType = tctx.OutMediaType } mayBeCachedOnDisk := transformationsToCacheOnDisk[tr.Key().Name] if !writeToFileCache { writeToFileCache = mayBeCachedOnDisk } if i > 0 { hasWrites := tctx.To.(*bytes.Buffer).Len() > 0 if hasWrites { counter++ // Switch the buffers if counter%2 == 0 { tctx.From = b2 b1.Reset() tctx.To = b1 } else { tctx.From = b1 b2.Reset() tctx.To = b2 } } } newErr := func(err error) error { msg := fmt.Sprintf("%s: failed to transform %q (%s)", strings.ToUpper(tr.Key().Name), tctx.InPath, tctx.InMediaType.Type()) if err == herrors.ErrFeatureNotAvailable { var errMsg string if tr.Key().Name == "postcss" { // This transformation is not available in this // Most likely because PostCSS is not installed. errMsg = ". Check your PostCSS installation; install with \"npm install postcss-cli\". See https://gohugo.io/hugo-pipes/postcss/" } else if tr.Key().Name == "tocss" { errMsg = ". Check your Hugo installation; you need the extended version to build SCSS/SASS." } else if tr.Key().Name == "tocss-dart" { errMsg = ". You need dart-sass-embedded in your system $PATH." } else if tr.Key().Name == "babel" { errMsg = ". You need to install Babel, see https://gohugo.io/hugo-pipes/babel/" } return errors.Wrap(err, msg+errMsg) } return errors.Wrap(err, msg) } var tryFileCache bool if mayBeCachedOnDisk && r.spec.BuildConfig.UseResourceCache(nil) { tryFileCache = true } else { err = tr.Transform(tctx) if err != nil && err != herrors.ErrFeatureNotAvailable { return newErr(err) } if mayBeCachedOnDisk { tryFileCache = r.spec.BuildConfig.UseResourceCache(err) } if err != nil && !tryFileCache { return newErr(err) } } if tryFileCache { f := r.target.tryTransformedFileCache(key, updates) if f == nil { if err != nil { return newErr(err) } return newErr(errors.Errorf("resource %q not found in file cache", key)) } transformedContentr = f updates.sourceFs = cache.fileCache.Fs defer f.Close() // The reader above is all we need. break } if tctx.OutPath != "" { tctx.InPath = tctx.OutPath tctx.OutPath = "" } } if transformedContentr == nil { updates.updateFromCtx(tctx) } var publishwriters []io.WriteCloser if publish { publicw, err := r.target.openPublishFileForWriting(updates.targetPath) if err != nil { return err } publishwriters = append(publishwriters, publicw) } if transformedContentr == nil { if writeToFileCache { // Also write it to the cache fi, metaw, err := cache.writeMeta(key, updates.toTransformedResourceMetadata()) if err != nil { return err } updates.sourceFilename = &fi.Name updates.sourceFs = cache.fileCache.Fs publishwriters = append(publishwriters, metaw) } // Any transformations reading from From must also write to To. // This means that if the target buffer is empty, we can just reuse // the original reader. if b, ok := tctx.To.(*bytes.Buffer); ok && b.Len() > 0 { transformedContentr = tctx.To.(*bytes.Buffer) } else { transformedContentr = contentrc } } // Also write it to memory var contentmemw *bytes.Buffer setContent = setContent || !writeToFileCache if setContent { contentmemw = bp.GetBuffer() defer bp.PutBuffer(contentmemw) publishwriters = append(publishwriters, hugio.ToWriteCloser(contentmemw)) } publishw := hugio.NewMultiWriteCloser(publishwriters...) _, err = io.Copy(publishw, transformedContentr) if err != nil { return err } publishw.Close() if setContent { s := contentmemw.String() updates.content = &s } newTarget, err := r.target.cloneWithUpdates(updates) if err != nil { return err } r.target = newTarget return nil } func (r *resourceAdapter) init(publish, setContent bool) { r.initTransform(publish, setContent) } func (r *resourceAdapter) initTransform(publish, setContent bool) { r.transformationsInit.Do(func() { if len(r.transformations) == 0 { // Nothing to do. return } if publish { // The transformation will write the content directly to // the destination. r.publishOnce = nil } r.transformationsErr = r.transform(publish, setContent) if r.transformationsErr != nil { if r.spec.ErrorSender != nil { r.spec.ErrorSender.SendError(r.transformationsErr) } else { r.spec.Logger.Errorf("Transformation failed: %s", r.transformationsErr) } } }) if publish && r.publishOnce != nil { r.publish() } } type resourceAdapterInner struct { target transformableResource spec *Spec // Handles publishing (to /public) if needed. *publishOnce } type resourceTransformations struct { transformationsInit sync.Once transformationsErr error transformations []ResourceTransformation } type transformableResource interface { baseResourceInternal resource.ContentProvider resource.Resource resource.Identifier } type transformationUpdate struct { content *string sourceFilename *string sourceFs afero.Fs targetPath string mediaType media.Type data map[string]interface{} startCtx ResourceTransformationCtx } func (u *transformationUpdate) isContentChanged() bool { return u.content != nil || u.sourceFilename != nil } func (u *transformationUpdate) toTransformedResourceMetadata() transformedResourceMetadata { return transformedResourceMetadata{ MediaTypeV: u.mediaType.Type(), Target: u.targetPath, MetaData: u.data, } } func (u *transformationUpdate) updateFromCtx(ctx *ResourceTransformationCtx) { u.targetPath = ctx.OutPath u.mediaType = ctx.OutMediaType u.data = ctx.Data u.targetPath = ctx.InPath } // We will persist this information to disk. type transformedResourceMetadata struct { Target string `json:"Target"` MediaTypeV string `json:"MediaType"` MetaData map[string]interface{} `json:"Data"` } // contentReadSeekerCloser returns a ReadSeekerCloser if possible for a given Resource. func contentReadSeekerCloser(r resource.Resource) (hugio.ReadSeekCloser, error) { switch rr := r.(type) { case resource.ReadSeekCloserResource: rc, err := rr.ReadSeekCloser() if err != nil { return nil, err } return rc, nil default: return nil, fmt.Errorf("cannot transform content of Resource of type %T", r) } } hugo-0.92.2/resources/transform_test.go000066400000000000000000000344251420147000300201600ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resources import ( "encoding/base64" "fmt" "io" "path/filepath" "strconv" "strings" "sync" "testing" "github.com/gohugoio/hugo/htesting" "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/internal" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/resources/resource" "github.com/spf13/afero" qt "github.com/frankban/quicktest" ) const gopher = `iVBORw0KGgoAAAANSUhEUgAAAEsAAAA8CAAAAAALAhhPAAAFfUlEQVRYw62XeWwUVRzHf2+OPbo9d7tsWyiyaZti6eWGAhISoIGKECEKCAiJJkYTiUgTMYSIosYYBBIUIxoSPIINEBDi2VhwkQrVsj1ESgu9doHWdrul7ba73WNm3vOPtsseM9MdwvvrzTs+8/t95ze/33sI5BqiabU6m9En8oNjduLnAEDLUsQXFF8tQ5oxK3vmnNmDSMtrncks9Hhtt/qeWZapHb1ha3UqYSWVl2ZmpWgaXMXGohQAvmeop3bjTRtv6SgaK/Pb9/bFzUrYslbFAmHPp+3WhAYdr+7GN/YnpN46Opv55VDsJkoEpMrY/vO2BIYQ6LLvm0ThY3MzDzzeSJeeWNyTkgnIE5ePKsvKlcg/0T9QMzXalwXMlj54z4c0rh/mzEfr+FgWEz2w6uk8dkzFAgcARAgNp1ZYef8bH2AgvuStbc2/i6CiWGj98y2tw2l4FAXKkQBIf+exyRnteY83LfEwDQAYCoK+P6bxkZm/0966LxcAAILHB56kgD95PPxltuYcMtFTWw/FKkY/6Opf3GGd9ZF+Qp6mzJxzuRSractOmJrH1u8XTvWFHINNkLQLMR+XHXvfPPHw967raE1xxwtA36IMRfkAAG29/7mLuQcb2WOnsJReZGfpiHsSBX81cvMKywYZHhX5hFPtOqPGWZCXnhWGAu6lX91ElKXSalcLXu3UaOXVay57ZSe5f6Gpx7J2MXAsi7EqSp09b/MirKSyJfnfEEgeDjl8FgDAfvewP03zZ+AJ0m9aFRM8eEHBDRKjfcreDXnZdQuAxXpT2NRJ7xl3UkLBhuVGU16gZiGOgZmrSbRdqkILuL/yYoSXHHkl9KXgqNu3PB8oRg0geC5vFmLjad6mUyTKLmF3OtraWDIfACyXqmephaDABawfpi6tqqBZytfQMqOz6S09iWXhktrRaB8Xz4Yi/8gyABDm5NVe6qq/3VzPrcjELWrebVuyY2T7ar4zQyybUCtsQ5Es1FGaZVrRVQwAgHGW2ZCRZshI5bGQi7HesyE972pOSeMM0dSktlzxRdrlqb3Osa6CCS8IJoQQQgBAbTAa5l5epO34rJszibJI8rxLfGzcp1dRosutGeb2VDNgqYrwTiPNsLxXiPi3dz7LiS1WBRBDBOnqEjyy3aQb+/bLiJzz9dIkscVBBLxMfSEac7kO4Fpkngi0ruNBeSOal+u8jgOuqPz12nryMLCniEjtOOOmpt+KEIqsEdocJjYXwrh9OZqWJQyPCTo67LNS/TdxLAv6R5ZNK9npEjbYdT33gRo4o5oTqR34R+OmaSzDBWsAIPhuRcgyoteNi9gF0KzNYWVItPf2TLoXEg+7isNC7uJkgo1iQWOfRSP9NR11RtbZZ3OMG/VhL6jvx+J1m87+RCfJChAtEBQkSBX2PnSiihc/Twh3j0h7qdYQAoRVsRGmq7HU2QRbaxVGa1D6nIOqaIWRjyRZpHMQKWKpZM5feA+lzC4ZFultV8S6T0mzQGhQohi5I8iw+CsqBSxhFMuwyLgSwbghGb0AiIKkSDmGZVmJSiKihsiyOAUs70UkywooYP0bii9GdH4sfr1UNysd3fUyLLMQN+rsmo3grHl9VNJHbbwxoa47Vw5gupIqrZcjPh9R4Nye3nRDk199V+aetmvVtDRE8/+cbgAAgMIWGb3UA0MGLE9SCbWX670TDy1y98c3D27eppUjsZ6fql3jcd5rUe7+ZIlLNQny3Rd+E5Tct3WVhTM5RBCEdiEK0b6B+/ca2gYU393nFj/n1AygRQxPIUA043M42u85+z2SnssKrPl8Mx76NL3E6eXc3be7OD+H4WHbJkKI8AU8irbITQjZ+0hQcPEgId/Fn/pl9crKH02+5o2b9T/eMx7pKoskYgAAAABJRU5ErkJggg==` func gopherPNG() io.Reader { return base64.NewDecoder(base64.StdEncoding, strings.NewReader(gopher)) } func TestTransform(t *testing.T) { c := qt.New(t) createTransformer := func(spec *Spec, filename, content string) Transformer { filename = filepath.FromSlash(filename) fs := spec.Fs.Source afero.WriteFile(fs, filename, []byte(content), 0777) r, _ := spec.New(ResourceSourceDescriptor{Fs: fs, SourceFilename: filename}) return r.(Transformer) } createContentReplacer := func(name, old, new string) ResourceTransformation { return &testTransformation{ name: name, transform: func(ctx *ResourceTransformationCtx) error { in := helpers.ReaderToString(ctx.From) in = strings.Replace(in, old, new, 1) ctx.AddOutPathIdentifier("." + name) fmt.Fprint(ctx.To, in) return nil }, } } // Verify that we publish the same file once only. assertNoDuplicateWrites := func(c *qt.C, spec *Spec) { c.Helper() d := spec.Fs.Destination.(hugofs.DuplicatesReporter) c.Assert(d.ReportDuplicates(), qt.Equals, "") } assertShouldExist := func(c *qt.C, spec *Spec, filename string, should bool) { c.Helper() exists, _ := helpers.Exists(filepath.FromSlash(filename), spec.Fs.Destination) c.Assert(exists, qt.Equals, should) } c.Run("All values", func(c *qt.C) { c.Parallel() spec := newTestResourceSpec(specDescriptor{c: c}) transformation := &testTransformation{ name: "test", transform: func(ctx *ResourceTransformationCtx) error { // Content in := helpers.ReaderToString(ctx.From) in = strings.Replace(in, "blue", "green", 1) fmt.Fprint(ctx.To, in) // Media type ctx.OutMediaType = media.CSVType // Change target ctx.ReplaceOutPathExtension(".csv") // Add some data to context ctx.Data["mydata"] = "Hugo Rocks!" return nil }, } r := createTransformer(spec, "f1.txt", "color is blue") tr, err := r.Transform(transformation) c.Assert(err, qt.IsNil) content, err := tr.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(content, qt.Equals, "color is green") c.Assert(tr.MediaType(), eq, media.CSVType) c.Assert(tr.RelPermalink(), qt.Equals, "/f1.csv") assertShouldExist(c, spec, "public/f1.csv", true) data := tr.Data().(map[string]interface{}) c.Assert(data["mydata"], qt.Equals, "Hugo Rocks!") assertNoDuplicateWrites(c, spec) }) c.Run("Meta only", func(c *qt.C) { c.Parallel() spec := newTestResourceSpec(specDescriptor{c: c}) transformation := &testTransformation{ name: "test", transform: func(ctx *ResourceTransformationCtx) error { // Change media type only ctx.OutMediaType = media.CSVType ctx.ReplaceOutPathExtension(".csv") return nil }, } r := createTransformer(spec, "f1.txt", "color is blue") tr, err := r.Transform(transformation) c.Assert(err, qt.IsNil) content, err := tr.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(content, qt.Equals, "color is blue") c.Assert(tr.MediaType(), eq, media.CSVType) // The transformed file should only be published if RelPermalink // or Permalink is called. n := htesting.Rnd.Intn(3) shouldExist := true switch n { case 0: tr.RelPermalink() case 1: tr.Permalink() default: shouldExist = false } assertShouldExist(c, spec, "public/f1.csv", shouldExist) assertNoDuplicateWrites(c, spec) }) c.Run("Memory-cached transformation", func(c *qt.C) { c.Parallel() spec := newTestResourceSpec(specDescriptor{c: c}) // Two transformations with same id, different behaviour. t1 := createContentReplacer("t1", "blue", "green") t2 := createContentReplacer("t1", "color", "car") for i, transformation := range []ResourceTransformation{t1, t2} { r := createTransformer(spec, "f1.txt", "color is blue") tr, _ := r.Transform(transformation) content, err := tr.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(content, qt.Equals, "color is green", qt.Commentf("i=%d", i)) assertShouldExist(c, spec, "public/f1.t1.txt", false) } assertNoDuplicateWrites(c, spec) }) c.Run("File-cached transformation", func(c *qt.C) { c.Parallel() fs := afero.NewMemMapFs() for i := 0; i < 2; i++ { spec := newTestResourceSpec(specDescriptor{c: c, fs: fs}) r := createTransformer(spec, "f1.txt", "color is blue") var transformation ResourceTransformation if i == 0 { // There is currently a hardcoded list of transformations that we // persist to disk (tocss, postcss). transformation = &testTransformation{ name: "tocss", transform: func(ctx *ResourceTransformationCtx) error { in := helpers.ReaderToString(ctx.From) in = strings.Replace(in, "blue", "green", 1) ctx.AddOutPathIdentifier("." + "cached") ctx.OutMediaType = media.CSVType ctx.Data = map[string]interface{}{ "Hugo": "Rocks!", } fmt.Fprint(ctx.To, in) return nil }, } } else { // Force read from file cache. transformation = &testTransformation{ name: "tocss", transform: func(ctx *ResourceTransformationCtx) error { return herrors.ErrFeatureNotAvailable }, } } msg := qt.Commentf("i=%d", i) tr, _ := r.Transform(transformation) c.Assert(tr.RelPermalink(), qt.Equals, "/f1.cached.txt", msg) content, err := tr.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(content, qt.Equals, "color is green", msg) c.Assert(tr.MediaType(), eq, media.CSVType) c.Assert(tr.Data(), qt.DeepEquals, map[string]interface{}{ "Hugo": "Rocks!", }) assertNoDuplicateWrites(c, spec) assertShouldExist(c, spec, "public/f1.cached.txt", true) } }) c.Run("Access RelPermalink first", func(c *qt.C) { c.Parallel() spec := newTestResourceSpec(specDescriptor{c: c}) t1 := createContentReplacer("t1", "blue", "green") r := createTransformer(spec, "f1.txt", "color is blue") tr, _ := r.Transform(t1) relPermalink := tr.RelPermalink() content, err := tr.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(relPermalink, qt.Equals, "/f1.t1.txt") c.Assert(content, qt.Equals, "color is green") c.Assert(tr.MediaType(), eq, media.TextType) assertNoDuplicateWrites(c, spec) assertShouldExist(c, spec, "public/f1.t1.txt", true) }) c.Run("Content two", func(c *qt.C) { c.Parallel() spec := newTestResourceSpec(specDescriptor{c: c}) t1 := createContentReplacer("t1", "blue", "green") t2 := createContentReplacer("t1", "color", "car") r := createTransformer(spec, "f1.txt", "color is blue") tr, _ := r.Transform(t1, t2) content, err := tr.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(content, qt.Equals, "car is green") c.Assert(tr.MediaType(), eq, media.TextType) assertNoDuplicateWrites(c, spec) }) c.Run("Content two chained", func(c *qt.C) { c.Parallel() spec := newTestResourceSpec(specDescriptor{c: c}) t1 := createContentReplacer("t1", "blue", "green") t2 := createContentReplacer("t2", "color", "car") r := createTransformer(spec, "f1.txt", "color is blue") tr1, _ := r.Transform(t1) tr2, _ := tr1.Transform(t2) content1, err := tr1.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) content2, err := tr2.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(content1, qt.Equals, "color is green") c.Assert(content2, qt.Equals, "car is green") assertNoDuplicateWrites(c, spec) }) c.Run("Content many", func(c *qt.C) { c.Parallel() spec := newTestResourceSpec(specDescriptor{c: c}) const count = 26 // A-Z transformations := make([]ResourceTransformation, count) for i := 0; i < count; i++ { transformations[i] = createContentReplacer(fmt.Sprintf("t%d", i), fmt.Sprint(i), string(rune(i+65))) } var countstr strings.Builder for i := 0; i < count; i++ { countstr.WriteString(fmt.Sprint(i)) } r := createTransformer(spec, "f1.txt", countstr.String()) tr, _ := r.Transform(transformations...) content, err := tr.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(content, qt.Equals, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") assertNoDuplicateWrites(c, spec) }) c.Run("Image", func(c *qt.C) { c.Parallel() spec := newTestResourceSpec(specDescriptor{c: c}) transformation := &testTransformation{ name: "test", transform: func(ctx *ResourceTransformationCtx) error { ctx.AddOutPathIdentifier(".changed") return nil }, } r := createTransformer(spec, "gopher.png", helpers.ReaderToString(gopherPNG())) tr, err := r.Transform(transformation) c.Assert(err, qt.IsNil) c.Assert(tr.MediaType(), eq, media.PNGType) img, ok := tr.(resource.Image) c.Assert(ok, qt.Equals, true) c.Assert(img.Width(), qt.Equals, 75) c.Assert(img.Height(), qt.Equals, 60) // RelPermalink called. resizedPublished1, err := img.Resize("40x40") c.Assert(err, qt.IsNil) c.Assert(resizedPublished1.Height(), qt.Equals, 40) c.Assert(resizedPublished1.RelPermalink(), qt.Equals, "/gopher.changed_hu2e827f5a78333ebc04166dd643235dea_1462_40x40_resize_linear_3.png") assertShouldExist(c, spec, "public/gopher.changed_hu2e827f5a78333ebc04166dd643235dea_1462_40x40_resize_linear_3.png", true) // Permalink called. resizedPublished2, err := img.Resize("30x30") c.Assert(err, qt.IsNil) c.Assert(resizedPublished2.Height(), qt.Equals, 30) c.Assert(resizedPublished2.Permalink(), qt.Equals, "https://example.com/gopher.changed_hu2e827f5a78333ebc04166dd643235dea_1462_30x30_resize_linear_3.png") assertShouldExist(c, spec, "public/gopher.changed_hu2e827f5a78333ebc04166dd643235dea_1462_30x30_resize_linear_3.png", true) // Not published because none of RelPermalink or Permalink was called. resizedNotPublished, err := img.Resize("50x50") c.Assert(err, qt.IsNil) c.Assert(resizedNotPublished.Height(), qt.Equals, 50) // c.Assert(resized.RelPermalink(), qt.Equals, "/gopher.changed_hu2e827f5a78333ebc04166dd643235dea_1462_50x50_resize_linear_2.png") assertShouldExist(c, spec, "public/gopher.changed_hu2e827f5a78333ebc04166dd643235dea_1462_50x50_resize_linear_3.png", false) assertNoDuplicateWrites(c, spec) }) c.Run("Concurrent", func(c *qt.C) { spec := newTestResourceSpec(specDescriptor{c: c}) transformers := make([]Transformer, 10) transformations := make([]ResourceTransformation, 10) for i := 0; i < 10; i++ { transformers[i] = createTransformer(spec, fmt.Sprintf("f%d.txt", i), fmt.Sprintf("color is %d", i)) transformations[i] = createContentReplacer("test", strconv.Itoa(i), "blue") } var wg sync.WaitGroup for i := 0; i < 13; i++ { wg.Add(1) go func(i int) { defer wg.Done() for j := 0; j < 23; j++ { id := (i + j) % 10 tr, err := transformers[id].Transform(transformations[id]) c.Assert(err, qt.IsNil) content, err := tr.(resource.ContentProvider).Content() c.Assert(err, qt.IsNil) c.Assert(content, qt.Equals, "color is blue") c.Assert(tr.RelPermalink(), qt.Equals, fmt.Sprintf("/f%d.test.txt", id)) } }(i) } wg.Wait() assertNoDuplicateWrites(c, spec) }) } type testTransformation struct { name string transform func(ctx *ResourceTransformationCtx) error } func (t *testTransformation) Key() internal.ResourceTransformationKey { return internal.NewResourceTransformationKey(t.name) } func (t *testTransformation) Transform(ctx *ResourceTransformationCtx) error { return t.transform(ctx) } hugo-0.92.2/scripts/000077500000000000000000000000001420147000300142245ustar00rootroot00000000000000hugo-0.92.2/scripts/fork_go_templates/000077500000000000000000000000001420147000300177305ustar00rootroot00000000000000hugo-0.92.2/scripts/fork_go_templates/.gitignore000066400000000000000000000000221420147000300217120ustar00rootroot00000000000000fork_go_templates hugo-0.92.2/scripts/fork_go_templates/main.go000066400000000000000000000144571420147000300212160ustar00rootroot00000000000000package main import ( "fmt" "io/ioutil" "log" "os" "path/filepath" "regexp" "strings" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/hugio" "github.com/spf13/afero" ) func main() { // TODO(bep) git checkout tag // The current is built with Go version 2f0da6d9e29d9b9d5a4d10427ca9f71d12bbacc8 / go1.16 fmt.Println("Forking ...") defer fmt.Println("Done ...") cleanFork() htmlRoot := filepath.Join(forkRoot, "htmltemplate") for _, pkg := range goPackages { copyGoPackage(pkg.dstPkg, pkg.srcPkg) } for _, pkg := range goPackages { doWithGoFiles(pkg.dstPkg, pkg.rewriter, pkg.replacer) } goimports(htmlRoot) gofmt(forkRoot) } const ( // TODO(bep) goSource = "/Users/bep/dev/go/dump/go/src" forkRoot = "../../tpl/internal/go_templates" ) type goPackage struct { srcPkg string dstPkg string replacer func(name, content string) string rewriter func(name string) } var ( textTemplateReplacers = strings.NewReplacer( `"text/template/`, `"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/`, `"internal/fmtsort"`, `"github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort"`, `"internal/testenv"`, `"github.com/gohugoio/hugo/tpl/internal/go_templates/testenv"`, "TestLinkerGC", "_TestLinkerGC", // Rename types and function that we want to overload. "type state struct", "type stateOld struct", "func (s *state) evalFunction", "func (s *state) evalFunctionOld", "func (s *state) evalField(", "func (s *state) evalFieldOld(", "func (s *state) evalCall(", "func (s *state) evalCallOld(", "func isTrue(val reflect.Value) (truth, ok bool) {", "func isTrueOld(val reflect.Value) (truth, ok bool) {", ) testEnvReplacers = strings.NewReplacer( `"internal/cfg"`, `"github.com/gohugoio/hugo/tpl/internal/go_templates/cfg"`, ) htmlTemplateReplacers = strings.NewReplacer( `. "html/template"`, `. "github.com/gohugoio/hugo/tpl/internal/go_templates/htmltemplate"`, `"html/template"`, `template "github.com/gohugoio/hugo/tpl/internal/go_templates/htmltemplate"`, "\"text/template\"\n", "template \"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate\"\n", `"html/template"`, `htmltemplate "html/template"`, `"fmt"`, `htmltemplate "html/template"`, `t.Skip("this test currently fails with -race; see issue #39807")`, `// t.Skip("this test currently fails with -race; see issue #39807")`, ) ) func commonReplace(name, content string) string { if strings.HasSuffix(name, "_test.go") { content = strings.Replace(content, "package template\n", `// +build go1.13,!windows package template `, 1) content = strings.Replace(content, "package template_test\n", `// +build go1.13 package template_test `, 1) content = strings.Replace(content, "package parse\n", `// +build go1.13 package parse `, 1) } return content } var goPackages = []goPackage{ { srcPkg: "text/template", dstPkg: "texttemplate", replacer: func(name, content string) string { return textTemplateReplacers.Replace(commonReplace(name, content)) }, }, { srcPkg: "html/template", dstPkg: "htmltemplate", replacer: func(name, content string) string { if strings.HasSuffix(name, "content.go") { // Remove template.HTML types. We need to use the Go types. content = removeAll(`(?s)// Strings of content.*?\)\n`, content) } content = commonReplace(name, content) return htmlTemplateReplacers.Replace(content) }, rewriter: func(name string) { for _, s := range []string{"CSS", "HTML", "HTMLAttr", "JS", "JSStr", "URL", "Srcset"} { rewrite(name, fmt.Sprintf("%s -> htmltemplate.%s", s, s)) } rewrite(name, `"text/template/parse" -> "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse"`) }, }, {srcPkg: "internal/fmtsort", dstPkg: "fmtsort", rewriter: func(name string) { rewrite(name, `"internal/fmtsort" -> "github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort"`) }}, { srcPkg: "internal/testenv", dstPkg: "testenv", replacer: func(name, content string) string { return testEnvReplacers.Replace(content) }, rewriter: func(name string) { rewrite(name, `"internal/testenv" -> "github.com/gohugoio/hugo/tpl/internal/go_templates/testenv"`) }, }, {srcPkg: "internal/cfg", dstPkg: "cfg", rewriter: func(name string) { rewrite(name, `"internal/cfg" -> "github.com/gohugoio/hugo/tpl/internal/go_templates/cfg"`) }}, } var fs = afero.NewOsFs() // Removes all non-Hugo files in the go_templates folder. func cleanFork() { must(filepath.Walk(filepath.Join(forkRoot), func(path string, info os.FileInfo, err error) error { if !info.IsDir() && len(path) > 10 && !strings.Contains(path, "hugo") { must(fs.Remove(path)) } return nil })) } func must(err error, what ...string) { if err != nil { log.Fatal(what, " ERROR: ", err) } } func copyGoPackage(dst, src string) { from := filepath.Join(goSource, src) to := filepath.Join(forkRoot, dst) fmt.Println("Copy", from, "to", to) must(hugio.CopyDir(fs, from, to, func(s string) bool { return true })) } func doWithGoFiles(dir string, rewrite func(name string), transform func(name, in string) string) { if rewrite == nil && transform == nil { return } must(filepath.Walk(filepath.Join(forkRoot, dir), func(path string, info os.FileInfo, err error) error { if info.IsDir() { return nil } if !strings.HasSuffix(path, ".go") || strings.Contains(path, "hugo_") { return nil } fmt.Println("Handle", path) if rewrite != nil { rewrite(path) } if transform == nil { return nil } data, err := ioutil.ReadFile(path) must(err) f, err := os.Create(path) must(err) defer f.Close() _, err = f.WriteString(transform(path, string(data))) must(err) return nil })) } func removeAll(expression, content string) string { re := regexp.MustCompile(expression) return re.ReplaceAllString(content, "") } func rewrite(filename, rule string) { cmf, _ := hexec.SafeCommand("gofmt", "-w", "-r", rule, filename) out, err := cmf.CombinedOutput() if err != nil { log.Fatal("gofmt failed:", string(out)) } } func goimports(dir string) { cmf, _ := hexec.SafeCommand("goimports", "-w", dir) out, err := cmf.CombinedOutput() if err != nil { log.Fatal("goimports failed:", string(out)) } } func gofmt(dir string) { cmf, _ := hexec.SafeCommand("gofmt", "-w", dir) out, err := cmf.CombinedOutput() if err != nil { log.Fatal("gofmt failed:", string(out)) } } hugo-0.92.2/snap/000077500000000000000000000000001420147000300134765ustar00rootroot00000000000000hugo-0.92.2/snap/plugins/000077500000000000000000000000001420147000300151575ustar00rootroot00000000000000hugo-0.92.2/snap/plugins/x-nodejs.yaml000066400000000000000000000002121420147000300175650ustar00rootroot00000000000000options: source: required: true source-type: source-tag: source-branch: nodejs-target: required: true hugo-0.92.2/snap/plugins/x_nodejs.py000066400000000000000000000304161420147000300173460ustar00rootroot00000000000000# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- # # Modified by Anthony Fok on 2018-10-01 to add support for ppc64el and s390x # # Copyright (C) 2015-2017 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # 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 . """The nodejs plugin is useful for node/npm based parts. The plugin uses node to install dependencies from `package.json`. It also sets up binaries defined in `package.json` into the `PATH`. This plugin uses the common plugin keywords as well as those for "sources". For more information check the 'plugins' topic for the former and the 'sources' topic for the latter. Additionally, this plugin uses the following plugin-specific keywords: - node-packages: (list) A list of dependencies to fetch using npm. - node-engine: (string) The version of nodejs you want the snap to run on. - npm-run: (list) A list of targets to `npm run`. These targets will be run in order, after `npm install` - npm-flags: (list) A list of flags for npm. - node-package-manager (string; default: npm) The language package manager to use to drive installation of node packages. Can be either `npm` (default) or `yarn`. """ import collections import contextlib import json import logging import os import shutil import subprocess import sys import snapcraft from snapcraft import sources from snapcraft.file_utils import link_or_copy_tree from snapcraft.internal import errors logger = logging.getLogger(__name__) _NODEJS_BASE = "node-v{version}-linux-{arch}" _NODEJS_VERSION = "12.18.4" _NODEJS_TMPL = "https://nodejs.org/dist/v{version}/{base}.tar.gz" _NODEJS_ARCHES = {"i386": "x86", "amd64": "x64", "armhf": "armv7l", "arm64": "arm64", "ppc64el": "ppc64le", "s390x": "s390x"} _YARN_URL = "https://yarnpkg.com/latest.tar.gz" class NodePlugin(snapcraft.BasePlugin): @classmethod def schema(cls): schema = super().schema() schema["properties"]["node-packages"] = { "type": "array", "minitems": 1, "uniqueItems": True, "items": {"type": "string"}, "default": [], } schema["properties"]["node-engine"] = { "type": "string", "default": _NODEJS_VERSION, } schema["properties"]["node-package-manager"] = { "type": "string", "default": "npm", "enum": ["npm", "yarn"], } schema["properties"]["npm-run"] = { "type": "array", "minitems": 1, "uniqueItems": False, "items": {"type": "string"}, "default": [], } schema["properties"]["npm-flags"] = { "type": "array", "minitems": 1, "uniqueItems": False, "items": {"type": "string"}, "default": [], } if "required" in schema: del schema["required"] return schema @classmethod def get_build_properties(cls): # Inform Snapcraft of the properties associated with building. If these # change in the YAML Snapcraft will consider the build step dirty. return ["node-packages", "npm-run", "npm-flags"] @classmethod def get_pull_properties(cls): # Inform Snapcraft of the properties associated with pulling. If these # change in the YAML Snapcraft will consider the build step dirty. return ["node-engine", "node-package-manager"] @property def _nodejs_tar(self): if self._nodejs_tar_handle is None: self._nodejs_tar_handle = sources.Tar( self._nodejs_release_uri, self._npm_dir ) return self._nodejs_tar_handle @property def _yarn_tar(self): if self._yarn_tar_handle is None: self._yarn_tar_handle = sources.Tar(_YARN_URL, self._npm_dir) return self._yarn_tar_handle def __init__(self, name, options, project): super().__init__(name, options, project) self._source_package_json = os.path.join( os.path.abspath(self.options.source), "package.json" ) self._npm_dir = os.path.join(self.partdir, "npm") self._manifest = collections.OrderedDict() self._nodejs_release_uri = get_nodejs_release( self.options.node_engine, self.project.deb_arch ) self._nodejs_tar_handle = None self._yarn_tar_handle = None def pull(self): super().pull() os.makedirs(self._npm_dir, exist_ok=True) self._nodejs_tar.download() if self.options.node_package_manager == "yarn": self._yarn_tar.download() # do the install in the pull phase to download all dependencies. if self.options.node_package_manager == "npm": self._npm_install(rootdir=self.sourcedir) else: self._yarn_install(rootdir=self.sourcedir) def clean_pull(self): super().clean_pull() # Remove the npm directory (if any) if os.path.exists(self._npm_dir): shutil.rmtree(self._npm_dir) def build(self): super().build() if self.options.node_package_manager == "npm": installed_node_packages = self._npm_install(rootdir=self.builddir) # Copy the content of the symlink to the build directory # LP: #1702661 modules_dir = os.path.join(self.installdir, "lib", "node_modules") _copy_symlinked_content(modules_dir) else: installed_node_packages = self._yarn_install(rootdir=self.builddir) lock_file_path = os.path.join(self.sourcedir, "yarn.lock") if os.path.isfile(lock_file_path): with open(lock_file_path) as lock_file: self._manifest["yarn-lock-contents"] = lock_file.read() self._manifest["node-packages"] = [ "{}={}".format(name, installed_node_packages[name]) for name in installed_node_packages ] def _npm_install(self, rootdir): self._nodejs_tar.provision( self.installdir, clean_target=False, keep_tarball=True ) npm_cmd = ["npm"] + self.options.npm_flags npm_install = npm_cmd + ["--cache-min=Infinity", "install"] for pkg in self.options.node_packages: self.run(npm_install + ["--global"] + [pkg], cwd=rootdir) if os.path.exists(os.path.join(rootdir, "package.json")): self.run(npm_install, cwd=rootdir) self.run(npm_install + ["--global"], cwd=rootdir) for target in self.options.npm_run: self.run(npm_cmd + ["run", target], cwd=rootdir) return self._get_installed_node_packages("npm", self.installdir) def _yarn_install(self, rootdir): self._nodejs_tar.provision( self.installdir, clean_target=False, keep_tarball=True ) self._yarn_tar.provision(self._npm_dir, clean_target=False, keep_tarball=True) yarn_cmd = [os.path.join(self._npm_dir, "bin", "yarn")] yarn_cmd.extend(self.options.npm_flags) if "http_proxy" in os.environ: yarn_cmd.extend(["--proxy", os.environ["http_proxy"]]) if "https_proxy" in os.environ: yarn_cmd.extend(["--https-proxy", os.environ["https_proxy"]]) flags = [] if rootdir == self.builddir: yarn_add = yarn_cmd + ["global", "add"] flags.extend( [ "--offline", "--prod", "--global-folder", self.installdir, "--prefix", self.installdir, ] ) else: yarn_add = yarn_cmd + ["add"] for pkg in self.options.node_packages: self.run(yarn_add + [pkg] + flags, cwd=rootdir) # local packages need to be added as if they were remote, we # remove the local package.json so `yarn add` doesn't pollute it. if os.path.exists(self._source_package_json): with contextlib.suppress(FileNotFoundError): os.unlink(os.path.join(rootdir, "package.json")) shutil.copy( self._source_package_json, os.path.join(rootdir, "package.json") ) self.run(yarn_add + ["file:{}".format(rootdir)] + flags, cwd=rootdir) # npm run would require to bring back package.json if self.options.npm_run and os.path.exists(self._source_package_json): # The current package.json is the yarn prefilled one. with contextlib.suppress(FileNotFoundError): os.unlink(os.path.join(rootdir, "package.json")) os.link(self._source_package_json, os.path.join(rootdir, "package.json")) for target in self.options.npm_run: self.run( yarn_cmd + ["run", target], cwd=rootdir, env=self._build_environment(rootdir), ) return self._get_installed_node_packages("npm", self.installdir) def _get_installed_node_packages(self, package_manager, cwd): try: output = self.run_output( [package_manager, "ls", "--global", "--json"], cwd=cwd ) except subprocess.CalledProcessError as error: # XXX When dependencies have missing dependencies, an error like # this is printed to stderr: # npm ERR! peer dep missing: glob@*, required by glob-promise@3.1.0 # retcode is not 0, which raises an exception. output = error.output.decode(sys.getfilesystemencoding()).strip() packages = collections.OrderedDict() dependencies = json.loads(output, object_pairs_hook=collections.OrderedDict)[ "dependencies" ] while dependencies: key, value = dependencies.popitem(last=False) # XXX Just as above, dependencies without version are the ones # missing. if "version" in value: packages[key] = value["version"] if "dependencies" in value: dependencies.update(value["dependencies"]) return packages def get_manifest(self): return self._manifest def _build_environment(self, rootdir): env = os.environ.copy() if rootdir.endswith("src"): hidden_path = os.path.join(rootdir, "node_modules", ".bin") if env.get("PATH"): new_path = "{}:{}".format(hidden_path, env.get("PATH")) else: new_path = hidden_path env["PATH"] = new_path return env def _get_nodejs_base(node_engine, machine): if machine not in _NODEJS_ARCHES: raise errors.SnapcraftEnvironmentError( "architecture not supported ({})".format(machine) ) return _NODEJS_BASE.format(version=node_engine, arch=_NODEJS_ARCHES[machine]) def get_nodejs_release(node_engine, arch): return _NODEJS_TMPL.format( version=node_engine, base=_get_nodejs_base(node_engine, arch) ) def _copy_symlinked_content(modules_dir): """Copy symlinked content. When running newer versions of npm, symlinks to the local tree are created from the part's installdir to the root of the builddir of the part (this only affects some build configurations in some projects) which is valid when running from the context of the part but invalid as soon as the artifacts migrate across the steps, i.e.; stage and prime. If modules_dir does not exist we simply return. """ if not os.path.exists(modules_dir): return modules = [os.path.join(modules_dir, d) for d in os.listdir(modules_dir)] symlinks = [l for l in modules if os.path.islink(l)] for link_path in symlinks: link_target = os.path.realpath(link_path) os.unlink(link_path) link_or_copy_tree(link_target, link_path) hugo-0.92.2/snap/snapcraft.yaml000066400000000000000000000051311420147000300163430ustar00rootroot00000000000000name: hugo version: git summary: Fast and Flexible Static Site Generator description: | Hugo is a static HTML and CSS website generator written in Go. It is optimized for speed, easy use and configurability. Hugo takes a directory with content and templates and renders them into a full HTML website. license: "Apache-2.0" base: core20 confinement: strict grade: stable # "devel" or "stable" package-repositories: - type: apt components: [main] suites: [focal] key-id: 9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280 url: https://deb.nodesource.com/node_16.x apps: hugo: command: bin/hugo completer: hugo-completion plugs: - home - network-bind - removable-media parts: git: plugin: nil stage-packages: - git organize: usr/bin/: bin/ prime: - bin/git hugo: plugin: nil build-snaps: [go/1.16/stable] source: . override-build: | set -ex echo "\nStarting override-build:" export GOPATH=$(realpath ../go) export PATH=$GOPATH/bin:$PATH echo ' * Running "go get -v github.com/magefile/mage"...' go get -v github.com/magefile/mage #echo ' * Running "mage -v test"...' #mage -v test echo " * SNAPCRAFT_IMAGE_INFO=${SNAPCRAFT_IMAGE_INFO=}" # Example: SNAPCRAFT_IMAGE_INFO='{"build_url": "https://launchpad.net/~gohugoio/+snap/hugo-extended-dev/+build/344022"}' export HUGO_BUILD_TAGS="" if echo $SNAPCRAFT_IMAGE_INFO | grep -q '/+snap/hugo-extended'; then HUGO_BUILD_TAGS="extended" fi echo " * Building hugo (HUGO_BUILD_TAGS=\"$HUGO_BUILD_TAGS\")..." [ "$SNAPCRAFT_PROJECT_GRADE" = "stable" ] && mage -v hugoNoGitInfo || mage -v hugo ./hugo version ldd hugo || : echo " * Building shell completion..." ./hugo completion bash > hugo-completion echo " * Installing to ${SNAPCRAFT_PART_INSTALL}..." install -d $SNAPCRAFT_PART_INSTALL/bin cp -av hugo $SNAPCRAFT_PART_INSTALL/bin/ mv -v hugo-completion $SNAPCRAFT_PART_INSTALL/ echo " * Stripping binary..." ls -l $SNAPCRAFT_PART_INSTALL/bin/hugo strip --remove-section=.comment --remove-section=.note $SNAPCRAFT_PART_INSTALL/bin/hugo ls -l $SNAPCRAFT_PART_INSTALL/bin/hugo node: plugin: nil stage-packages: - nodejs organize: usr/bin/: bin/ usr/lib/: lib/ prime: - bin/node - lib/*/lib*.so* pandoc: plugin: nil stage-packages: - libatomic1 - pandoc - pandoc-data organize: usr/bin/: bin/ usr/lib/: lib/ prime: - bin/pandoc hugo-0.92.2/source/000077500000000000000000000000001420147000300140355ustar00rootroot00000000000000hugo-0.92.2/source/content_directory_test.go000066400000000000000000000037521420147000300211700ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package source import ( "path/filepath" "testing" "github.com/gohugoio/hugo/helpers" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/hugofs" ) func TestIgnoreDotFilesAndDirectories(t *testing.T) { c := qt.New(t) tests := []struct { path string ignore bool ignoreFilesRegexpes interface{} }{ {".foobar/", true, nil}, {"foobar/.barfoo/", true, nil}, {"barfoo.md", false, nil}, {"foobar/barfoo.md", false, nil}, {"foobar/.barfoo.md", true, nil}, {".barfoo.md", true, nil}, {".md", true, nil}, {"foobar/barfoo.md~", true, nil}, {".foobar/barfoo.md~", true, nil}, {"foobar~/barfoo.md", false, nil}, {"foobar/bar~foo.md", false, nil}, {"foobar/foo.md", true, []string{"\\.md$", "\\.boo$"}}, {"foobar/foo.html", false, []string{"\\.md$", "\\.boo$"}}, {"foobar/foo.md", true, []string{"foo.md$"}}, {"foobar/foo.md", true, []string{"*", "\\.md$", "\\.boo$"}}, {"foobar/.#content.md", true, []string{"/\\.#"}}, {".#foobar.md", true, []string{"^\\.#"}}, } for i, test := range tests { v := newTestConfig() v.Set("ignoreFiles", test.ignoreFilesRegexpes) fs := hugofs.NewMem(v) ps, err := helpers.NewPathSpec(fs, v, nil) c.Assert(err, qt.IsNil) s := NewSourceSpec(ps, nil, fs.Source) if ignored := s.IgnoreFile(filepath.FromSlash(test.path)); test.ignore != ignored { t.Errorf("[%d] File not ignored", i) } } } hugo-0.92.2/source/fileInfo.go000066400000000000000000000200151420147000300161150ustar00rootroot00000000000000// Copyright 2021 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package source import ( "path/filepath" "strings" "sync" "github.com/gohugoio/hugo/common/paths" "github.com/gohugoio/hugo/hugofs/files" "github.com/pkg/errors" "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/helpers" ) // fileInfo implements the File interface. var ( _ File = (*FileInfo)(nil) ) // File represents a source file. // This is a temporary construct until we resolve page.Page conflicts. // TODO(bep) remove this construct once we have resolved page deprecations type File interface { fileOverlap FileWithoutOverlap } // Temporary to solve duplicate/deprecated names in page.Page type fileOverlap interface { // Path gets the relative path including file name and extension. // The directory is relative to the content root. Path() string // Section is first directory below the content root. // For page bundles in root, the Section will be empty. Section() string // Lang is the language code for this page. It will be the // same as the site's language code. Lang() string IsZero() bool } type FileWithoutOverlap interface { // Filename gets the full path and filename to the file. Filename() string // Dir gets the name of the directory that contains this file. // The directory is relative to the content root. Dir() string // Extension gets the file extension, i.e "myblogpost.md" will return "md". Extension() string // Ext is an alias for Extension. Ext() string // Hmm... Deprecate Extension // LogicalName is filename and extension of the file. LogicalName() string // BaseFileName is a filename without extension. BaseFileName() string // TranslationBaseName is a filename with no extension, // not even the optional language extension part. TranslationBaseName() string // ContentBaseName is a either TranslationBaseName or name of containing folder // if file is a leaf bundle. ContentBaseName() string // UniqueID is the MD5 hash of the file's path and is for most practical applications, // Hugo content files being one of them, considered to be unique. UniqueID() string FileInfo() hugofs.FileMetaInfo } // FileInfo describes a source file. type FileInfo struct { // Absolute filename to the file on disk. filename string sp *SourceSpec fi hugofs.FileMetaInfo // Derived from filename ext string // Extension without any "." lang string name string dir string relDir string relPath string baseName string translationBaseName string contentBaseName string section string classifier files.ContentClass uniqueID string lazyInit sync.Once } // Filename returns a file's absolute path and filename on disk. func (fi *FileInfo) Filename() string { return fi.filename } // Path gets the relative path including file name and extension. The directory // is relative to the content root. func (fi *FileInfo) Path() string { return fi.relPath } // Dir gets the name of the directory that contains this file. The directory is // relative to the content root. func (fi *FileInfo) Dir() string { return fi.relDir } // Extension is an alias to Ext(). func (fi *FileInfo) Extension() string { return fi.Ext() } // Ext returns a file's extension without the leading period (ie. "md"). func (fi *FileInfo) Ext() string { return fi.ext } // Lang returns a file's language (ie. "sv"). func (fi *FileInfo) Lang() string { return fi.lang } // LogicalName returns a file's name and extension (ie. "page.sv.md"). func (fi *FileInfo) LogicalName() string { return fi.name } // BaseFileName returns a file's name without extension (ie. "page.sv"). func (fi *FileInfo) BaseFileName() string { return fi.baseName } // TranslationBaseName returns a file's translation base name without the // language segment (ie. "page"). func (fi *FileInfo) TranslationBaseName() string { return fi.translationBaseName } // ContentBaseName is a either TranslationBaseName or name of containing folder // if file is a leaf bundle. func (fi *FileInfo) ContentBaseName() string { fi.init() return fi.contentBaseName } // Section returns a file's section. func (fi *FileInfo) Section() string { fi.init() return fi.section } // UniqueID returns a file's unique, MD5 hash identifier. func (fi *FileInfo) UniqueID() string { fi.init() return fi.uniqueID } // FileInfo returns a file's underlying os.FileInfo. func (fi *FileInfo) FileInfo() hugofs.FileMetaInfo { return fi.fi } func (fi *FileInfo) String() string { return fi.BaseFileName() } // Open implements ReadableFile. func (fi *FileInfo) Open() (hugio.ReadSeekCloser, error) { f, err := fi.fi.Meta().Open() return f, err } func (fi *FileInfo) IsZero() bool { return fi == nil } // We create a lot of these FileInfo objects, but there are parts of it used only // in some cases that is slightly expensive to construct. func (fi *FileInfo) init() { fi.lazyInit.Do(func() { relDir := strings.Trim(fi.relDir, helpers.FilePathSeparator) parts := strings.Split(relDir, helpers.FilePathSeparator) var section string if (fi.classifier != files.ContentClassLeaf && len(parts) == 1) || len(parts) > 1 { section = parts[0] } fi.section = section if fi.classifier.IsBundle() && len(parts) > 0 { fi.contentBaseName = parts[len(parts)-1] } else { fi.contentBaseName = fi.translationBaseName } fi.uniqueID = helpers.MD5String(filepath.ToSlash(fi.relPath)) }) } // NewTestFile creates a partially filled File used in unit tests. // TODO(bep) improve this package func NewTestFile(filename string) *FileInfo { base := filepath.Base(filepath.Dir(filename)) return &FileInfo{ filename: filename, translationBaseName: base, } } func (sp *SourceSpec) NewFileInfoFrom(path, filename string) (*FileInfo, error) { meta := &hugofs.FileMeta{ Filename: filename, Path: path, } return sp.NewFileInfo(hugofs.NewFileMetaInfo(nil, meta)) } func (sp *SourceSpec) NewFileInfo(fi hugofs.FileMetaInfo) (*FileInfo, error) { m := fi.Meta() filename := m.Filename relPath := m.Path if relPath == "" { return nil, errors.Errorf("no Path provided by %v (%T)", m, m.Fs) } if filename == "" { return nil, errors.Errorf("no Filename provided by %v (%T)", m, m.Fs) } relDir := filepath.Dir(relPath) if relDir == "." { relDir = "" } if !strings.HasSuffix(relDir, helpers.FilePathSeparator) { relDir = relDir + helpers.FilePathSeparator } lang := m.Lang translationBaseName := m.TranslationBaseName dir, name := filepath.Split(relPath) if !strings.HasSuffix(dir, helpers.FilePathSeparator) { dir = dir + helpers.FilePathSeparator } ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(name), ".")) baseName := paths.Filename(name) if translationBaseName == "" { // This is usually provided by the filesystem. But this FileInfo is also // created in a standalone context when doing "hugo new". This is // an approximate implementation, which is "good enough" in that case. fileLangExt := filepath.Ext(baseName) translationBaseName = strings.TrimSuffix(baseName, fileLangExt) } f := &FileInfo{ sp: sp, filename: filename, fi: fi, lang: lang, ext: ext, dir: dir, relDir: relDir, // Dir() relPath: relPath, // Path() name: name, baseName: baseName, // BaseFileName() translationBaseName: translationBaseName, classifier: m.Classifier, } return f, nil } hugo-0.92.2/source/fileInfo_test.go000066400000000000000000000037511420147000300171640ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package source import ( "path/filepath" "strings" "testing" qt "github.com/frankban/quicktest" ) func TestFileInfo(t *testing.T) { c := qt.New(t) s := newTestSourceSpec() for _, this := range []struct { base string filename string assert func(f *FileInfo) }{ {filepath.FromSlash("/a/"), filepath.FromSlash("/a/b/page.md"), func(f *FileInfo) { c.Assert(f.Filename(), qt.Equals, filepath.FromSlash("/a/b/page.md")) c.Assert(f.Dir(), qt.Equals, filepath.FromSlash("b/")) c.Assert(f.Path(), qt.Equals, filepath.FromSlash("b/page.md")) c.Assert(f.Section(), qt.Equals, "b") c.Assert(f.TranslationBaseName(), qt.Equals, filepath.FromSlash("page")) c.Assert(f.BaseFileName(), qt.Equals, filepath.FromSlash("page")) }}, {filepath.FromSlash("/a/"), filepath.FromSlash("/a/b/c/d/page.md"), func(f *FileInfo) { c.Assert(f.Section(), qt.Equals, "b") }}, {filepath.FromSlash("/a/"), filepath.FromSlash("/a/b/page.en.MD"), func(f *FileInfo) { c.Assert(f.Section(), qt.Equals, "b") c.Assert(f.Path(), qt.Equals, filepath.FromSlash("b/page.en.MD")) c.Assert(f.TranslationBaseName(), qt.Equals, filepath.FromSlash("page")) c.Assert(f.BaseFileName(), qt.Equals, filepath.FromSlash("page.en")) }}, } { path := strings.TrimPrefix(this.filename, this.base) f, err := s.NewFileInfoFrom(path, this.filename) c.Assert(err, qt.IsNil) this.assert(f) } } hugo-0.92.2/source/filesystem.go000066400000000000000000000050071420147000300165520ustar00rootroot00000000000000// Copyright 2016 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package source import ( "path/filepath" "sync" "github.com/pkg/errors" "github.com/gohugoio/hugo/hugofs" ) // Filesystem represents a source filesystem. type Filesystem struct { files []File filesInit sync.Once filesInitErr error Base string fi hugofs.FileMetaInfo SourceSpec } // NewFilesystem returns a new filesytem for a given source spec. func (sp SourceSpec) NewFilesystem(base string) *Filesystem { return &Filesystem{SourceSpec: sp, Base: base} } func (sp SourceSpec) NewFilesystemFromFileMetaInfo(fi hugofs.FileMetaInfo) *Filesystem { return &Filesystem{SourceSpec: sp, fi: fi} } // Files returns a slice of readable files. func (f *Filesystem) Files() ([]File, error) { f.filesInit.Do(func() { err := f.captureFiles() if err != nil { f.filesInitErr = errors.Wrap(err, "capture files") } }) return f.files, f.filesInitErr } // add populates a file in the Filesystem.files func (f *Filesystem) add(name string, fi hugofs.FileMetaInfo) (err error) { var file File file, err = f.SourceSpec.NewFileInfo(fi) if err != nil { return err } f.files = append(f.files, file) return err } func (f *Filesystem) captureFiles() error { walker := func(path string, fi hugofs.FileMetaInfo, err error) error { if err != nil { return err } if fi.IsDir() { return nil } meta := fi.Meta() filename := meta.Filename b, err := f.shouldRead(filename, fi) if err != nil { return err } if b { err = f.add(filename, fi) } return err } w := hugofs.NewWalkway(hugofs.WalkwayConfig{ Fs: f.SourceFs, Info: f.fi, Root: f.Base, WalkFn: walker, }) return w.Walk() } func (f *Filesystem) shouldRead(filename string, fi hugofs.FileMetaInfo) (bool, error) { ignore := f.SourceSpec.IgnoreFile(fi.Meta().Filename) if fi.IsDir() { if ignore { return false, filepath.SkipDir } return false, nil } if ignore { return false, nil } return true, nil } hugo-0.92.2/source/filesystem_test.go000066400000000000000000000053521420147000300176140ustar00rootroot00000000000000// Copyright 2015 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package source import ( "fmt" "path/filepath" "runtime" "testing" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/modules" "github.com/gohugoio/hugo/langs" "github.com/spf13/afero" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" ) func TestEmptySourceFilesystem(t *testing.T) { c := qt.New(t) ss := newTestSourceSpec() src := ss.NewFilesystem("") files, err := src.Files() c.Assert(err, qt.IsNil) if len(files) != 0 { t.Errorf("new filesystem should contain 0 files.") } } func TestUnicodeNorm(t *testing.T) { if runtime.GOOS != "darwin" { // Normalization code is only for Mac OS, since it is not necessary for other OSes. return } c := qt.New(t) paths := []struct { NFC string NFD string }{ {NFC: "å", NFD: "\x61\xcc\x8a"}, {NFC: "é", NFD: "\x65\xcc\x81"}, } ss := newTestSourceSpec() fi := hugofs.NewFileMetaInfo(nil, hugofs.NewFileMeta()) for i, path := range paths { base := fmt.Sprintf("base%d", i) c.Assert(afero.WriteFile(ss.Fs.Source, filepath.Join(base, path.NFD), []byte("some data"), 0777), qt.IsNil) src := ss.NewFilesystem(base) _ = src.add(path.NFD, fi) files, err := src.Files() c.Assert(err, qt.IsNil) f := files[0] if f.BaseFileName() != path.NFC { t.Fatalf("file %q name in NFD form should be normalized (%s)", f.BaseFileName(), path.NFC) } } } func newTestConfig() config.Provider { v := config.New() v.Set("contentDir", "content") v.Set("dataDir", "data") v.Set("i18nDir", "i18n") v.Set("layoutDir", "layouts") v.Set("archetypeDir", "archetypes") v.Set("resourceDir", "resources") v.Set("publishDir", "public") v.Set("assetDir", "assets") _, err := langs.LoadLanguageSettings(v, nil) if err != nil { panic(err) } mod, err := modules.CreateProjectModule(v) if err != nil { panic(err) } v.Set("allModules", modules.Modules{mod}) return v } func newTestSourceSpec() *SourceSpec { v := newTestConfig() fs := hugofs.NewFrom(hugofs.NewBaseFileDecorator(afero.NewMemMapFs()), v) ps, err := helpers.NewPathSpec(fs, v, nil) if err != nil { panic(err) } return NewSourceSpec(ps, nil, fs.Source) } hugo-0.92.2/source/sourceSpec.go000066400000000000000000000074201420147000300165020ustar00rootroot00000000000000// Copyright 2017-present The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package source import ( "os" "path/filepath" "regexp" "runtime" "github.com/gohugoio/hugo/hugofs/glob" "github.com/gohugoio/hugo/langs" "github.com/spf13/afero" "github.com/gohugoio/hugo/helpers" "github.com/spf13/cast" ) // SourceSpec abstracts language-specific file creation. // TODO(bep) rename to Spec type SourceSpec struct { *helpers.PathSpec SourceFs afero.Fs shouldInclude func(filename string) bool Languages map[string]interface{} DefaultContentLanguage string DisabledLanguages map[string]bool } // NewSourceSpec initializes SourceSpec using languages the given filesystem and PathSpec. func NewSourceSpec(ps *helpers.PathSpec, inclusionFilter *glob.FilenameFilter, fs afero.Fs) *SourceSpec { cfg := ps.Cfg defaultLang := cfg.GetString("defaultContentLanguage") languages := cfg.GetStringMap("languages") disabledLangsSet := make(map[string]bool) for _, disabledLang := range cfg.GetStringSlice("disableLanguages") { disabledLangsSet[disabledLang] = true } if len(languages) == 0 { l := langs.NewDefaultLanguage(cfg) languages[l.Lang] = l defaultLang = l.Lang } ignoreFiles := cast.ToStringSlice(cfg.Get("ignoreFiles")) var regexps []*regexp.Regexp if len(ignoreFiles) > 0 { for _, ignorePattern := range ignoreFiles { re, err := regexp.Compile(ignorePattern) if err != nil { helpers.DistinctErrorLog.Printf("Invalid regexp %q in ignoreFiles: %s", ignorePattern, err) } else { regexps = append(regexps, re) } } } shouldInclude := func(filename string) bool { if !inclusionFilter.Match(filename, false) { return false } for _, r := range regexps { if r.MatchString(filename) { return false } } return true } return &SourceSpec{shouldInclude: shouldInclude, PathSpec: ps, SourceFs: fs, Languages: languages, DefaultContentLanguage: defaultLang, DisabledLanguages: disabledLangsSet} } // IgnoreFile returns whether a given file should be ignored. func (s *SourceSpec) IgnoreFile(filename string) bool { if filename == "" { if _, ok := s.SourceFs.(*afero.OsFs); ok { return true } return false } base := filepath.Base(filename) if len(base) > 0 { first := base[0] last := base[len(base)-1] if first == '.' || first == '#' || last == '~' { return true } } if !s.shouldInclude(filename) { return true } if runtime.GOOS == "windows" { // Also check the forward slash variant if different. unixFilename := filepath.ToSlash(filename) if unixFilename != filename { if !s.shouldInclude(unixFilename) { return true } } } return false } // IsRegularSourceFile returns whether filename represents a regular file in the // source filesystem. func (s *SourceSpec) IsRegularSourceFile(filename string) (bool, error) { fi, err := helpers.LstatIfPossible(s.SourceFs, filename) if err != nil { return false, err } if fi.IsDir() { return false, nil } if fi.Mode()&os.ModeSymlink == os.ModeSymlink { link, err := filepath.EvalSymlinks(filename) if err != nil { return false, err } fi, err = helpers.LstatIfPossible(s.SourceFs, link) if err != nil { return false, err } if fi.IsDir() { return false, nil } } return true, nil } hugo-0.92.2/temp/000077500000000000000000000000001420147000300135025ustar00rootroot00000000000000hugo-0.92.2/temp/0.86.1-relnotes-ready.md000066400000000000000000000004371420147000300175150ustar00rootroot00000000000000 This is a bug-fix release with one important fix. * config: Fix a potential deadlock in config reading [94b616bd](https://github.com/gohugoio/hugo/commit/94b616bdfad177daa99f5e87535943f509198f6f) [@bep](https://github.com/bep) [#8791](https://github.com/gohugoio/hugo/issues/8791) hugo-0.92.2/temp/0.92.2-relnotes-ready.md000066400000000000000000000044331420147000300175130ustar00rootroot00000000000000 This is a bug-fix release with a couple of important fixes. * Add HUGO_ENV to the os/exec environment 4f4cec73 [@jmooring](https://github.com/jmooring) #9490 * Simplify some integration tests da4866c2 [@bep](https://github.com/bep) * Fix validation of Page Kind in cascade target map d1109f59 [@jmooring](https://github.com/jmooring) #8888 * Add another cascade benchmark a7d182ce [@bep](https://github.com/bep) * commands: Fix server deadlock on config error a2a660ed [@bep](https://github.com/bep) #9486 * Exclude event attributes when rendering markdown f7bc4cc5 [@jmooring](https://github.com/jmooring) #9463 * Remove the "check" command 54f8d8a7 [@jmooring](https://github.com/jmooring) #9454 * Update the application/javascript media type 3036d0ac [@jmooring](https://github.com/jmooring) #9483 * tpl/templates: Fix templates.Exist issue with base templates 6a238a72 [@bep](https://github.com/bep) #9477 * Add a migration test helper f60714b5 [@bep](https://github.com/bep) * babel: Port integration tests to their own package 215a715d [@bep](https://github.com/bep) * js: Port integration tests to its own package d128d260 [@bep](https://github.com/bep) * postcss: Move integration test to its own package c4aaf1d5 [@bep](https://github.com/bep) * minifier: Port integration tests to its package 94f10cf4 [@bep](https://github.com/bep) * templates: Port integration test to its package b06c2103 [@bep](https://github.com/bep) * tocss: Port integration tests to their package d22f7795 [@bep](https://github.com/bep) * openapi3: Port integration test into correct package 39f69ca7 [@bep](https://github.com/bep) * Add a new integration test framework 64f75adc [@bep](https://github.com/bep) * Validate comparison operator argument count 92627190 [@jmooring](https://github.com/jmooring) #9462 * Remove hugo gen autocomplete 33367629 [@jmooring](https://github.com/jmooring) #8862 * deps: Update github.com/pelletier/go-toml/v2 to v2.0.0-beta.6 5ca40c8f [@bep](https://github.com/bep) #9439 #9417 * Fix erroneous warning with .Page.RenderString on a page without a backing file ef7d14a2 [@bep](https://github.com/bep) #9433 * Fix typo in panicOnWarning message c05c99f0 [@jmooring](https://github.com/jmooring) * releaser: Prepare repository for 0.93.0-DEV ff7689ce [@bep](https://github.com/bep) hugo-0.92.2/tpl/000077500000000000000000000000001420147000300133345ustar00rootroot00000000000000hugo-0.92.2/tpl/cast/000077500000000000000000000000001420147000300142665ustar00rootroot00000000000000hugo-0.92.2/tpl/cast/cast.go000066400000000000000000000033121420147000300155460ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package cast provides template functions for data type conversions. package cast import ( "html/template" _cast "github.com/spf13/cast" ) // New returns a new instance of the cast-namespaced template functions. func New() *Namespace { return &Namespace{} } // Namespace provides template functions for the "cast" namespace. type Namespace struct { } // ToInt converts the given value to an int. func (ns *Namespace) ToInt(v interface{}) (int, error) { v = convertTemplateToString(v) return _cast.ToIntE(v) } // ToString converts the given value to a string. func (ns *Namespace) ToString(v interface{}) (string, error) { return _cast.ToStringE(v) } // ToFloat converts the given value to a float. func (ns *Namespace) ToFloat(v interface{}) (float64, error) { v = convertTemplateToString(v) return _cast.ToFloat64E(v) } func convertTemplateToString(v interface{}) interface{} { switch vv := v.(type) { case template.HTML: v = string(vv) case template.CSS: v = string(vv) case template.HTMLAttr: v = string(vv) case template.JS: v = string(vv) case template.JSStr: v = string(vv) } return v } hugo-0.92.2/tpl/cast/cast_test.go000066400000000000000000000050021420147000300166030ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cast import ( "html/template" "testing" qt "github.com/frankban/quicktest" ) func TestToInt(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for i, test := range []struct { v interface{} expect interface{} }{ {"1", 1}, {template.HTML("2"), 2}, {template.CSS("3"), 3}, {template.HTMLAttr("4"), 4}, {template.JS("5"), 5}, {template.JSStr("6"), 6}, {"a", false}, {t, false}, } { errMsg := qt.Commentf("[%d] %v", i, test.v) result, err := ns.ToInt(test.v) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } func TestToString(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for i, test := range []struct { v interface{} expect interface{} }{ {1, "1"}, {template.HTML("2"), "2"}, {"a", "a"}, {t, false}, } { errMsg := qt.Commentf("[%d] %v", i, test.v) result, err := ns.ToString(test.v) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } func TestToFloat(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for i, test := range []struct { v interface{} expect interface{} }{ {"1", 1.0}, {template.HTML("2"), 2.0}, {template.CSS("3"), 3.0}, {template.HTMLAttr("4"), 4.0}, {template.JS("-5.67"), -5.67}, {template.JSStr("6"), 6.0}, {"1.23", 1.23}, {"-1.23", -1.23}, {"0", 0.0}, {float64(2.12), 2.12}, {int64(123), 123.0}, {2, 2.0}, {t, false}, } { errMsg := qt.Commentf("[%d] %v", i, test.v) result, err := ns.ToFloat(test.v) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } hugo-0.92.2/tpl/cast/docshelper.go000066400000000000000000000033261420147000300167510ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cast import ( "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/docshelper" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/tpl/internal" ) // This file provides documentation support and is randomly put into this package. func init() { docsProvider := func() docshelper.DocProvider { cfg := config.New() d := &deps.Deps{ Cfg: cfg, Log: loggers.NewErrorLogger(), BuildStartListeners: &deps.Listeners{}, Language: langs.NewDefaultLanguage(cfg), Site: page.NewDummyHugoSite(newTestConfig()), } var namespaces internal.TemplateFuncsNamespaces for _, nsf := range internal.TemplateFuncsNamespaceRegistry { nf := nsf(d) namespaces = append(namespaces, nf) } return docshelper.DocProvider{"tpl": map[string]interface{}{"funcs": namespaces}} } docshelper.AddDocProviderFunc(docsProvider) } func newTestConfig() config.Provider { v := config.New() v.Set("contentDir", "content") return v } hugo-0.92.2/tpl/cast/init.go000066400000000000000000000026251420147000300155650ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cast import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "cast" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil }, } ns.AddMethodMapping(ctx.ToInt, []string{"int"}, [][2]string{ {`{{ "1234" | int | printf "%T" }}`, `int`}, }, ) ns.AddMethodMapping(ctx.ToString, []string{"string"}, [][2]string{ {`{{ 1234 | string | printf "%T" }}`, `string`}, }, ) ns.AddMethodMapping(ctx.ToFloat, []string{"float"}, [][2]string{ {`{{ "1234" | float | printf "%T" }}`, `float64`}, }, ) return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/cast/init_test.go000066400000000000000000000022331420147000300166170ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cast import ( "testing" "github.com/gohugoio/hugo/htesting/hqt" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(&deps.Deps{}) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, &Namespace{}) } hugo-0.92.2/tpl/collections/000077500000000000000000000000001420147000300156525ustar00rootroot00000000000000hugo-0.92.2/tpl/collections/append.go000066400000000000000000000024521420147000300174530ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "errors" "github.com/gohugoio/hugo/common/collections" ) // Append appends the arguments up to the last one to the slice in the last argument. // This construct allows template constructs like this: // {{ $pages = $pages | append $p2 $p1 }} // Note that with 2 arguments where both are slices of the same type, // the first slice will be appended to the second: // {{ $pages = $pages | append .Site.RegularPages }} func (ns *Namespace) Append(args ...interface{}) (interface{}, error) { if len(args) < 2 { return nil, errors.New("need at least 2 arguments to append") } to := args[len(args)-1] from := args[:len(args)-1] return collections.Append(to, from...) } hugo-0.92.2/tpl/collections/append_test.go000066400000000000000000000034631420147000300205150ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "reflect" "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" ) // Also see tests in common/collection. func TestAppend(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { start interface{} addend []interface{} expected interface{} }{ {[]string{"a", "b"}, []interface{}{"c"}, []string{"a", "b", "c"}}, {[]string{"a", "b"}, []interface{}{"c", "d", "e"}, []string{"a", "b", "c", "d", "e"}}, {[]string{"a", "b"}, []interface{}{[]string{"c", "d", "e"}}, []string{"a", "b", "c", "d", "e"}}, // Errors {"", []interface{}{[]string{"a", "b"}}, false}, {[]string{"a", "b"}, []interface{}{}, false}, // No string concatenation. { "ab", []interface{}{"c"}, false, }, } { errMsg := qt.Commentf("[%d]", i) args := append(test.addend, test.start) result, err := ns.Append(args...) if b, ok := test.expected.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) if !reflect.DeepEqual(test.expected, result) { t.Fatalf("%s got\n%T: %v\nexpected\n%T: %v", errMsg, result, result, test.expected, test.expected) } } } hugo-0.92.2/tpl/collections/apply.go000066400000000000000000000075431420147000300173370ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "errors" "fmt" "reflect" "strings" "github.com/gohugoio/hugo/tpl" ) // Apply takes a map, array, or slice and returns a new slice with the function fname applied over it. func (ns *Namespace) Apply(seq interface{}, fname string, args ...interface{}) (interface{}, error) { if seq == nil { return make([]interface{}, 0), nil } if fname == "apply" { return nil, errors.New("can't apply myself (no turtles allowed)") } seqv := reflect.ValueOf(seq) seqv, isNil := indirect(seqv) if isNil { return nil, errors.New("can't iterate over a nil value") } fnv, found := ns.lookupFunc(fname) if !found { return nil, errors.New("can't find function " + fname) } // fnv := reflect.ValueOf(fn) switch seqv.Kind() { case reflect.Array, reflect.Slice: r := make([]interface{}, seqv.Len()) for i := 0; i < seqv.Len(); i++ { vv := seqv.Index(i) vvv, err := applyFnToThis(fnv, vv, args...) if err != nil { return nil, err } r[i] = vvv.Interface() } return r, nil default: return nil, fmt.Errorf("can't apply over %v", seq) } } func applyFnToThis(fn, this reflect.Value, args ...interface{}) (reflect.Value, error) { n := make([]reflect.Value, len(args)) for i, arg := range args { if arg == "." { n[i] = this } else { n[i] = reflect.ValueOf(arg) } } num := fn.Type().NumIn() if fn.Type().IsVariadic() { num-- } // TODO(bep) see #1098 - also see template_tests.go /*if len(args) < num { return reflect.ValueOf(nil), errors.New("Too few arguments") } else if len(args) > num { return reflect.ValueOf(nil), errors.New("Too many arguments") }*/ for i := 0; i < num; i++ { // AssignableTo reports whether xt is assignable to type targ. if xt, targ := n[i].Type(), fn.Type().In(i); !xt.AssignableTo(targ) { return reflect.ValueOf(nil), errors.New("called apply using " + xt.String() + " as type " + targ.String()) } } res := fn.Call(n) if len(res) == 1 || res[1].IsNil() { return res[0], nil } return reflect.ValueOf(nil), res[1].Interface().(error) } func (ns *Namespace) lookupFunc(fname string) (reflect.Value, bool) { if !strings.ContainsRune(fname, '.') { templ := ns.deps.Tmpl().(tpl.TemplateFuncGetter) return templ.GetFunc(fname) } ss := strings.SplitN(fname, ".", 2) // Namespace nv, found := ns.lookupFunc(ss[0]) if !found { return reflect.Value{}, false } fn, ok := nv.Interface().(func(...interface{}) (interface{}, error)) if !ok { return reflect.Value{}, false } v, err := fn() if err != nil { panic(err) } nv = reflect.ValueOf(v) // method m := nv.MethodByName(ss[1]) if m.Kind() == reflect.Invalid { return reflect.Value{}, false } return m, true } // indirect is borrowed from the Go stdlib: 'text/template/exec.go' func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { if v.IsNil() { return v, true } if v.Kind() == reflect.Interface && v.NumMethod() > 0 { break } } return v, false } func indirectInterface(v reflect.Value) (rv reflect.Value, isNil bool) { for ; v.Kind() == reflect.Interface; v = v.Elem() { if v.IsNil() { return v, true } if v.Kind() == reflect.Interface && v.NumMethod() > 0 { break } } return v, false } hugo-0.92.2/tpl/collections/apply_test.go000066400000000000000000000044121420147000300203660ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "fmt" "io" "reflect" "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/tpl" ) type templateFinder int func (templateFinder) Lookup(name string) (tpl.Template, bool) { return nil, false } func (templateFinder) HasTemplate(name string) bool { return false } func (templateFinder) LookupVariant(name string, variants tpl.TemplateVariants) (tpl.Template, bool, bool) { return nil, false, false } func (templateFinder) LookupVariants(name string) []tpl.Template { return nil } func (templateFinder) LookupLayout(d output.LayoutDescriptor, f output.Format) (tpl.Template, bool, error) { return nil, false, nil } func (templateFinder) Execute(t tpl.Template, wr io.Writer, data interface{}) error { return nil } func (templateFinder) GetFunc(name string) (reflect.Value, bool) { if name == "dobedobedo" { return reflect.Value{}, false } return reflect.ValueOf(fmt.Sprint), true } func TestApply(t *testing.T) { t.Parallel() c := qt.New(t) d := &deps.Deps{} d.SetTmpl(new(templateFinder)) ns := New(d) strings := []interface{}{"a\n", "b\n"} result, err := ns.Apply(strings, "print", "a", "b", "c") c.Assert(err, qt.IsNil) c.Assert(result, qt.DeepEquals, []interface{}{"abc", "abc"}) _, err = ns.Apply(strings, "apply", ".") c.Assert(err, qt.Not(qt.IsNil)) var nilErr *error _, err = ns.Apply(nilErr, "chomp", ".") c.Assert(err, qt.Not(qt.IsNil)) _, err = ns.Apply(strings, "dobedobedo", ".") c.Assert(err, qt.Not(qt.IsNil)) _, err = ns.Apply(strings, "foo.Chomp", "c\n") if err == nil { t.Errorf("apply with unknown func should fail") } } hugo-0.92.2/tpl/collections/collections.go000066400000000000000000000442761420147000300205340ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package collections provides template functions for manipulating collections // such as arrays, maps, and slices. package collections import ( "fmt" "html/template" "math/rand" "net/url" "reflect" "strings" "time" "github.com/gohugoio/hugo/common/collections" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/helpers" "github.com/pkg/errors" "github.com/spf13/cast" ) func init() { rand.Seed(time.Now().UTC().UnixNano()) } // New returns a new instance of the collections-namespaced template functions. func New(deps *deps.Deps) *Namespace { return &Namespace{ deps: deps, } } // Namespace provides template functions for the "collections" namespace. type Namespace struct { deps *deps.Deps } // After returns all the items after the first N in a rangeable list. func (ns *Namespace) After(index interface{}, seq interface{}) (interface{}, error) { if index == nil || seq == nil { return nil, errors.New("both limit and seq must be provided") } indexv, err := cast.ToIntE(index) if err != nil { return nil, err } if indexv < 0 { return nil, errors.New("sequence bounds out of range [" + cast.ToString(indexv) + ":]") } seqv := reflect.ValueOf(seq) seqv, isNil := indirect(seqv) if isNil { return nil, errors.New("can't iterate over a nil value") } switch seqv.Kind() { case reflect.Array, reflect.Slice, reflect.String: // okay default: return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String()) } if indexv >= seqv.Len() { return seqv.Slice(0, 0).Interface(), nil } return seqv.Slice(indexv, seqv.Len()).Interface(), nil } // Delimit takes a given sequence and returns a delimited HTML string. // If last is passed to the function, it will be used as the final delimiter. func (ns *Namespace) Delimit(seq, delimiter interface{}, last ...interface{}) (template.HTML, error) { d, err := cast.ToStringE(delimiter) if err != nil { return "", err } var dLast *string if len(last) > 0 { l := last[0] dStr, err := cast.ToStringE(l) if err != nil { dLast = nil } else { dLast = &dStr } } seqv := reflect.ValueOf(seq) seqv, isNil := indirect(seqv) if isNil { return "", errors.New("can't iterate over a nil value") } var str string switch seqv.Kind() { case reflect.Map: sortSeq, err := ns.Sort(seq) if err != nil { return "", err } seqv = reflect.ValueOf(sortSeq) fallthrough case reflect.Array, reflect.Slice, reflect.String: for i := 0; i < seqv.Len(); i++ { val := seqv.Index(i).Interface() valStr, err := cast.ToStringE(val) if err != nil { continue } switch { case i == seqv.Len()-2 && dLast != nil: str += valStr + *dLast case i == seqv.Len()-1: str += valStr default: str += valStr + d } } default: return "", fmt.Errorf("can't iterate over %v", seq) } return template.HTML(str), nil } // Dictionary creates a map[string]interface{} from the given parameters by // walking the parameters and treating them as key-value pairs. The number // of parameters must be even. // The keys can be string slices, which will create the needed nested structure. func (ns *Namespace) Dictionary(values ...interface{}) (map[string]interface{}, error) { if len(values)%2 != 0 { return nil, errors.New("invalid dictionary call") } root := make(map[string]interface{}) for i := 0; i < len(values); i += 2 { dict := root var key string switch v := values[i].(type) { case string: key = v case []string: for i := 0; i < len(v)-1; i++ { key = v[i] var m map[string]interface{} v, found := dict[key] if found { m = v.(map[string]interface{}) } else { m = make(map[string]interface{}) dict[key] = m } dict = m } key = v[len(v)-1] default: return nil, errors.New("invalid dictionary key") } dict[key] = values[i+1] } return root, nil } // EchoParam returns a given value if it is set; otherwise, it returns an // empty string. func (ns *Namespace) EchoParam(a, key interface{}) interface{} { av, isNil := indirect(reflect.ValueOf(a)) if isNil { return "" } var avv reflect.Value switch av.Kind() { case reflect.Array, reflect.Slice: index, ok := key.(int) if ok && av.Len() > index { avv = av.Index(index) } case reflect.Map: kv := reflect.ValueOf(key) if kv.Type().AssignableTo(av.Type().Key()) { avv = av.MapIndex(kv) } } avv, isNil = indirect(avv) if isNil { return "" } if avv.IsValid() { switch avv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return avv.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return avv.Uint() case reflect.Float32, reflect.Float64: return avv.Float() case reflect.String: return avv.String() } } return "" } // First returns the first N items in a rangeable list. func (ns *Namespace) First(limit interface{}, seq interface{}) (interface{}, error) { if limit == nil || seq == nil { return nil, errors.New("both limit and seq must be provided") } limitv, err := cast.ToIntE(limit) if err != nil { return nil, err } if limitv < 0 { return nil, errors.New("sequence length must be non-negative") } seqv := reflect.ValueOf(seq) seqv, isNil := indirect(seqv) if isNil { return nil, errors.New("can't iterate over a nil value") } switch seqv.Kind() { case reflect.Array, reflect.Slice, reflect.String: // okay default: return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String()) } if limitv > seqv.Len() { limitv = seqv.Len() } return seqv.Slice(0, limitv).Interface(), nil } // In returns whether v is in the set l. l may be an array or slice. func (ns *Namespace) In(l interface{}, v interface{}) (bool, error) { if l == nil || v == nil { return false, nil } lv := reflect.ValueOf(l) vv := reflect.ValueOf(v) vvk := normalize(vv) switch lv.Kind() { case reflect.Array, reflect.Slice: for i := 0; i < lv.Len(); i++ { lvv, isNil := indirectInterface(lv.Index(i)) if isNil { continue } lvvk := normalize(lvv) if lvvk == vvk { return true, nil } } } ss, err := cast.ToStringE(l) if err != nil { return false, nil } su, err := cast.ToStringE(v) if err != nil { return false, nil } return strings.Contains(ss, su), nil } // Intersect returns the common elements in the given sets, l1 and l2. l1 and // l2 must be of the same type and may be either arrays or slices. func (ns *Namespace) Intersect(l1, l2 interface{}) (interface{}, error) { if l1 == nil || l2 == nil { return make([]interface{}, 0), nil } var ins *intersector l1v := reflect.ValueOf(l1) l2v := reflect.ValueOf(l2) switch l1v.Kind() { case reflect.Array, reflect.Slice: ins = &intersector{r: reflect.MakeSlice(l1v.Type(), 0, 0), seen: make(map[interface{}]bool)} switch l2v.Kind() { case reflect.Array, reflect.Slice: for i := 0; i < l1v.Len(); i++ { l1vv := l1v.Index(i) if !l1vv.Type().Comparable() { return make([]interface{}, 0), errors.New("intersect does not support slices or arrays of uncomparable types") } for j := 0; j < l2v.Len(); j++ { l2vv := l2v.Index(j) if !l2vv.Type().Comparable() { return make([]interface{}, 0), errors.New("intersect does not support slices or arrays of uncomparable types") } ins.handleValuePair(l1vv, l2vv) } } return ins.r.Interface(), nil default: return nil, errors.New("can't iterate over " + reflect.ValueOf(l2).Type().String()) } default: return nil, errors.New("can't iterate over " + reflect.ValueOf(l1).Type().String()) } } // Group groups a set of elements by the given key. // This is currently only supported for Pages. func (ns *Namespace) Group(key interface{}, items interface{}) (interface{}, error) { if key == nil { return nil, errors.New("nil is not a valid key to group by") } if g, ok := items.(collections.Grouper); ok { return g.Group(key, items) } in := newSliceElement(items) if g, ok := in.(collections.Grouper); ok { return g.Group(key, items) } return nil, fmt.Errorf("grouping not supported for type %T %T", items, in) } // IsSet returns whether a given array, channel, slice, or map has a key // defined. func (ns *Namespace) IsSet(a interface{}, key interface{}) (bool, error) { av := reflect.ValueOf(a) kv := reflect.ValueOf(key) switch av.Kind() { case reflect.Array, reflect.Chan, reflect.Slice: k, err := cast.ToIntE(key) if err != nil { return false, fmt.Errorf("isset unable to use key of type %T as index", key) } if av.Len() > k { return true, nil } case reflect.Map: if kv.Type() == av.Type().Key() { return av.MapIndex(kv).IsValid(), nil } default: helpers.DistinctErrorLog.Printf("WARNING: calling IsSet with unsupported type %q (%T) will always return false.\n", av.Kind(), a) } return false, nil } // Last returns the last N items in a rangeable list. func (ns *Namespace) Last(limit interface{}, seq interface{}) (interface{}, error) { if limit == nil || seq == nil { return nil, errors.New("both limit and seq must be provided") } limitv, err := cast.ToIntE(limit) if err != nil { return nil, err } if limitv < 0 { return nil, errors.New("sequence length must be non-negative") } seqv := reflect.ValueOf(seq) seqv, isNil := indirect(seqv) if isNil { return nil, errors.New("can't iterate over a nil value") } switch seqv.Kind() { case reflect.Array, reflect.Slice, reflect.String: // okay default: return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String()) } if limitv > seqv.Len() { limitv = seqv.Len() } return seqv.Slice(seqv.Len()-limitv, seqv.Len()).Interface(), nil } // Querify encodes the given parameters in URL-encoded form ("bar=baz&foo=quux") sorted by key. func (ns *Namespace) Querify(params ...interface{}) (string, error) { qs := url.Values{} if len(params) == 1 { switch v := params[0].(type) { case []string: if len(v)%2 != 0 { return "", errors.New("invalid query") } for i := 0; i < len(v); i += 2 { qs.Add(v[i], v[i+1]) } return qs.Encode(), nil case []interface{}: params = v default: return "", errors.New("query keys must be strings") } } if len(params)%2 != 0 { return "", errors.New("invalid query") } for i := 0; i < len(params); i += 2 { switch v := params[i].(type) { case string: qs.Add(v, fmt.Sprintf("%v", params[i+1])) default: return "", errors.New("query keys must be strings") } } return qs.Encode(), nil } // Reverse creates a copy of slice and reverses it. func (ns *Namespace) Reverse(slice interface{}) (interface{}, error) { if slice == nil { return nil, nil } v := reflect.ValueOf(slice) switch v.Kind() { case reflect.Slice: default: return nil, errors.New("argument must be a slice") } sliceCopy := reflect.MakeSlice(v.Type(), v.Len(), v.Len()) for i := v.Len() - 1; i >= 0; i-- { element := sliceCopy.Index(i) element.Set(v.Index(v.Len() - 1 - i)) } return sliceCopy.Interface(), nil } // Seq creates a sequence of integers. It's named and used as GNU's seq. // // Examples: // 3 => 1, 2, 3 // 1 2 4 => 1, 3 // -3 => -1, -2, -3 // 1 4 => 1, 2, 3, 4 // 1 -2 => 1, 0, -1, -2 func (ns *Namespace) Seq(args ...interface{}) ([]int, error) { if len(args) < 1 || len(args) > 3 { return nil, errors.New("invalid number of arguments to Seq") } intArgs := cast.ToIntSlice(args) if len(intArgs) < 1 || len(intArgs) > 3 { return nil, errors.New("invalid arguments to Seq") } inc := 1 var last int first := intArgs[0] if len(intArgs) == 1 { last = first if last == 0 { return []int{}, nil } else if last > 0 { first = 1 } else { first = -1 inc = -1 } } else if len(intArgs) == 2 { last = intArgs[1] if last < first { inc = -1 } } else { inc = intArgs[1] last = intArgs[2] if inc == 0 { return nil, errors.New("'increment' must not be 0") } if first < last && inc < 0 { return nil, errors.New("'increment' must be > 0") } if first > last && inc > 0 { return nil, errors.New("'increment' must be < 0") } } // sanity check if last < -100000 { return nil, errors.New("size of result exceeds limit") } size := ((last - first) / inc) + 1 // sanity check if size <= 0 || size > 2000 { return nil, errors.New("size of result exceeds limit") } seq := make([]int, size) val := first for i := 0; ; i++ { seq[i] = val val += inc if (inc < 0 && val < last) || (inc > 0 && val > last) { break } } return seq, nil } // Shuffle returns the given rangeable list in a randomised order. func (ns *Namespace) Shuffle(seq interface{}) (interface{}, error) { if seq == nil { return nil, errors.New("both count and seq must be provided") } seqv := reflect.ValueOf(seq) seqv, isNil := indirect(seqv) if isNil { return nil, errors.New("can't iterate over a nil value") } switch seqv.Kind() { case reflect.Array, reflect.Slice, reflect.String: // okay default: return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String()) } shuffled := reflect.MakeSlice(reflect.TypeOf(seq), seqv.Len(), seqv.Len()) randomIndices := rand.Perm(seqv.Len()) for index, value := range randomIndices { shuffled.Index(value).Set(seqv.Index(index)) } return shuffled.Interface(), nil } // Slice returns a slice of all passed arguments. func (ns *Namespace) Slice(args ...interface{}) interface{} { if len(args) == 0 { return args } return collections.Slice(args...) } type intersector struct { r reflect.Value seen map[interface{}]bool } func (i *intersector) appendIfNotSeen(v reflect.Value) { vi := v.Interface() if !i.seen[vi] { i.r = reflect.Append(i.r, v) i.seen[vi] = true } } func (i *intersector) handleValuePair(l1vv, l2vv reflect.Value) { switch kind := l1vv.Kind(); { case kind == reflect.String: l2t, err := toString(l2vv) if err == nil && l1vv.String() == l2t { i.appendIfNotSeen(l1vv) } case isNumber(kind): f1, err1 := numberToFloat(l1vv) f2, err2 := numberToFloat(l2vv) if err1 == nil && err2 == nil && f1 == f2 { i.appendIfNotSeen(l1vv) } case kind == reflect.Ptr, kind == reflect.Struct: if l1vv.Interface() == l2vv.Interface() { i.appendIfNotSeen(l1vv) } case kind == reflect.Interface: i.handleValuePair(reflect.ValueOf(l1vv.Interface()), l2vv) } } // Union returns the union of the given sets, l1 and l2. l1 and // l2 must be of the same type and may be either arrays or slices. // If l1 and l2 aren't of the same type then l1 will be returned. // If either l1 or l2 is nil then the non-nil list will be returned. func (ns *Namespace) Union(l1, l2 interface{}) (interface{}, error) { if l1 == nil && l2 == nil { return []interface{}{}, nil } else if l1 == nil && l2 != nil { return l2, nil } else if l1 != nil && l2 == nil { return l1, nil } l1v := reflect.ValueOf(l1) l2v := reflect.ValueOf(l2) var ins *intersector switch l1v.Kind() { case reflect.Array, reflect.Slice: switch l2v.Kind() { case reflect.Array, reflect.Slice: ins = &intersector{r: reflect.MakeSlice(l1v.Type(), 0, 0), seen: make(map[interface{}]bool)} if l1v.Type() != l2v.Type() && l1v.Type().Elem().Kind() != reflect.Interface && l2v.Type().Elem().Kind() != reflect.Interface { return ins.r.Interface(), nil } var ( l1vv reflect.Value isNil bool ) for i := 0; i < l1v.Len(); i++ { l1vv, isNil = indirectInterface(l1v.Index(i)) if !l1vv.Type().Comparable() { return []interface{}{}, errors.New("union does not support slices or arrays of uncomparable types") } if !isNil { ins.appendIfNotSeen(l1vv) } } if !l1vv.IsValid() { // The first slice may be empty. Pick the first value of the second // to use as a prototype. if l2v.Len() > 0 { l1vv = l2v.Index(0) } } for j := 0; j < l2v.Len(); j++ { l2vv := l2v.Index(j) switch kind := l1vv.Kind(); { case kind == reflect.String: l2t, err := toString(l2vv) if err == nil { ins.appendIfNotSeen(reflect.ValueOf(l2t)) } case isNumber(kind): var err error l2vv, err = convertNumber(l2vv, kind) if err == nil { ins.appendIfNotSeen(l2vv) } case kind == reflect.Interface, kind == reflect.Struct, kind == reflect.Ptr: ins.appendIfNotSeen(l2vv) } } return ins.r.Interface(), nil default: return nil, errors.New("can't iterate over " + reflect.ValueOf(l2).Type().String()) } default: return nil, errors.New("can't iterate over " + reflect.ValueOf(l1).Type().String()) } } // Uniq takes in a slice or array and returns a slice with subsequent // duplicate elements removed. func (ns *Namespace) Uniq(seq interface{}) (interface{}, error) { if seq == nil { return make([]interface{}, 0), nil } v := reflect.ValueOf(seq) var slice reflect.Value switch v.Kind() { case reflect.Slice: slice = reflect.MakeSlice(v.Type(), 0, 0) case reflect.Array: slice = reflect.MakeSlice(reflect.SliceOf(v.Type().Elem()), 0, 0) default: return nil, errors.Errorf("type %T not supported", seq) } seen := make(map[interface{}]bool) for i := 0; i < v.Len(); i++ { ev, _ := indirectInterface(v.Index(i)) key := normalize(ev) if _, found := seen[key]; !found { slice = reflect.Append(slice, ev) seen[key] = true } } return slice.Interface(), nil } // KeyVals creates a key and values wrapper. func (ns *Namespace) KeyVals(key interface{}, vals ...interface{}) (types.KeyValues, error) { return types.KeyValues{Key: key, Values: vals}, nil } // NewScratch creates a new Scratch which can be used to store values in a // thread safe way. func (ns *Namespace) NewScratch() *maps.Scratch { return maps.NewScratch() } hugo-0.92.2/tpl/collections/collections_test.go000066400000000000000000000727631420147000300215750ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "errors" "fmt" "html/template" "math/rand" "reflect" "testing" "time" "github.com/gohugoio/hugo/common/maps" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/langs" "github.com/spf13/afero" ) type tstNoStringer struct{} func TestAfter(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { index interface{} seq interface{} expect interface{} }{ {int(2), []string{"a", "b", "c", "d"}, []string{"c", "d"}}, {int32(3), []string{"a", "b"}, []string{}}, {int64(2), []int{100, 200, 300}, []int{300}}, {100, []int{100, 200}, []int{}}, {"1", []int{100, 200, 300}, []int{200, 300}}, {0, []int{100, 200, 300, 400, 500}, []int{100, 200, 300, 400, 500}}, {0, []string{"a", "b", "c", "d", "e"}, []string{"a", "b", "c", "d", "e"}}, {int64(-1), []int{100, 200, 300}, false}, {"noint", []int{100, 200, 300}, false}, {2, []string{}, []string{}}, {1, nil, false}, {nil, []int{100}, false}, {1, t, false}, {1, (*string)(nil), false}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.After(test.index, test.seq) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.DeepEquals, test.expect, errMsg) } } type tstGrouper struct { } type tstGroupers []*tstGrouper func (g tstGrouper) Group(key interface{}, items interface{}) (interface{}, error) { ilen := reflect.ValueOf(items).Len() return fmt.Sprintf("%v(%d)", key, ilen), nil } type tstGrouper2 struct { } func (g *tstGrouper2) Group(key interface{}, items interface{}) (interface{}, error) { ilen := reflect.ValueOf(items).Len() return fmt.Sprintf("%v(%d)", key, ilen), nil } func TestGroup(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { key interface{} items interface{} expect interface{} }{ {"a", []*tstGrouper{{}, {}}, "a(2)"}, {"b", tstGroupers{&tstGrouper{}, &tstGrouper{}}, "b(2)"}, {"a", []tstGrouper{{}, {}}, "a(2)"}, {"a", []*tstGrouper2{{}, {}}, "a(2)"}, {"b", []tstGrouper2{{}, {}}, "b(2)"}, {"a", []*tstGrouper{}, "a(0)"}, {"a", []string{"a", "b"}, false}, {"a", "asdf", false}, {"a", nil, false}, {nil, []*tstGrouper{{}, {}}, false}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.Group(test.key, test.items) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } func TestDelimit(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { seq interface{} delimiter interface{} last interface{} expect template.HTML }{ {[]string{"class1", "class2", "class3"}, " ", nil, "class1 class2 class3"}, {[]int{1, 2, 3, 4, 5}, ",", nil, "1,2,3,4,5"}, {[]int{1, 2, 3, 4, 5}, ", ", nil, "1, 2, 3, 4, 5"}, {[]string{"class1", "class2", "class3"}, " ", " and ", "class1 class2 and class3"}, {[]int{1, 2, 3, 4, 5}, ",", ",", "1,2,3,4,5"}, {[]int{1, 2, 3, 4, 5}, ", ", ", and ", "1, 2, 3, 4, and 5"}, // test maps with and without sorting required {map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, "--", nil, "10--20--30--40--50"}, {map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, "--", nil, "30--20--10--40--50"}, {map[string]string{"1": "10", "2": "20", "3": "30", "4": "40", "5": "50"}, "--", nil, "10--20--30--40--50"}, {map[string]string{"3": "10", "2": "20", "1": "30", "4": "40", "5": "50"}, "--", nil, "30--20--10--40--50"}, {map[string]string{"one": "10", "two": "20", "three": "30", "four": "40", "five": "50"}, "--", nil, "50--40--10--30--20"}, {map[int]string{1: "10", 2: "20", 3: "30", 4: "40", 5: "50"}, "--", nil, "10--20--30--40--50"}, {map[int]string{3: "10", 2: "20", 1: "30", 4: "40", 5: "50"}, "--", nil, "30--20--10--40--50"}, {map[float64]string{3.3: "10", 2.3: "20", 1.3: "30", 4.3: "40", 5.3: "50"}, "--", nil, "30--20--10--40--50"}, // test maps with a last delimiter {map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, "--", "--and--", "10--20--30--40--and--50"}, {map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, "--", "--and--", "30--20--10--40--and--50"}, {map[string]string{"1": "10", "2": "20", "3": "30", "4": "40", "5": "50"}, "--", "--and--", "10--20--30--40--and--50"}, {map[string]string{"3": "10", "2": "20", "1": "30", "4": "40", "5": "50"}, "--", "--and--", "30--20--10--40--and--50"}, {map[string]string{"one": "10", "two": "20", "three": "30", "four": "40", "five": "50"}, "--", "--and--", "50--40--10--30--and--20"}, {map[int]string{1: "10", 2: "20", 3: "30", 4: "40", 5: "50"}, "--", "--and--", "10--20--30--40--and--50"}, {map[int]string{3: "10", 2: "20", 1: "30", 4: "40", 5: "50"}, "--", "--and--", "30--20--10--40--and--50"}, {map[float64]string{3.5: "10", 2.5: "20", 1.5: "30", 4.5: "40", 5.5: "50"}, "--", "--and--", "30--20--10--40--and--50"}, } { errMsg := qt.Commentf("[%d] %v", i, test) var result template.HTML var err error if test.last == nil { result, err = ns.Delimit(test.seq, test.delimiter) } else { result, err = ns.Delimit(test.seq, test.delimiter, test.last) } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } func TestDictionary(t *testing.T) { c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { values []interface{} expect interface{} }{ {[]interface{}{"a", "b"}, map[string]interface{}{"a": "b"}}, {[]interface{}{[]string{"a", "b"}, "c"}, map[string]interface{}{"a": map[string]interface{}{"b": "c"}}}, { []interface{}{[]string{"a", "b"}, "c", []string{"a", "b2"}, "c2", "b", "c"}, map[string]interface{}{"a": map[string]interface{}{"b": "c", "b2": "c2"}, "b": "c"}, }, {[]interface{}{"a", 12, "b", []int{4}}, map[string]interface{}{"a": 12, "b": []int{4}}}, // errors {[]interface{}{5, "b"}, false}, {[]interface{}{"a", "b", "c"}, false}, } { i := i test := test c.Run(fmt.Sprint(i), func(c *qt.C) { c.Parallel() errMsg := qt.Commentf("[%d] %v", i, test.values) result, err := ns.Dictionary(test.values...) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) return } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.DeepEquals, test.expect, qt.Commentf(fmt.Sprint(result))) }) } } func TestReverse(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) s := []string{"a", "b", "c"} reversed, err := ns.Reverse(s) c.Assert(err, qt.IsNil) c.Assert(reversed, qt.DeepEquals, []string{"c", "b", "a"}, qt.Commentf(fmt.Sprint(reversed))) c.Assert(s, qt.DeepEquals, []string{"a", "b", "c"}) reversed, err = ns.Reverse(nil) c.Assert(err, qt.IsNil) c.Assert(reversed, qt.IsNil) _, err = ns.Reverse(43) c.Assert(err, qt.Not(qt.IsNil)) } func TestEchoParam(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { a interface{} key interface{} expect interface{} }{ {[]int{1, 2, 3}, 1, int64(2)}, {[]uint{1, 2, 3}, 1, uint64(2)}, {[]float64{1.1, 2.2, 3.3}, 1, float64(2.2)}, {[]string{"foo", "bar", "baz"}, 1, "bar"}, {[]TstX{{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}}, 1, ""}, {map[string]int{"foo": 1, "bar": 2, "baz": 3}, "bar", int64(2)}, {map[string]uint{"foo": 1, "bar": 2, "baz": 3}, "bar", uint64(2)}, {map[string]float64{"foo": 1.1, "bar": 2.2, "baz": 3.3}, "bar", float64(2.2)}, {map[string]string{"foo": "FOO", "bar": "BAR", "baz": "BAZ"}, "bar", "BAR"}, {map[string]TstX{"foo": {A: "a", B: "b"}, "bar": {A: "c", B: "d"}, "baz": {A: "e", B: "f"}}, "bar", ""}, {map[string]interface{}{"foo": nil}, "foo", ""}, {(*[]string)(nil), "bar", ""}, } { errMsg := qt.Commentf("[%d] %v", i, test) result := ns.EchoParam(test.a, test.key) c.Assert(result, qt.Equals, test.expect, errMsg) } } func TestFirst(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { limit interface{} seq interface{} expect interface{} }{ {int(2), []string{"a", "b", "c"}, []string{"a", "b"}}, {int32(3), []string{"a", "b"}, []string{"a", "b"}}, {int64(2), []int{100, 200, 300}, []int{100, 200}}, {100, []int{100, 200}, []int{100, 200}}, {"1", []int{100, 200, 300}, []int{100}}, {0, []string{"h", "u", "g", "o"}, []string{}}, {int64(-1), []int{100, 200, 300}, false}, {"noint", []int{100, 200, 300}, false}, {1, nil, false}, {nil, []int{100}, false}, {1, t, false}, {1, (*string)(nil), false}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.First(test.limit, test.seq) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil) c.Assert(result, qt.DeepEquals, test.expect, errMsg) } } func TestIn(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { l1 interface{} l2 interface{} expect bool }{ {[]string{"a", "b", "c"}, "b", true}, {[]interface{}{"a", "b", "c"}, "b", true}, {[]interface{}{"a", "b", "c"}, "d", false}, {[]string{"a", "b", "c"}, "d", false}, {[]string{"a", "12", "c"}, 12, false}, {[]string{"a", "b", "c"}, nil, false}, {[]int{1, 2, 4}, 2, true}, {[]interface{}{1, 2, 4}, 2, true}, {[]interface{}{1, 2, 4}, nil, false}, {[]interface{}{nil}, nil, false}, {[]int{1, 2, 4}, 3, false}, {[]float64{1.23, 2.45, 4.67}, 1.23, true}, {[]float64{1.234567, 2.45, 4.67}, 1.234568, false}, {[]float64{1, 2, 3}, 1, true}, {[]float32{1, 2, 3}, 1, true}, {"this substring should be found", "substring", true}, {"this substring should not be found", "subseastring", false}, {nil, "foo", false}, // Pointers {pagesPtr{p1, p2, p3, p2}, p2, true}, {pagesPtr{p1, p2, p3, p2}, p4, false}, // Structs {pagesVals{p3v, p2v, p3v, p2v}, p2v, true}, {pagesVals{p3v, p2v, p3v, p2v}, p4v, false}, // template.HTML {template.HTML("this substring should be found"), "substring", true}, {template.HTML("this substring should not be found"), "subseastring", false}, // Uncomparable, use hashstructure {[]string{"a", "b"}, []string{"a", "b"}, false}, {[][]string{{"a", "b"}}, []string{"a", "b"}, true}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.In(test.l1, test.l2) c.Assert(err, qt.IsNil) c.Assert(result, qt.Equals, test.expect, errMsg) } } type testPage struct { Title string } func (p testPage) String() string { return "p-" + p.Title } type ( pagesPtr []*testPage pagesVals []testPage ) var ( p1 = &testPage{"A"} p2 = &testPage{"B"} p3 = &testPage{"C"} p4 = &testPage{"D"} p1v = testPage{"A"} p2v = testPage{"B"} p3v = testPage{"C"} p4v = testPage{"D"} ) func TestIntersect(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { l1, l2 interface{} expect interface{} }{ {[]string{"a", "b", "c", "c"}, []string{"a", "b", "b"}, []string{"a", "b"}}, {[]string{"a", "b"}, []string{"a", "b", "c"}, []string{"a", "b"}}, {[]string{"a", "b", "c"}, []string{"d", "e"}, []string{}}, {[]string{}, []string{}, []string{}}, {[]string{"a", "b"}, nil, []interface{}{}}, {nil, []string{"a", "b"}, []interface{}{}}, {nil, nil, []interface{}{}}, {[]string{"1", "2"}, []int{1, 2}, []string{}}, {[]int{1, 2}, []string{"1", "2"}, []int{}}, {[]int{1, 2, 4}, []int{2, 4}, []int{2, 4}}, {[]int{2, 4}, []int{1, 2, 4}, []int{2, 4}}, {[]int{1, 2, 4}, []int{3, 6}, []int{}}, {[]float64{2.2, 4.4}, []float64{1.1, 2.2, 4.4}, []float64{2.2, 4.4}}, // []interface{} ∩ []interface{} {[]interface{}{"a", "b", "c"}, []interface{}{"a", "b", "b"}, []interface{}{"a", "b"}}, {[]interface{}{1, 2, 3}, []interface{}{1, 2, 2}, []interface{}{1, 2}}, {[]interface{}{int8(1), int8(2), int8(3)}, []interface{}{int8(1), int8(2), int8(2)}, []interface{}{int8(1), int8(2)}}, {[]interface{}{int16(1), int16(2), int16(3)}, []interface{}{int16(1), int16(2), int16(2)}, []interface{}{int16(1), int16(2)}}, {[]interface{}{int32(1), int32(2), int32(3)}, []interface{}{int32(1), int32(2), int32(2)}, []interface{}{int32(1), int32(2)}}, {[]interface{}{int64(1), int64(2), int64(3)}, []interface{}{int64(1), int64(2), int64(2)}, []interface{}{int64(1), int64(2)}}, {[]interface{}{float32(1), float32(2), float32(3)}, []interface{}{float32(1), float32(2), float32(2)}, []interface{}{float32(1), float32(2)}}, {[]interface{}{float64(1), float64(2), float64(3)}, []interface{}{float64(1), float64(2), float64(2)}, []interface{}{float64(1), float64(2)}}, // []interface{} ∩ []T {[]interface{}{"a", "b", "c"}, []string{"a", "b", "b"}, []interface{}{"a", "b"}}, {[]interface{}{1, 2, 3}, []int{1, 2, 2}, []interface{}{1, 2}}, {[]interface{}{int8(1), int8(2), int8(3)}, []int8{1, 2, 2}, []interface{}{int8(1), int8(2)}}, {[]interface{}{int16(1), int16(2), int16(3)}, []int16{1, 2, 2}, []interface{}{int16(1), int16(2)}}, {[]interface{}{int32(1), int32(2), int32(3)}, []int32{1, 2, 2}, []interface{}{int32(1), int32(2)}}, {[]interface{}{int64(1), int64(2), int64(3)}, []int64{1, 2, 2}, []interface{}{int64(1), int64(2)}}, {[]interface{}{uint(1), uint(2), uint(3)}, []uint{1, 2, 2}, []interface{}{uint(1), uint(2)}}, {[]interface{}{float32(1), float32(2), float32(3)}, []float32{1, 2, 2}, []interface{}{float32(1), float32(2)}}, {[]interface{}{float64(1), float64(2), float64(3)}, []float64{1, 2, 2}, []interface{}{float64(1), float64(2)}}, // []T ∩ []interface{} {[]string{"a", "b", "c"}, []interface{}{"a", "b", "b"}, []string{"a", "b"}}, {[]int{1, 2, 3}, []interface{}{1, 2, 2}, []int{1, 2}}, {[]int8{1, 2, 3}, []interface{}{int8(1), int8(2), int8(2)}, []int8{1, 2}}, {[]int16{1, 2, 3}, []interface{}{int16(1), int16(2), int16(2)}, []int16{1, 2}}, {[]int32{1, 2, 3}, []interface{}{int32(1), int32(2), int32(2)}, []int32{1, 2}}, {[]int64{1, 2, 3}, []interface{}{int64(1), int64(2), int64(2)}, []int64{1, 2}}, {[]float32{1, 2, 3}, []interface{}{float32(1), float32(2), float32(2)}, []float32{1, 2}}, {[]float64{1, 2, 3}, []interface{}{float64(1), float64(2), float64(2)}, []float64{1, 2}}, // Structs {pagesPtr{p1, p4, p2, p3}, pagesPtr{p4, p2, p2}, pagesPtr{p4, p2}}, {pagesVals{p1v, p4v, p2v, p3v}, pagesVals{p1v, p3v, p3v}, pagesVals{p1v, p3v}}, {[]interface{}{p1, p4, p2, p3}, []interface{}{p4, p2, p2}, []interface{}{p4, p2}}, {[]interface{}{p1v, p4v, p2v, p3v}, []interface{}{p1v, p3v, p3v}, []interface{}{p1v, p3v}}, {pagesPtr{p1, p4, p2, p3}, pagesPtr{}, pagesPtr{}}, {pagesVals{}, pagesVals{p1v, p3v, p3v}, pagesVals{}}, {[]interface{}{p1, p4, p2, p3}, []interface{}{}, []interface{}{}}, {[]interface{}{}, []interface{}{p1v, p3v, p3v}, []interface{}{}}, // errors {"not array or slice", []string{"a"}, false}, {[]string{"a"}, "not array or slice", false}, // uncomparable types - #3820 {[]map[int]int{{1: 1}, {2: 2}}, []map[int]int{{2: 2}, {3: 3}}, false}, {[][]int{{1, 1}, {1, 2}}, [][]int{{1, 2}, {1, 2}, {1, 3}}, false}, {[]int{1, 1}, [][]int{{1, 2}, {1, 2}, {1, 3}}, false}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.Intersect(test.l1, test.l2) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) if !reflect.DeepEqual(result, test.expect) { t.Fatalf("[%d] Got\n%v expected\n%v", i, result, test.expect) } } } func TestIsSet(t *testing.T) { t.Parallel() c := qt.New(t) ns := newTestNs() for i, test := range []struct { a interface{} key interface{} expect bool isErr bool }{ {[]interface{}{1, 2, 3, 5}, 2, true, false}, {[]interface{}{1, 2, 3, 5}, "2", true, false}, {[]interface{}{1, 2, 3, 5}, 2.0, true, false}, {[]interface{}{1, 2, 3, 5}, 22, false, false}, {map[string]interface{}{"a": 1, "b": 2}, "b", true, false}, {map[string]interface{}{"a": 1, "b": 2}, "bc", false, false}, {time.Now(), "Day", false, false}, {nil, "nil", false, false}, {[]interface{}{1, 2, 3, 5}, TstX{}, false, true}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.IsSet(test.a, test.key) if test.isErr { continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } func TestLast(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { limit interface{} seq interface{} expect interface{} }{ {int(2), []string{"a", "b", "c"}, []string{"b", "c"}}, {int32(3), []string{"a", "b"}, []string{"a", "b"}}, {int64(2), []int{100, 200, 300}, []int{200, 300}}, {100, []int{100, 200}, []int{100, 200}}, {"1", []int{100, 200, 300}, []int{300}}, {"0", []int{100, 200, 300}, []int{}}, {"0", []string{"a", "b", "c"}, []string{}}, // errors {int64(-1), []int{100, 200, 300}, false}, {"noint", []int{100, 200, 300}, false}, {1, nil, false}, {nil, []int{100}, false}, {1, t, false}, {1, (*string)(nil), false}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.Last(test.limit, test.seq) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.DeepEquals, test.expect, errMsg) } } func TestQuerify(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { params []interface{} expect interface{} }{ {[]interface{}{"a", "b"}, "a=b"}, {[]interface{}{"a", "b", "c", "d", "f", " &"}, `a=b&c=d&f=+%26`}, {[]interface{}{[]string{"a", "b"}}, "a=b"}, {[]interface{}{[]string{"a", "b", "c", "d", "f", " &"}}, `a=b&c=d&f=+%26`}, {[]interface{}{[]interface{}{"x", "y"}}, `x=y`}, {[]interface{}{[]interface{}{"x", 5}}, `x=5`}, // errors {[]interface{}{5, "b"}, false}, {[]interface{}{"a", "b", "c"}, false}, {[]interface{}{[]string{"a", "b", "c"}}, false}, {[]interface{}{[]string{"a", "b"}, "c"}, false}, {[]interface{}{[]interface{}{"c", "d", "e"}}, false}, } { errMsg := qt.Commentf("[%d] %v", i, test.params) result, err := ns.Querify(test.params...) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } func BenchmarkQuerify(b *testing.B) { ns := New(&deps.Deps{}) params := []interface{}{"a", "b", "c", "d", "f", " &"} b.ResetTimer() for i := 0; i < b.N; i++ { _, err := ns.Querify(params...) if err != nil { b.Fatal(err) } } } func BenchmarkQuerifySlice(b *testing.B) { ns := New(&deps.Deps{}) params := []string{"a", "b", "c", "d", "f", " &"} b.ResetTimer() for i := 0; i < b.N; i++ { _, err := ns.Querify(params) if err != nil { b.Fatal(err) } } } func TestSeq(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { args []interface{} expect interface{} }{ {[]interface{}{-2, 5}, []int{-2, -1, 0, 1, 2, 3, 4, 5}}, {[]interface{}{1, 2, 4}, []int{1, 3}}, {[]interface{}{1}, []int{1}}, {[]interface{}{3}, []int{1, 2, 3}}, {[]interface{}{3.2}, []int{1, 2, 3}}, {[]interface{}{0}, []int{}}, {[]interface{}{-1}, []int{-1}}, {[]interface{}{-3}, []int{-1, -2, -3}}, {[]interface{}{3, -2}, []int{3, 2, 1, 0, -1, -2}}, {[]interface{}{6, -2, 2}, []int{6, 4, 2}}, // errors {[]interface{}{1, 0, 2}, false}, {[]interface{}{1, -1, 2}, false}, {[]interface{}{2, 1, 1}, false}, {[]interface{}{2, 1, 1, 1}, false}, {[]interface{}{2001}, false}, {[]interface{}{}, false}, {[]interface{}{0, -1000000}, false}, {[]interface{}{tstNoStringer{}}, false}, {nil, false}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.Seq(test.args...) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.DeepEquals, test.expect, errMsg) } } func TestShuffle(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { seq interface{} success bool }{ {[]string{"a", "b", "c", "d"}, true}, {[]int{100, 200, 300}, true}, {[]int{100, 200, 300}, true}, {[]int{100, 200}, true}, {[]string{"a", "b"}, true}, {[]int{100, 200, 300}, true}, {[]int{100, 200, 300}, true}, {[]int{100}, true}, // errors {nil, false}, {t, false}, {(*string)(nil), false}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.Shuffle(test.seq) if !test.success { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) resultv := reflect.ValueOf(result) seqv := reflect.ValueOf(test.seq) c.Assert(seqv.Len(), qt.Equals, resultv.Len(), errMsg) } } func TestShuffleRandomising(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) // Note that this test can fail with false negative result if the shuffle // of the sequence happens to be the same as the original sequence. However // the probability of the event is 10^-158 which is negligible. seqLen := 100 rand.Seed(time.Now().UTC().UnixNano()) for _, test := range []struct { seq []int }{ {rand.Perm(seqLen)}, } { result, err := ns.Shuffle(test.seq) resultv := reflect.ValueOf(result) c.Assert(err, qt.IsNil) allSame := true for i, v := range test.seq { allSame = allSame && (resultv.Index(i).Interface() == v) } c.Assert(allSame, qt.Equals, false) } } // Also see tests in commons/collection. func TestSlice(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { args []interface{} expected interface{} }{ {[]interface{}{"a", "b"}, []string{"a", "b"}}, {[]interface{}{}, []interface{}{}}, {[]interface{}{nil}, []interface{}{nil}}, {[]interface{}{5, "b"}, []interface{}{5, "b"}}, {[]interface{}{tstNoStringer{}}, []tstNoStringer{{}}}, } { errMsg := qt.Commentf("[%d] %v", i, test.args) result := ns.Slice(test.args...) c.Assert(result, qt.DeepEquals, test.expected, errMsg) } } func TestUnion(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { l1 interface{} l2 interface{} expect interface{} isErr bool }{ {nil, nil, []interface{}{}, false}, {nil, []string{"a", "b"}, []string{"a", "b"}, false}, {[]string{"a", "b"}, nil, []string{"a", "b"}, false}, // []A ∪ []B {[]string{"1", "2"}, []int{3}, []string{}, false}, {[]int{1, 2}, []string{"1", "2"}, []int{}, false}, // []T ∪ []T {[]string{"a", "b", "c", "c"}, []string{"a", "b", "b"}, []string{"a", "b", "c"}, false}, {[]string{"a", "b"}, []string{"a", "b", "c"}, []string{"a", "b", "c"}, false}, {[]string{"a", "b", "c"}, []string{"d", "e"}, []string{"a", "b", "c", "d", "e"}, false}, {[]string{}, []string{}, []string{}, false}, {[]int{1, 2, 3}, []int{3, 4, 5}, []int{1, 2, 3, 4, 5}, false}, {[]int{1, 2, 3}, []int{1, 2, 3}, []int{1, 2, 3}, false}, {[]int{1, 2, 4}, []int{2, 4}, []int{1, 2, 4}, false}, {[]int{2, 4}, []int{1, 2, 4}, []int{2, 4, 1}, false}, {[]int{1, 2, 4}, []int{3, 6}, []int{1, 2, 4, 3, 6}, false}, {[]float64{2.2, 4.4}, []float64{1.1, 2.2, 4.4}, []float64{2.2, 4.4, 1.1}, false}, {[]interface{}{"a", "b", "c", "c"}, []interface{}{"a", "b", "b"}, []interface{}{"a", "b", "c"}, false}, // []T ∪ []interface{} {[]string{"1", "2"}, []interface{}{"9"}, []string{"1", "2", "9"}, false}, {[]int{2, 4}, []interface{}{1, 2, 4}, []int{2, 4, 1}, false}, {[]int8{2, 4}, []interface{}{int8(1), int8(2), int8(4)}, []int8{2, 4, 1}, false}, {[]int8{2, 4}, []interface{}{1, 2, 4}, []int8{2, 4, 1}, false}, {[]int16{2, 4}, []interface{}{1, 2, 4}, []int16{2, 4, 1}, false}, {[]int32{2, 4}, []interface{}{1, 2, 4}, []int32{2, 4, 1}, false}, {[]int64{2, 4}, []interface{}{1, 2, 4}, []int64{2, 4, 1}, false}, {[]float64{2.2, 4.4}, []interface{}{1.1, 2.2, 4.4}, []float64{2.2, 4.4, 1.1}, false}, {[]float32{2.2, 4.4}, []interface{}{1.1, 2.2, 4.4}, []float32{2.2, 4.4, 1.1}, false}, // []interface{} ∪ []T {[]interface{}{"a", "b", "c", "c"}, []string{"a", "b", "d"}, []interface{}{"a", "b", "c", "d"}, false}, {[]interface{}{}, []string{}, []interface{}{}, false}, {[]interface{}{1, 2}, []int{2, 3}, []interface{}{1, 2, 3}, false}, {[]interface{}{1, 2}, []int8{2, 3}, []interface{}{1, 2, 3}, false}, // 28 {[]interface{}{uint(1), uint(2)}, []uint{2, 3}, []interface{}{uint(1), uint(2), uint(3)}, false}, {[]interface{}{1.1, 2.2}, []float64{2.2, 3.3}, []interface{}{1.1, 2.2, 3.3}, false}, // Structs {pagesPtr{p1, p4}, pagesPtr{p4, p2, p2}, pagesPtr{p1, p4, p2}, false}, {pagesVals{p1v}, pagesVals{p3v, p3v}, pagesVals{p1v, p3v}, false}, {[]interface{}{p1, p4}, []interface{}{p4, p2, p2}, []interface{}{p1, p4, p2}, false}, {[]interface{}{p1v}, []interface{}{p3v, p3v}, []interface{}{p1v, p3v}, false}, // #3686 {[]interface{}{p1v}, []interface{}{}, []interface{}{p1v}, false}, {[]interface{}{}, []interface{}{p1v}, []interface{}{p1v}, false}, {pagesPtr{p1}, pagesPtr{}, pagesPtr{p1}, false}, {pagesVals{p1v}, pagesVals{}, pagesVals{p1v}, false}, {pagesPtr{}, pagesPtr{p1}, pagesPtr{p1}, false}, {pagesVals{}, pagesVals{p1v}, pagesVals{p1v}, false}, // errors {"not array or slice", []string{"a"}, false, true}, {[]string{"a"}, "not array or slice", false, true}, // uncomparable types - #3820 {[]map[string]int{{"K1": 1}}, []map[string]int{{"K2": 2}, {"K2": 2}}, false, true}, {[][]int{{1, 1}, {1, 2}}, [][]int{{2, 1}, {2, 2}}, false, true}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.Union(test.l1, test.l2) if test.isErr { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) if !reflect.DeepEqual(result, test.expect) { t.Fatalf("[%d] Got\n%v expected\n%v", i, result, test.expect) } } } func TestUniq(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { l interface{} expect interface{} isErr bool }{ {[]string{"a", "b", "c"}, []string{"a", "b", "c"}, false}, {[]string{"a", "b", "c", "c"}, []string{"a", "b", "c"}, false}, {[]string{"a", "b", "b", "c"}, []string{"a", "b", "c"}, false}, {[]string{"a", "b", "c", "b"}, []string{"a", "b", "c"}, false}, {[]int{1, 2, 3}, []int{1, 2, 3}, false}, {[]int{1, 2, 3, 3}, []int{1, 2, 3}, false}, {[]int{1, 2, 2, 3}, []int{1, 2, 3}, false}, {[]int{1, 2, 3, 2}, []int{1, 2, 3}, false}, {[4]int{1, 2, 3, 2}, []int{1, 2, 3}, false}, {nil, make([]interface{}, 0), false}, // Pointers {pagesPtr{p1, p2, p3, p2}, pagesPtr{p1, p2, p3}, false}, {pagesPtr{}, pagesPtr{}, false}, // Structs {pagesVals{p3v, p2v, p3v, p2v}, pagesVals{p3v, p2v}, false}, // not Comparable(), use hashstructure {[]map[string]int{ {"K1": 1}, {"K2": 2}, {"K1": 1}, {"K2": 1}, }, []map[string]int{ {"K1": 1}, {"K2": 2}, {"K2": 1}, }, false}, // should fail {1, 1, true}, {"foo", "fo", true}, } { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.Uniq(test.l) if test.isErr { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.DeepEquals, test.expect, errMsg) } } func (x *TstX) TstRp() string { return "r" + x.A } func (x TstX) TstRv() string { return "r" + x.B } func (x TstX) TstRv2() string { return "r" + x.B } func (x TstX) unexportedMethod() string { return x.unexported } func (x TstX) MethodWithArg(s string) string { return s } func (x TstX) MethodReturnNothing() {} func (x TstX) MethodReturnErrorOnly() error { return errors.New("some error occurred") } func (x TstX) MethodReturnTwoValues() (string, string) { return "foo", "bar" } func (x TstX) MethodReturnValueWithError() (string, error) { return "", errors.New("some error occurred") } func (x TstX) String() string { return fmt.Sprintf("A: %s, B: %s", x.A, x.B) } type TstX struct { A, B string unexported string } type TstParams struct { params maps.Params } func (x TstParams) Params() maps.Params { return x.params } type TstXIHolder struct { XI TstXI } // Partially implemented by the TstX struct. type TstXI interface { TstRv2() string } func ToTstXIs(slice interface{}) []TstXI { s := reflect.ValueOf(slice) if s.Kind() != reflect.Slice { return nil } tis := make([]TstXI, s.Len()) for i := 0; i < s.Len(); i++ { tsti, ok := s.Index(i).Interface().(TstXI) if !ok { return nil } tis[i] = tsti } return tis } func newDeps(cfg config.Provider) *deps.Deps { l := langs.NewLanguage("en", cfg) l.Set("i18nDir", "i18n") cs, err := helpers.NewContentSpec(l, loggers.NewErrorLogger(), afero.NewMemMapFs(), nil) if err != nil { panic(err) } return &deps.Deps{ Cfg: cfg, Fs: hugofs.NewMem(l), ContentSpec: cs, Log: loggers.NewErrorLogger(), } } func newTestNs() *Namespace { v := config.New() v.Set("contentDir", "content") return New(newDeps(v)) } hugo-0.92.2/tpl/collections/complement.go000066400000000000000000000032331420147000300203450ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "errors" "fmt" "reflect" ) // Complement gives the elements in the last element of seqs that are not in // any of the others. // All elements of seqs must be slices or arrays of comparable types. // // The reasoning behind this rather clumsy API is so we can do this in the templates: // {{ $c := .Pages | complement $last4 }} func (ns *Namespace) Complement(seqs ...interface{}) (interface{}, error) { if len(seqs) < 2 { return nil, errors.New("complement needs at least two arguments") } universe := seqs[len(seqs)-1] as := seqs[:len(seqs)-1] aset, err := collectIdentities(as...) if err != nil { return nil, err } v := reflect.ValueOf(universe) switch v.Kind() { case reflect.Array, reflect.Slice: sl := reflect.MakeSlice(v.Type(), 0, 0) for i := 0; i < v.Len(); i++ { ev, _ := indirectInterface(v.Index(i)) if _, found := aset[normalize(ev)]; !found { sl = reflect.Append(sl, ev) } } return sl.Interface(), nil default: return nil, fmt.Errorf("arguments to complement must be slices or arrays") } } hugo-0.92.2/tpl/collections/complement_test.go000066400000000000000000000056441420147000300214140ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "reflect" "testing" "github.com/gohugoio/hugo/deps" qt "github.com/frankban/quicktest" ) type StructWithSlice struct { A string B []string } type StructWithSlicePointers []*StructWithSlice func TestComplement(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) s1 := []TstX{{A: "a"}, {A: "b"}, {A: "d"}, {A: "e"}} s2 := []TstX{{A: "b"}, {A: "e"}} xa, xb, xd, xe := &StructWithSlice{A: "a"}, &StructWithSlice{A: "b"}, &StructWithSlice{A: "d"}, &StructWithSlice{A: "e"} sp1 := []*StructWithSlice{xa, xb, xd, xe} sp2 := []*StructWithSlice{xb, xe} sp1_2 := StructWithSlicePointers{xa, xb, xd, xe} sp2_2 := StructWithSlicePointers{xb, xe} for i, test := range []struct { s interface{} t []interface{} expected interface{} }{ {[]string{"a", "b", "c"}, []interface{}{[]string{"c", "d"}}, []string{"a", "b"}}, {[]string{"a", "b", "c"}, []interface{}{[]string{"c", "d"}, []string{"a", "b"}}, []string{}}, {[]interface{}{"a", "b", nil}, []interface{}{[]string{"a", "d"}}, []interface{}{"b", nil}}, {[]int{1, 2, 3, 4, 5}, []interface{}{[]int{1, 3}, []string{"a", "b"}, []int{1, 2}}, []int{4, 5}}, {[]int{1, 2, 3, 4, 5}, []interface{}{[]int64{1, 3}}, []int{2, 4, 5}}, {s1, []interface{}{s2}, []TstX{{A: "a"}, {A: "d"}}}, {sp1, []interface{}{sp2}, []*StructWithSlice{xa, xd}}, {sp1_2, []interface{}{sp2_2}, StructWithSlicePointers{xa, xd}}, // Errors {[]string{"a", "b", "c"}, []interface{}{"error"}, false}, {"error", []interface{}{[]string{"c", "d"}, []string{"a", "b"}}, false}, {[]string{"a", "b", "c"}, []interface{}{[][]string{{"c", "d"}}}, false}, { []interface{}{[][]string{{"c", "d"}}}, []interface{}{[]string{"c", "d"}, []string{"a", "b"}}, []interface{}{[][]string{{"c", "d"}}}, }, } { errMsg := qt.Commentf("[%d]", i) args := append(test.t, test.s) result, err := ns.Complement(args...) if b, ok := test.expected.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) if !reflect.DeepEqual(test.expected, result) { t.Fatalf("%s got\n%T: %v\nexpected\n%T: %v", errMsg, result, result, test.expected, test.expected) } } _, err := ns.Complement() c.Assert(err, qt.Not(qt.IsNil)) _, err = ns.Complement([]string{"a", "b"}) c.Assert(err, qt.Not(qt.IsNil)) } hugo-0.92.2/tpl/collections/index.go000066400000000000000000000075241420147000300173200ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "errors" "fmt" "reflect" "github.com/spf13/cast" "github.com/gohugoio/hugo/common/maps" ) // Index returns the result of indexing its first argument by the following // arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each // indexed item must be a map, slice, or array. // // Copied from Go stdlib src/text/template/funcs.go. // // We deviate from the stdlib due to https://github.com/golang/go/issues/14751. // // TODO(moorereason): merge upstream changes. func (ns *Namespace) Index(item interface{}, args ...interface{}) (interface{}, error) { v := reflect.ValueOf(item) if !v.IsValid() { return nil, errors.New("index of untyped nil") } lowerm, ok := item.(maps.Params) if ok { return lowerm.Get(cast.ToStringSlice(args)...), nil } var indices []interface{} if len(args) == 1 { v := reflect.ValueOf(args[0]) if v.Kind() == reflect.Slice { for i := 0; i < v.Len(); i++ { indices = append(indices, v.Index(i).Interface()) } } } if indices == nil { indices = args } for _, i := range indices { index := reflect.ValueOf(i) var isNil bool if v, isNil = indirect(v); isNil { return nil, errors.New("index of nil pointer") } switch v.Kind() { case reflect.Array, reflect.Slice, reflect.String: var x int64 switch index.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: x = index.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: x = int64(index.Uint()) case reflect.Invalid: return nil, errors.New("cannot index slice/array with nil") default: return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type()) } if x < 0 || x >= int64(v.Len()) { // We deviate from stdlib here. Don't return an error if the // index is out of range. return nil, nil } v = v.Index(int(x)) case reflect.Map: index, err := prepareArg(index, v.Type().Key()) if err != nil { return nil, err } if x := v.MapIndex(index); x.IsValid() { v = x } else { v = reflect.Zero(v.Type().Elem()) } case reflect.Invalid: // the loop holds invariant: v.IsValid() panic("unreachable") default: return nil, fmt.Errorf("can't index item of type %s", v.Type()) } } return v.Interface(), nil } // prepareArg checks if value can be used as an argument of type argType, and // converts an invalid value to appropriate zero if possible. // // Copied from Go stdlib src/text/template/funcs.go. func prepareArg(value reflect.Value, argType reflect.Type) (reflect.Value, error) { if !value.IsValid() { if !canBeNil(argType) { return reflect.Value{}, fmt.Errorf("value is nil; should be of type %s", argType) } value = reflect.Zero(argType) } if !value.Type().AssignableTo(argType) { return reflect.Value{}, fmt.Errorf("value has type %s; should be %s", value.Type(), argType) } return value, nil } // canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero. // // Copied from Go stdlib src/text/template/exec.go. func canBeNil(typ reflect.Type) bool { switch typ.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: return true } return false } hugo-0.92.2/tpl/collections/index_test.go000066400000000000000000000045041420147000300203520ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "fmt" "testing" "github.com/gohugoio/hugo/common/maps" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" ) func TestIndex(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) for i, test := range []struct { item interface{} indices []interface{} expect interface{} isErr bool }{ {[]int{0, 1}, []interface{}{0}, 0, false}, {[]int{0, 1}, []interface{}{9}, nil, false}, // index out of range {[]uint{0, 1}, nil, []uint{0, 1}, false}, {[][]int{{1, 2}, {3, 4}}, []interface{}{0, 0}, 1, false}, {map[int]int{1: 10, 2: 20}, []interface{}{1}, 10, false}, {map[int]int{1: 10, 2: 20}, []interface{}{0}, 0, false}, {map[string]map[string]string{"a": {"b": "c"}}, []interface{}{"a", "b"}, "c", false}, {[]map[string]map[string]string{{"a": {"b": "c"}}}, []interface{}{0, "a", "b"}, "c", false}, {map[string]map[string]interface{}{"a": {"b": []string{"c", "d"}}}, []interface{}{"a", "b", 1}, "d", false}, {map[string]map[string]string{"a": {"b": "c"}}, []interface{}{[]string{"a", "b"}}, "c", false}, {maps.Params{"a": "av"}, []interface{}{"A"}, "av", false}, {maps.Params{"a": map[string]interface{}{"b": "bv"}}, []interface{}{"A", "B"}, "bv", false}, // errors {nil, nil, nil, true}, {[]int{0, 1}, []interface{}{"1"}, nil, true}, {[]int{0, 1}, []interface{}{nil}, nil, true}, {tstNoStringer{}, []interface{}{0}, nil, true}, } { c.Run(fmt.Sprint(i), func(c *qt.C) { errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.Index(test.item, test.indices...) if test.isErr { c.Assert(err, qt.Not(qt.IsNil), errMsg) return } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.DeepEquals, test.expect, errMsg) }) } } hugo-0.92.2/tpl/collections/init.go000066400000000000000000000115031420147000300171440ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "collections" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil }, } ns.AddMethodMapping(ctx.After, []string{"after"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Apply, []string{"apply"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Complement, []string{"complement"}, [][2]string{ {`{{ slice "a" "b" "c" "d" "e" "f" | complement (slice "b" "c") (slice "d" "e") }}`, `[a f]`}, }, ) ns.AddMethodMapping(ctx.SymDiff, []string{"symdiff"}, [][2]string{ {`{{ slice 1 2 3 | symdiff (slice 3 4) }}`, `[1 2 4]`}, }, ) ns.AddMethodMapping(ctx.Delimit, []string{"delimit"}, [][2]string{ {`{{ delimit (slice "A" "B" "C") ", " " and " }}`, `A, B and C`}, }, ) ns.AddMethodMapping(ctx.Dictionary, []string{"dict"}, [][2]string{}, ) ns.AddMethodMapping(ctx.EchoParam, []string{"echoParam"}, [][2]string{ {`{{ echoParam .Params "langCode" }}`, `en`}, }, ) ns.AddMethodMapping(ctx.First, []string{"first"}, [][2]string{}, ) ns.AddMethodMapping(ctx.KeyVals, []string{"keyVals"}, [][2]string{ {`{{ keyVals "key" "a" "b" }}`, `key: [a b]`}, }, ) ns.AddMethodMapping(ctx.In, []string{"in"}, [][2]string{ {`{{ if in "this string contains a substring" "substring" }}Substring found!{{ end }}`, `Substring found!`}, }, ) ns.AddMethodMapping(ctx.Index, []string{"index"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Intersect, []string{"intersect"}, [][2]string{}, ) ns.AddMethodMapping(ctx.IsSet, []string{"isSet", "isset"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Last, []string{"last"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Querify, []string{"querify"}, [][2]string{ { `{{ (querify "foo" 1 "bar" 2 "baz" "with spaces" "qux" "this&that=those") | safeHTML }}`, `bar=2&baz=with+spaces&foo=1&qux=this%26that%3Dthose`, }, { `Search`, `Search`, }, { `{{ slice "foo" 1 "bar" 2 | querify | safeHTML }}`, `bar=2&foo=1`, }, }, ) ns.AddMethodMapping(ctx.Shuffle, []string{"shuffle"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Slice, []string{"slice"}, [][2]string{ {`{{ slice "B" "C" "A" | sort }}`, `[A B C]`}, }, ) ns.AddMethodMapping(ctx.Sort, []string{"sort"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Union, []string{"union"}, [][2]string{ {`{{ union (slice 1 2 3) (slice 3 4 5) }}`, `[1 2 3 4 5]`}, }, ) ns.AddMethodMapping(ctx.Where, []string{"where"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Append, []string{"append"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Group, []string{"group"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Seq, []string{"seq"}, [][2]string{ {`{{ seq 3 }}`, `[1 2 3]`}, }, ) ns.AddMethodMapping(ctx.NewScratch, []string{"newScratch"}, [][2]string{ {`{{ $scratch := newScratch }}{{ $scratch.Add "b" 2 }}{{ $scratch.Add "b" 2 }}{{ $scratch.Get "b" }}`, `4`}, }, ) ns.AddMethodMapping(ctx.Uniq, []string{"uniq"}, [][2]string{ {`{{ slice 1 2 3 2 | uniq }}`, `[1 2 3]`}, }, ) ns.AddMethodMapping(ctx.Merge, []string{"merge"}, [][2]string{ { `{{ dict "title" "Hugo Rocks!" | collections.Merge (dict "title" "Default Title" "description" "Yes, Hugo Rocks!") | sort }}`, `[Yes, Hugo Rocks! Hugo Rocks!]`, }, { `{{ merge (dict "title" "Default Title" "description" "Yes, Hugo Rocks!") (dict "title" "Hugo Rocks!") | sort }}`, `[Yes, Hugo Rocks! Hugo Rocks!]`, }, { `{{ merge (dict "title" "Default Title" "description" "Yes, Hugo Rocks!") (dict "title" "Hugo Rocks!") (dict "extra" "For reals!") | sort }}`, `[Yes, Hugo Rocks! For reals! Hugo Rocks!]`, }, }, ) return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/collections/init_test.go000066400000000000000000000022421420147000300202030ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "testing" "github.com/gohugoio/hugo/htesting/hqt" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(&deps.Deps{}) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, &Namespace{}) } hugo-0.92.2/tpl/collections/merge.go000066400000000000000000000064401420147000300173040ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "reflect" "strings" "github.com/gohugoio/hugo/common/hreflect" "github.com/gohugoio/hugo/common/maps" "github.com/pkg/errors" ) // Merge creates a copy of the final parameter and merges the preceding // parameters into it in reverse order. // Currently only maps are supported. Key handling is case insensitive. func (ns *Namespace) Merge(params ...interface{}) (interface{}, error) { if len(params) < 2 { return nil, errors.New("merge requires at least two parameters") } var err error result := params[len(params)-1] for i := len(params) - 2; i >= 0; i-- { result, err = ns.merge(params[i], result) if err != nil { return nil, err } } return result, nil } // merge creates a copy of dst and merges src into it. func (ns *Namespace) merge(src, dst interface{}) (interface{}, error) { vdst, vsrc := reflect.ValueOf(dst), reflect.ValueOf(src) if vdst.Kind() != reflect.Map { return nil, errors.Errorf("destination must be a map, got %T", dst) } if !hreflect.IsTruthfulValue(vsrc) { return dst, nil } if vsrc.Kind() != reflect.Map { return nil, errors.Errorf("source must be a map, got %T", src) } if vsrc.Type().Key() != vdst.Type().Key() { return nil, errors.Errorf("incompatible map types, got %T to %T", src, dst) } return mergeMap(vdst, vsrc).Interface(), nil } func caseInsensitiveLookup(m, k reflect.Value) (reflect.Value, bool) { if m.Type().Key().Kind() != reflect.String || k.Kind() != reflect.String { // Fall back to direct lookup. v := m.MapIndex(k) return v, hreflect.IsTruthfulValue(v) } for _, key := range m.MapKeys() { if strings.EqualFold(k.String(), key.String()) { return m.MapIndex(key), true } } return reflect.Value{}, false } func mergeMap(dst, src reflect.Value) reflect.Value { out := reflect.MakeMap(dst.Type()) // If the destination is Params, we must lower case all keys. _, lowerCase := dst.Interface().(maps.Params) // Copy the destination map. for _, key := range dst.MapKeys() { v := dst.MapIndex(key) out.SetMapIndex(key, v) } // Add all keys in src not already in destination. // Maps of the same type will be merged. for _, key := range src.MapKeys() { sv := src.MapIndex(key) dv, found := caseInsensitiveLookup(dst, key) if found { // If both are the same map key type, merge. dve := dv.Elem() if dve.Kind() == reflect.Map { sve := sv.Elem() if sve.Kind() != reflect.Map { continue } if dve.Type().Key() == sve.Type().Key() { out.SetMapIndex(key, mergeMap(dve, sve)) } } } else { if lowerCase && key.Kind() == reflect.String { key = reflect.ValueOf(strings.ToLower(key.String())) } out.SetMapIndex(key, sv) } } return out } hugo-0.92.2/tpl/collections/merge_test.go000066400000000000000000000137361420147000300203510ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "bytes" "reflect" "testing" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/parser" "github.com/gohugoio/hugo/parser/metadecoders" qt "github.com/frankban/quicktest" ) func TestMerge(t *testing.T) { ns := New(&deps.Deps{}) simpleMap := map[string]interface{}{"a": 1, "b": 2} for i, test := range []struct { name string params []interface{} expect interface{} isErr bool }{ { "basic", []interface{}{ map[string]interface{}{"a": 42, "c": 3}, map[string]interface{}{"a": 1, "b": 2}, }, map[string]interface{}{"a": 1, "b": 2, "c": 3}, false, }, { "multi", []interface{}{ map[string]interface{}{"a": 42, "c": 3, "e": 11}, map[string]interface{}{"a": 1, "b": 2}, map[string]interface{}{"a": 9, "c": 4, "d": 7}, }, map[string]interface{}{"a": 9, "b": 2, "c": 4, "d": 7, "e": 11}, false, }, { "basic case insensitive", []interface{}{ map[string]interface{}{"A": 42, "c": 3}, map[string]interface{}{"a": 1, "b": 2}, }, map[string]interface{}{"a": 1, "b": 2, "c": 3}, false, }, { "nested", []interface{}{ map[string]interface{}{"a": 42, "c": 3, "b": map[string]interface{}{"d": 55, "e": 66, "f": 3}}, map[string]interface{}{"a": 1, "b": map[string]interface{}{"d": 1, "e": 2}}, }, map[string]interface{}{"a": 1, "b": map[string]interface{}{"d": 1, "e": 2, "f": 3}, "c": 3}, false, }, { // https://github.com/gohugoio/hugo/issues/6633 "params dst", []interface{}{ map[string]interface{}{"a": 42, "c": 3}, maps.Params{"a": 1, "b": 2}, }, maps.Params{"a": int(1), "b": int(2), "c": int(3)}, false, }, { "params dst, upper case src", []interface{}{ map[string]interface{}{"a": 42, "C": 3}, maps.Params{"a": 1, "b": 2}, }, maps.Params{"a": int(1), "b": int(2), "c": int(3)}, false, }, { "params src", []interface{}{ maps.Params{"a": 42, "c": 3}, map[string]interface{}{"a": 1, "c": 2}, }, map[string]interface{}{"a": int(1), "c": int(2)}, false, }, { "params src, upper case dst", []interface{}{ maps.Params{"a": 42, "c": 3}, map[string]interface{}{"a": 1, "C": 2}, }, map[string]interface{}{"a": int(1), "C": int(2)}, false, }, { "nested, params dst", []interface{}{ map[string]interface{}{"a": 42, "c": 3, "b": map[string]interface{}{"d": 55, "e": 66, "f": 3}}, maps.Params{"a": 1, "b": maps.Params{"d": 1, "e": 2}}, }, maps.Params{"a": 1, "b": maps.Params{"d": 1, "e": 2, "f": 3}, "c": 3}, false, }, { // https://github.com/gohugoio/hugo/issues/7899 "matching keys with non-map src value", []interface{}{ map[string]interface{}{"k": "v"}, map[string]interface{}{"k": map[string]interface{}{"k2": "v2"}}, }, map[string]interface{}{"k": map[string]interface{}{"k2": "v2"}}, false, }, {"src nil", []interface{}{nil, simpleMap}, simpleMap, false}, // Error cases. {"dst not a map", []interface{}{nil, "not a map"}, nil, true}, {"src not a map", []interface{}{"not a map", simpleMap}, nil, true}, {"different map types", []interface{}{map[int]interface{}{32: "a"}, simpleMap}, nil, true}, {"all nil", []interface{}{nil, nil}, nil, true}, } { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() errMsg := qt.Commentf("[%d] %v", i, test) c := qt.New(t) result, err := ns.Merge(test.params...) if test.isErr { c.Assert(err, qt.Not(qt.IsNil), errMsg) return } c.Assert(err, qt.IsNil) c.Assert(result, qt.DeepEquals, test.expect, errMsg) }) } } func TestMergeDataFormats(t *testing.T) { c := qt.New(t) ns := New(&deps.Deps{}) toml1 := ` V1 = "v1_1" [V2s] V21 = "v21_1" ` toml2 := ` V1 = "v1_2" V2 = "v2_2" [V2s] V21 = "v21_2" V22 = "v22_2" ` meta1, err := metadecoders.Default.UnmarshalToMap([]byte(toml1), metadecoders.TOML) c.Assert(err, qt.IsNil) meta2, err := metadecoders.Default.UnmarshalToMap([]byte(toml2), metadecoders.TOML) c.Assert(err, qt.IsNil) for _, format := range []metadecoders.Format{metadecoders.JSON, metadecoders.YAML, metadecoders.TOML} { var dataStr1, dataStr2 bytes.Buffer err = parser.InterfaceToConfig(meta1, format, &dataStr1) c.Assert(err, qt.IsNil) err = parser.InterfaceToConfig(meta2, format, &dataStr2) c.Assert(err, qt.IsNil) dst, err := metadecoders.Default.UnmarshalToMap(dataStr1.Bytes(), format) c.Assert(err, qt.IsNil) src, err := metadecoders.Default.UnmarshalToMap(dataStr2.Bytes(), format) c.Assert(err, qt.IsNil) merged, err := ns.Merge(src, dst) c.Assert(err, qt.IsNil) c.Assert( merged, qt.DeepEquals, map[string]interface{}{ "V1": "v1_1", "V2": "v2_2", "V2s": map[string]interface{}{"V21": "v21_1", "V22": "v22_2"}, }) } } func TestCaseInsensitiveMapLookup(t *testing.T) { c := qt.New(t) m1 := reflect.ValueOf(map[string]interface{}{ "a": 1, "B": 2, }) m2 := reflect.ValueOf(map[int]interface{}{ 1: 1, 2: 2, }) var found bool a, found := caseInsensitiveLookup(m1, reflect.ValueOf("A")) c.Assert(found, qt.Equals, true) c.Assert(a.Interface(), qt.Equals, 1) b, found := caseInsensitiveLookup(m1, reflect.ValueOf("b")) c.Assert(found, qt.Equals, true) c.Assert(b.Interface(), qt.Equals, 2) two, found := caseInsensitiveLookup(m2, reflect.ValueOf(2)) c.Assert(found, qt.Equals, true) c.Assert(two.Interface(), qt.Equals, 2) } hugo-0.92.2/tpl/collections/reflect_helpers.go000066400000000000000000000117731420147000300213600ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "fmt" "reflect" "time" "github.com/mitchellh/hashstructure" "github.com/pkg/errors" ) var ( zero reflect.Value errorType = reflect.TypeOf((*error)(nil)).Elem() timeType = reflect.TypeOf((*time.Time)(nil)).Elem() ) func numberToFloat(v reflect.Value) (float64, error) { switch kind := v.Kind(); { case isFloat(kind): return v.Float(), nil case isInt(kind): return float64(v.Int()), nil case isUint(kind): return float64(v.Uint()), nil case kind == reflect.Interface: return numberToFloat(v.Elem()) default: return 0, fmt.Errorf("invalid kind %s in numberToFloat", kind) } } // normalizes different numeric types if isNumber // or get the hash values if not Comparable (such as map or struct) // to make them comparable func normalize(v reflect.Value) interface{} { k := v.Kind() switch { case !v.Type().Comparable(): h, err := hashstructure.Hash(v.Interface(), nil) if err != nil { panic(err) } return h case isNumber(k): f, err := numberToFloat(v) if err == nil { return f } } return v.Interface() } // collects identities from the slices in seqs into a set. Numeric values are normalized, // pointers unwrapped. func collectIdentities(seqs ...interface{}) (map[interface{}]bool, error) { seen := make(map[interface{}]bool) for _, seq := range seqs { v := reflect.ValueOf(seq) switch v.Kind() { case reflect.Array, reflect.Slice: for i := 0; i < v.Len(); i++ { ev, _ := indirectInterface(v.Index(i)) if !ev.Type().Comparable() { return nil, errors.New("elements must be comparable") } seen[normalize(ev)] = true } default: return nil, fmt.Errorf("arguments must be slices or arrays") } } return seen, nil } // We have some different numeric and string types that we try to behave like // they were the same. func convertValue(v reflect.Value, to reflect.Type) (reflect.Value, error) { if v.Type().AssignableTo(to) { return v, nil } switch kind := to.Kind(); { case kind == reflect.String: s, err := toString(v) return reflect.ValueOf(s), err case isNumber(kind): return convertNumber(v, kind) default: return reflect.Value{}, errors.Errorf("%s is not assignable to %s", v.Type(), to) } } // There are potential overflows in this function, but the downconversion of // int64 etc. into int8 etc. is coming from the synthetic unit tests for Union etc. // TODO(bep) We should consider normalizing the slices to int64 etc. func convertNumber(v reflect.Value, to reflect.Kind) (reflect.Value, error) { var n reflect.Value if isFloat(to) { f, err := toFloat(v) if err != nil { return n, err } switch to { case reflect.Float32: n = reflect.ValueOf(float32(f)) default: n = reflect.ValueOf(float64(f)) } } else if isInt(to) { i, err := toInt(v) if err != nil { return n, err } switch to { case reflect.Int: n = reflect.ValueOf(int(i)) case reflect.Int8: n = reflect.ValueOf(int8(i)) case reflect.Int16: n = reflect.ValueOf(int16(i)) case reflect.Int32: n = reflect.ValueOf(int32(i)) case reflect.Int64: n = reflect.ValueOf(int64(i)) } } else if isUint(to) { i, err := toUint(v) if err != nil { return n, err } switch to { case reflect.Uint: n = reflect.ValueOf(uint(i)) case reflect.Uint8: n = reflect.ValueOf(uint8(i)) case reflect.Uint16: n = reflect.ValueOf(uint16(i)) case reflect.Uint32: n = reflect.ValueOf(uint32(i)) case reflect.Uint64: n = reflect.ValueOf(uint64(i)) } } if !n.IsValid() { return n, errors.New("invalid values") } return n, nil } func newSliceElement(items interface{}) interface{} { tp := reflect.TypeOf(items) if tp == nil { return nil } switch tp.Kind() { case reflect.Array, reflect.Slice: tp = tp.Elem() if tp.Kind() == reflect.Ptr { tp = tp.Elem() } return reflect.New(tp).Interface() } return nil } func isNumber(kind reflect.Kind) bool { return isInt(kind) || isUint(kind) || isFloat(kind) } func isInt(kind reflect.Kind) bool { switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return true default: return false } } func isUint(kind reflect.Kind) bool { switch kind { case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return true default: return false } } func isFloat(kind reflect.Kind) bool { switch kind { case reflect.Float32, reflect.Float64: return true default: return false } } hugo-0.92.2/tpl/collections/sort.go000066400000000000000000000111231420147000300171660ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "errors" "reflect" "sort" "strings" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/tpl/compare" "github.com/spf13/cast" ) var sortComp = compare.New(true) // Sort returns a sorted sequence. func (ns *Namespace) Sort(seq interface{}, args ...interface{}) (interface{}, error) { if seq == nil { return nil, errors.New("sequence must be provided") } seqv, isNil := indirect(reflect.ValueOf(seq)) if isNil { return nil, errors.New("can't iterate over a nil value") } var sliceType reflect.Type switch seqv.Kind() { case reflect.Array, reflect.Slice: sliceType = seqv.Type() case reflect.Map: sliceType = reflect.SliceOf(seqv.Type().Elem()) default: return nil, errors.New("can't sort " + reflect.ValueOf(seq).Type().String()) } // Create a list of pairs that will be used to do the sort p := pairList{SortAsc: true, SliceType: sliceType} p.Pairs = make([]pair, seqv.Len()) var sortByField string for i, l := range args { dStr, err := cast.ToStringE(l) switch { case i == 0 && err != nil: sortByField = "" case i == 0 && err == nil: sortByField = dStr case i == 1 && err == nil && dStr == "desc": p.SortAsc = false case i == 1: p.SortAsc = true } } path := strings.Split(strings.Trim(sortByField, "."), ".") switch seqv.Kind() { case reflect.Array, reflect.Slice: for i := 0; i < seqv.Len(); i++ { p.Pairs[i].Value = seqv.Index(i) if sortByField == "" || sortByField == "value" { p.Pairs[i].Key = p.Pairs[i].Value } else { v := p.Pairs[i].Value var err error for i, elemName := range path { v, err = evaluateSubElem(v, elemName) if err != nil { return nil, err } if !v.IsValid() { continue } // Special handling of lower cased maps. if params, ok := v.Interface().(maps.Params); ok { v = reflect.ValueOf(params.Get(path[i+1:]...)) break } } p.Pairs[i].Key = v } } case reflect.Map: keys := seqv.MapKeys() for i := 0; i < seqv.Len(); i++ { p.Pairs[i].Value = seqv.MapIndex(keys[i]) if sortByField == "" { p.Pairs[i].Key = keys[i] } else if sortByField == "value" { p.Pairs[i].Key = p.Pairs[i].Value } else { v := p.Pairs[i].Value var err error for i, elemName := range path { v, err = evaluateSubElem(v, elemName) if err != nil { return nil, err } if !v.IsValid() { continue } // Special handling of lower cased maps. if params, ok := v.Interface().(maps.Params); ok { v = reflect.ValueOf(params.Get(path[i+1:]...)) break } } p.Pairs[i].Key = v } } } return p.sort(), nil } // Credit for pair sorting method goes to Andrew Gerrand // https://groups.google.com/forum/#!topic/golang-nuts/FT7cjmcL7gw // A data structure to hold a key/value pair. type pair struct { Key reflect.Value Value reflect.Value } // A slice of pairs that implements sort.Interface to sort by Value. type pairList struct { Pairs []pair SortAsc bool SliceType reflect.Type } func (p pairList) Swap(i, j int) { p.Pairs[i], p.Pairs[j] = p.Pairs[j], p.Pairs[i] } func (p pairList) Len() int { return len(p.Pairs) } func (p pairList) Less(i, j int) bool { iv := p.Pairs[i].Key jv := p.Pairs[j].Key if iv.IsValid() { if jv.IsValid() { // can only call Interface() on valid reflect Values return sortComp.Lt(iv.Interface(), jv.Interface()) } // if j is invalid, test i against i's zero value return sortComp.Lt(iv.Interface(), reflect.Zero(iv.Type())) } if jv.IsValid() { // if i is invalid, test j against j's zero value return sortComp.Lt(reflect.Zero(jv.Type()), jv.Interface()) } return false } // sorts a pairList and returns a slice of sorted values func (p pairList) sort() interface{} { if p.SortAsc { sort.Sort(p) } else { sort.Sort(sort.Reverse(p)) } sorted := reflect.MakeSlice(p.SliceType, len(p.Pairs), len(p.Pairs)) for i, v := range p.Pairs { sorted.Index(i).Set(v.Value) } return sorted.Interface() } hugo-0.92.2/tpl/collections/sort_test.go000066400000000000000000000262641420147000300202410ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "fmt" "reflect" "testing" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/deps" ) type stringsSlice []string func TestSort(t *testing.T) { t.Parallel() ns := New(&deps.Deps{}) type ts struct { MyInt int MyFloat float64 MyString string } type mid struct { Tst TstX } for i, test := range []struct { seq interface{} sortByField interface{} sortAsc string expect interface{} }{ {[]string{"class1", "class2", "class3"}, nil, "asc", []string{"class1", "class2", "class3"}}, {[]string{"class3", "class1", "class2"}, nil, "asc", []string{"class1", "class2", "class3"}}, {[]string{"CLASS3", "class1", "class2"}, nil, "asc", []string{"class1", "class2", "CLASS3"}}, // Issue 6023 {stringsSlice{"class3", "class1", "class2"}, nil, "asc", stringsSlice{"class1", "class2", "class3"}}, {[]int{1, 2, 3, 4, 5}, nil, "asc", []int{1, 2, 3, 4, 5}}, {[]int{5, 4, 3, 1, 2}, nil, "asc", []int{1, 2, 3, 4, 5}}, // test sort key parameter is forcibly set empty {[]string{"class3", "class1", "class2"}, map[int]string{1: "a"}, "asc", []string{"class1", "class2", "class3"}}, // test map sorting by keys {map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, nil, "asc", []int{10, 20, 30, 40, 50}}, {map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, nil, "asc", []int{30, 20, 10, 40, 50}}, {map[string]string{"1": "10", "2": "20", "3": "30", "4": "40", "5": "50"}, nil, "asc", []string{"10", "20", "30", "40", "50"}}, {map[string]string{"3": "10", "2": "20", "1": "30", "4": "40", "5": "50"}, nil, "asc", []string{"30", "20", "10", "40", "50"}}, {map[string]string{"one": "10", "two": "20", "three": "30", "four": "40", "five": "50"}, nil, "asc", []string{"50", "40", "10", "30", "20"}}, {map[int]string{1: "10", 2: "20", 3: "30", 4: "40", 5: "50"}, nil, "asc", []string{"10", "20", "30", "40", "50"}}, {map[int]string{3: "10", 2: "20", 1: "30", 4: "40", 5: "50"}, nil, "asc", []string{"30", "20", "10", "40", "50"}}, {map[float64]string{3.3: "10", 2.3: "20", 1.3: "30", 4.3: "40", 5.3: "50"}, nil, "asc", []string{"30", "20", "10", "40", "50"}}, // test map sorting by value {map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, "value", "asc", []int{10, 20, 30, 40, 50}}, {map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, "value", "asc", []int{10, 20, 30, 40, 50}}, // test map sorting by field value { map[string]ts{"1": {10, 10.5, "ten"}, "2": {20, 20.5, "twenty"}, "3": {30, 30.5, "thirty"}, "4": {40, 40.5, "forty"}, "5": {50, 50.5, "fifty"}}, "MyInt", "asc", []ts{{10, 10.5, "ten"}, {20, 20.5, "twenty"}, {30, 30.5, "thirty"}, {40, 40.5, "forty"}, {50, 50.5, "fifty"}}, }, { map[string]ts{"1": {10, 10.5, "ten"}, "2": {20, 20.5, "twenty"}, "3": {30, 30.5, "thirty"}, "4": {40, 40.5, "forty"}, "5": {50, 50.5, "fifty"}}, "MyFloat", "asc", []ts{{10, 10.5, "ten"}, {20, 20.5, "twenty"}, {30, 30.5, "thirty"}, {40, 40.5, "forty"}, {50, 50.5, "fifty"}}, }, { map[string]ts{"1": {10, 10.5, "ten"}, "2": {20, 20.5, "twenty"}, "3": {30, 30.5, "thirty"}, "4": {40, 40.5, "forty"}, "5": {50, 50.5, "fifty"}}, "MyString", "asc", []ts{{50, 50.5, "fifty"}, {40, 40.5, "forty"}, {10, 10.5, "ten"}, {30, 30.5, "thirty"}, {20, 20.5, "twenty"}}, }, // test sort desc {[]string{"class1", "class2", "class3"}, "value", "desc", []string{"class3", "class2", "class1"}}, {[]string{"class3", "class1", "class2"}, "value", "desc", []string{"class3", "class2", "class1"}}, // test sort by struct's method { []TstX{{A: "i", B: "j"}, {A: "e", B: "f"}, {A: "c", B: "d"}, {A: "g", B: "h"}, {A: "a", B: "b"}}, "TstRv", "asc", []TstX{{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}, {A: "g", B: "h"}, {A: "i", B: "j"}}, }, { []*TstX{{A: "i", B: "j"}, {A: "e", B: "f"}, {A: "c", B: "d"}, {A: "g", B: "h"}, {A: "a", B: "b"}}, "TstRp", "asc", []*TstX{{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}, {A: "g", B: "h"}, {A: "i", B: "j"}}, }, // Lower case Params, slice { []TstParams{{params: maps.Params{"color": "indigo"}}, {params: maps.Params{"color": "blue"}}, {params: maps.Params{"color": "green"}}}, ".Params.COLOR", "asc", []TstParams{{params: maps.Params{"color": "blue"}}, {params: maps.Params{"color": "green"}}, {params: maps.Params{"color": "indigo"}}}, }, // Lower case Params, map { map[string]TstParams{"1": {params: maps.Params{"color": "indigo"}}, "2": {params: maps.Params{"color": "blue"}}, "3": {params: maps.Params{"color": "green"}}}, ".Params.CoLoR", "asc", []TstParams{{params: maps.Params{"color": "blue"}}, {params: maps.Params{"color": "green"}}, {params: maps.Params{"color": "indigo"}}}, }, // test map sorting by struct's method { map[string]TstX{"1": {A: "i", B: "j"}, "2": {A: "e", B: "f"}, "3": {A: "c", B: "d"}, "4": {A: "g", B: "h"}, "5": {A: "a", B: "b"}}, "TstRv", "asc", []TstX{{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}, {A: "g", B: "h"}, {A: "i", B: "j"}}, }, { map[string]*TstX{"1": {A: "i", B: "j"}, "2": {A: "e", B: "f"}, "3": {A: "c", B: "d"}, "4": {A: "g", B: "h"}, "5": {A: "a", B: "b"}}, "TstRp", "asc", []*TstX{{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}, {A: "g", B: "h"}, {A: "i", B: "j"}}, }, // test sort by dot chaining key argument { []map[string]TstX{{"foo": TstX{A: "e", B: "f"}}, {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}}, "foo.A", "asc", []map[string]TstX{{"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}}}, }, { []map[string]TstX{{"foo": TstX{A: "e", B: "f"}}, {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}}, ".foo.A", "asc", []map[string]TstX{{"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}}}, }, { []map[string]TstX{{"foo": TstX{A: "e", B: "f"}}, {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}}, "foo.TstRv", "asc", []map[string]TstX{{"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}}}, }, { []map[string]*TstX{{"foo": &TstX{A: "e", B: "f"}}, {"foo": &TstX{A: "a", B: "b"}}, {"foo": &TstX{A: "c", B: "d"}}}, "foo.TstRp", "asc", []map[string]*TstX{{"foo": &TstX{A: "a", B: "b"}}, {"foo": &TstX{A: "c", B: "d"}}, {"foo": &TstX{A: "e", B: "f"}}}, }, { []map[string]mid{{"foo": mid{Tst: TstX{A: "e", B: "f"}}}, {"foo": mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": mid{Tst: TstX{A: "c", B: "d"}}}}, "foo.Tst.A", "asc", []map[string]mid{{"foo": mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": mid{Tst: TstX{A: "e", B: "f"}}}}, }, { []map[string]mid{{"foo": mid{Tst: TstX{A: "e", B: "f"}}}, {"foo": mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": mid{Tst: TstX{A: "c", B: "d"}}}}, "foo.Tst.TstRv", "asc", []map[string]mid{{"foo": mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": mid{Tst: TstX{A: "e", B: "f"}}}}, }, // test map sorting by dot chaining key argument { map[string]map[string]TstX{"1": {"foo": TstX{A: "e", B: "f"}}, "2": {"foo": TstX{A: "a", B: "b"}}, "3": {"foo": TstX{A: "c", B: "d"}}}, "foo.A", "asc", []map[string]TstX{{"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}}}, }, { map[string]map[string]TstX{"1": {"foo": TstX{A: "e", B: "f"}}, "2": {"foo": TstX{A: "a", B: "b"}}, "3": {"foo": TstX{A: "c", B: "d"}}}, ".foo.A", "asc", []map[string]TstX{{"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}}}, }, { map[string]map[string]TstX{"1": {"foo": TstX{A: "e", B: "f"}}, "2": {"foo": TstX{A: "a", B: "b"}}, "3": {"foo": TstX{A: "c", B: "d"}}}, "foo.TstRv", "asc", []map[string]TstX{{"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}}}, }, { map[string]map[string]*TstX{"1": {"foo": &TstX{A: "e", B: "f"}}, "2": {"foo": &TstX{A: "a", B: "b"}}, "3": {"foo": &TstX{A: "c", B: "d"}}}, "foo.TstRp", "asc", []map[string]*TstX{{"foo": &TstX{A: "a", B: "b"}}, {"foo": &TstX{A: "c", B: "d"}}, {"foo": &TstX{A: "e", B: "f"}}}, }, { map[string]map[string]mid{"1": {"foo": mid{Tst: TstX{A: "e", B: "f"}}}, "2": {"foo": mid{Tst: TstX{A: "a", B: "b"}}}, "3": {"foo": mid{Tst: TstX{A: "c", B: "d"}}}}, "foo.Tst.A", "asc", []map[string]mid{{"foo": mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": mid{Tst: TstX{A: "e", B: "f"}}}}, }, { map[string]map[string]mid{"1": {"foo": mid{Tst: TstX{A: "e", B: "f"}}}, "2": {"foo": mid{Tst: TstX{A: "a", B: "b"}}}, "3": {"foo": mid{Tst: TstX{A: "c", B: "d"}}}}, "foo.Tst.TstRv", "asc", []map[string]mid{{"foo": mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": mid{Tst: TstX{A: "e", B: "f"}}}}, }, // interface slice with missing elements { []interface{}{ map[interface{}]interface{}{"Title": "Foo", "Weight": 10}, map[interface{}]interface{}{"Title": "Bar"}, map[interface{}]interface{}{"Title": "Zap", "Weight": 5}, }, "Weight", "asc", []interface{}{ map[interface{}]interface{}{"Title": "Bar"}, map[interface{}]interface{}{"Title": "Zap", "Weight": 5}, map[interface{}]interface{}{"Title": "Foo", "Weight": 10}, }, }, // test boolean values {[]bool{false, true, false}, "value", "asc", []bool{false, false, true}}, {[]bool{false, true, false}, "value", "desc", []bool{true, false, false}}, // test error cases {(*[]TstX)(nil), nil, "asc", false}, {TstX{A: "a", B: "b"}, nil, "asc", false}, { []map[string]TstX{{"foo": TstX{A: "e", B: "f"}}, {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}}, "foo.NotAvailable", "asc", false, }, { map[string]map[string]TstX{"1": {"foo": TstX{A: "e", B: "f"}}, "2": {"foo": TstX{A: "a", B: "b"}}, "3": {"foo": TstX{A: "c", B: "d"}}}, "foo.NotAvailable", "asc", false, }, {nil, nil, "asc", false}, } { t.Run(fmt.Sprintf("test%d", i), func(t *testing.T) { var result interface{} var err error if test.sortByField == nil { result, err = ns.Sort(test.seq) } else { result, err = ns.Sort(test.seq, test.sortByField, test.sortAsc) } if b, ok := test.expect.(bool); ok && !b { if err == nil { t.Fatal("Sort didn't return an expected error") } } else { if err != nil { t.Fatalf("failed: %s", err) } if !reflect.DeepEqual(result, test.expect) { t.Fatalf("Sort called on sequence: %#v | sortByField: `%v` | got\n%#v but expected\n%#v", test.seq, test.sortByField, result, test.expect) } } }) } } hugo-0.92.2/tpl/collections/symdiff.go000066400000000000000000000035151420147000300176460ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "fmt" "reflect" "github.com/pkg/errors" ) // SymDiff returns the symmetric difference of s1 and s2. // Arguments must be either a slice or an array of comparable types. func (ns *Namespace) SymDiff(s2, s1 interface{}) (interface{}, error) { ids1, err := collectIdentities(s1) if err != nil { return nil, err } ids2, err := collectIdentities(s2) if err != nil { return nil, err } var slice reflect.Value var sliceElemType reflect.Type for i, s := range []interface{}{s1, s2} { v := reflect.ValueOf(s) switch v.Kind() { case reflect.Array, reflect.Slice: if i == 0 { sliceType := v.Type() sliceElemType = sliceType.Elem() slice = reflect.MakeSlice(sliceType, 0, 0) } for i := 0; i < v.Len(); i++ { ev, _ := indirectInterface(v.Index(i)) key := normalize(ev) // Append if the key is not in their intersection. if ids1[key] != ids2[key] { v, err := convertValue(ev, sliceElemType) if err != nil { return nil, errors.WithMessage(err, "symdiff: failed to convert value") } slice = reflect.Append(slice, v) } } default: return nil, fmt.Errorf("arguments to symdiff must be slices or arrays") } } return slice.Interface(), nil } hugo-0.92.2/tpl/collections/symdiff_test.go000066400000000000000000000042701420147000300207040ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "reflect" "testing" "github.com/gohugoio/hugo/deps" qt "github.com/frankban/quicktest" ) func TestSymDiff(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(&deps.Deps{}) s1 := []TstX{{A: "a"}, {A: "b"}} s2 := []TstX{{A: "a"}, {A: "e"}} xa, xb, xd, xe := &StructWithSlice{A: "a"}, &StructWithSlice{A: "b"}, &StructWithSlice{A: "d"}, &StructWithSlice{A: "e"} sp1 := []*StructWithSlice{xa, xb, xd, xe} sp2 := []*StructWithSlice{xb, xe} for i, test := range []struct { s1 interface{} s2 interface{} expected interface{} }{ {[]string{"a", "x", "b", "c"}, []string{"a", "b", "y", "c"}, []string{"x", "y"}}, {[]string{"a", "b", "c"}, []string{"a", "b", "c"}, []string{}}, {[]interface{}{"a", "b", nil}, []interface{}{"a"}, []interface{}{"b", nil}}, {[]int{1, 2, 3}, []int{3, 4}, []int{1, 2, 4}}, {[]int{1, 2, 3}, []int64{3, 4}, []int{1, 2, 4}}, {s1, s2, []TstX{{A: "b"}, {A: "e"}}}, {sp1, sp2, []*StructWithSlice{xa, xd}}, // Errors {"error", "error", false}, {[]int{1, 2, 3}, []string{"3", "4"}, false}, } { errMsg := qt.Commentf("[%d]", i) result, err := ns.SymDiff(test.s2, test.s1) if b, ok := test.expected.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) if !reflect.DeepEqual(test.expected, result) { t.Fatalf("%s got\n%T: %v\nexpected\n%T: %v", errMsg, result, result, test.expected, test.expected) } } _, err := ns.Complement() c.Assert(err, qt.Not(qt.IsNil)) _, err = ns.Complement([]string{"a", "b"}) c.Assert(err, qt.Not(qt.IsNil)) } hugo-0.92.2/tpl/collections/where.go000066400000000000000000000334001420147000300173130ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "errors" "fmt" "reflect" "strings" "github.com/gohugoio/hugo/common/maps" ) // Where returns a filtered subset of a given data type. func (ns *Namespace) Where(seq, key interface{}, args ...interface{}) (interface{}, error) { seqv, isNil := indirect(reflect.ValueOf(seq)) if isNil { return nil, errors.New("can't iterate over a nil value of type " + reflect.ValueOf(seq).Type().String()) } mv, op, err := parseWhereArgs(args...) if err != nil { return nil, err } var path []string kv := reflect.ValueOf(key) if kv.Kind() == reflect.String { path = strings.Split(strings.Trim(kv.String(), "."), ".") } switch seqv.Kind() { case reflect.Array, reflect.Slice: return ns.checkWhereArray(seqv, kv, mv, path, op) case reflect.Map: return ns.checkWhereMap(seqv, kv, mv, path, op) default: return nil, fmt.Errorf("can't iterate over %v", seq) } } func (ns *Namespace) checkCondition(v, mv reflect.Value, op string) (bool, error) { v, vIsNil := indirect(v) if !v.IsValid() { vIsNil = true } mv, mvIsNil := indirect(mv) if !mv.IsValid() { mvIsNil = true } if vIsNil || mvIsNil { switch op { case "", "=", "==", "eq": return vIsNil == mvIsNil, nil case "!=", "<>", "ne": return vIsNil != mvIsNil, nil } return false, nil } if v.Kind() == reflect.Bool && mv.Kind() == reflect.Bool { switch op { case "", "=", "==", "eq": return v.Bool() == mv.Bool(), nil case "!=", "<>", "ne": return v.Bool() != mv.Bool(), nil } return false, nil } var ivp, imvp *int64 var fvp, fmvp *float64 var svp, smvp *string var slv, slmv interface{} var ima []int64 var fma []float64 var sma []string if mv.Kind() == v.Kind() { switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: iv := v.Int() ivp = &iv imv := mv.Int() imvp = &imv case reflect.String: sv := v.String() svp = &sv smv := mv.String() smvp = &smv case reflect.Float64: fv := v.Float() fvp = &fv fmv := mv.Float() fmvp = &fmv case reflect.Struct: switch v.Type() { case timeType: iv := toTimeUnix(v) ivp = &iv imv := toTimeUnix(mv) imvp = &imv } case reflect.Array, reflect.Slice: slv = v.Interface() slmv = mv.Interface() } } else if isNumber(v.Kind()) && isNumber(mv.Kind()) { fv, err := toFloat(v) if err != nil { return false, err } fvp = &fv fmv, err := toFloat(mv) if err != nil { return false, err } fmvp = &fmv } else { if mv.Kind() != reflect.Array && mv.Kind() != reflect.Slice { return false, nil } if mv.Len() == 0 { return false, nil } if v.Kind() != reflect.Interface && mv.Type().Elem().Kind() != reflect.Interface && mv.Type().Elem() != v.Type() && v.Kind() != reflect.Array && v.Kind() != reflect.Slice { return false, nil } switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: iv := v.Int() ivp = &iv for i := 0; i < mv.Len(); i++ { if anInt, err := toInt(mv.Index(i)); err == nil { ima = append(ima, anInt) } } case reflect.String: sv := v.String() svp = &sv for i := 0; i < mv.Len(); i++ { if aString, err := toString(mv.Index(i)); err == nil { sma = append(sma, aString) } } case reflect.Float64: fv := v.Float() fvp = &fv for i := 0; i < mv.Len(); i++ { if aFloat, err := toFloat(mv.Index(i)); err == nil { fma = append(fma, aFloat) } } case reflect.Struct: switch v.Type() { case timeType: iv := toTimeUnix(v) ivp = &iv for i := 0; i < mv.Len(); i++ { ima = append(ima, toTimeUnix(mv.Index(i))) } } case reflect.Array, reflect.Slice: slv = v.Interface() slmv = mv.Interface() } } switch op { case "", "=", "==", "eq": switch { case ivp != nil && imvp != nil: return *ivp == *imvp, nil case svp != nil && smvp != nil: return *svp == *smvp, nil case fvp != nil && fmvp != nil: return *fvp == *fmvp, nil } case "!=", "<>", "ne": switch { case ivp != nil && imvp != nil: return *ivp != *imvp, nil case svp != nil && smvp != nil: return *svp != *smvp, nil case fvp != nil && fmvp != nil: return *fvp != *fmvp, nil } case ">=", "ge": switch { case ivp != nil && imvp != nil: return *ivp >= *imvp, nil case svp != nil && smvp != nil: return *svp >= *smvp, nil case fvp != nil && fmvp != nil: return *fvp >= *fmvp, nil } case ">", "gt": switch { case ivp != nil && imvp != nil: return *ivp > *imvp, nil case svp != nil && smvp != nil: return *svp > *smvp, nil case fvp != nil && fmvp != nil: return *fvp > *fmvp, nil } case "<=", "le": switch { case ivp != nil && imvp != nil: return *ivp <= *imvp, nil case svp != nil && smvp != nil: return *svp <= *smvp, nil case fvp != nil && fmvp != nil: return *fvp <= *fmvp, nil } case "<", "lt": switch { case ivp != nil && imvp != nil: return *ivp < *imvp, nil case svp != nil && smvp != nil: return *svp < *smvp, nil case fvp != nil && fmvp != nil: return *fvp < *fmvp, nil } case "in", "not in": var r bool switch { case ivp != nil && len(ima) > 0: r, _ = ns.In(ima, *ivp) case fvp != nil && len(fma) > 0: r, _ = ns.In(fma, *fvp) case svp != nil: if len(sma) > 0 { r, _ = ns.In(sma, *svp) } else if smvp != nil { r, _ = ns.In(*smvp, *svp) } default: return false, nil } if op == "not in" { return !r, nil } return r, nil case "intersect": r, err := ns.Intersect(slv, slmv) if err != nil { return false, err } if reflect.TypeOf(r).Kind() == reflect.Slice { s := reflect.ValueOf(r) if s.Len() > 0 { return true, nil } return false, nil } return false, errors.New("invalid intersect values") default: return false, errors.New("no such operator") } return false, nil } func evaluateSubElem(obj reflect.Value, elemName string) (reflect.Value, error) { if !obj.IsValid() { return zero, errors.New("can't evaluate an invalid value") } typ := obj.Type() obj, isNil := indirect(obj) if obj.Kind() == reflect.Interface { // If obj is an interface, we need to inspect the value it contains // to see the full set of methods and fields. // Indirect returns the value that it points to, which is what's needed // below to be able to reflect on its fields. obj = reflect.Indirect(obj.Elem()) } // first, check whether obj has a method. In this case, obj is // a struct or its pointer. If obj is a struct, // to check all T and *T method, use obj pointer type Value objPtr := obj if objPtr.Kind() != reflect.Interface && objPtr.CanAddr() { objPtr = objPtr.Addr() } mt, ok := objPtr.Type().MethodByName(elemName) if ok { switch { case mt.PkgPath != "": return zero, fmt.Errorf("%s is an unexported method of type %s", elemName, typ) case mt.Type.NumIn() > 1: return zero, fmt.Errorf("%s is a method of type %s but requires more than 1 parameter", elemName, typ) case mt.Type.NumOut() == 0: return zero, fmt.Errorf("%s is a method of type %s but returns no output", elemName, typ) case mt.Type.NumOut() > 2: return zero, fmt.Errorf("%s is a method of type %s but returns more than 2 outputs", elemName, typ) case mt.Type.NumOut() == 1 && mt.Type.Out(0).Implements(errorType): return zero, fmt.Errorf("%s is a method of type %s but only returns an error type", elemName, typ) case mt.Type.NumOut() == 2 && !mt.Type.Out(1).Implements(errorType): return zero, fmt.Errorf("%s is a method of type %s returning two values but the second value is not an error type", elemName, typ) } res := objPtr.Method(mt.Index).Call([]reflect.Value{}) if len(res) == 2 && !res[1].IsNil() { return zero, fmt.Errorf("error at calling a method %s of type %s: %s", elemName, typ, res[1].Interface().(error)) } return res[0], nil } // elemName isn't a method so next start to check whether it is // a struct field or a map value. In both cases, it mustn't be // a nil value if isNil { return zero, fmt.Errorf("can't evaluate a nil pointer of type %s by a struct field or map key name %s", typ, elemName) } switch obj.Kind() { case reflect.Struct: ft, ok := obj.Type().FieldByName(elemName) if ok { if ft.PkgPath != "" && !ft.Anonymous { return zero, fmt.Errorf("%s is an unexported field of struct type %s", elemName, typ) } return obj.FieldByIndex(ft.Index), nil } return zero, fmt.Errorf("%s isn't a field of struct type %s", elemName, typ) case reflect.Map: kv := reflect.ValueOf(elemName) if kv.Type().AssignableTo(obj.Type().Key()) { return obj.MapIndex(kv), nil } return zero, fmt.Errorf("%s isn't a key of map type %s", elemName, typ) } return zero, fmt.Errorf("%s is neither a struct field, a method nor a map element of type %s", elemName, typ) } // parseWhereArgs parses the end arguments to the where function. Return a // match value and an operator, if one is defined. func parseWhereArgs(args ...interface{}) (mv reflect.Value, op string, err error) { switch len(args) { case 1: mv = reflect.ValueOf(args[0]) case 2: var ok bool if op, ok = args[0].(string); !ok { err = errors.New("operator argument must be string type") return } op = strings.TrimSpace(strings.ToLower(op)) mv = reflect.ValueOf(args[1]) default: err = errors.New("can't evaluate the array by no match argument or more than or equal to two arguments") } return } // checkWhereArray handles the where-matching logic when the seqv value is an // Array or Slice. func (ns *Namespace) checkWhereArray(seqv, kv, mv reflect.Value, path []string, op string) (interface{}, error) { rv := reflect.MakeSlice(seqv.Type(), 0, 0) for i := 0; i < seqv.Len(); i++ { var vvv reflect.Value rvv := seqv.Index(i) if kv.Kind() == reflect.String { if params, ok := rvv.Interface().(maps.Params); ok { vvv = reflect.ValueOf(params.Get(path...)) } else { vvv = rvv for i, elemName := range path { var err error vvv, err = evaluateSubElem(vvv, elemName) if err != nil { continue } if i < len(path)-1 && vvv.IsValid() { if params, ok := vvv.Interface().(maps.Params); ok { // The current path element is the map itself, .Params. vvv = reflect.ValueOf(params.Get(path[i+1:]...)) break } } } } } else { vv, _ := indirect(rvv) if vv.Kind() == reflect.Map && kv.Type().AssignableTo(vv.Type().Key()) { vvv = vv.MapIndex(kv) } } if ok, err := ns.checkCondition(vvv, mv, op); ok { rv = reflect.Append(rv, rvv) } else if err != nil { return nil, err } } return rv.Interface(), nil } // checkWhereMap handles the where-matching logic when the seqv value is a Map. func (ns *Namespace) checkWhereMap(seqv, kv, mv reflect.Value, path []string, op string) (interface{}, error) { rv := reflect.MakeMap(seqv.Type()) keys := seqv.MapKeys() for _, k := range keys { elemv := seqv.MapIndex(k) switch elemv.Kind() { case reflect.Array, reflect.Slice: r, err := ns.checkWhereArray(elemv, kv, mv, path, op) if err != nil { return nil, err } switch rr := reflect.ValueOf(r); rr.Kind() { case reflect.Slice: if rr.Len() > 0 { rv.SetMapIndex(k, elemv) } } case reflect.Interface: elemvv, isNil := indirect(elemv) if isNil { continue } switch elemvv.Kind() { case reflect.Array, reflect.Slice: r, err := ns.checkWhereArray(elemvv, kv, mv, path, op) if err != nil { return nil, err } switch rr := reflect.ValueOf(r); rr.Kind() { case reflect.Slice: if rr.Len() > 0 { rv.SetMapIndex(k, elemv) } } } } } return rv.Interface(), nil } // toFloat returns the float value if possible. func toFloat(v reflect.Value) (float64, error) { switch v.Kind() { case reflect.Float32, reflect.Float64: return v.Float(), nil case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Convert(reflect.TypeOf(float64(0))).Float(), nil case reflect.Interface: return toFloat(v.Elem()) } return -1, errors.New("unable to convert value to float") } // toInt returns the int value if possible, -1 if not. // TODO(bep) consolidate all these reflect funcs. func toInt(v reflect.Value) (int64, error) { switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Int(), nil case reflect.Interface: return toInt(v.Elem()) } return -1, errors.New("unable to convert value to int") } func toUint(v reflect.Value) (uint64, error) { switch v.Kind() { case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return v.Uint(), nil case reflect.Interface: return toUint(v.Elem()) } return 0, errors.New("unable to convert value to uint") } // toString returns the string value if possible, "" if not. func toString(v reflect.Value) (string, error) { switch v.Kind() { case reflect.String: return v.String(), nil case reflect.Interface: return toString(v.Elem()) } return "", errors.New("unable to convert value to string") } func toTimeUnix(v reflect.Value) int64 { if v.Kind() == reflect.Interface { return toTimeUnix(v.Elem()) } if v.Type() != timeType { panic("coding error: argument must be time.Time type reflect Value") } return v.MethodByName("Unix").Call([]reflect.Value{})[0].Int() } hugo-0.92.2/tpl/collections/where_test.go000066400000000000000000000651331420147000300203620ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package collections import ( "fmt" "html/template" "reflect" "strings" "testing" "time" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/deps" ) func TestWhere(t *testing.T) { t.Parallel() ns := New(&deps.Deps{}) type Mid struct { Tst TstX } d1 := time.Now() d2 := d1.Add(1 * time.Hour) d3 := d2.Add(1 * time.Hour) d4 := d3.Add(1 * time.Hour) d5 := d4.Add(1 * time.Hour) d6 := d5.Add(1 * time.Hour) type testt struct { seq interface{} key interface{} op string match interface{} expect interface{} } createTestVariants := func(test testt) []testt { testVariants := []testt{test} if islice := ToTstXIs(test.seq); islice != nil { variant := test variant.seq = islice expect := ToTstXIs(test.expect) if expect != nil { variant.expect = expect } testVariants = append(testVariants, variant) } return testVariants } for i, test := range []testt{ { seq: []map[int]string{ {1: "a", 2: "m"}, {1: "c", 2: "d"}, {1: "e", 3: "m"}, }, key: 2, match: "m", expect: []map[int]string{ {1: "a", 2: "m"}, }, }, { seq: []map[string]int{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "x": 4}, }, key: "b", match: 4, expect: []map[string]int{ {"a": 3, "b": 4}, }, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "x": 4}, }, key: "b", match: 4.0, expect: []map[string]float64{{"a": 3, "b": 4}}, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "x": 4}, }, key: "b", match: 4.0, op: "!=", expect: []map[string]float64{{"a": 1, "b": 2}, {"a": 5, "x": 4}}, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "x": 4}, }, key: "b", match: 4.0, op: "<", expect: []map[string]float64{{"a": 1, "b": 2}}, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "x": 4}, }, key: "b", match: 4, op: "<", expect: []map[string]float64{{"a": 1, "b": 2}}, }, { seq: []map[string]int{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "x": 4}, }, key: "b", match: 4.0, op: "<", expect: []map[string]int{{"a": 1, "b": 2}}, }, { seq: []map[string]int{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "x": 4}, }, key: "b", match: 4.2, op: "<", expect: []map[string]int{{"a": 1, "b": 2}, {"a": 3, "b": 4}}, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "x": 4}, }, key: "b", match: 4.0, op: "<=", expect: []map[string]float64{{"a": 1, "b": 2}, {"a": 3, "b": 4}}, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3, "b": 3}, {"a": 5, "x": 4}, }, key: "b", match: 2.0, op: ">", expect: []map[string]float64{{"a": 3, "b": 3}}, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3, "b": 3}, {"a": 5, "x": 4}, }, key: "b", match: 2.0, op: ">=", expect: []map[string]float64{{"a": 1, "b": 2}, {"a": 3, "b": 3}}, }, // Issue #8353 // String type mismatch. { seq: []map[string]interface{}{ {"a": "1", "b": "2"}, {"a": "3", "b": template.HTML("4")}, {"a": "5", "x": "4"}, }, key: "b", match: "4", expect: []map[string]interface{}{ {"a": "3", "b": template.HTML("4")}, }, }, { seq: []TstX{ {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}, }, key: "B", match: "f", expect: []TstX{ {A: "e", B: "f"}, }, }, { seq: []*map[int]string{ {1: "a", 2: "m"}, {1: "c", 2: "d"}, {1: "e", 3: "m"}, }, key: 2, match: "m", expect: []*map[int]string{ {1: "a", 2: "m"}, }, }, // Case insensitive maps.Params // Slice of structs { seq: []TstParams{{params: maps.Params{"i": 0, "color": "indigo"}}, {params: maps.Params{"i": 1, "color": "blue"}}, {params: maps.Params{"i": 2, "color": "green"}}, {params: maps.Params{"i": 3, "color": "blue"}}}, key: ".Params.COLOR", match: "blue", expect: []TstParams{{params: maps.Params{"i": 1, "color": "blue"}}, {params: maps.Params{"i": 3, "color": "blue"}}}, }, { seq: []TstParams{{params: maps.Params{"nested": map[string]interface{}{"color": "indigo"}}}, {params: maps.Params{"nested": map[string]interface{}{"color": "blue"}}}}, key: ".Params.NEsTED.COLOR", match: "blue", expect: []TstParams{{params: maps.Params{"nested": map[string]interface{}{"color": "blue"}}}}, }, { seq: []TstParams{{params: maps.Params{"i": 0, "color": "indigo"}}, {params: maps.Params{"i": 1, "color": "blue"}}, {params: maps.Params{"i": 2, "color": "green"}}, {params: maps.Params{"i": 3, "color": "blue"}}}, key: ".Params", match: "blue", expect: []TstParams{}, }, // Slice of maps { seq: []maps.Params{ {"a": "a1", "b": "b1"}, {"a": "a2", "b": "b2"}, }, key: "B", match: "b2", expect: []maps.Params{ {"a": "a2", "b": "b2"}, }, }, { seq: []maps.Params{ { "a": map[string]interface{}{ "b": "b1", }, }, { "a": map[string]interface{}{ "b": "b2", }, }, }, key: "A.B", match: "b2", expect: []maps.Params{ { "a": map[string]interface{}{ "b": "b2", }, }, }, }, { seq: []*TstX{ {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}, }, key: "B", match: "f", expect: []*TstX{ {A: "e", B: "f"}, }, }, { seq: []*TstX{ {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "c"}, }, key: "TstRp", match: "rc", expect: []*TstX{ {A: "c", B: "d"}, }, }, { seq: []TstX{ {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "c"}, }, key: "TstRv", match: "rc", expect: []TstX{ {A: "e", B: "c"}, }, }, { seq: []map[string]TstX{ {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}}, }, key: "foo.B", match: "d", expect: []map[string]TstX{ {"foo": TstX{A: "c", B: "d"}}, }, }, { seq: []map[string]TstX{ {"baz": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}}, }, key: "foo.B", match: "d", expect: []map[string]TstX{ {"foo": TstX{A: "c", B: "d"}}, }, }, { seq: []map[string]TstX{ {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}}, }, key: ".foo.B", match: "d", expect: []map[string]TstX{ {"foo": TstX{A: "c", B: "d"}}, }, }, { seq: []map[string]TstX{ {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}}, }, key: "foo.TstRv", match: "rd", expect: []map[string]TstX{ {"foo": TstX{A: "c", B: "d"}}, }, }, { seq: []map[string]*TstX{ {"foo": &TstX{A: "a", B: "b"}}, {"foo": &TstX{A: "c", B: "d"}}, {"foo": &TstX{A: "e", B: "f"}}, }, key: "foo.TstRp", match: "rc", expect: []map[string]*TstX{ {"foo": &TstX{A: "c", B: "d"}}, }, }, { seq: []TstXIHolder{ {&TstX{A: "a", B: "b"}}, {&TstX{A: "c", B: "d"}}, {&TstX{A: "e", B: "f"}}, }, key: "XI.TstRp", match: "rc", expect: []TstXIHolder{ {&TstX{A: "c", B: "d"}}, }, }, { seq: []TstXIHolder{ {&TstX{A: "a", B: "b"}}, {&TstX{A: "c", B: "d"}}, {&TstX{A: "e", B: "f"}}, }, key: "XI.A", match: "e", expect: []TstXIHolder{ {&TstX{A: "e", B: "f"}}, }, }, { seq: []map[string]Mid{ {"foo": Mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": Mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": Mid{Tst: TstX{A: "e", B: "f"}}}, }, key: "foo.Tst.B", match: "d", expect: []map[string]Mid{ {"foo": Mid{Tst: TstX{A: "c", B: "d"}}}, }, }, { seq: []map[string]Mid{ {"foo": Mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": Mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": Mid{Tst: TstX{A: "e", B: "f"}}}, }, key: "foo.Tst.TstRv", match: "rd", expect: []map[string]Mid{ {"foo": Mid{Tst: TstX{A: "c", B: "d"}}}, }, }, { seq: []map[string]*Mid{ {"foo": &Mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": &Mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": &Mid{Tst: TstX{A: "e", B: "f"}}}, }, key: "foo.Tst.TstRp", match: "rc", expect: []map[string]*Mid{ {"foo": &Mid{Tst: TstX{A: "c", B: "d"}}}, }, }, { seq: []map[string]int{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}, }, key: "b", op: ">", match: 3, expect: []map[string]int{ {"a": 3, "b": 4}, {"a": 5, "b": 6}, }, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}, }, key: "b", op: ">", match: 3.0, expect: []map[string]float64{ {"a": 3, "b": 4}, {"a": 5, "b": 6}, }, }, { seq: []TstX{ {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}, }, key: "B", op: "!=", match: "f", expect: []TstX{ {A: "a", B: "b"}, {A: "c", B: "d"}, }, }, { seq: []map[string]int{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}, }, key: "b", op: "in", match: []int{3, 4, 5}, expect: []map[string]int{ {"a": 3, "b": 4}, }, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}, }, key: "b", op: "in", match: []float64{3, 4, 5}, expect: []map[string]float64{ {"a": 3, "b": 4}, }, }, { seq: []map[string][]string{ {"a": []string{"A", "B", "C"}, "b": []string{"D", "E", "F"}}, {"a": []string{"G", "H", "I"}, "b": []string{"J", "K", "L"}}, {"a": []string{"M", "N", "O"}, "b": []string{"P", "Q", "R"}}, }, key: "b", op: "intersect", match: []string{"D", "P", "Q"}, expect: []map[string][]string{ {"a": []string{"A", "B", "C"}, "b": []string{"D", "E", "F"}}, {"a": []string{"M", "N", "O"}, "b": []string{"P", "Q", "R"}}, }, }, { seq: []map[string][]int{ {"a": []int{1, 2, 3}, "b": []int{4, 5, 6}}, {"a": []int{7, 8, 9}, "b": []int{10, 11, 12}}, {"a": []int{13, 14, 15}, "b": []int{16, 17, 18}}, }, key: "b", op: "intersect", match: []int{4, 10, 12}, expect: []map[string][]int{ {"a": []int{1, 2, 3}, "b": []int{4, 5, 6}}, {"a": []int{7, 8, 9}, "b": []int{10, 11, 12}}, }, }, { seq: []map[string][]int8{ {"a": []int8{1, 2, 3}, "b": []int8{4, 5, 6}}, {"a": []int8{7, 8, 9}, "b": []int8{10, 11, 12}}, {"a": []int8{13, 14, 15}, "b": []int8{16, 17, 18}}, }, key: "b", op: "intersect", match: []int8{4, 10, 12}, expect: []map[string][]int8{ {"a": []int8{1, 2, 3}, "b": []int8{4, 5, 6}}, {"a": []int8{7, 8, 9}, "b": []int8{10, 11, 12}}, }, }, { seq: []map[string][]int16{ {"a": []int16{1, 2, 3}, "b": []int16{4, 5, 6}}, {"a": []int16{7, 8, 9}, "b": []int16{10, 11, 12}}, {"a": []int16{13, 14, 15}, "b": []int16{16, 17, 18}}, }, key: "b", op: "intersect", match: []int16{4, 10, 12}, expect: []map[string][]int16{ {"a": []int16{1, 2, 3}, "b": []int16{4, 5, 6}}, {"a": []int16{7, 8, 9}, "b": []int16{10, 11, 12}}, }, }, { seq: []map[string][]int32{ {"a": []int32{1, 2, 3}, "b": []int32{4, 5, 6}}, {"a": []int32{7, 8, 9}, "b": []int32{10, 11, 12}}, {"a": []int32{13, 14, 15}, "b": []int32{16, 17, 18}}, }, key: "b", op: "intersect", match: []int32{4, 10, 12}, expect: []map[string][]int32{ {"a": []int32{1, 2, 3}, "b": []int32{4, 5, 6}}, {"a": []int32{7, 8, 9}, "b": []int32{10, 11, 12}}, }, }, { seq: []map[string][]int64{ {"a": []int64{1, 2, 3}, "b": []int64{4, 5, 6}}, {"a": []int64{7, 8, 9}, "b": []int64{10, 11, 12}}, {"a": []int64{13, 14, 15}, "b": []int64{16, 17, 18}}, }, key: "b", op: "intersect", match: []int64{4, 10, 12}, expect: []map[string][]int64{ {"a": []int64{1, 2, 3}, "b": []int64{4, 5, 6}}, {"a": []int64{7, 8, 9}, "b": []int64{10, 11, 12}}, }, }, { seq: []map[string][]float32{ {"a": []float32{1.0, 2.0, 3.0}, "b": []float32{4.0, 5.0, 6.0}}, {"a": []float32{7.0, 8.0, 9.0}, "b": []float32{10.0, 11.0, 12.0}}, {"a": []float32{13.0, 14.0, 15.0}, "b": []float32{16.0, 17.0, 18.0}}, }, key: "b", op: "intersect", match: []float32{4, 10, 12}, expect: []map[string][]float32{ {"a": []float32{1.0, 2.0, 3.0}, "b": []float32{4.0, 5.0, 6.0}}, {"a": []float32{7.0, 8.0, 9.0}, "b": []float32{10.0, 11.0, 12.0}}, }, }, { seq: []map[string][]float64{ {"a": []float64{1.0, 2.0, 3.0}, "b": []float64{4.0, 5.0, 6.0}}, {"a": []float64{7.0, 8.0, 9.0}, "b": []float64{10.0, 11.0, 12.0}}, {"a": []float64{13.0, 14.0, 15.0}, "b": []float64{16.0, 17.0, 18.0}}, }, key: "b", op: "intersect", match: []float64{4, 10, 12}, expect: []map[string][]float64{ {"a": []float64{1.0, 2.0, 3.0}, "b": []float64{4.0, 5.0, 6.0}}, {"a": []float64{7.0, 8.0, 9.0}, "b": []float64{10.0, 11.0, 12.0}}, }, }, { seq: []map[string]int{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}, }, key: "b", op: "in", match: ns.Slice(3, 4, 5), expect: []map[string]int{ {"a": 3, "b": 4}, }, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}, }, key: "b", op: "in", match: ns.Slice(3.0, 4.0, 5.0), expect: []map[string]float64{ {"a": 3, "b": 4}, }, }, { seq: []map[string]time.Time{ {"a": d1, "b": d2}, {"a": d3, "b": d4}, {"a": d5, "b": d6}, }, key: "b", op: "in", match: ns.Slice(d3, d4, d5), expect: []map[string]time.Time{ {"a": d3, "b": d4}, }, }, { seq: []TstX{ {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}, }, key: "B", op: "not in", match: []string{"c", "d", "e"}, expect: []TstX{ {A: "a", B: "b"}, {A: "e", B: "f"}, }, }, { seq: []TstX{ {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}, }, key: "B", op: "not in", match: ns.Slice("c", t, "d", "e"), expect: []TstX{ {A: "a", B: "b"}, {A: "e", B: "f"}, }, }, { seq: []map[string]int{ {"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6}, }, key: "b", op: "", match: nil, expect: []map[string]int{ {"a": 3}, }, }, { seq: []map[string]int{ {"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6}, }, key: "b", op: "!=", match: nil, expect: []map[string]int{ {"a": 1, "b": 2}, {"a": 5, "b": 6}, }, }, { seq: []map[string]int{ {"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6}, }, key: "b", op: ">", match: nil, expect: []map[string]int{}, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6}, }, key: "b", op: "", match: nil, expect: []map[string]float64{ {"a": 3}, }, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6}, }, key: "b", op: "!=", match: nil, expect: []map[string]float64{ {"a": 1, "b": 2}, {"a": 5, "b": 6}, }, }, { seq: []map[string]float64{ {"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6}, }, key: "b", op: ">", match: nil, expect: []map[string]float64{}, }, { seq: []map[string]bool{ {"a": true, "b": false}, {"c": true, "b": true}, {"d": true, "b": false}, }, key: "b", op: "", match: true, expect: []map[string]bool{ {"c": true, "b": true}, }, }, { seq: []map[string]bool{ {"a": true, "b": false}, {"c": true, "b": true}, {"d": true, "b": false}, }, key: "b", op: "!=", match: true, expect: []map[string]bool{ {"a": true, "b": false}, {"d": true, "b": false}, }, }, { seq: []map[string]bool{ {"a": true, "b": false}, {"c": true, "b": true}, {"d": true, "b": false}, }, key: "b", op: ">", match: false, expect: []map[string]bool{}, }, { seq: []map[string]bool{ {"a": true, "b": false}, {"c": true, "b": true}, {"d": true, "b": false}, }, key: "b.z", match: false, expect: []map[string]bool{}, }, {seq: (*[]TstX)(nil), key: "A", match: "a", expect: false}, {seq: TstX{A: "a", B: "b"}, key: "A", match: "a", expect: false}, {seq: []map[string]*TstX{{"foo": nil}}, key: "foo.B", match: "d", expect: []map[string]*TstX{}}, {seq: []map[string]*TstX{{"foo": nil}}, key: "foo.B.Z", match: "d", expect: []map[string]*TstX{}}, { seq: []TstX{ {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}, }, key: "B", op: "op", match: "f", expect: false, }, { seq: map[string]interface{}{ "foo": []interface{}{map[interface{}]interface{}{"a": 1, "b": 2}}, "bar": []interface{}{map[interface{}]interface{}{"a": 3, "b": 4}}, "zap": []interface{}{map[interface{}]interface{}{"a": 5, "b": 6}}, }, key: "b", op: "in", match: ns.Slice(3, 4, 5), expect: map[string]interface{}{ "bar": []interface{}{map[interface{}]interface{}{"a": 3, "b": 4}}, }, }, { seq: map[string]interface{}{ "foo": []interface{}{map[interface{}]interface{}{"a": 1, "b": 2}}, "bar": []interface{}{map[interface{}]interface{}{"a": 3, "b": 4}}, "zap": []interface{}{map[interface{}]interface{}{"a": 5, "b": 6}}, }, key: "b", op: ">", match: 3, expect: map[string]interface{}{ "bar": []interface{}{map[interface{}]interface{}{"a": 3, "b": 4}}, "zap": []interface{}{map[interface{}]interface{}{"a": 5, "b": 6}}, }, }, { seq: map[string]interface{}{ "foo": []interface{}{maps.Params{"a": 1, "b": 2}}, "bar": []interface{}{maps.Params{"a": 3, "b": 4}}, "zap": []interface{}{maps.Params{"a": 5, "b": 6}}, }, key: "B", op: ">", match: 3, expect: map[string]interface{}{ "bar": []interface{}{maps.Params{"a": 3, "b": 4}}, "zap": []interface{}{maps.Params{"a": 5, "b": 6}}, }, }, } { testVariants := createTestVariants(test) for j, test := range testVariants { name := fmt.Sprintf("%d/%d %T %s %s", i, j, test.seq, test.op, test.key) name = strings.ReplaceAll(name, "[]", "slice-of-") t.Run(name, func(t *testing.T) { var results interface{} var err error if len(test.op) > 0 { results, err = ns.Where(test.seq, test.key, test.op, test.match) } else { results, err = ns.Where(test.seq, test.key, test.match) } if b, ok := test.expect.(bool); ok && !b { if err == nil { t.Fatalf("[%d] Where didn't return an expected error", i) } } else { if err != nil { t.Fatalf("[%d] failed: %s", i, err) } if !reflect.DeepEqual(results, test.expect) { t.Fatalf("Where clause matching %v with %v in seq %v (%T),\ngot\n%v (%T) but expected\n%v (%T)", test.key, test.match, test.seq, test.seq, results, results, test.expect, test.expect) } } }) } } var err error _, err = ns.Where(map[string]int{"a": 1, "b": 2}, "a", []byte("="), 1) if err == nil { t.Errorf("Where called with none string op value didn't return an expected error") } _, err = ns.Where(map[string]int{"a": 1, "b": 2}, "a", []byte("="), 1, 2) if err == nil { t.Errorf("Where called with more than two variable arguments didn't return an expected error") } _, err = ns.Where(map[string]int{"a": 1, "b": 2}, "a") if err == nil { t.Errorf("Where called with no variable arguments didn't return an expected error") } } func TestCheckCondition(t *testing.T) { t.Parallel() ns := New(&deps.Deps{}) type expect struct { result bool isError bool } for i, test := range []struct { value reflect.Value match reflect.Value op string expect }{ {reflect.ValueOf(123), reflect.ValueOf(123), "", expect{true, false}}, {reflect.ValueOf("foo"), reflect.ValueOf("foo"), "", expect{true, false}}, { reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)), reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)), "", expect{true, false}, }, {reflect.ValueOf(true), reflect.ValueOf(true), "", expect{true, false}}, {reflect.ValueOf(nil), reflect.ValueOf(nil), "", expect{true, false}}, {reflect.ValueOf(123), reflect.ValueOf(456), "!=", expect{true, false}}, {reflect.ValueOf("foo"), reflect.ValueOf("bar"), "!=", expect{true, false}}, { reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)), reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)), "!=", expect{true, false}, }, {reflect.ValueOf(true), reflect.ValueOf(false), "!=", expect{true, false}}, {reflect.ValueOf(123), reflect.ValueOf(nil), "!=", expect{true, false}}, {reflect.ValueOf(456), reflect.ValueOf(123), ">=", expect{true, false}}, {reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">=", expect{true, false}}, { reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)), reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)), ">=", expect{true, false}, }, {reflect.ValueOf(456), reflect.ValueOf(123), ">", expect{true, false}}, {reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">", expect{true, false}}, { reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)), reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)), ">", expect{true, false}, }, {reflect.ValueOf(123), reflect.ValueOf(456), "<=", expect{true, false}}, {reflect.ValueOf("bar"), reflect.ValueOf("foo"), "<=", expect{true, false}}, { reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)), reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)), "<=", expect{true, false}, }, {reflect.ValueOf(123), reflect.ValueOf(456), "<", expect{true, false}}, {reflect.ValueOf("bar"), reflect.ValueOf("foo"), "<", expect{true, false}}, { reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)), reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)), "<", expect{true, false}, }, {reflect.ValueOf(123), reflect.ValueOf([]int{123, 45, 678}), "in", expect{true, false}}, {reflect.ValueOf("foo"), reflect.ValueOf([]string{"foo", "bar", "baz"}), "in", expect{true, false}}, { reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)), reflect.ValueOf([]time.Time{ time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC), time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC), time.Date(2015, time.June, 26, 19, 18, 56, 12345, time.UTC), }), "in", expect{true, false}, }, {reflect.ValueOf(123), reflect.ValueOf([]int{45, 678}), "not in", expect{true, false}}, {reflect.ValueOf("foo"), reflect.ValueOf([]string{"bar", "baz"}), "not in", expect{true, false}}, { reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)), reflect.ValueOf([]time.Time{ time.Date(2015, time.February, 26, 19, 18, 56, 12345, time.UTC), time.Date(2015, time.March, 26, 19, 18, 56, 12345, time.UTC), time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC), }), "not in", expect{true, false}, }, {reflect.ValueOf("foo"), reflect.ValueOf("bar-foo-baz"), "in", expect{true, false}}, {reflect.ValueOf("foo"), reflect.ValueOf("bar--baz"), "not in", expect{true, false}}, {reflect.Value{}, reflect.ValueOf("foo"), "", expect{false, false}}, {reflect.ValueOf("foo"), reflect.Value{}, "", expect{false, false}}, {reflect.ValueOf((*TstX)(nil)), reflect.ValueOf("foo"), "", expect{false, false}}, {reflect.ValueOf("foo"), reflect.ValueOf((*TstX)(nil)), "", expect{false, false}}, {reflect.ValueOf(true), reflect.ValueOf("foo"), "", expect{false, false}}, {reflect.ValueOf("foo"), reflect.ValueOf(true), "", expect{false, false}}, {reflect.ValueOf("foo"), reflect.ValueOf(map[int]string{}), "", expect{false, false}}, {reflect.ValueOf("foo"), reflect.ValueOf([]int{1, 2}), "", expect{false, false}}, {reflect.ValueOf((*TstX)(nil)), reflect.ValueOf((*TstX)(nil)), ">", expect{false, false}}, {reflect.ValueOf(true), reflect.ValueOf(false), ">", expect{false, false}}, {reflect.ValueOf(123), reflect.ValueOf([]int{}), "in", expect{false, false}}, {reflect.ValueOf(123), reflect.ValueOf(123), "op", expect{false, true}}, // Issue #3718 {reflect.ValueOf([]interface{}{"a"}), reflect.ValueOf([]string{"a", "b"}), "intersect", expect{true, false}}, {reflect.ValueOf([]string{"a"}), reflect.ValueOf([]interface{}{"a", "b"}), "intersect", expect{true, false}}, {reflect.ValueOf([]interface{}{1, 2}), reflect.ValueOf([]int{1}), "intersect", expect{true, false}}, {reflect.ValueOf([]int{1}), reflect.ValueOf([]interface{}{1, 2}), "intersect", expect{true, false}}, } { result, err := ns.checkCondition(test.value, test.match, test.op) if test.expect.isError { if err == nil { t.Errorf("[%d] checkCondition didn't return an expected error", i) } } else { if err != nil { t.Errorf("[%d] failed: %s", i, err) continue } if result != test.expect.result { t.Errorf("[%d] check condition %v %s %v, got %v but expected %v", i, test.value, test.op, test.match, result, test.expect.result) } } } } func TestEvaluateSubElem(t *testing.T) { t.Parallel() tstx := TstX{A: "foo", B: "bar"} var inner struct { S fmt.Stringer } inner.S = tstx interfaceValue := reflect.ValueOf(&inner).Elem().Field(0) for i, test := range []struct { value reflect.Value key string expect interface{} }{ {reflect.ValueOf(tstx), "A", "foo"}, {reflect.ValueOf(&tstx), "TstRp", "rfoo"}, {reflect.ValueOf(tstx), "TstRv", "rbar"}, //{reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), 1, "foo"}, {reflect.ValueOf(map[string]string{"key1": "foo", "key2": "bar"}), "key1", "foo"}, {interfaceValue, "String", "A: foo, B: bar"}, {reflect.Value{}, "foo", false}, //{reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), 1.2, false}, {reflect.ValueOf(tstx), "unexported", false}, {reflect.ValueOf(tstx), "unexportedMethod", false}, {reflect.ValueOf(tstx), "MethodWithArg", false}, {reflect.ValueOf(tstx), "MethodReturnNothing", false}, {reflect.ValueOf(tstx), "MethodReturnErrorOnly", false}, {reflect.ValueOf(tstx), "MethodReturnTwoValues", false}, {reflect.ValueOf(tstx), "MethodReturnValueWithError", false}, {reflect.ValueOf((*TstX)(nil)), "A", false}, {reflect.ValueOf(tstx), "C", false}, {reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), "1", false}, {reflect.ValueOf([]string{"foo", "bar"}), "1", false}, } { result, err := evaluateSubElem(test.value, test.key) if b, ok := test.expect.(bool); ok && !b { if err == nil { t.Errorf("[%d] evaluateSubElem didn't return an expected error", i) } } else { if err != nil { t.Errorf("[%d] failed: %s", i, err) continue } if result.Kind() != reflect.String || result.String() != test.expect { t.Errorf("[%d] evaluateSubElem with %v got %v but expected %v", i, test.key, result, test.expect) } } } } hugo-0.92.2/tpl/compare/000077500000000000000000000000001420147000300147625ustar00rootroot00000000000000hugo-0.92.2/tpl/compare/compare.go000066400000000000000000000201201420147000300167320ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package compare provides template functions for comparing values. package compare import ( "fmt" "reflect" "strconv" "time" "github.com/gohugoio/hugo/compare" "github.com/gohugoio/hugo/common/types" ) // New returns a new instance of the compare-namespaced template functions. func New(caseInsensitive bool) *Namespace { return &Namespace{caseInsensitive: caseInsensitive} } // Namespace provides template functions for the "compare" namespace. type Namespace struct { // Enable to do case insensitive string compares. caseInsensitive bool } // Default checks whether a given value is set and returns a default value if it // is not. "Set" in this context means non-zero for numeric types and times; // non-zero length for strings, arrays, slices, and maps; // any boolean or struct value; or non-nil for any other types. func (*Namespace) Default(dflt interface{}, given ...interface{}) (interface{}, error) { // given is variadic because the following construct will not pass a piped // argument when the key is missing: {{ index . "key" | default "foo" }} // The Go template will complain that we got 1 argument when we expected 2. if len(given) == 0 { return dflt, nil } if len(given) != 1 { return nil, fmt.Errorf("wrong number of args for default: want 2 got %d", len(given)+1) } g := reflect.ValueOf(given[0]) if !g.IsValid() { return dflt, nil } set := false switch g.Kind() { case reflect.Bool: set = true case reflect.String, reflect.Array, reflect.Slice, reflect.Map: set = g.Len() != 0 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: set = g.Int() != 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: set = g.Uint() != 0 case reflect.Float32, reflect.Float64: set = g.Float() != 0 case reflect.Complex64, reflect.Complex128: set = g.Complex() != 0 case reflect.Struct: switch actual := given[0].(type) { case time.Time: set = !actual.IsZero() default: set = true } default: set = !g.IsNil() } if set { return given[0], nil } return dflt, nil } // Eq returns the boolean truth of arg1 == arg2 || arg1 == arg3 || arg1 == arg4. func (n *Namespace) Eq(first interface{}, others ...interface{}) bool { if n.caseInsensitive { panic("caseInsensitive not implemented for Eq") } n.checkComparisonArgCount(1, others...) normalize := func(v interface{}) interface{} { if types.IsNil(v) { return nil } vv := reflect.ValueOf(v) switch vv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return vv.Int() case reflect.Float32, reflect.Float64: return vv.Float() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return vv.Uint() case reflect.String: return vv.String() default: return v } } normFirst := normalize(first) for _, other := range others { if e, ok := first.(compare.Eqer); ok { if e.Eq(other) { return true } continue } if e, ok := other.(compare.Eqer); ok { if e.Eq(first) { return true } continue } other = normalize(other) if reflect.DeepEqual(normFirst, other) { return true } } return false } // Ne returns the boolean truth of arg1 != arg2 && arg1 != arg3 && arg1 != arg4. func (n *Namespace) Ne(first interface{}, others ...interface{}) bool { n.checkComparisonArgCount(1, others...) for _, other := range others { if n.Eq(first, other) { return false } } return true } // Ge returns the boolean truth of arg1 >= arg2 && arg1 >= arg3 && arg1 >= arg4. func (n *Namespace) Ge(first interface{}, others ...interface{}) bool { n.checkComparisonArgCount(1, others...) for _, other := range others { left, right := n.compareGet(first, other) if !(left >= right) { return false } } return true } // Gt returns the boolean truth of arg1 > arg2 && arg1 > arg3 && arg1 > arg4. func (n *Namespace) Gt(first interface{}, others ...interface{}) bool { n.checkComparisonArgCount(1, others...) for _, other := range others { left, right := n.compareGet(first, other) if !(left > right) { return false } } return true } // Le returns the boolean truth of arg1 <= arg2 && arg1 <= arg3 && arg1 <= arg4. func (n *Namespace) Le(first interface{}, others ...interface{}) bool { n.checkComparisonArgCount(1, others...) for _, other := range others { left, right := n.compareGet(first, other) if !(left <= right) { return false } } return true } // Lt returns the boolean truth of arg1 < arg2 && arg1 < arg3 && arg1 < arg4. func (n *Namespace) Lt(first interface{}, others ...interface{}) bool { n.checkComparisonArgCount(1, others...) for _, other := range others { left, right := n.compareGet(first, other) if !(left < right) { return false } } return true } func (n *Namespace) checkComparisonArgCount(min int, others ...interface{}) bool { if len(others) < min { panic("missing arguments for comparison") } return true } // Conditional can be used as a ternary operator. // It returns a if condition, else b. func (n *Namespace) Conditional(condition bool, a, b interface{}) interface{} { if condition { return a } return b } func (ns *Namespace) compareGet(a interface{}, b interface{}) (float64, float64) { if ac, ok := a.(compare.Comparer); ok { c := ac.Compare(b) if c < 0 { return 1, 0 } else if c == 0 { return 0, 0 } else { return 0, 1 } } if bc, ok := b.(compare.Comparer); ok { c := bc.Compare(a) if c < 0 { return 0, 1 } else if c == 0 { return 0, 0 } else { return 1, 0 } } var left, right float64 var leftStr, rightStr *string av := reflect.ValueOf(a) switch av.Kind() { case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: left = float64(av.Len()) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: left = float64(av.Int()) case reflect.Float32, reflect.Float64: left = av.Float() case reflect.String: var err error left, err = strconv.ParseFloat(av.String(), 64) if err != nil { str := av.String() leftStr = &str } case reflect.Struct: switch av.Type() { case timeType: left = float64(toTimeUnix(av)) } case reflect.Bool: left = 0 if av.Bool() { left = 1 } } bv := reflect.ValueOf(b) switch bv.Kind() { case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: right = float64(bv.Len()) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: right = float64(bv.Int()) case reflect.Float32, reflect.Float64: right = bv.Float() case reflect.String: var err error right, err = strconv.ParseFloat(bv.String(), 64) if err != nil { str := bv.String() rightStr = &str } case reflect.Struct: switch bv.Type() { case timeType: right = float64(toTimeUnix(bv)) } case reflect.Bool: right = 0 if bv.Bool() { right = 1 } } if ns.caseInsensitive && leftStr != nil && rightStr != nil { c := compare.Strings(*leftStr, *rightStr) if c < 0 { return 0, 1 } else if c > 0 { return 1, 0 } else { return 0, 0 } } switch { case leftStr == nil || rightStr == nil: case *leftStr < *rightStr: return 0, 1 case *leftStr > *rightStr: return 1, 0 default: return 0, 0 } return left, right } var timeType = reflect.TypeOf((*time.Time)(nil)).Elem() func toTimeUnix(v reflect.Value) int64 { if v.Kind() == reflect.Interface { return toTimeUnix(v.Elem()) } if v.Type() != timeType { panic("coding error: argument must be time.Time type reflect Value") } return v.MethodByName("Unix").Call([]reflect.Value{})[0].Int() } hugo-0.92.2/tpl/compare/compare_test.go000066400000000000000000000251601420147000300200020ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package compare import ( "path" "reflect" "runtime" "testing" "time" "github.com/gohugoio/hugo/htesting/hqt" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/common/hugo" "github.com/spf13/cast" ) type T struct { NonEmptyInterfaceNil I NonEmptyInterfaceTypedNil I } type I interface { Foo() string } func (t *T) Foo() string { return "foo" } var testT = &T{ NonEmptyInterfaceTypedNil: (*T)(nil), } type ( tstEqerType1 string tstEqerType2 string ) func (t tstEqerType2) Eq(other interface{}) bool { return cast.ToString(t) == cast.ToString(other) } func (t tstEqerType2) String() string { return string(t) } func (t tstEqerType1) Eq(other interface{}) bool { return cast.ToString(t) == cast.ToString(other) } func (t tstEqerType1) String() string { return string(t) } type stringType string type tstCompareType int const ( tstEq tstCompareType = iota tstNe tstGt tstGe tstLt tstLe ) func tstIsEq(tp tstCompareType) bool { return tp == tstEq || tp == tstGe || tp == tstLe } func tstIsGt(tp tstCompareType) bool { return tp == tstGt || tp == tstGe } func tstIsLt(tp tstCompareType) bool { return tp == tstLt || tp == tstLe } func TestDefaultFunc(t *testing.T) { t.Parallel() c := qt.New(t) then := time.Now() now := time.Now() ns := New(false) for i, test := range []struct { dflt interface{} given interface{} expect interface{} }{ {true, false, false}, {"5", 0, "5"}, {"test1", "set", "set"}, {"test2", "", "test2"}, {"test3", nil, "test3"}, {[2]int{10, 20}, [2]int{1, 2}, [2]int{1, 2}}, {[2]int{10, 20}, [0]int{}, [2]int{10, 20}}, {[2]int{100, 200}, nil, [2]int{100, 200}}, {[]string{"one"}, []string{"uno"}, []string{"uno"}}, {[]string{"two"}, []string{}, []string{"two"}}, {[]string{"three"}, nil, []string{"three"}}, {map[string]int{"one": 1}, map[string]int{"uno": 1}, map[string]int{"uno": 1}}, {map[string]int{"one": 1}, map[string]int{}, map[string]int{"one": 1}}, {map[string]int{"two": 2}, nil, map[string]int{"two": 2}}, {10, 1, 1}, {10, 0, 10}, {20, nil, 20}, {float32(10), float32(1), float32(1)}, {float32(10), 0, float32(10)}, {float32(20), nil, float32(20)}, {complex(2, -2), complex(1, -1), complex(1, -1)}, {complex(2, -2), complex(0, 0), complex(2, -2)}, {complex(3, -3), nil, complex(3, -3)}, {struct{ f string }{f: "one"}, struct{}{}, struct{}{}}, {struct{ f string }{f: "two"}, nil, struct{ f string }{f: "two"}}, {then, now, now}, {then, time.Time{}, then}, } { eq := qt.CmpEquals(hqt.DeepAllowUnexported(test.dflt)) errMsg := qt.Commentf("[%d] %v", i, test) result, err := ns.Default(test.dflt, test.given) c.Assert(err, qt.IsNil, errMsg) c.Assert(result, eq, test.expect, errMsg) } } func TestCompare(t *testing.T) { t.Parallel() n := New(false) twoEq := func(a, b interface{}) bool { return n.Eq(a, b) } twoGt := func(a, b interface{}) bool { return n.Gt(a, b) } twoLt := func(a, b interface{}) bool { return n.Lt(a, b) } twoGe := func(a, b interface{}) bool { return n.Ge(a, b) } twoLe := func(a, b interface{}) bool { return n.Le(a, b) } twoNe := func(a, b interface{}) bool { return n.Ne(a, b) } for _, test := range []struct { tstCompareType funcUnderTest func(a, b interface{}) bool }{ {tstGt, twoGt}, {tstLt, twoLt}, {tstGe, twoGe}, {tstLe, twoLe}, {tstEq, twoEq}, {tstNe, twoNe}, } { doTestCompare(t, test.tstCompareType, test.funcUnderTest) } } func doTestCompare(t *testing.T, tp tstCompareType, funcUnderTest func(a, b interface{}) bool) { for i, test := range []struct { left interface{} right interface{} expectIndicator int }{ {5, 8, -1}, {8, 5, 1}, {5, 5, 0}, {int(5), int64(5), 0}, {int32(5), int(5), 0}, {int16(4), int(5), -1}, {uint(15), uint64(15), 0}, {-2, 1, -1}, {2, -5, 1}, {0.0, 1.23, -1}, {1.1, 1.1, 0}, {float32(1.0), float64(1.0), 0}, {1.23, 0.0, 1}, {"5", "5", 0}, {"8", "5", 1}, {"5", "0001", 1}, {[]int{100, 99}, []int{1, 2, 3, 4}, -1}, {cast.ToTime("2015-11-20"), cast.ToTime("2015-11-20"), 0}, {cast.ToTime("2015-11-19"), cast.ToTime("2015-11-20"), -1}, {cast.ToTime("2015-11-20"), cast.ToTime("2015-11-19"), 1}, {"a", "a", 0}, {"a", "b", -1}, {"b", "a", 1}, {tstEqerType1("a"), tstEqerType1("a"), 0}, {tstEqerType1("a"), tstEqerType2("a"), 0}, {tstEqerType2("a"), tstEqerType1("a"), 0}, {tstEqerType2("a"), tstEqerType1("b"), -1}, {hugo.MustParseVersion("0.32.1").Version(), hugo.MustParseVersion("0.32").Version(), 1}, {hugo.MustParseVersion("0.35").Version(), hugo.MustParseVersion("0.32").Version(), 1}, {hugo.MustParseVersion("0.36").Version(), hugo.MustParseVersion("0.36").Version(), 0}, {hugo.MustParseVersion("0.32").Version(), hugo.MustParseVersion("0.36").Version(), -1}, {hugo.MustParseVersion("0.32").Version(), "0.36", -1}, {"0.36", hugo.MustParseVersion("0.32").Version(), 1}, {"0.36", hugo.MustParseVersion("0.36").Version(), 0}, {"0.37", hugo.MustParseVersion("0.37-DEV").Version(), 1}, {"0.37-DEV", hugo.MustParseVersion("0.37").Version(), -1}, {"0.36", hugo.MustParseVersion("0.37-DEV").Version(), -1}, {"0.37-DEV", hugo.MustParseVersion("0.37-DEV").Version(), 0}, // https://github.com/gohugoio/hugo/issues/5905 {nil, nil, 0}, {testT.NonEmptyInterfaceNil, nil, 0}, {testT.NonEmptyInterfaceTypedNil, nil, 0}, } { result := funcUnderTest(test.left, test.right) success := false if test.expectIndicator == 0 { if tstIsEq(tp) { success = result } else { success = !result } } if test.expectIndicator < 0 { success = result && (tstIsLt(tp) || tp == tstNe) success = success || (!result && !tstIsLt(tp)) } if test.expectIndicator > 0 { success = result && (tstIsGt(tp) || tp == tstNe) success = success || (!result && (!tstIsGt(tp) || tp != tstNe)) } if !success { t.Fatalf("[%d][%s] %v compared to %v: %t", i, path.Base(runtime.FuncForPC(reflect.ValueOf(funcUnderTest).Pointer()).Name()), test.left, test.right, result) } } } func TestEqualExtend(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(false) for _, test := range []struct { first interface{} others []interface{} expect bool }{ {1, []interface{}{1, 2}, true}, {1, []interface{}{2, 1}, true}, {1, []interface{}{2, 3}, false}, {tstEqerType1("a"), []interface{}{tstEqerType1("a"), tstEqerType1("b")}, true}, {tstEqerType1("a"), []interface{}{tstEqerType1("b"), tstEqerType1("a")}, true}, {tstEqerType1("a"), []interface{}{tstEqerType1("b"), tstEqerType1("c")}, false}, } { result := ns.Eq(test.first, test.others...) c.Assert(result, qt.Equals, test.expect) } } func TestNotEqualExtend(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(false) for _, test := range []struct { first interface{} others []interface{} expect bool }{ {1, []interface{}{2, 3}, true}, {1, []interface{}{2, 1}, false}, {1, []interface{}{1, 2}, false}, } { result := ns.Ne(test.first, test.others...) c.Assert(result, qt.Equals, test.expect) } } func TestGreaterEqualExtend(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(false) for _, test := range []struct { first interface{} others []interface{} expect bool }{ {5, []interface{}{2, 3}, true}, {5, []interface{}{5, 5}, true}, {3, []interface{}{4, 2}, false}, {3, []interface{}{2, 4}, false}, } { result := ns.Ge(test.first, test.others...) c.Assert(result, qt.Equals, test.expect) } } func TestGreaterThanExtend(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(false) for _, test := range []struct { first interface{} others []interface{} expect bool }{ {5, []interface{}{2, 3}, true}, {5, []interface{}{5, 4}, false}, {3, []interface{}{4, 2}, false}, } { result := ns.Gt(test.first, test.others...) c.Assert(result, qt.Equals, test.expect) } } func TestLessEqualExtend(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(false) for _, test := range []struct { first interface{} others []interface{} expect bool }{ {1, []interface{}{2, 3}, true}, {1, []interface{}{1, 2}, true}, {2, []interface{}{1, 2}, false}, {3, []interface{}{2, 4}, false}, } { result := ns.Le(test.first, test.others...) c.Assert(result, qt.Equals, test.expect) } } func TestLessThanExtend(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(false) for _, test := range []struct { first interface{} others []interface{} expect bool }{ {1, []interface{}{2, 3}, true}, {1, []interface{}{1, 2}, false}, {2, []interface{}{1, 2}, false}, {3, []interface{}{2, 4}, false}, } { result := ns.Lt(test.first, test.others...) c.Assert(result, qt.Equals, test.expect) } } func TestCase(t *testing.T) { c := qt.New(t) n := New(false) c.Assert(n.Eq("az", "az"), qt.Equals, true) c.Assert(n.Eq("az", stringType("az")), qt.Equals, true) } func TestStringType(t *testing.T) { c := qt.New(t) n := New(true) c.Assert(n.Lt("az", "Za"), qt.Equals, true) c.Assert(n.Gt("ab", "Ab"), qt.Equals, true) } func TestTimeUnix(t *testing.T) { t.Parallel() var sec int64 = 1234567890 tv := reflect.ValueOf(time.Unix(sec, 0)) i := 1 res := toTimeUnix(tv) if sec != res { t.Errorf("[%d] timeUnix got %v but expected %v", i, res, sec) } i++ func(t *testing.T) { defer func() { if err := recover(); err == nil { t.Errorf("[%d] timeUnix didn't return an expected error", i) } }() iv := reflect.ValueOf(sec) toTimeUnix(iv) }(t) } func TestConditional(t *testing.T) { c := qt.New(t) n := New(false) a, b := "a", "b" c.Assert(n.Conditional(true, a, b), qt.Equals, a) c.Assert(n.Conditional(false, a, b), qt.Equals, b) } // Issue 9462 func TestComparisonArgCount(t *testing.T) { t.Parallel() c := qt.New(t) ns := New(false) panicMsg := "missing arguments for comparison" c.Assert(func() { ns.Eq(1) }, qt.PanicMatches, panicMsg) c.Assert(func() { ns.Ge(1) }, qt.PanicMatches, panicMsg) c.Assert(func() { ns.Gt(1) }, qt.PanicMatches, panicMsg) c.Assert(func() { ns.Le(1) }, qt.PanicMatches, panicMsg) c.Assert(func() { ns.Lt(1) }, qt.PanicMatches, panicMsg) c.Assert(func() { ns.Ne(1) }, qt.PanicMatches, panicMsg) } hugo-0.92.2/tpl/compare/init.go000066400000000000000000000037511420147000300162620ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package compare import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "compare" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(false) ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil }, } ns.AddMethodMapping(ctx.Default, []string{"default"}, [][2]string{ {`{{ "Hugo Rocks!" | default "Hugo Rules!" }}`, `Hugo Rocks!`}, {`{{ "" | default "Hugo Rules!" }}`, `Hugo Rules!`}, }, ) ns.AddMethodMapping(ctx.Eq, []string{"eq"}, [][2]string{ {`{{ if eq .Section "blog" }}current{{ end }}`, `current`}, }, ) ns.AddMethodMapping(ctx.Ge, []string{"ge"}, [][2]string{ {`{{ if ge .Hugo.Version "0.36" }}Reasonable new Hugo version!{{ end }}`, `Reasonable new Hugo version!`}, }, ) ns.AddMethodMapping(ctx.Gt, []string{"gt"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Le, []string{"le"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Lt, []string{"lt"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Ne, []string{"ne"}, [][2]string{}, ) ns.AddMethodMapping(ctx.Conditional, []string{"cond"}, [][2]string{ {`{{ cond (eq (add 2 2) 4) "2+2 is 4" "what?" | safeHTML }}`, `2+2 is 4`}, }, ) return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/compare/init_test.go000066400000000000000000000022351420147000300173150ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package compare import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/htesting/hqt" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(&deps.Deps{}) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, &Namespace{}) } hugo-0.92.2/tpl/crypto/000077500000000000000000000000001420147000300146545ustar00rootroot00000000000000hugo-0.92.2/tpl/crypto/crypto.go000066400000000000000000000051511420147000300165250ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package crypto provides template functions for cryptographic operations. package crypto import ( "crypto/hmac" "crypto/md5" "crypto/sha1" "crypto/sha256" "crypto/sha512" "encoding/hex" "fmt" "hash" "github.com/spf13/cast" ) // New returns a new instance of the crypto-namespaced template functions. func New() *Namespace { return &Namespace{} } // Namespace provides template functions for the "crypto" namespace. type Namespace struct{} // MD5 hashes the given input and returns its MD5 checksum. func (ns *Namespace) MD5(in interface{}) (string, error) { conv, err := cast.ToStringE(in) if err != nil { return "", err } hash := md5.Sum([]byte(conv)) return hex.EncodeToString(hash[:]), nil } // SHA1 hashes the given input and returns its SHA1 checksum. func (ns *Namespace) SHA1(in interface{}) (string, error) { conv, err := cast.ToStringE(in) if err != nil { return "", err } hash := sha1.Sum([]byte(conv)) return hex.EncodeToString(hash[:]), nil } // SHA256 hashes the given input and returns its SHA256 checksum. func (ns *Namespace) SHA256(in interface{}) (string, error) { conv, err := cast.ToStringE(in) if err != nil { return "", err } hash := sha256.Sum256([]byte(conv)) return hex.EncodeToString(hash[:]), nil } // HMAC returns a cryptographic hash that uses a key to sign a message. func (ns *Namespace) HMAC(h interface{}, k interface{}, m interface{}) (string, error) { ha, err := cast.ToStringE(h) if err != nil { return "", err } var hash func() hash.Hash switch ha { case "md5": hash = md5.New case "sha1": hash = sha1.New case "sha256": hash = sha256.New case "sha512": hash = sha512.New default: return "", fmt.Errorf("hmac: %s is not a supported hash function", ha) } msg, err := cast.ToStringE(m) if err != nil { return "", err } key, err := cast.ToStringE(k) if err != nil { return "", err } mac := hmac.New(hash, []byte(key)) _, err = mac.Write([]byte(msg)) if err != nil { return "", err } return hex.EncodeToString(mac.Sum(nil)[:]), nil } hugo-0.92.2/tpl/crypto/crypto_test.go000066400000000000000000000067221420147000300175710ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package crypto import ( "testing" qt "github.com/frankban/quicktest" ) func TestMD5(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for i, test := range []struct { in interface{} expect interface{} }{ {"Hello world, gophers!", "b3029f756f98f79e7f1b7f1d1f0dd53b"}, {"Lorem ipsum dolor", "06ce65ac476fc656bea3fca5d02cfd81"}, {t, false}, } { errMsg := qt.Commentf("[%d] %v", i, test.in) result, err := ns.MD5(test.in) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } func TestSHA1(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for i, test := range []struct { in interface{} expect interface{} }{ {"Hello world, gophers!", "c8b5b0e33d408246e30f53e32b8f7627a7a649d4"}, {"Lorem ipsum dolor", "45f75b844be4d17b3394c6701768daf39419c99b"}, {t, false}, } { errMsg := qt.Commentf("[%d] %v", i, test.in) result, err := ns.SHA1(test.in) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } func TestSHA256(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for i, test := range []struct { in interface{} expect interface{} }{ {"Hello world, gophers!", "6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46"}, {"Lorem ipsum dolor", "9b3e1beb7053e0f900a674dd1c99aca3355e1275e1b03d3cb1bc977f5154e196"}, {t, false}, } { errMsg := qt.Commentf("[%d] %v", i, test.in) result, err := ns.SHA256(test.in) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } func TestHMAC(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for i, test := range []struct { hash interface{} key interface{} msg interface{} expect interface{} }{ {"md5", "Secret key", "Hello world, gophers!", "36eb69b6bf2de96b6856fdee8bf89754"}, {"sha1", "Secret key", "Hello world, gophers!", "84a76647de6cd47ac6ae4258e3753f711172ce68"}, {"sha256", "Secret key", "Hello world, gophers!", "b6d11b6c53830b9d87036272ca9fe9d19306b8f9d8aa07b15da27d89e6e34f40"}, {"sha512", "Secret key", "Hello world, gophers!", "dc3e586cd936865e2abc4c12665e9cc568b2dad714df3c9037cbea159d036cfc4209da9e3fcd30887ff441056941966899f6fb7eec9646ff9ddb592595a8eb7f"}, {"", t, "", false}, } { errMsg := qt.Commentf("[%d] %v, %v, %v", i, test.hash, test.key, test.msg) result, err := ns.HMAC(test.hash, test.key, test.msg) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil), errMsg) continue } c.Assert(err, qt.IsNil, errMsg) c.Assert(result, qt.Equals, test.expect, errMsg) } } hugo-0.92.2/tpl/crypto/init.go000066400000000000000000000034711420147000300161530ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package crypto import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "crypto" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil }, } ns.AddMethodMapping(ctx.MD5, []string{"md5"}, [][2]string{ {`{{ md5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`}, {`{{ crypto.MD5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`}, }, ) ns.AddMethodMapping(ctx.SHA1, []string{"sha1"}, [][2]string{ {`{{ sha1 "Hello world, gophers!" }}`, `c8b5b0e33d408246e30f53e32b8f7627a7a649d4`}, }, ) ns.AddMethodMapping(ctx.SHA256, []string{"sha256"}, [][2]string{ {`{{ sha256 "Hello world, gophers!" }}`, `6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46`}, }, ) ns.AddMethodMapping(ctx.HMAC, []string{"hmac"}, [][2]string{ {`{{ hmac "sha256" "Secret key" "Hello world, gophers!" }}`, `b6d11b6c53830b9d87036272ca9fe9d19306b8f9d8aa07b15da27d89e6e34f40`}, }, ) return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/crypto/init_test.go000066400000000000000000000022341420147000300172060ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package crypto import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/htesting/hqt" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(&deps.Deps{}) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, &Namespace{}) } hugo-0.92.2/tpl/data/000077500000000000000000000000001420147000300142455ustar00rootroot00000000000000hugo-0.92.2/tpl/data/data.go000066400000000000000000000127461420147000300155170ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package data provides template functions for working with external data // sources. package data import ( "bytes" "encoding/csv" "encoding/json" "errors" "net/http" "strings" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/config/security" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/common/constants" "github.com/gohugoio/hugo/common/loggers" "github.com/spf13/cast" "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/deps" _errors "github.com/pkg/errors" ) // New returns a new instance of the data-namespaced template functions. func New(deps *deps.Deps) *Namespace { return &Namespace{ deps: deps, cacheGetCSV: deps.FileCaches.GetCSVCache(), cacheGetJSON: deps.FileCaches.GetJSONCache(), client: http.DefaultClient, } } // Namespace provides template functions for the "data" namespace. type Namespace struct { deps *deps.Deps cacheGetJSON *filecache.Cache cacheGetCSV *filecache.Cache client *http.Client } // GetCSV expects a data separator and one or n-parts of a URL to a resource which // can either be a local or a remote one. // The data separator can be a comma, semi-colon, pipe, etc, but only one character. // If you provide multiple parts for the URL they will be joined together to the final URL. // GetCSV returns nil or a slice slice to use in a short code. func (ns *Namespace) GetCSV(sep string, args ...interface{}) (d [][]string, err error) { url, headers := toURLAndHeaders(args) cache := ns.cacheGetCSV unmarshal := func(b []byte) (bool, error) { if d, err = parseCSV(b, sep); err != nil { err = _errors.Wrapf(err, "failed to parse CSV file %s", url) return true, err } return false, nil } var req *http.Request req, err = http.NewRequest("GET", url, nil) if err != nil { return nil, _errors.Wrapf(err, "failed to create request for getCSV for resource %s", url) } // Add custom user headers. addUserProvidedHeaders(headers, req) addDefaultHeaders(req, "text/csv", "text/plain") err = ns.getResource(cache, unmarshal, req) if err != nil { if security.IsAccessDenied(err) { return nil, err } ns.deps.Log.(loggers.IgnorableLogger).Errorsf(constants.ErrRemoteGetCSV, "Failed to get CSV resource %q: %s", url, err) return nil, nil } return } // GetJSON expects one or n-parts of a URL to a resource which can either be a local or a remote one. // If you provide multiple parts they will be joined together to the final URL. // GetJSON returns nil or parsed JSON to use in a short code. func (ns *Namespace) GetJSON(args ...interface{}) (interface{}, error) { var v interface{} url, headers := toURLAndHeaders(args) cache := ns.cacheGetJSON req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, _errors.Wrapf(err, "Failed to create request for getJSON resource %s", url) } unmarshal := func(b []byte) (bool, error) { err := json.Unmarshal(b, &v) if err != nil { return true, err } return false, nil } addUserProvidedHeaders(headers, req) addDefaultHeaders(req, "application/json") err = ns.getResource(cache, unmarshal, req) if err != nil { if security.IsAccessDenied(err) { return nil, err } ns.deps.Log.(loggers.IgnorableLogger).Errorsf(constants.ErrRemoteGetJSON, "Failed to get JSON resource %q: %s", url, err) return nil, nil } return v, nil } func addDefaultHeaders(req *http.Request, accepts ...string) { for _, accept := range accepts { if !hasHeaderValue(req.Header, "Accept", accept) { req.Header.Add("Accept", accept) } } if !hasHeaderKey(req.Header, "User-Agent") { req.Header.Add("User-Agent", "Hugo Static Site Generator") } } func addUserProvidedHeaders(headers map[string]interface{}, req *http.Request) { if headers == nil { return } for key, val := range headers { vals := types.ToStringSlicePreserveString(val) for _, s := range vals { req.Header.Add(key, s) } } } func hasHeaderValue(m http.Header, key, value string) bool { var s []string var ok bool if s, ok = m[key]; !ok { return false } for _, v := range s { if v == value { return true } } return false } func hasHeaderKey(m http.Header, key string) bool { _, ok := m[key] return ok } func toURLAndHeaders(urlParts []interface{}) (string, map[string]interface{}) { if len(urlParts) == 0 { return "", nil } // The last argument may be a map. headers, err := maps.ToStringMapE(urlParts[len(urlParts)-1]) if err == nil { urlParts = urlParts[:len(urlParts)-1] } else { headers = nil } return strings.Join(cast.ToStringSlice(urlParts), ""), headers } // parseCSV parses bytes of CSV data into a slice slice string or an error func parseCSV(c []byte, sep string) ([][]string, error) { if len(sep) != 1 { return nil, errors.New("Incorrect length of CSV separator: " + sep) } b := bytes.NewReader(c) r := csv.NewReader(b) rSep := []rune(sep) r.Comma = rSep[0] r.FieldsPerRecord = 0 return r.ReadAll() } hugo-0.92.2/tpl/data/data_test.go000066400000000000000000000212701420147000300165460ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package data import ( "bytes" "html/template" "net/http" "net/http/httptest" "path/filepath" "strings" "testing" "github.com/gohugoio/hugo/common/maps" qt "github.com/frankban/quicktest" ) func TestGetCSV(t *testing.T) { t.Parallel() c := qt.New(t) for i, test := range []struct { sep string url string content string expect interface{} }{ // Remotes { ",", `http://success/`, "gomeetup,city\nyes,Sydney\nyes,San Francisco\nyes,Stockholm\n", [][]string{{"gomeetup", "city"}, {"yes", "Sydney"}, {"yes", "San Francisco"}, {"yes", "Stockholm"}}, }, { ",", `http://error.extra.field/`, "gomeetup,city\nyes,Sydney\nyes,San Francisco\nyes,Stockholm,EXTRA\n", false, }, { ",", `http://nofound/404`, ``, false, }, // Locals { ";", "pass/semi", "gomeetup;city\nyes;Sydney\nyes;San Francisco\nyes;Stockholm\n", [][]string{{"gomeetup", "city"}, {"yes", "Sydney"}, {"yes", "San Francisco"}, {"yes", "Stockholm"}}, }, { ";", "fail/no-file", "", false, }, } { c.Run(test.url, func(c *qt.C) { msg := qt.Commentf("Test %d", i) ns := newTestNs() // Setup HTTP test server var srv *httptest.Server srv, ns.client = getTestServer(func(w http.ResponseWriter, r *http.Request) { if !hasHeaderValue(r.Header, "Accept", "text/csv") && !hasHeaderValue(r.Header, "Accept", "text/plain") { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } if r.URL.Path == "/404" { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } w.Header().Add("Content-type", "text/csv") w.Write([]byte(test.content)) }) defer func() { srv.Close() }() // Setup local test file for schema-less URLs if !strings.Contains(test.url, ":") && !strings.HasPrefix(test.url, "fail/") { f, err := ns.deps.Fs.Source.Create(filepath.Join(ns.deps.Cfg.GetString("workingDir"), test.url)) c.Assert(err, qt.IsNil, msg) f.WriteString(test.content) f.Close() } // Get on with it got, err := ns.GetCSV(test.sep, test.url) if _, ok := test.expect.(bool); ok { c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 1) c.Assert(got, qt.IsNil) return } c.Assert(err, qt.IsNil, msg) c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 0) c.Assert(got, qt.Not(qt.IsNil), msg) c.Assert(got, qt.DeepEquals, test.expect, msg) }) } } func TestGetJSON(t *testing.T) { t.Parallel() c := qt.New(t) for i, test := range []struct { url string content string expect interface{} }{ { `http://success/`, `{"gomeetup":["Sydney","San Francisco","Stockholm"]}`, map[string]interface{}{"gomeetup": []interface{}{"Sydney", "San Francisco", "Stockholm"}}, }, { `http://malformed/`, `{gomeetup:["Sydney","San Francisco","Stockholm"]}`, false, }, { `http://nofound/404`, ``, false, }, // Locals { "pass/semi", `{"gomeetup":["Sydney","San Francisco","Stockholm"]}`, map[string]interface{}{"gomeetup": []interface{}{"Sydney", "San Francisco", "Stockholm"}}, }, { "fail/no-file", "", false, }, { `pass/üńīçøðê-url.json`, `{"gomeetup":["Sydney","San Francisco","Stockholm"]}`, map[string]interface{}{"gomeetup": []interface{}{"Sydney", "San Francisco", "Stockholm"}}, }, } { c.Run(test.url, func(c *qt.C) { msg := qt.Commentf("Test %d", i) ns := newTestNs() // Setup HTTP test server var srv *httptest.Server srv, ns.client = getTestServer(func(w http.ResponseWriter, r *http.Request) { if !hasHeaderValue(r.Header, "Accept", "application/json") { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } if r.URL.Path == "/404" { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } w.Header().Add("Content-type", "application/json") w.Write([]byte(test.content)) }) defer func() { srv.Close() }() // Setup local test file for schema-less URLs if !strings.Contains(test.url, ":") && !strings.HasPrefix(test.url, "fail/") { f, err := ns.deps.Fs.Source.Create(filepath.Join(ns.deps.Cfg.GetString("workingDir"), test.url)) c.Assert(err, qt.IsNil, msg) f.WriteString(test.content) f.Close() } // Get on with it got, _ := ns.GetJSON(test.url) if _, ok := test.expect.(bool); ok { c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 1) return } c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 0, msg) c.Assert(got, qt.Not(qt.IsNil), msg) c.Assert(got, qt.DeepEquals, test.expect) }) } } func TestHeaders(t *testing.T) { t.Parallel() c := qt.New(t) for _, test := range []struct { name string headers interface{} assert func(c *qt.C, headers string) }{ { `Misc header variants`, map[string]interface{}{ "Accept-Charset": "utf-8", "Max-forwards": "10", "X-Int": 32, "X-Templ": template.HTML("a"), "X-Multiple": []string{"a", "b"}, "X-MultipleInt": []int{3, 4}, }, func(c *qt.C, headers string) { c.Assert(headers, qt.Contains, "Accept-Charset: utf-8") c.Assert(headers, qt.Contains, "Max-Forwards: 10") c.Assert(headers, qt.Contains, "X-Int: 32") c.Assert(headers, qt.Contains, "X-Templ: a") c.Assert(headers, qt.Contains, "X-Multiple: a") c.Assert(headers, qt.Contains, "X-Multiple: b") c.Assert(headers, qt.Contains, "X-Multipleint: 3") c.Assert(headers, qt.Contains, "X-Multipleint: 4") c.Assert(headers, qt.Contains, "User-Agent: Hugo Static Site Generator") }, }, { `Params`, maps.Params{ "Accept-Charset": "utf-8", }, func(c *qt.C, headers string) { c.Assert(headers, qt.Contains, "Accept-Charset: utf-8") }, }, { `Override User-Agent`, map[string]interface{}{ "User-Agent": "007", }, func(c *qt.C, headers string) { c.Assert(headers, qt.Contains, "User-Agent: 007") }, }, } { c.Run(test.name, func(c *qt.C) { ns := newTestNs() // Setup HTTP test server var srv *httptest.Server var headers bytes.Buffer srv, ns.client = getTestServer(func(w http.ResponseWriter, r *http.Request) { c.Assert(r.URL.String(), qt.Equals, "http://gohugo.io/api?foo") w.Write([]byte("{}")) r.Header.Write(&headers) }) defer func() { srv.Close() }() testFunc := func(fn func(args ...interface{}) error) { defer headers.Reset() err := fn("http://example.org/api", "?foo", test.headers) c.Assert(err, qt.IsNil) c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 0) test.assert(c, headers.String()) } testFunc(func(args ...interface{}) error { _, err := ns.GetJSON(args...) return err }) testFunc(func(args ...interface{}) error { _, err := ns.GetCSV(",", args...) return err }) }) } } func TestToURLAndHeaders(t *testing.T) { t.Parallel() c := qt.New(t) url, headers := toURLAndHeaders([]interface{}{"https://foo?id=", 32}) c.Assert(url, qt.Equals, "https://foo?id=32") c.Assert(headers, qt.IsNil) url, headers = toURLAndHeaders([]interface{}{"https://foo?id=", 32, map[string]interface{}{"a": "b"}}) c.Assert(url, qt.Equals, "https://foo?id=32") c.Assert(headers, qt.DeepEquals, map[string]interface{}{"a": "b"}) } func TestParseCSV(t *testing.T) { t.Parallel() c := qt.New(t) for i, test := range []struct { csv []byte sep string exp string err bool }{ {[]byte("a,b,c\nd,e,f\n"), "", "", true}, {[]byte("a,b,c\nd,e,f\n"), "~/", "", true}, {[]byte("a,b,c\nd,e,f"), "|", "a,b,cd,e,f", false}, {[]byte("q,w,e\nd,e,f"), ",", "qwedef", false}, {[]byte("a|b|c\nd|e|f|g"), "|", "abcdefg", true}, {[]byte("z|y|c\nd|e|f"), "|", "zycdef", false}, } { msg := qt.Commentf("Test %d: %v", i, test) csv, err := parseCSV(test.csv, test.sep) if test.err { c.Assert(err, qt.Not(qt.IsNil), msg) continue } c.Assert(err, qt.IsNil, msg) act := "" for _, v := range csv { act = act + strings.Join(v, "") } c.Assert(act, qt.Equals, test.exp, msg) } } hugo-0.92.2/tpl/data/init.go000066400000000000000000000022401420147000300155350ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package data import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "data" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil }, } ns.AddMethodMapping(ctx.GetCSV, []string{"getCSV"}, [][2]string{}, ) ns.AddMethodMapping(ctx.GetJSON, []string{"getJSON"}, [][2]string{}, ) return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/data/init_test.go000066400000000000000000000024241420147000300166000ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package data import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/htesting/hqt" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace v := config.New() v.Set("contentDir", "content") langs.LoadLanguageSettings(v, nil) for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(newDeps(v)) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, &Namespace{}) } hugo-0.92.2/tpl/data/resources.go000066400000000000000000000066531420147000300166200ustar00rootroot00000000000000// Copyright 2016 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package data import ( "bytes" "io/ioutil" "net/http" "net/url" "path/filepath" "time" "github.com/pkg/errors" "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/helpers" "github.com/spf13/afero" ) var ( resSleep = time.Second * 2 // if JSON decoding failed sleep for n seconds before retrying resRetries = 1 // number of retries to load the JSON from URL ) // getRemote loads the content of a remote file. This method is thread safe. func (ns *Namespace) getRemote(cache *filecache.Cache, unmarshal func([]byte) (bool, error), req *http.Request) error { url := req.URL.String() if err := ns.deps.ExecHelper.Sec().CheckAllowedHTTPURL(url); err != nil { return err } if err := ns.deps.ExecHelper.Sec().CheckAllowedHTTPMethod("GET"); err != nil { return err } var headers bytes.Buffer req.Header.Write(&headers) id := helpers.MD5String(url + headers.String()) var handled bool var retry bool _, b, err := cache.GetOrCreateBytes(id, func() ([]byte, error) { var err error handled = true for i := 0; i <= resRetries; i++ { ns.deps.Log.Infof("Downloading: %s ...", url) var res *http.Response res, err = ns.client.Do(req) if err != nil { return nil, err } var b []byte b, err = ioutil.ReadAll(res.Body) if err != nil { return nil, err } res.Body.Close() if isHTTPError(res) { return nil, errors.Errorf("Failed to retrieve remote file: %s, body: %q", http.StatusText(res.StatusCode), b) } retry, err = unmarshal(b) if err == nil { // Return it so it can be cached. return b, nil } if !retry { return nil, err } ns.deps.Log.Infof("Cannot read remote resource %s: %s", url, err) ns.deps.Log.Infof("Retry #%d for %s and sleeping for %s", i+1, url, resSleep) time.Sleep(resSleep) } return nil, err }) if !handled { // This is cached content and should be correct. _, err = unmarshal(b) } return err } // getLocal loads the content of a local file func getLocal(url string, fs afero.Fs, cfg config.Provider) ([]byte, error) { filename := filepath.Join(cfg.GetString("workingDir"), url) return afero.ReadFile(fs, filename) } // getResource loads the content of a local or remote file and returns its content and the // cache ID used, if relevant. func (ns *Namespace) getResource(cache *filecache.Cache, unmarshal func(b []byte) (bool, error), req *http.Request) error { switch req.URL.Scheme { case "": url, err := url.QueryUnescape(req.URL.String()) if err != nil { return err } b, err := getLocal(url, ns.deps.Fs.Source, ns.deps.Cfg) if err != nil { return err } _, err = unmarshal(b) return err default: return ns.getRemote(cache, unmarshal, req) } } func isHTTPError(res *http.Response) bool { return res.StatusCode < 200 || res.StatusCode > 299 } hugo-0.92.2/tpl/data/resources_test.go000066400000000000000000000134301420147000300176460ustar00rootroot00000000000000// Copyright 2016 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package data import ( "bytes" "net/http" "net/http/httptest" "net/url" "sync" "testing" "time" "github.com/gohugoio/hugo/config/security" "github.com/gohugoio/hugo/modules" "github.com/gohugoio/hugo/helpers" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/langs" "github.com/spf13/afero" ) func TestScpGetLocal(t *testing.T) { t.Parallel() v := config.New() fs := hugofs.NewMem(v) ps := helpers.FilePathSeparator tests := []struct { path string content []byte }{ {"testpath" + ps + "test.txt", []byte(`T€st Content 123 fOO,bar:foo%bAR`)}, {"FOo" + ps + "BaR.html", []byte(`FOo/BaR.html T€st Content 123`)}, {"трям" + ps + "трям", []byte(`T€st трям/трям Content 123`)}, {"은행", []byte(`T€st C은행ontent 123`)}, {"Банковский кассир", []byte(`Банковский кассир T€st Content 123`)}, } for _, test := range tests { r := bytes.NewReader(test.content) err := helpers.WriteToDisk(test.path, r, fs.Source) if err != nil { t.Error(err) } c, err := getLocal(test.path, fs.Source, v) if err != nil { t.Errorf("Error getting resource content: %s", err) } if !bytes.Equal(c, test.content) { t.Errorf("\nExpected: %s\nActual: %s\n", string(test.content), string(c)) } } } func getTestServer(handler func(w http.ResponseWriter, r *http.Request)) (*httptest.Server, *http.Client) { testServer := httptest.NewServer(http.HandlerFunc(handler)) client := &http.Client{ Transport: &http.Transport{Proxy: func(r *http.Request) (*url.URL, error) { // Remove when https://github.com/golang/go/issues/13686 is fixed r.Host = "gohugo.io" return url.Parse(testServer.URL) }}, } return testServer, client } func TestScpGetRemote(t *testing.T) { t.Parallel() c := qt.New(t) fs := new(afero.MemMapFs) cache := filecache.NewCache(fs, 100, "") tests := []struct { path string content []byte }{ {"http://Foo.Bar/foo_Bar-Foo", []byte(`T€st Content 123`)}, {"http://Doppel.Gänger/foo_Bar-Foo", []byte(`T€st Cont€nt 123`)}, {"http://Doppel.Gänger/Fizz_Bazz-Foo", []byte(`T€st Банковский кассир Cont€nt 123`)}, {"http://Doppel.Gänger/Fizz_Bazz-Bar", []byte(`T€st Банковский кассир Cont€nt 456`)}, } for _, test := range tests { msg := qt.Commentf("%v", test) req, err := http.NewRequest("GET", test.path, nil) c.Assert(err, qt.IsNil, msg) srv, cl := getTestServer(func(w http.ResponseWriter, r *http.Request) { w.Write(test.content) }) defer func() { srv.Close() }() ns := newTestNs() ns.client = cl var cb []byte f := func(b []byte) (bool, error) { cb = b return false, nil } err = ns.getRemote(cache, f, req) c.Assert(err, qt.IsNil, msg) c.Assert(string(cb), qt.Equals, string(test.content)) c.Assert(string(cb), qt.Equals, string(test.content)) } } func TestScpGetRemoteParallel(t *testing.T) { t.Parallel() c := qt.New(t) content := []byte(`T€st Content 123`) srv, cl := getTestServer(func(w http.ResponseWriter, r *http.Request) { w.Write(content) }) defer func() { srv.Close() }() url := "http://Foo.Bar/foo_Bar-Foo" req, err := http.NewRequest("GET", url, nil) c.Assert(err, qt.IsNil) for _, ignoreCache := range []bool{false} { cfg := config.New() cfg.Set("ignoreCache", ignoreCache) cfg.Set("contentDir", "content") ns := New(newDeps(cfg)) ns.client = cl var wg sync.WaitGroup for i := 0; i < 1; i++ { wg.Add(1) go func(gor int) { defer wg.Done() for j := 0; j < 10; j++ { var cb []byte f := func(b []byte) (bool, error) { cb = b return false, nil } err := ns.getRemote(ns.cacheGetJSON, f, req) c.Assert(err, qt.IsNil) if string(content) != string(cb) { t.Errorf("expected\n%q\ngot\n%q", content, cb) } time.Sleep(23 * time.Millisecond) } }(i) } wg.Wait() } } func newDeps(cfg config.Provider) *deps.Deps { cfg.Set("resourceDir", "resources") cfg.Set("dataDir", "resources") cfg.Set("i18nDir", "i18n") cfg.Set("assetDir", "assets") cfg.Set("layoutDir", "layouts") cfg.Set("archetypeDir", "archetypes") langs.LoadLanguageSettings(cfg, nil) mod, err := modules.CreateProjectModule(cfg) if err != nil { panic(err) } cfg.Set("allModules", modules.Modules{mod}) ex := hexec.New(security.DefaultConfig) logger := loggers.NewIgnorableLogger(loggers.NewErrorLogger(), "none") cs, err := helpers.NewContentSpec(cfg, logger, afero.NewMemMapFs(), ex) if err != nil { panic(err) } fs := hugofs.NewMem(cfg) p, err := helpers.NewPathSpec(fs, cfg, nil) if err != nil { panic(err) } fileCaches, err := filecache.NewCaches(p) if err != nil { panic(err) } return &deps.Deps{ Cfg: cfg, Fs: fs, FileCaches: fileCaches, ExecHelper: ex, ContentSpec: cs, Log: logger, LogDistinct: helpers.NewDistinctLogger(logger), } } func newTestNs() *Namespace { v := config.New() v.Set("contentDir", "content") return New(newDeps(v)) } hugo-0.92.2/tpl/debug/000077500000000000000000000000001420147000300144225ustar00rootroot00000000000000hugo-0.92.2/tpl/debug/debug.go000066400000000000000000000026211420147000300160400ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package debug provides template functions to help debugging templates. package debug import ( "github.com/sanity-io/litter" "github.com/gohugoio/hugo/deps" ) // New returns a new instance of the debug-namespaced template functions. func New(d *deps.Deps) *Namespace { return &Namespace{} } // Namespace provides template functions for the "debug" namespace. type Namespace struct { } // Dump returns a object dump of val as a string. // Note that not every value passed to Dump will print so nicely, but // we'll improve on that. We recommend using the "go" Chroma lexer to format the output // nicely. // Also note that the output from Dump may change from Hugo version to the next, // so don't depend on a specific output. func (ns *Namespace) Dump(val interface{}) string { return litter.Sdump(val) } hugo-0.92.2/tpl/debug/init.go000066400000000000000000000023471420147000300157220ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package debug import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "debug" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil }, } ns.AddMethodMapping(ctx.Dump, nil, [][2]string{ {`{{- $m := newScratch -}} {{- $m.Set "Hugo" "Rocks!" -}} {{- $m.Values | debug.Dump | safeHTML -}}`, "map[string]interface {}{\n \"Hugo\": \"Rocks!\",\n}"}, }, ) return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/debug/init_test.go000066400000000000000000000023441420147000300167560ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package debug import ( "testing" "github.com/gohugoio/hugo/htesting/hqt" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(&deps.Deps{Log: loggers.NewErrorLogger()}) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, &Namespace{}) } hugo-0.92.2/tpl/encoding/000077500000000000000000000000001420147000300151225ustar00rootroot00000000000000hugo-0.92.2/tpl/encoding/encoding.go000066400000000000000000000047061420147000300172460ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package encoding provides template functions for encoding content. package encoding import ( "encoding/base64" "encoding/json" "errors" "html/template" "github.com/gohugoio/hugo/common/maps" "github.com/spf13/cast" ) // New returns a new instance of the encoding-namespaced template functions. func New() *Namespace { return &Namespace{} } // Namespace provides template functions for the "encoding" namespace. type Namespace struct{} // Base64Decode returns the base64 decoding of the given content. func (ns *Namespace) Base64Decode(content interface{}) (string, error) { conv, err := cast.ToStringE(content) if err != nil { return "", err } dec, err := base64.StdEncoding.DecodeString(conv) return string(dec), err } // Base64Encode returns the base64 encoding of the given content. func (ns *Namespace) Base64Encode(content interface{}) (string, error) { conv, err := cast.ToStringE(content) if err != nil { return "", err } return base64.StdEncoding.EncodeToString([]byte(conv)), nil } // Jsonify encodes a given object to JSON. To pretty print the JSON, pass a map // or dictionary of options as the first argument. Supported options are // "prefix" and "indent". Each JSON element in the output will begin on a new // line beginning with prefix followed by one or more copies of indent according // to the indentation nesting. func (ns *Namespace) Jsonify(args ...interface{}) (template.HTML, error) { var ( b []byte err error ) switch len(args) { case 0: return "", nil case 1: b, err = json.Marshal(args[0]) case 2: var opts map[string]string opts, err = maps.ToStringMapStringE(args[0]) if err != nil { break } b, err = json.MarshalIndent(args[1], opts["prefix"], opts["indent"]) default: err = errors.New("too many arguments to jsonify") } if err != nil { return "", err } return template.HTML(b), nil } hugo-0.92.2/tpl/encoding/encoding_test.go000066400000000000000000000053111420147000300202760ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package encoding import ( "html/template" "math" "testing" qt "github.com/frankban/quicktest" ) type tstNoStringer struct{} func TestBase64Decode(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for _, test := range []struct { v interface{} expect interface{} }{ {"YWJjMTIzIT8kKiYoKSctPUB+", "abc123!?$*&()'-=@~"}, // errors {t, false}, } { result, err := ns.Base64Decode(test.v) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil)) continue } c.Assert(err, qt.IsNil) c.Assert(result, qt.Equals, test.expect) } } func TestBase64Encode(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for _, test := range []struct { v interface{} expect interface{} }{ {"YWJjMTIzIT8kKiYoKSctPUB+", "WVdKak1USXpJVDhrS2lZb0tTY3RQVUIr"}, // errors {t, false}, } { result, err := ns.Base64Encode(test.v) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil)) continue } c.Assert(err, qt.IsNil) c.Assert(result, qt.Equals, test.expect) } } func TestJsonify(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for _, test := range []struct { opts interface{} v interface{} expect interface{} }{ {nil, []string{"a", "b"}, template.HTML(`["a","b"]`)}, {map[string]string{"indent": ""}, []string{"a", "b"}, template.HTML("[\n\"a\",\n\"b\"\n]")}, {map[string]string{"prefix": "

    "}, []string{"a", "b"}, template.HTML("[\n

    \"a\",\n

    \"b\"\n

    ]")}, {map[string]string{"prefix": "

    ", "indent": ""}, []string{"a", "b"}, template.HTML("[\n

    \"a\",\n

    \"b\"\n

    ]")}, {nil, tstNoStringer{}, template.HTML("{}")}, {nil, nil, template.HTML("null")}, // errors {nil, math.NaN(), false}, {tstNoStringer{}, []string{"a", "b"}, false}, } { args := []interface{}{} if test.opts != nil { args = append(args, test.opts) } args = append(args, test.v) result, err := ns.Jsonify(args...) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil)) continue } c.Assert(err, qt.IsNil) c.Assert(result, qt.Equals, test.expect) } } hugo-0.92.2/tpl/encoding/init.go000066400000000000000000000031671420147000300164230ustar00rootroot00000000000000// Copyright 2020 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package encoding import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "encoding" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil }, } ns.AddMethodMapping(ctx.Base64Decode, []string{"base64Decode"}, [][2]string{ {`{{ "SGVsbG8gd29ybGQ=" | base64Decode }}`, `Hello world`}, {`{{ 42 | base64Encode | base64Decode }}`, `42`}, }, ) ns.AddMethodMapping(ctx.Base64Encode, []string{"base64Encode"}, [][2]string{ {`{{ "Hello world" | base64Encode }}`, `SGVsbG8gd29ybGQ=`}, }, ) ns.AddMethodMapping(ctx.Jsonify, []string{"jsonify"}, [][2]string{ {`{{ (slice "A" "B" "C") | jsonify }}`, `["A","B","C"]`}, {`{{ (slice "A" "B" "C") | jsonify (dict "indent" " ") }}`, "[\n \"A\",\n \"B\",\n \"C\"\n]"}, }, ) return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/encoding/init_test.go000066400000000000000000000022361420147000300174560ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package encoding import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/htesting/hqt" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(&deps.Deps{}) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, &Namespace{}) } hugo-0.92.2/tpl/fmt/000077500000000000000000000000001420147000300141225ustar00rootroot00000000000000hugo-0.92.2/tpl/fmt/fmt.go000066400000000000000000000051741420147000300152460ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package fmt provides template functions for formatting strings. package fmt import ( _fmt "fmt" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/helpers" ) // New returns a new instance of the fmt-namespaced template functions. func New(d *deps.Deps) *Namespace { ignorableLogger, ok := d.Log.(loggers.IgnorableLogger) if !ok { ignorableLogger = loggers.NewIgnorableLogger(d.Log) } distinctLogger := helpers.NewDistinctLogger(d.Log) ns := &Namespace{ distinctLogger: ignorableLogger.Apply(distinctLogger), } d.BuildStartListeners.Add(func() { ns.distinctLogger.Reset() }) return ns } // Namespace provides template functions for the "fmt" namespace. type Namespace struct { distinctLogger loggers.IgnorableLogger } // Print returns string representation of the passed arguments. func (ns *Namespace) Print(a ...interface{}) string { return _fmt.Sprint(a...) } // Printf returns a formatted string representation of the passed arguments. func (ns *Namespace) Printf(format string, a ...interface{}) string { return _fmt.Sprintf(format, a...) } // Println returns string representation of the passed arguments ending with a newline. func (ns *Namespace) Println(a ...interface{}) string { return _fmt.Sprintln(a...) } // Errorf formats according to a format specifier and logs an ERROR. // It returns an empty string. func (ns *Namespace) Errorf(format string, a ...interface{}) string { ns.distinctLogger.Errorf(format, a...) return "" } // Erroridf formats according to a format specifier and logs an ERROR and // an information text that the error with the given ID can be suppressed in config. // It returns an empty string. func (ns *Namespace) Erroridf(id, format string, a ...interface{}) string { ns.distinctLogger.Errorsf(id, format, a...) return "" } // Warnf formats according to a format specifier and logs a WARNING. // It returns an empty string. func (ns *Namespace) Warnf(format string, a ...interface{}) string { ns.distinctLogger.Warnf(format, a...) return "" } hugo-0.92.2/tpl/fmt/init.go000066400000000000000000000034011420147000300154120ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package fmt import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "fmt" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil }, } ns.AddMethodMapping(ctx.Print, []string{"print"}, [][2]string{ {`{{ print "works!" }}`, `works!`}, }, ) ns.AddMethodMapping(ctx.Println, []string{"println"}, [][2]string{ {`{{ println "works!" }}`, "works!\n"}, }, ) ns.AddMethodMapping(ctx.Printf, []string{"printf"}, [][2]string{ {`{{ printf "%s!" "works" }}`, `works!`}, }, ) ns.AddMethodMapping(ctx.Errorf, []string{"errorf"}, [][2]string{ {`{{ errorf "%s." "failed" }}`, ``}, }, ) ns.AddMethodMapping(ctx.Erroridf, []string{"erroridf"}, [][2]string{ {`{{ erroridf "my-err-id" "%s." "failed" }}`, ``}, }, ) ns.AddMethodMapping(ctx.Warnf, []string{"warnf"}, [][2]string{ {`{{ warnf "%s." "warning" }}`, ``}, }, ) return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/fmt/init_test.go000066400000000000000000000023761420147000300164630ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package fmt import ( "testing" "github.com/gohugoio/hugo/htesting/hqt" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(&deps.Deps{Log: loggers.NewIgnorableLogger(loggers.NewErrorLogger())}) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, &Namespace{}) } hugo-0.92.2/tpl/hugo/000077500000000000000000000000001420147000300142765ustar00rootroot00000000000000hugo-0.92.2/tpl/hugo/init.go000066400000000000000000000022371420147000300155740ustar00rootroot00000000000000// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package hugo provides template functions for accessing the Site Hugo object. package hugo import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "hugo" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { h := d.Site.Hugo() ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return h, nil }, } // We just add the Hugo struct as the namespace here. No method mappings. return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/hugo/init_test.go000066400000000000000000000024771420147000300166410ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hugo import ( "testing" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/htesting/hqt" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace v := config.New() v.Set("contentDir", "content") s := page.NewDummyHugoSite(v) for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(&deps.Deps{Site: s}) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, s.Hugo()) } hugo-0.92.2/tpl/images/000077500000000000000000000000001420147000300146015ustar00rootroot00000000000000hugo-0.92.2/tpl/images/images.go000066400000000000000000000047341420147000300164050ustar00rootroot00000000000000// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package images provides template functions for manipulating images. package images import ( "image" "sync" "github.com/pkg/errors" "github.com/gohugoio/hugo/resources/images" "github.com/gohugoio/hugo/resources/resource" // Importing image codecs for image.DecodeConfig _ "image/gif" _ "image/jpeg" _ "image/png" // Import webp codec _ "golang.org/x/image/webp" "github.com/gohugoio/hugo/deps" "github.com/spf13/cast" ) // New returns a new instance of the images-namespaced template functions. func New(deps *deps.Deps) *Namespace { return &Namespace{ Filters: &images.Filters{}, cache: map[string]image.Config{}, deps: deps, } } // Namespace provides template functions for the "images" namespace. type Namespace struct { *images.Filters cacheMu sync.RWMutex cache map[string]image.Config deps *deps.Deps } // Config returns the image.Config for the specified path relative to the // working directory. func (ns *Namespace) Config(path interface{}) (image.Config, error) { filename, err := cast.ToStringE(path) if err != nil { return image.Config{}, err } if filename == "" { return image.Config{}, errors.New("config needs a filename") } // Check cache for image config. ns.cacheMu.RLock() config, ok := ns.cache[filename] ns.cacheMu.RUnlock() if ok { return config, nil } f, err := ns.deps.Fs.WorkingDir.Open(filename) if err != nil { return image.Config{}, err } defer f.Close() config, _, err = image.DecodeConfig(f) if err != nil { return config, err } ns.cacheMu.Lock() ns.cache[filename] = config ns.cacheMu.Unlock() return config, nil } func (ns *Namespace) Filter(args ...interface{}) (resource.Image, error) { if len(args) < 2 { return nil, errors.New("must provide an image and one or more filters") } img := args[len(args)-1].(resource.Image) filtersv := args[:len(args)-1] return img.Filter(filtersv...) } hugo-0.92.2/tpl/images/images_test.go000066400000000000000000000052511420147000300174370ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "bytes" "image" "image/color" "image/png" "path/filepath" "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/hugofs" "github.com/spf13/afero" "github.com/spf13/cast" ) type tstNoStringer struct{} var configTests = []struct { path interface{} input []byte expect interface{} }{ { path: "a.png", input: blankImage(10, 10), expect: image.Config{ Width: 10, Height: 10, ColorModel: color.NRGBAModel, }, }, { path: "a.png", input: blankImage(10, 10), expect: image.Config{ Width: 10, Height: 10, ColorModel: color.NRGBAModel, }, }, { path: "b.png", input: blankImage(20, 15), expect: image.Config{ Width: 20, Height: 15, ColorModel: color.NRGBAModel, }, }, { path: "a.png", input: blankImage(20, 15), expect: image.Config{ Width: 10, Height: 10, ColorModel: color.NRGBAModel, }, }, // errors {path: tstNoStringer{}, expect: false}, {path: "non-existent.png", expect: false}, {path: "", expect: false}, } func TestNSConfig(t *testing.T) { t.Parallel() c := qt.New(t) v := config.New() v.Set("workingDir", "/a/b") ns := New(&deps.Deps{Fs: hugofs.NewMem(v)}) for _, test := range configTests { // check for expected errors early to avoid writing files if b, ok := test.expect.(bool); ok && !b { _, err := ns.Config(test.path) c.Assert(err, qt.Not(qt.IsNil)) continue } // cast path to string for afero.WriteFile sp, err := cast.ToStringE(test.path) c.Assert(err, qt.IsNil) afero.WriteFile(ns.deps.Fs.Source, filepath.Join(v.GetString("workingDir"), sp), test.input, 0755) result, err := ns.Config(test.path) c.Assert(err, qt.IsNil) c.Assert(result, qt.Equals, test.expect) c.Assert(len(ns.cache), qt.Not(qt.Equals), 0) } } func blankImage(width, height int) []byte { var buf bytes.Buffer img := image.NewRGBA(image.Rect(0, 0, width, height)) if err := png.Encode(&buf, img); err != nil { panic(err) } return buf.Bytes() } hugo-0.92.2/tpl/images/init.go000066400000000000000000000021301420147000300160670ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "images" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil }, } ns.AddMethodMapping(ctx.Config, []string{"imageConfig"}, [][2]string{}, ) return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/images/init_test.go000066400000000000000000000022341420147000300171330ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package images import ( "testing" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/htesting/hqt" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(&deps.Deps{}) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, &Namespace{}) } hugo-0.92.2/tpl/inflect/000077500000000000000000000000001420147000300147605ustar00rootroot00000000000000hugo-0.92.2/tpl/inflect/inflect.go000066400000000000000000000043571420147000300167440ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package inflect provides template functions for the inflection of words. package inflect import ( "strconv" "strings" _inflect "github.com/gobuffalo/flect" "github.com/spf13/cast" ) // New returns a new instance of the inflect-namespaced template functions. func New() *Namespace { return &Namespace{} } // Namespace provides template functions for the "inflect" namespace. type Namespace struct{} // Humanize returns the humanized form of a single parameter. // // If the parameter is either an integer or a string containing an integer // value, the behavior is to add the appropriate ordinal. // // Example: "my-first-post" -> "My first post" // Example: "103" -> "103rd" // Example: 52 -> "52nd" func (ns *Namespace) Humanize(in interface{}) (string, error) { word, err := cast.ToStringE(in) if err != nil { return "", err } if word == "" { return "", nil } _, ok := in.(int) // original param was literal int value _, err = strconv.Atoi(word) // original param was string containing an int value if ok || err == nil { return _inflect.Ordinalize(word), nil } str := _inflect.Humanize(word) return _inflect.Humanize(strings.ToLower(str)), nil } // Pluralize returns the plural form of a single word. func (ns *Namespace) Pluralize(in interface{}) (string, error) { word, err := cast.ToStringE(in) if err != nil { return "", err } return _inflect.Pluralize(word), nil } // Singularize returns the singular form of a single word. func (ns *Namespace) Singularize(in interface{}) (string, error) { word, err := cast.ToStringE(in) if err != nil { return "", err } return _inflect.Singularize(word), nil } hugo-0.92.2/tpl/inflect/inflect_test.go000066400000000000000000000020521420147000300177710ustar00rootroot00000000000000package inflect import ( "testing" qt "github.com/frankban/quicktest" ) func TestInflect(t *testing.T) { t.Parallel() c := qt.New(t) ns := New() for _, test := range []struct { fn func(i interface{}) (string, error) in interface{} expect interface{} }{ {ns.Humanize, "MyCamel", "My camel"}, {ns.Humanize, "óbito", "Óbito"}, {ns.Humanize, "", ""}, {ns.Humanize, "103", "103rd"}, {ns.Humanize, "41", "41st"}, {ns.Humanize, 103, "103rd"}, {ns.Humanize, int64(92), "92nd"}, {ns.Humanize, "5.5", "5.5"}, {ns.Humanize, t, false}, {ns.Humanize, "this is a TEST", "This is a test"}, {ns.Humanize, "my-first-Post", "My first post"}, {ns.Pluralize, "cat", "cats"}, {ns.Pluralize, "", ""}, {ns.Pluralize, t, false}, {ns.Singularize, "cats", "cat"}, {ns.Singularize, "", ""}, {ns.Singularize, t, false}, } { result, err := test.fn(test.in) if b, ok := test.expect.(bool); ok && !b { c.Assert(err, qt.Not(qt.IsNil)) continue } c.Assert(err, qt.IsNil) c.Assert(result, qt.Equals, test.expect) } } hugo-0.92.2/tpl/inflect/init.go000066400000000000000000000030421420147000300162510ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package inflect import ( "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) const name = "inflect" func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil }, } ns.AddMethodMapping(ctx.Humanize, []string{"humanize"}, [][2]string{ {`{{ humanize "my-first-post" }}`, `My first post`}, {`{{ humanize "myCamelPost" }}`, `My camel post`}, {`{{ humanize "52" }}`, `52nd`}, {`{{ humanize 103 }}`, `103rd`}, }, ) ns.AddMethodMapping(ctx.Pluralize, []string{"pluralize"}, [][2]string{ {`{{ "cat" | pluralize }}`, `cats`}, }, ) ns.AddMethodMapping(ctx.Singularize, []string{"singularize"}, [][2]string{ {`{{ "cats" | singularize }}`, `cat`}, }, ) return ns } internal.AddTemplateFuncsNamespace(f) } hugo-0.92.2/tpl/inflect/init_test.go000066400000000000000000000022361420147000300173140ustar00rootroot00000000000000// Copyright 2017 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package inflect import ( "testing" "github.com/gohugoio/hugo/htesting/hqt" qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/tpl/internal" ) func TestInit(t *testing.T) { c := qt.New(t) var found bool var ns *internal.TemplateFuncsNamespace for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns = nsf(&deps.Deps{}) if ns.Name == name { found = true break } } c.Assert(found, qt.Equals, true) ctx, err := ns.Context() c.Assert(err, qt.IsNil) c.Assert(ctx, hqt.IsSameType, &Namespace{}) } hugo-0.92.2/tpl/internal/000077500000000000000000000000001420147000300151505ustar00rootroot00000000000000hugo-0.92.2/tpl/internal/go_templates/000077500000000000000000000000001420147000300176335ustar00rootroot00000000000000hugo-0.92.2/tpl/internal/go_templates/cfg/000077500000000000000000000000001420147000300203725ustar00rootroot00000000000000hugo-0.92.2/tpl/internal/go_templates/cfg/cfg.go000066400000000000000000000021161420147000300214600ustar00rootroot00000000000000// Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package cfg holds configuration shared by the Go command and internal/testenv. // Definitions that don't need to be exposed outside of cmd/go should be in // cmd/go/internal/cfg instead of this package. package cfg // KnownEnv is a list of environment variables that affect the operation // of the Go command. const KnownEnv = ` AR CC CGO_CFLAGS CGO_CFLAGS_ALLOW CGO_CFLAGS_DISALLOW CGO_CPPFLAGS CGO_CPPFLAGS_ALLOW CGO_CPPFLAGS_DISALLOW CGO_CXXFLAGS CGO_CXXFLAGS_ALLOW CGO_CXXFLAGS_DISALLOW CGO_ENABLED CGO_FFLAGS CGO_FFLAGS_ALLOW CGO_FFLAGS_DISALLOW CGO_LDFLAGS CGO_LDFLAGS_ALLOW CGO_LDFLAGS_DISALLOW CXX FC GCCGO GO111MODULE GO386 GOARCH GOARM GOBIN GOCACHE GOENV GOEXE GOFLAGS GOGCCFLAGS GOHOSTARCH GOHOSTOS GOINSECURE GOMIPS GOMIPS64 GOMODCACHE GONOPROXY GONOSUMDB GOOS GOPATH GOPPC64 GOPRIVATE GOPROXY GOROOT GOSUMDB GOTMPDIR GOTOOLDIR GOVCS GOWASM GO_EXTLINK_ENABLED PKG_CONFIG ` hugo-0.92.2/tpl/internal/go_templates/fmtsort/000077500000000000000000000000001420147000300213315ustar00rootroot00000000000000hugo-0.92.2/tpl/internal/go_templates/fmtsort/export_test.go000066400000000000000000000004021420147000300242340ustar00rootroot00000000000000// Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package fmtsort import "reflect" func Compare(a, b reflect.Value) int { return compare(a, b) } hugo-0.92.2/tpl/internal/go_templates/fmtsort/sort.go000066400000000000000000000135221420147000300226520ustar00rootroot00000000000000// Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package fmtsort provides a general stable ordering mechanism // for maps, on behalf of the fmt and text/template packages. // It is not guaranteed to be efficient and works only for types // that are valid map keys. package fmtsort import ( "reflect" "sort" ) // Note: Throughout this package we avoid calling reflect.Value.Interface as // it is not always legal to do so and it's easier to avoid the issue than to face it. // SortedMap represents a map's keys and values. The keys and values are // aligned in index order: Value[i] is the value in the map corresponding to Key[i]. type SortedMap struct { Key []reflect.Value Value []reflect.Value } func (o *SortedMap) Len() int { return len(o.Key) } func (o *SortedMap) Less(i, j int) bool { return compare(o.Key[i], o.Key[j]) < 0 } func (o *SortedMap) Swap(i, j int) { o.Key[i], o.Key[j] = o.Key[j], o.Key[i] o.Value[i], o.Value[j] = o.Value[j], o.Value[i] } // Sort accepts a map and returns a SortedMap that has the same keys and // values but in a stable sorted order according to the keys, modulo issues // raised by unorderable key values such as NaNs. // // The ordering rules are more general than with Go's < operator: // // - when applicable, nil compares low // - ints, floats, and strings order by < // - NaN compares less than non-NaN floats // - bool compares false before true // - complex compares real, then imag // - pointers compare by machine address // - channel values compare by machine address // - structs compare each field in turn // - arrays compare each element in turn. // Otherwise identical arrays compare by length. // - interface values compare first by reflect.Type describing the concrete type // and then by concrete value as described in the previous rules. // func Sort(mapValue reflect.Value) *SortedMap { if mapValue.Type().Kind() != reflect.Map { return nil } // Note: this code is arranged to not panic even in the presence // of a concurrent map update. The runtime is responsible for // yelling loudly if that happens. See issue 33275. n := mapValue.Len() key := make([]reflect.Value, 0, n) value := make([]reflect.Value, 0, n) iter := mapValue.MapRange() for iter.Next() { key = append(key, iter.Key()) value = append(value, iter.Value()) } sorted := &SortedMap{ Key: key, Value: value, } sort.Stable(sorted) return sorted } // compare compares two values of the same type. It returns -1, 0, 1 // according to whether a > b (1), a == b (0), or a < b (-1). // If the types differ, it returns -1. // See the comment on Sort for the comparison rules. func compare(aVal, bVal reflect.Value) int { aType, bType := aVal.Type(), bVal.Type() if aType != bType { return -1 // No good answer possible, but don't return 0: they're not equal. } switch aVal.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: a, b := aVal.Int(), bVal.Int() switch { case a < b: return -1 case a > b: return 1 default: return 0 } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: a, b := aVal.Uint(), bVal.Uint() switch { case a < b: return -1 case a > b: return 1 default: return 0 } case reflect.String: a, b := aVal.String(), bVal.String() switch { case a < b: return -1 case a > b: return 1 default: return 0 } case reflect.Float32, reflect.Float64: return floatCompare(aVal.Float(), bVal.Float()) case reflect.Complex64, reflect.Complex128: a, b := aVal.Complex(), bVal.Complex() if c := floatCompare(real(a), real(b)); c != 0 { return c } return floatCompare(imag(a), imag(b)) case reflect.Bool: a, b := aVal.Bool(), bVal.Bool() switch { case a == b: return 0 case a: return 1 default: return -1 } case reflect.Ptr, reflect.UnsafePointer: a, b := aVal.Pointer(), bVal.Pointer() switch { case a < b: return -1 case a > b: return 1 default: return 0 } case reflect.Chan: if c, ok := nilCompare(aVal, bVal); ok { return c } ap, bp := aVal.Pointer(), bVal.Pointer() switch { case ap < bp: return -1 case ap > bp: return 1 default: return 0 } case reflect.Struct: for i := 0; i < aVal.NumField(); i++ { if c := compare(aVal.Field(i), bVal.Field(i)); c != 0 { return c } } return 0 case reflect.Array: for i := 0; i < aVal.Len(); i++ { if c := compare(aVal.Index(i), bVal.Index(i)); c != 0 { return c } } return 0 case reflect.Interface: if c, ok := nilCompare(aVal, bVal); ok { return c } c := compare(reflect.ValueOf(aVal.Elem().Type()), reflect.ValueOf(bVal.Elem().Type())) if c != 0 { return c } return compare(aVal.Elem(), bVal.Elem()) default: // Certain types cannot appear as keys (maps, funcs, slices), but be explicit. panic("bad type in compare: " + aType.String()) } } // nilCompare checks whether either value is nil. If not, the boolean is false. // If either value is nil, the boolean is true and the integer is the comparison // value. The comparison is defined to be 0 if both are nil, otherwise the one // nil value compares low. Both arguments must represent a chan, func, // interface, map, pointer, or slice. func nilCompare(aVal, bVal reflect.Value) (int, bool) { if aVal.IsNil() { if bVal.IsNil() { return 0, true } return -1, true } if bVal.IsNil() { return 1, true } return 0, false } // floatCompare compares two floating-point values. NaNs compare low. func floatCompare(a, b float64) int { switch { case isNaN(a): return -1 // No good answer if b is a NaN so don't bother checking. case isNaN(b): return 1 case a < b: return -1 case a > b: return 1 } return 0 } func isNaN(a float64) bool { return a != a } hugo-0.92.2/tpl/internal/go_templates/fmtsort/sort_test.go000066400000000000000000000154771420147000300237240ustar00rootroot00000000000000// Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package fmtsort_test import ( "fmt" "github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort" "math" "reflect" "strings" "testing" "unsafe" ) var compareTests = [][]reflect.Value{ ct(reflect.TypeOf(int(0)), -1, 0, 1), ct(reflect.TypeOf(int8(0)), -1, 0, 1), ct(reflect.TypeOf(int16(0)), -1, 0, 1), ct(reflect.TypeOf(int32(0)), -1, 0, 1), ct(reflect.TypeOf(int64(0)), -1, 0, 1), ct(reflect.TypeOf(uint(0)), 0, 1, 5), ct(reflect.TypeOf(uint8(0)), 0, 1, 5), ct(reflect.TypeOf(uint16(0)), 0, 1, 5), ct(reflect.TypeOf(uint32(0)), 0, 1, 5), ct(reflect.TypeOf(uint64(0)), 0, 1, 5), ct(reflect.TypeOf(uintptr(0)), 0, 1, 5), ct(reflect.TypeOf(string("")), "", "a", "ab"), ct(reflect.TypeOf(float32(0)), math.NaN(), math.Inf(-1), -1e10, 0, 1e10, math.Inf(1)), ct(reflect.TypeOf(float64(0)), math.NaN(), math.Inf(-1), -1e10, 0, 1e10, math.Inf(1)), ct(reflect.TypeOf(complex64(0+1i)), -1-1i, -1+0i, -1+1i, 0-1i, 0+0i, 0+1i, 1-1i, 1+0i, 1+1i), ct(reflect.TypeOf(complex128(0+1i)), -1-1i, -1+0i, -1+1i, 0-1i, 0+0i, 0+1i, 1-1i, 1+0i, 1+1i), ct(reflect.TypeOf(false), false, true), ct(reflect.TypeOf(&ints[0]), &ints[0], &ints[1], &ints[2]), ct(reflect.TypeOf(unsafe.Pointer(&ints[0])), unsafe.Pointer(&ints[0]), unsafe.Pointer(&ints[1]), unsafe.Pointer(&ints[2])), ct(reflect.TypeOf(chans[0]), chans[0], chans[1], chans[2]), ct(reflect.TypeOf(toy{}), toy{0, 1}, toy{0, 2}, toy{1, -1}, toy{1, 1}), ct(reflect.TypeOf([2]int{}), [2]int{1, 1}, [2]int{1, 2}, [2]int{2, 0}), ct(reflect.TypeOf(interface{}(interface{}(0))), iFace, 1, 2, 3), } var iFace interface{} func ct(typ reflect.Type, args ...interface{}) []reflect.Value { value := make([]reflect.Value, len(args)) for i, v := range args { x := reflect.ValueOf(v) if !x.IsValid() { // Make it a typed nil. x = reflect.Zero(typ) } else { x = x.Convert(typ) } value[i] = x } return value } func TestCompare(t *testing.T) { for _, test := range compareTests { for i, v0 := range test { for j, v1 := range test { c := fmtsort.Compare(v0, v1) var expect int switch { case i == j: expect = 0 // NaNs are tricky. if typ := v0.Type(); (typ.Kind() == reflect.Float32 || typ.Kind() == reflect.Float64) && math.IsNaN(v0.Float()) { expect = -1 } case i < j: expect = -1 case i > j: expect = 1 } if c != expect { t.Errorf("%s: compare(%v,%v)=%d; expect %d", v0.Type(), v0, v1, c, expect) } } } } } type sortTest struct { data interface{} // Always a map. print string // Printed result using our custom printer. } var sortTests = []sortTest{ { map[int]string{7: "bar", -3: "foo"}, "-3:foo 7:bar", }, { map[uint8]string{7: "bar", 3: "foo"}, "3:foo 7:bar", }, { map[string]string{"7": "bar", "3": "foo"}, "3:foo 7:bar", }, { map[float64]string{7: "bar", -3: "foo", math.NaN(): "nan", math.Inf(0): "inf"}, "NaN:nan -3:foo 7:bar +Inf:inf", }, { map[complex128]string{7 + 2i: "bar2", 7 + 1i: "bar", -3: "foo", complex(math.NaN(), 0i): "nan", complex(math.Inf(0), 0i): "inf"}, "(NaN+0i):nan (-3+0i):foo (7+1i):bar (7+2i):bar2 (+Inf+0i):inf", }, { map[bool]string{true: "true", false: "false"}, "false:false true:true", }, { chanMap(), "CHAN0:0 CHAN1:1 CHAN2:2", }, { pointerMap(), "PTR0:0 PTR1:1 PTR2:2", }, { unsafePointerMap(), "UNSAFEPTR0:0 UNSAFEPTR1:1 UNSAFEPTR2:2", }, { map[toy]string{{7, 2}: "72", {7, 1}: "71", {3, 4}: "34"}, "{3 4}:34 {7 1}:71 {7 2}:72", }, { map[[2]int]string{{7, 2}: "72", {7, 1}: "71", {3, 4}: "34"}, "[3 4]:34 [7 1]:71 [7 2]:72", }, } func sprint(data interface{}) string { om := fmtsort.Sort(reflect.ValueOf(data)) if om == nil { return "nil" } b := new(strings.Builder) for i, key := range om.Key { if i > 0 { b.WriteRune(' ') } b.WriteString(sprintKey(key)) b.WriteRune(':') b.WriteString(fmt.Sprint(om.Value[i])) } return b.String() } // sprintKey formats a reflect.Value but gives reproducible values for some // problematic types such as pointers. Note that it only does special handling // for the troublesome types used in the test cases; it is not a general // printer. func sprintKey(key reflect.Value) string { switch str := key.Type().String(); str { case "*int": ptr := key.Interface().(*int) for i := range ints { if ptr == &ints[i] { return fmt.Sprintf("PTR%d", i) } } return "PTR???" case "unsafe.Pointer": ptr := key.Interface().(unsafe.Pointer) for i := range ints { if ptr == unsafe.Pointer(&ints[i]) { return fmt.Sprintf("UNSAFEPTR%d", i) } } return "UNSAFEPTR???" case "chan int": c := key.Interface().(chan int) for i := range chans { if c == chans[i] { return fmt.Sprintf("CHAN%d", i) } } return "CHAN???" default: return fmt.Sprint(key) } } var ( ints [3]int chans = [3]chan int{make(chan int), make(chan int), make(chan int)} ) func pointerMap() map[*int]string { m := make(map[*int]string) for i := 2; i >= 0; i-- { m[&ints[i]] = fmt.Sprint(i) } return m } func unsafePointerMap() map[unsafe.Pointer]string { m := make(map[unsafe.Pointer]string) for i := 2; i >= 0; i-- { m[unsafe.Pointer(&ints[i])] = fmt.Sprint(i) } return m } func chanMap() map[chan int]string { m := make(map[chan int]string) for i := 2; i >= 0; i-- { m[chans[i]] = fmt.Sprint(i) } return m } type toy struct { A int // Exported. b int // Unexported. } func TestOrder(t *testing.T) { for _, test := range sortTests { got := sprint(test.data) if got != test.print { t.Errorf("%s: got %q, want %q", reflect.TypeOf(test.data), got, test.print) } } } func TestInterface(t *testing.T) { // A map containing multiple concrete types should be sorted by type, // then value. However, the relative ordering of types is unspecified, // so test this by checking the presence of sorted subgroups. m := map[interface{}]string{ [2]int{1, 0}: "", [2]int{0, 1}: "", true: "", false: "", 3.1: "", 2.1: "", 1.1: "", math.NaN(): "", 3: "", 2: "", 1: "", "c": "", "b": "", "a": "", struct{ x, y int }{1, 0}: "", struct{ x, y int }{0, 1}: "", } got := sprint(m) typeGroups := []string{ "NaN: 1.1: 2.1: 3.1:", // float64 "false: true:", // bool "1: 2: 3:", // int "a: b: c:", // string "[0 1]: [1 0]:", // [2]int "{0 1}: {1 0}:", // struct{ x int; y int } } for _, g := range typeGroups { if !strings.Contains(got, g) { t.Errorf("sorted map should contain %q", g) } } } hugo-0.92.2/tpl/internal/go_templates/htmltemplate/000077500000000000000000000000001420147000300223335ustar00rootroot00000000000000hugo-0.92.2/tpl/internal/go_templates/htmltemplate/attr.go000066400000000000000000000143651420147000300236450ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package template import ( "strings" ) // attrTypeMap[n] describes the value of the given attribute. // If an attribute affects (or can mask) the encoding or interpretation of // other content, or affects the contents, idempotency, or credentials of a // network message, then the value in this map is contentTypeUnsafe. // This map is derived from HTML5, specifically // https://www.w3.org/TR/html5/Overview.html#attributes-1 // as well as "%URI"-typed attributes from // https://www.w3.org/TR/html4/index/attributes.html var attrTypeMap = map[string]contentType{ "accept": contentTypePlain, "accept-charset": contentTypeUnsafe, "action": contentTypeURL, "alt": contentTypePlain, "archive": contentTypeURL, "async": contentTypeUnsafe, "autocomplete": contentTypePlain, "autofocus": contentTypePlain, "autoplay": contentTypePlain, "background": contentTypeURL, "border": contentTypePlain, "checked": contentTypePlain, "cite": contentTypeURL, "challenge": contentTypeUnsafe, "charset": contentTypeUnsafe, "class": contentTypePlain, "classid": contentTypeURL, "codebase": contentTypeURL, "cols": contentTypePlain, "colspan": contentTypePlain, "content": contentTypeUnsafe, "contenteditable": contentTypePlain, "contextmenu": contentTypePlain, "controls": contentTypePlain, "coords": contentTypePlain, "crossorigin": contentTypeUnsafe, "data": contentTypeURL, "datetime": contentTypePlain, "default": contentTypePlain, "defer": contentTypeUnsafe, "dir": contentTypePlain, "dirname": contentTypePlain, "disabled": contentTypePlain, "draggable": contentTypePlain, "dropzone": contentTypePlain, "enctype": contentTypeUnsafe, "for": contentTypePlain, "form": contentTypeUnsafe, "formaction": contentTypeURL, "formenctype": contentTypeUnsafe, "formmethod": contentTypeUnsafe, "formnovalidate": contentTypeUnsafe, "formtarget": contentTypePlain, "headers": contentTypePlain, "height": contentTypePlain, "hidden": contentTypePlain, "high": contentTypePlain, "href": contentTypeURL, "hreflang": contentTypePlain, "http-equiv": contentTypeUnsafe, "icon": contentTypeURL, "id": contentTypePlain, "ismap": contentTypePlain, "keytype": contentTypeUnsafe, "kind": contentTypePlain, "label": contentTypePlain, "lang": contentTypePlain, "language": contentTypeUnsafe, "list": contentTypePlain, "longdesc": contentTypeURL, "loop": contentTypePlain, "low": contentTypePlain, "manifest": contentTypeURL, "max": contentTypePlain, "maxlength": contentTypePlain, "media": contentTypePlain, "mediagroup": contentTypePlain, "method": contentTypeUnsafe, "min": contentTypePlain, "multiple": contentTypePlain, "name": contentTypePlain, "novalidate": contentTypeUnsafe, // Skip handler names from // https://www.w3.org/TR/html5/webappapis.html#event-handlers-on-elements,-document-objects,-and-window-objects // since we have special handling in attrType. "open": contentTypePlain, "optimum": contentTypePlain, "pattern": contentTypeUnsafe, "placeholder": contentTypePlain, "poster": contentTypeURL, "profile": contentTypeURL, "preload": contentTypePlain, "pubdate": contentTypePlain, "radiogroup": contentTypePlain, "readonly": contentTypePlain, "rel": contentTypeUnsafe, "required": contentTypePlain, "reversed": contentTypePlain, "rows": contentTypePlain, "rowspan": contentTypePlain, "sandbox": contentTypeUnsafe, "spellcheck": contentTypePlain, "scope": contentTypePlain, "scoped": contentTypePlain, "seamless": contentTypePlain, "selected": contentTypePlain, "shape": contentTypePlain, "size": contentTypePlain, "sizes": contentTypePlain, "span": contentTypePlain, "src": contentTypeURL, "srcdoc": contentTypeHTML, "srclang": contentTypePlain, "srcset": contentTypeSrcset, "start": contentTypePlain, "step": contentTypePlain, "style": contentTypeCSS, "tabindex": contentTypePlain, "target": contentTypePlain, "title": contentTypePlain, "type": contentTypeUnsafe, "usemap": contentTypeURL, "value": contentTypeUnsafe, "width": contentTypePlain, "wrap": contentTypePlain, "xmlns": contentTypeURL, } // attrType returns a conservative (upper-bound on authority) guess at the // type of the lowercase named attribute. func attrType(name string) contentType { if strings.HasPrefix(name, "data-") { // Strip data- so that custom attribute heuristics below are // widely applied. // Treat data-action as URL below. name = name[5:] } else if colon := strings.IndexRune(name, ':'); colon != -1 { if name[:colon] == "xmlns" { return contentTypeURL } // Treat svg:href and xlink:href as href below. name = name[colon+1:] } if t, ok := attrTypeMap[name]; ok { return t } // Treat partial event handler names as script. if strings.HasPrefix(name, "on") { return contentTypeJS } // Heuristics to prevent "javascript:..." injection in custom // data attributes and custom attributes like g:tweetUrl. // https://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes // "Custom data attributes are intended to store custom data // private to the page or application, for which there are no // more appropriate attributes or elements." // Developers seem to store URL content in data URLs that start // or end with "URI" or "URL". if strings.Contains(name, "src") || strings.Contains(name, "uri") || strings.Contains(name, "url") { return contentTypeURL } return contentTypePlain } hugo-0.92.2/tpl/internal/go_templates/htmltemplate/attr_string.go000066400000000000000000000006351420147000300252260ustar00rootroot00000000000000// Code generated by "stringer -type attr"; DO NOT EDIT. package template import "strconv" const _attr_name = "attrNoneattrScriptattrScriptTypeattrStyleattrURLattrSrcset" var _attr_index = [...]uint8{0, 8, 18, 32, 41, 48, 58} func (i attr) String() string { if i >= attr(len(_attr_index)-1) { return "attr(" + strconv.FormatInt(int64(i), 10) + ")" } return _attr_name[_attr_index[i]:_attr_index[i+1]] } hugo-0.92.2/tpl/internal/go_templates/htmltemplate/clone_test.go000066400000000000000000000200671420147000300250260ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build go1.13,!windows package template import ( "bytes" "errors" "fmt" "io" "strings" "sync" "testing" "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse" ) func TestAddParseTreeHTML(t *testing.T) { root := Must(New("root").Parse(`{{define "a"}} {{.}} {{template "b"}} {{.}} ">{{end}}`)) tree, err := parse.Parse("t", `{{define "b"}}0") if err != nil { t.Fatal(err) } if got, want := b.String(), ` 1>0 `; got != want { t.Errorf("got %q want %q", got, want) } } func TestClone(t *testing.T) { // The {{.}} will be executed with data "*/" in different contexts. // In the t0 template, it will be in a text context. // In the t1 template, it will be in a URL context. // In the t2 template, it will be in a JavaScript context. // In the t3 template, it will be in a CSS context. const tmpl = `{{define "a"}}{{template "lhs"}}{{.}}{{template "rhs"}}{{end}}` b := new(bytes.Buffer) // Create an incomplete template t0. t0 := Must(New("t0").Parse(tmpl)) // Clone t0 as t1. t1 := Must(t0.Clone()) Must(t1.Parse(`{{define "lhs"}} {{end}}`)) // Execute t1. b.Reset() if err := t1.ExecuteTemplate(b, "a", "*/"); err != nil { t.Fatal(err) } if got, want := b.String(), ` `; got != want { t.Errorf("t1: got %q want %q", got, want) } // Clone t0 as t2. t2 := Must(t0.Clone()) Must(t2.Parse(`{{define "lhs"}}

    {{end}}`)) // Execute t2. b.Reset() if err := t2.ExecuteTemplate(b, "a", "*/"); err != nil { t.Fatal(err) } if got, want := b.String(), `

    `; got != want { t.Errorf("t2: got %q want %q", got, want) } // Clone t0 as t3, but do not execute t3 yet. t3 := Must(t0.Clone()) Must(t3.Parse(`{{define "lhs"}} {{end}}`)) // Complete t0. Must(t0.Parse(`{{define "lhs"}} ( {{end}}`)) Must(t0.Parse(`{{define "rhs"}} ) {{end}}`)) // Clone t0 as t4. Redefining the "lhs" template should not fail. t4 := Must(t0.Clone()) if _, err := t4.Parse(`{{define "lhs"}} OK {{end}}`); err != nil { t.Errorf(`redefine "lhs": got err %v want nil`, err) } // Cloning t1 should fail as it has been executed. if _, err := t1.Clone(); err == nil { t.Error("cloning t1: got nil err want non-nil") } // Redefining the "lhs" template in t1 should fail as it has been executed. if _, err := t1.Parse(`{{define "lhs"}} OK {{end}}`); err == nil { t.Error(`redefine "lhs": got nil err want non-nil`) } // Execute t0. b.Reset() if err := t0.ExecuteTemplate(b, "a", "*/"); err != nil { t.Fatal(err) } if got, want := b.String(), ` ( <i>*/ ) `; got != want { t.Errorf("t0: got %q want %q", got, want) } // Clone t0. This should fail, as t0 has already executed. if _, err := t0.Clone(); err == nil { t.Error(`t0.Clone(): got nil err want non-nil`) } // Similarly, cloning sub-templates should fail. if _, err := t0.Lookup("a").Clone(); err == nil { t.Error(`t0.Lookup("a").Clone(): got nil err want non-nil`) } if _, err := t0.Lookup("lhs").Clone(); err == nil { t.Error(`t0.Lookup("lhs").Clone(): got nil err want non-nil`) } // Execute t3. b.Reset() if err := t3.ExecuteTemplate(b, "a", "*/"); err != nil { t.Fatal(err) } if got, want := b.String(), ` `; got != want { t.Errorf("t3: got %q want %q", got, want) } } func TestTemplates(t *testing.T) { names := []string{"t0", "a", "lhs", "rhs"} // Some template definitions borrowed from TestClone. const tmpl = ` {{define "a"}}{{template "lhs"}}{{.}}{{template "rhs"}}{{end}} {{define "lhs"}} {{end}}` t0 := Must(New("t0").Parse(tmpl)) templates := t0.Templates() if len(templates) != len(names) { t.Errorf("expected %d templates; got %d", len(names), len(templates)) } for _, name := range names { found := false for _, tmpl := range templates { if name == tmpl.text.Name() { found = true break } } if !found { t.Error("could not find template", name) } } } // This used to crash; https://golang.org/issue/3281 func TestCloneCrash(t *testing.T) { t1 := New("all") Must(t1.New("t1").Parse(`{{define "foo"}}foo{{end}}`)) t1.Clone() } // Ensure that this guarantee from the docs is upheld: // "Further calls to Parse in the copy will add templates // to the copy but not to the original." func TestCloneThenParse(t *testing.T) { t0 := Must(New("t0").Parse(`{{define "a"}}{{template "embedded"}}{{end}}`)) t1 := Must(t0.Clone()) Must(t1.Parse(`{{define "embedded"}}t1{{end}}`)) if len(t0.Templates())+1 != len(t1.Templates()) { t.Error("adding a template to a clone added it to the original") } // double check that the embedded template isn't available in the original err := t0.ExecuteTemplate(io.Discard, "a", nil) if err == nil { t.Error("expected 'no such template' error") } } // https://golang.org/issue/5980 func TestFuncMapWorksAfterClone(t *testing.T) { funcs := FuncMap{"customFunc": func() (string, error) { return "", errors.New("issue5980") }} // get the expected error output (no clone) uncloned := Must(New("").Funcs(funcs).Parse("{{customFunc}}")) wantErr := uncloned.Execute(io.Discard, nil) // toClone must be the same as uncloned. It has to be recreated from scratch, // since cloning cannot occur after execution. toClone := Must(New("").Funcs(funcs).Parse("{{customFunc}}")) cloned := Must(toClone.Clone()) gotErr := cloned.Execute(io.Discard, nil) if wantErr.Error() != gotErr.Error() { t.Errorf("clone error message mismatch want %q got %q", wantErr, gotErr) } } // https://golang.org/issue/16101 func TestTemplateCloneExecuteRace(t *testing.T) { const ( input = `{{block "a" .}}a{{end}}{{block "b" .}}b{{end}}` overlay = `{{define "b"}}A{{end}}` ) outer := Must(New("outer").Parse(input)) tmpl := Must(Must(outer.Clone()).Parse(overlay)) var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() for i := 0; i < 100; i++ { if err := tmpl.Execute(io.Discard, "data"); err != nil { panic(err) } } }() } wg.Wait() } func TestTemplateCloneLookup(t *testing.T) { // Template.escape makes an assumption that the template associated // with t.Name() is t. Check that this holds. tmpl := Must(New("x").Parse("a")) tmpl = Must(tmpl.Clone()) if tmpl.Lookup(tmpl.Name()) != tmpl { t.Error("after Clone, tmpl.Lookup(tmpl.Name()) != tmpl") } } func TestCloneGrowth(t *testing.T) { tmpl := Must(New("root").Parse(`{{block "B". }}Arg{{end}}`)) tmpl = Must(tmpl.Clone()) Must(tmpl.Parse(`{{define "B"}}Text{{end}}`)) for i := 0; i < 10; i++ { tmpl.Execute(io.Discard, nil) } if len(tmpl.DefinedTemplates()) > 200 { t.Fatalf("too many templates: %v", len(tmpl.DefinedTemplates())) } } // https://golang.org/issue/17735 func TestCloneRedefinedName(t *testing.T) { const base = ` {{ define "a" -}}{{ template "b" . -}}{{ end -}} {{ define "b" }}{{ end -}} ` const page = `{{ template "a" . }}` t1 := Must(New("a").Parse(base)) for i := 0; i < 2; i++ { t2 := Must(t1.Clone()) t2 = Must(t2.New(fmt.Sprintf("%d", i)).Parse(page)) err := t2.Execute(io.Discard, nil) if err != nil { t.Fatal(err) } } } // Issue 24791. func TestClonePipe(t *testing.T) { a := Must(New("a").Parse(`{{define "a"}}{{range $v := .A}}{{$v}}{{end}}{{end}}`)) data := struct{ A []string }{A: []string{"hi"}} b := Must(a.Clone()) var buf strings.Builder if err := b.Execute(&buf, &data); err != nil { t.Fatal(err) } if got, want := buf.String(), "hi"; got != want { t.Errorf("got %q want %q", got, want) } } hugo-0.92.2/tpl/internal/go_templates/htmltemplate/content.go000066400000000000000000000052711420147000300243410ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package template import ( "fmt" htmltemplate "html/template" "reflect" ) type contentType uint8 const ( contentTypePlain contentType = iota contentTypeCSS contentTypeHTML contentTypeHTMLAttr contentTypeJS contentTypeJSStr contentTypeURL contentTypeSrcset // contentTypeUnsafe is used in attr.go for values that affect how // embedded content and network messages are formed, vetted, // or interpreted; or which credentials network messages carry. contentTypeUnsafe ) // indirect returns the value, after dereferencing as many times // as necessary to reach the base type (or nil). func indirect(a interface{}) interface{} { if a == nil { return nil } if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr { // Avoid creating a reflect.Value if it's not a pointer. return a } v := reflect.ValueOf(a) for v.Kind() == reflect.Ptr && !v.IsNil() { v = v.Elem() } return v.Interface() } var ( errorType = reflect.TypeOf((*error)(nil)).Elem() fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() ) // indirectToStringerOrError returns the value, after dereferencing as many times // as necessary to reach the base type (or nil) or an implementation of fmt.Stringer // or error, func indirectToStringerOrError(a interface{}) interface{} { if a == nil { return nil } v := reflect.ValueOf(a) for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() { v = v.Elem() } return v.Interface() } // stringify converts its arguments to a string and the type of the content. // All pointers are dereferenced, as in the text/template package. func stringify(args ...interface{}) (string, contentType) { if len(args) == 1 { switch s := indirect(args[0]).(type) { case string: return s, contentTypePlain case htmltemplate.CSS: return string(s), contentTypeCSS case htmltemplate.HTML: return string(s), contentTypeHTML case htmltemplate.HTMLAttr: return string(s), contentTypeHTMLAttr case htmltemplate.JS: return string(s), contentTypeJS case htmltemplate.JSStr: return string(s), contentTypeJSStr case htmltemplate.URL: return string(s), contentTypeURL case htmltemplate.Srcset: return string(s), contentTypeSrcset } } i := 0 for _, arg := range args { // We skip untyped nil arguments for backward compatibility. // Without this they would be output as , escaped. // See issue 25875. if arg == nil { continue } args[i] = indirectToStringerOrError(arg) i++ } return fmt.Sprint(args[:i]...), contentTypePlain } hugo-0.92.2/tpl/internal/go_templates/htmltemplate/content_test.go000066400000000000000000000331701420147000300253770ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build go1.13,!windows package template import ( "bytes" "fmt" htmltemplate "html/template" "strings" "testing" ) func TestTypedContent(t *testing.T) { data := []interface{}{ ` "foo%" O'Reilly &bar;`, htmltemplate.CSS(`a[href =~ "//example.com"]#foo`), htmltemplate.HTML(`Hello, World &tc!`), htmltemplate.HTMLAttr(` dir="ltr"`), htmltemplate.JS(`c && alert("Hello, World!");`), htmltemplate.JSStr(`Hello, World & O'Reilly\u0021`), htmltemplate.URL(`greeting=H%69,&addressee=(World)`), htmltemplate.Srcset(`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`), htmltemplate.URL(`,foo/,`), } // For each content sensitive escaper, see how it does on // each of the typed strings above. tests := []struct { // A template containing a single {{.}}. input string want []string }{ { ``, []string{ `ZgotmplZ`, // Allowed but not escaped. `a[href =~ "//example.com"]#foo`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, }, }, { `
    `, []string{ `ZgotmplZ`, // Allowed and HTML escaped. `a[href =~ "//example.com"]#foo`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, }, }, { `{{.}}`, []string{ `<b> "foo%" O'Reilly &bar;`, `a[href =~ "//example.com"]#foo`, // Not escaped. `Hello, World &tc!`, ` dir="ltr"`, `c && alert("Hello, World!");`, `Hello, World & O'Reilly\u0021`, `greeting=H%69,&addressee=(World)`, `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, `,foo/,`, }, }, { ``, []string{ `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, // Allowed and HTML escaped. ` dir="ltr"`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, `ZgotmplZ`, }, }, { ``, []string{ `<b> "foo%" O'Reilly &bar;`, `a[href =~ "//example.com"]#foo`, // Tags stripped, spaces escaped, entity not re-escaped. `Hello, World &tc!`, ` dir="ltr"`, `c && alert("Hello, World!");`, `Hello, World & O'Reilly\u0021`, `greeting=H%69,&addressee=(World)`, `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, `,foo/,`, }, }, { ``, []string{ `<b> "foo%" O'Reilly &bar;`, `a[href =~ "//example.com"]#foo`, // Tags stripped, entity not re-escaped. `Hello, World &tc!`, ` dir="ltr"`, `c && alert("Hello, World!");`, `Hello, World & O'Reilly\u0021`, `greeting=H%69,&addressee=(World)`, `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, `,foo/,`, }, }, { ``, []string{ `<b> "foo%" O'Reilly &bar;`, `a[href =~ "//example.com"]#foo`, // Angle brackets escaped to prevent injection of close tags, entity not re-escaped. `Hello, <b>World</b> &tc!`, ` dir="ltr"`, `c && alert("Hello, World!");`, `Hello, World & O'Reilly\u0021`, `greeting=H%69,&addressee=(World)`, `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, `,foo/,`, }, }, { ``, []string{ `"\u003cb\u003e \"foo%\" O'Reilly \u0026bar;"`, `"a[href =~ \"//example.com\"]#foo"`, `"Hello, \u003cb\u003eWorld\u003c/b\u003e \u0026amp;tc!"`, `" dir=\"ltr\""`, // Not escaped. `c && alert("Hello, World!");`, // Escape sequence not over-escaped. `"Hello, World & O'Reilly\u0021"`, `"greeting=H%69,\u0026addressee=(World)"`, `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`, `",foo/,"`, }, }, { `

    '޳'DP(KIb D1Cm # :ˈCþjS9}q? Qq842If491UIZp$:H),LT-C ъfdt0܍Vh[Z=w.@A:HYU.Kd@N&Ix_ ܊ZN|n0A˔ڡP}F14'D/E v!!ʡx92}|q%5-q /kaCJ&$dD`,%Gez?\QLt }/g> ?Ds Dsp\SeÛٝs)na*JnMN4S0I7JOWao"4=je e@͛oiYs 0ݐvlR]ZxB\%P|V< 9 oUU% Vt!xѥDLX3 GU5Pм+pAWCP Qzn֕\OahİGGr3&"hTP[&{%K1Xڧ2uBS9x)La&)vBH<aPB*C*Jn0pvd WTc:?<)`H@\A )!%|!o =˜x_0Ա 9[oZ/^KQI0X8{njINHg+q'ʴNj`)ӷ?} %ZS7=҂C=w͟g8g"%U*2%'*D*4Ǟ{__ ;ќ29#}=1(&xߴE \0@M5NN`Цð'6D180 E2D~c 8ꄆ[B\͜[ã'аŜfrv 7eLn!(DPy*E U0ðDLzR1D1|9 LD WH4e!n>&']LA% ɜ[0pHM&|d0Փ  Q=Qěd:mtfFH#˿U {|7"K6uJX|P_(0m>nSBH %.JOE3vBKupTCIEp/+ RArM_aD{0QRmɱp AzT0vv`xoI?3p|G#lG괮u.Wܢ&'Ia0C0@aVGV PXft8Jɠ JIJ `D MdbCF1}II/A/jc*;ћe 9bM>LdhaXe 5Cx}#"CL3=91s8 }X"D/IАoEdV1k_:l>V\mpqxSB^j+Q⑙QKs>bG,i=^POH,-pVxjȠrZ JHϚRBDC@OZl*2̫࣌/273'j0gBݜw5kVmB2 b RKQM2y& _C˓ .NPhA8NiO>}N"bq2’&g.TSӉ9qCo0G3Q'AVUF-!AbD0]e6F Mu#[L X|u ɠDz =j9~.H!e}Z8Ҳ_#-Nem 6>&gZz{Veb޿ Ҕ#x+>F`Qb}÷:~At=x(^V b/𪈳- #‰ް ! J) (!c?k*GStI-\! {lYN4'=MAPGBY;7' Oi(o3c 1819f{{G[,vdKL!2'ХHDa| b fc( (lY"KCZneZ(YQLB(2 :gN_qAY316X[Rۍ j͠[P)%98ə.S2~:_7mb:SG*"ȷY<0s& ]X|zo}/7){5~I Qaď LbH$|%0,tPVF"fHV|nP"1FM% W.d 9QBx'g0]MT+4`Hj1gIB%,O*)\b͋-IA(?A eX8@񃁍,{EyGyp!#}eG!IaRj&'# ݻfo^bi JrT!W E$1bjo>k߳IpF!Z6j(.cAaGSB&<%`Ec{m= c((Tl|FfДO. RT!PJ"CPy"!4 JT!!)ae`?dH5 vJV}/ͱ|*CtHou: LeTCQs$By c=B_ăOy^G*YFPą#:] Ay _5mǻ~:/C$`Μ'<"RfF}Ț)7^]#@mE'@(FWBD(`|l!%0 ʊ #j) )A]cǁRAhP]3ghወ +3^_TJBKʌ" ;@QJ>cW+-pCf}!A4 ?Xt|_[ ýŀ BؒɒJ7 DH(jb` %+*QM_k(_2)|u7>.&#ʓ6%6 m%\(* 8G(R8Ԇ B2ZAQkAʑZE`H2E[`_k_z祯Q|i;64|u A~`p}85 ހtA% "JtJ3ڿ+p'fJүOCعB(aۇ_)Ё77kPQ_TnPeӐ@ H! {UDdwBpGzJW0fPX>}>>;gNkB*9Q./ ABɌ73ƍ҄P~wƄ%R@='"W w CFpLX@C1!oQRjFa#E`7Bw|T_EXRegS~. TB?&ls31v ZFCg>v,c3i$* B@(ڍNtk] _yg:!]%t;IŊB %GwV ׀eR !ISķHbFDŽWk71ƄSmZAa'My}CWGm()Z:Aa aSWJ8{\ PFĻ PxI& **Nh3hRĘP: TNb#;@j%=̕|(1ä\JjK&Lf- Q>FjRC,*:ې!~n ŃBK4—>v) h9:8gGYqw܅ ao:h1"a#4CVw̔E:fl\y~˝DWw{KOr9+3~QNXR[JaG2UHfc<$F(ABG !Ϗa=p n%O0{F٥\41c} Bgp~Krd~hC͠P#(GIٙN P)%(=!5, 5] ۊ'Jݑ*DK)m9ҭJ޺BhG(,#SKngBx̲;?pB5V-T`'L N(%Z Q냱^SY+~ 4J;2yHm=FzJy섻dfs8( ffU&[ Ob P?RJB`ජ:^)l> :R趯p2ڍ%GQ)JB1a_XS^BnI܉^CȆ %UΕ;fحR3yFAB !njkC4A‹Cx!E)Xkrr wԼשsS BK 31*Kur'%4rGPԢ*'6G6H#PAػ7 )ڍ&@P̢ČܚO;&DD5`h % vy ń:W,PfMZCG~T)0 -r ٵ9٫ֽu'*1vL>L\\:UՇ}˚lQx A7* ܌e&̋_'4 P)᫚6&!cQK7 tT}_7&׋nLaFʖhw^px8O# QL( 4\P@QU.Ca!s!) ){߉Q !KR-@Lq|sh]\n«|D%d *7`E +JS)#2Wœ5!#*! J0 &ݹoIeUB!_Mۨ|T@S*LB6:  {8O7۷3rB$?VT$)#=(y4B}2Ąn[c Z _Uy.\8;j8Y5嗁USBuTb&ᑌ=<Ω3A3@2Ztp㖴5o ̒9w3IW'd\iǕ_1,?33…xx.OBd/D? BdQ!/$*a]ꭴ5{*bR|8;+a+- 4ǷJH$nJTo fТ0~)BmIvNlEs̨9؏fwZ%P(.Z ^j&A&f,ei!d/j%)1\ aS"Т0B1786ZӔ0SvTݞ(sfi1 “`P HQ6?_6*d&ܰ=Ҽ,՞g!7Oaq-x]ݙ++NAö0LO?Nɐn5ntPs<5^HL*aEBnj/WBy, %=)ض{AK2bB6 + (R{B~Op p&~;3hC (ܦJ ,ͣE; r5Kvwb .?%G 7R IDAT4)pVAbӨղ&h2<3غ}B6_]Pqh+p3)WXEfS F"Bu"^jl~FӕvK 5U#oL0vʷF<@5-=PP(iPq(?<p E( w *d&݂ Ia A`DiGMTB5cPYSU CJOeG U*oK:UYoʗ !%j-Yn7$0p5}V{SBVOsv(ܧz /ieYJ(w*_ձ>pGKm/3ѫAaHA033_aB SPka2aa((+a(D3a5n-T['f<% odFw&1 PBlo&w.!Fss33 Q,P*Iڻgd@E Oa ʌ;]% 68,$lJD?z)!xQJ "%T ʜ 0BrbFfG+3Ąehߤ]PWJ rY.ضf2t'w;3;Q#.* 㐴׻P/l: }4'?>}yYC:PVfnuh|4?zVBP*Z8[ƄfJXf<V0]v%406֡DҲp:nt-lvk0Ǚ)o;|>33AXX1aSJ A^8(ѿŅ(dsh5b'Sn{eݕ*X뗬ԏ7: MfBW !J>ЫBZLy f"p>1&Š&㩻>J⽣|~.!CvTꥤs hɻGxS^h1\忬C!Sjx2eELdU B5f/ ՜hgx ;za0 )!dtJQYxĴLjh{;ъ:!^&LFҕ4SiBw:\$c7)L@XR_h_yY)ts3q)nDOh:`33dnjCfʎr+Lppʘj̖63\gCX؞B*QЇ۬ߧMuB̅_p[F,mrpF@BXcvcf& cKڃZ"853*Pх u~ Sڗ&%w,v4qkzoo.;F"YTh!(̥^Bp89*GL DuWPW4!MJxGQ-R(9/sZ}0GSAbL3$G[LJ _x 3*aEY?uJXʖh.aN t\2T0Զ$ܨg!VavI'6{ ).I9f4 EH SB)Nj4.\2iee ݅0%|V3 dp#c-i:ao73 {0:h{w@#q -njǛ6oR;f4Z |//Q)M;M1;juس ;C$ftdX߶ f'./R F̘֙u Oe0hG3Jˌ"!4J ͠bVLh]ϕ'plS`+ oמpw] %flfv̔jG!ax9,/?$?ԤZoQ8xgaI铼?WLRPJ /2iQHK+xd;ZֿڪkРDqb¼n>Op:_ɛ{Yh;! 78t>«7ލ>CmV U(^x0|I*E,;^Ϯ=׏ y^J#c~BoLh.zKM"H ;f=gvL5~yДbvC$h($ġ}5wCpzCb= \aoʆp`;񗒣IAaD m3 aPMpPRfmv^fGs9gtLU ܥFԘ0aeƎs~Ί'7$޶hj(:~уr>Zkv:DN||[`u\.<}EP[e VBW*!JhzGۖ$T/OuBO֑_+y3v;;Sb})nM^ro$7KqkҧDIW/~~G ̪/-\oat䠧2|3'!\Ln 2dbOT^&-=!OUvtlzx;LI̸R #(8v:SRwQ𞚄9{RϨI;mw๣;*eKD(lnȰv4<9TeңWYJ8q+!g9"i^Ƅo1!/„Z s*CEcfqSEmy2zGDNSebŒ`w^İ6- 3(1W Gր%2.;VZKR&fT>ƌ/ul aJKmR2F,-x+Զ +gy;܍.ޫ2k ~f1~f[x[RA7WpBV<&\%&,˲7͒J7JhRV0mXeKRf$)G+3҆Q(pV[yQEI|,A 0g[Tayao VJPMΞ-`?n uBH̬azhmqb¢ H{, l2,b^% Bx-ZLl)&5!Sph󇗄k5Z ly*kKt?Cʣh SBXo1-,0;*7Ϡ-n\AOpmV ?2!j%oقpqr>)CXm͸&Xצܠ=lՎ&r/!%$G.t!\,9\0M ҩn K3>(ySOs EGQš_?(Aowp_yT0 . HaӫeM+ S&'0ݍC]&Qʋ?zUfK ń!),JZ=T%|Sܘj &$tn6[QLḐA(a4۝1/_?sk8g|޽xܽGԿVӁ RB23@V(!\QcYe VhqZ }LW{ם cG%$+ MZF,QB͠~) Rkaljq6YhBy~44{%t_]W,0!#_ + 7(EUvff…cA)̜ˮ )1:x:!ѝ_ec)!eҜ}M?6p/2J8T'Wف1EEQ(vgz NUi|a%·TC}^<7JᏜV|m[3Ao3 !$ +! )f%[Đ?NYo+aQBGܥ@!,G߷'9v"nebur%gU-\/l)_GOue&4 r=))vT?<;!CJG0\W!4 Z>^Kw Lp}0ƣ -K PBdLəM_(eG/UG ܮ5$B2);JĘ\w:fuG3@Y =.jfRi?{ƌA}; "#*:u VQD@ |hAM[OԊ|X8|pkkk'qG_ta[?na܍& Q ˩.'i!{킰M\cJFNE aPLJ q+_B׏Ҟ^iG+**;^|7ʋL kx !`$ll/=TS!a?`LxS^YBoǂVOvBXZ-!o~x+E<$]k:JB9d7 {?T3XV(v5H%,'fcŠĶ5;C*İUEȡCpй3?>ȇeaـ,W{mg06&=*~]BߍJ â%M~^S3sX~|p!lX-7JeztOA!IB@.+ Dik)1aNr" a?]g7qlٳ_lyD5;gU't稭Db[ o:) 7F s/tO!pOЍf\PɑT?/fzXM iP3NQh!lyӣBBQJH w-]%fƒbǎ*%L,ZЛBE%JɎ.ZaFHsAZIh!TKB$6v Dž(#W=dm[j# ?2{xʆt7˜g:flJ [J;A@V1 B g)I *=ʥpFNhoƄ (*x|#_.Z*{ް()Jp~|A!*Ϛ9~-_?;/SX )!@H&h Xė8J7)xQ J7JpZw $A,94& #jHp}#( ඤ8Jq8j8ҏ.ѕk_U,)%L bPUe@hܨo(ցE)T w&/5CVDžP@8b#ҏrd©BT9j kyupe!iQKTA%B#ç¶BP a9RO䜜O  AB¥JG] ivB_]0?Z-!phJ {xUv{) $7ZC sj3SmCF+m"io ވ|nD)d*aeA{= !"$!\$a7CACFF .34kWj) P11"jG.1KK D5c!Uq~aͨ=s"ѥ0aLéT"~3Hᰇ܌ΘyY$0K0_{ŠOO$ a>!Sk 0B@QjԄ*L˔.DbP(SX~U Ąy "XBֽ! )Tydw2[(!QI?p*1+s!C*)T4,<&k O02x`n0(YhziK>KvLQLʈOeJeⅉbpB| * 0 eeD.b+W5`1d4J^9\ uPÔV/̾]tp|L Û16ܰm q)@!8R#nl{!P^LLoA $7Z8I+~ȑڍP5&UF CH _PaG!t0é.5٣@_Vk)D9\ 3}%)Q 4l8~ IDATT0 b(@ mkaB[7ojCn I#uZy[[dď>:ښ  7BO ȡ 9e0ݍ^Q*OX1eT(K&H-0a1a5DD)T Vi)N$'F`$Ωq>%MP:F# u*Kj0PQ-'e&>M`A(N0hX!EL+ &i90(+E VUM)vT +D QH3GJ4ӝ m=}3A!axhXcq-^"J/P PbfFQJkA _xsI!ǰ 1#ZQl~dT(%E V/&CnE ] N%z+o]33=|Jj5ko56i#8RtZhp෇NbxI^Z1+(/-hFihHXCHU-2$Bo1( b8jلe˘.%DC( a9+Mi,Za !8.ZuŰ_3PLt rf=La?/!28D 1Hg$OQjPAdp ġ{8bCCoZ&DPԃe B^}asGfh{0T ݷ,M6U uڥ1;:^&,2.\L ZF^10%?cuD0&5H!ibFݘvWw3ƺTARA  T# Ye~(W{ cNtϯ,f4F۩: a\ z= +/~b> X)pDK[͒ \F:(QBipyГ +Ѣ :e j}6CBh0\U'guY懦.d\#3608f5‘I|[2f͜M[|t.|q0 x}B+KP08WEy7PN-!1r_b/FC؄nA KL\ 'LpeIbv))!\a'ъ vXn.NA 0BDŽ+5 ! ,O&hz ٪ %j@M1&\S+9k<ç &=Wz%}'|@0x0ȉ80 a[w ;Aw- )G |j C NҞ25ہC'ZwƦK8"&%G]&Pń$R _X.P<'Z(CC/%cOз%|̗I-)nn\G`c#8Eڒ ׆Z˓21̹{zsl`FК1 k[Apc=i,@C(WCOY23fգdɽB "!;6r> >5AJ4Ci-}y(oYSnDWBFR !C02h +I |_#RTF@R~W#D7IA"P b89sj0)gn[341+3ths74t3z/1+Ka vRq⊕DKyd[dQ= _~'tYlǑ u.tQy#uBƠ&q!(а:Q#`p mEiZX -BgA:oԅJz^G2'` j `(ޔ~)CvOù)| K,1|Y<{^3w\EOyBڮS+ϒO%(}q-.ۦk$RL0ĨrAㄆ:T4NAKA=!)!'W-ZNmBpMZj3ek6ړ>Y ? u0`D}uuvY,1ekCq}7N1E0MiN-c E) zB8A~,v^4B#%%Gҏ"D J+Z=kjA){10D pFpAԓ/&#Z=3$sb8Јa6 ӂ F9AF;X^Ti,1B0`<,PvY-}pvD*w7t^z*BH~P{.r3pJ8Ra9! bST j' ÉA=4.GbdzepYk  7Bj|F[ Ttc0v=8?h'TwJ '2hY ,X;AGӅPfGVq31\6ޥhG5a עJ Z yfcj/AToA)H* 5 B- A% Vg(e@pSuw596nd96'`OyĞaeh+W|j_t/,qxRa0F;Blf;Q agw}PBG@مfuhشD7;ȁe&&5Tu4UOɇih>'a,&d4u.2) M i/޴`S!Zl ֳ>7o}/nM߽&xq(tT՝@u!WƐRR!r(C u>4X,588(_肍*4^% ݫڥa8'V3"yD18H]Ҡ1QTDihqhZ{<Ɉ+?)X -gb4`\EyB+M6aƄnI Xdj)1.WS.V/qr$ ^B=A7.nz}Wٽa8buP0Df{o쏕 [3.mBFL?=^H [nSi'!,D{W= La> J@[wl& 9&*rA}OgޤY=i2ۨ3=(,9ERхbBpQ]A*CPFp `DšFPT,2N ڄz8Bp8] jmQ `| k hqj%sh(&P".G"wIa'O>)(? xT3ULP= *GZa-#B ưŔ`!3Q{i=(GnK9O,2bO*apK CGq gʿaH5(T׃%BpХ3RVyA(ulA WWMR " !ؐ\ H)!P+Zv ZdBEń3Ad<ah@$GFXktdCCXL:TN% O}[t,Aq F$SAAܷ: } -×6P . ckQFbM8*|tn3QGnBj0tHϿt2QB{ pEeB!!H:rY' 0'X-#-1ߺ(dX J9"SB ShpARl0"Pbl z ` я!Csrb mm@b':X] 91374a$ $jn|j@ݞPm3׃.yUsHGCj^eD x%F~ gA2!B*\QqDx b0hpx4iQ}~MEd5xE( f)`8TC02ȳFh:$VC bpgƨ~|"`Wi| Q(2,|Px[!lB Ȅ_vx /cWlBBpc~n*歚PHM>R"8K HE  jUB].VW':{3J` E" XPmkЈ6[a^Z-#6#cKN3EWaЂbee@E'Vnwܙ~a4*0@'%}1!wf~Մ o* qc 5{~0A(dx]q@^7YD'&C D8a\YxDH* Wq [H27QA=yњpb@PB:r%֥˸/;$$}t+|%, B܆@nVbBOrx.XQ[y0.2SD ^ AAT|!ԲA7`p܉vD1B ?ʞBb aAb_kki(^(*g &!ol\}hFه. /ᾤ0^ !x AS L!8.\ [^q.P8dQ' ?\$޺":&U>]ZRNQ ҞZK;%v_(Jx%a9C1%k0z!ĉaMI {X!Q5G(2`HeB𚛒jVvҜI윛kSΡ/gm#1r9B  ˊAQ!b Dك-k!Aۂ oBpX#RtaP@DǖȆH=!.S%DLG`Q`СĘtl#~0.P>xμ ԟ Lt6&$ʠ^G Ń 1~,i95!bIh%KvI Ze9V&Ȅ{W˨۷EB ,B؋*B 3EhWz(=V>b24FZ,J0a永8AG1(&>Ox>Cܴs_ g{TZЭ 3,mԘaMxW-8fEB WڐSRV!`;,U:18KZFa2J2#HP-Kׄ-Fp1 B 2#rna]-ĄvawZ ȎF >M(s kP_y(>XKn@@M&bQQGmϜ(6E6#`a'L6wraGɃYM6 -WA M }@Wmn-ow<&0vT`w714 )84횐7Kpi"8xRFDvP <h0 sg46%Ch[Gf2 m۷2-ufNG CP!8ש0$B!ssApvA+!2xTx@! =gW& #IAEan\ HaA6!PHDiZŚB O &O-s`2~28mۘ3BlL(vdDؓhsvQa3UdB dvRF%ae%Gm ɨ*WtTLx hBĐ\&SZ!EobhT42ݖp+ƦǦDFxqfxt`J}MxWLfMB=0 nчݶݟ1GGڣmܗps ))젎IDATdT\;˝!uHۈADёaeYdB`o(WdBEkI(B JHa?2!% nor؎LV`]~ k 1dp 1ԛ@..^*fMчЭ#â⤈(ϱ.udO,4djۜ +ҟ cRLΌ{bm~fmpW@4g6DŽAY!"[|6 R9X QJE"*$n >-~(\쇅c$p7`XDp Xިs ). 94tRIw[`01-!(tN$= F !eBasTwf|%ڏmŃ| 4&;E!ܨaP?9e2"TUa28Z$ R>nPTV~tTOIXr=*<]hLjVy^f q8$18iAQH=(lD}Vu!rX ҅`X""1^IbDdB~`Lsߗq9g rT^xgP8̈ 1U&|s^fH ,H}k`PG^ #E91٦Uu)qYB8@?PTXmz2ܒEBBE. @+B .eBѠ` P8U N9c* }r %$HpwLdYG}810/s./=U)í0A&lgCk=)PLՕ1ho3%dBXRRJ p_R )FQ!,8* i5SH1 p:*MH2 E/q@aD0]6UJ51ZAw *.[NoZ~c빎}1 /PdP CxQc8, ͱQ!ːA $mmRZ"@ Gq Vh ɄբSdBrej&$ Gok ATA"H \Ca0hiE}l 㚮aw!>]E 1ӜEէ!szqJSypsSe2qSs~&W|o_W Cf(T( qB!}ӼPɄ2# 1,bYH(x[M)d DV L6 (1HD 後0!xU!׏F&'-P2d=2,XxP8k$ 6I K]kX2,%pK8ҕ> vE>Jgb )[o_Urۗח s|_aMH2 g=0S!8$ckY@0a+NA)ݎKQax))'X`@LxB9gu P]I\:U2ݖ)#) T`tXvՀN >L]]&1xiLJ@0AC>/g%4G$P>0abL2=i!OHo#6KNöNc66!$DXVhj 0mJE- Ԅ'ńA80 k؄:~Li)Ex 5x %z^~BM[v*7@p4 :eW2ySܗy3 ӗ9M_FA8G*hw8oz\.  2FVIk&PTf(o ^LhaX V:* PDHqsQ !b2JKTx\=ُ;dEPeD Ab276EzñzdL(a,vHfaq`_>9v`: FߗYs2k}_}T~!>(^JM(# Ɛ;37ٯwל2<@ 6.& ۃ&QTTs>B.G+ù!"xa62x['xTXtE8YÝQPD!R jlSzV!n bR%D`5[Qlɦ#̠DŽ̫oլ)ssg](a w(ČPB*ic:~oǐF5"FL=h0Gy](U@auOa63Ba-QK!y0“a%BC@o X3Y)3 BDFO4rMX___Q@ˍJVҕ'>S4ϒ`A*=r_i2R;e 32!e(P,s: ݰtj6 /X8jWh(X REHZP\FkU2 hlAY% @Ma0De"$ e{TANEuR Ha=!8)iÒ]w-vVϙC3OY]^^=E|29eLE䣟5jBk\"C}C ÎkN>ګY|u:w< 9l "CzMHr>J ń`)Ֆ5lTa1!5E2Mn:j7-PpJ14]1 0HKѮ k`ZOAG@ُ-R̉0r(l+$Jї_ d4LHr[ۣ߂sZ_.ZFez]]xEX$M'Hh"քet[QGk vF 9*@a W)r!{P׃ԕqz^׃H@Zne$ND^9L(19ք5ᶋU/{Zh:2/!Q) 1|P CmЬZ3ӝB^u$B5!Ai,!ذB PP#x2a1!e9ڴ A8,İF-2 uG+4H&zJE Cv0KrďRj0;99Ԡ~w2l@t4[weLF1x$sqrѠ Y5?A1 "(CAmBNH*"m'P#(]!i6;,IqH"pEM u*Z堪@Pz2@:TlPRܚ LƐC/ 2Eښ{h-/ss (gdB]RIȽ[<@oYfevO Ʉ$:2ar$ 5H!qh0$+ ! #B6\rA6<(,2XMx\yucB PLXLHi5BWKJ%B"qwJ#ܺ;Q-9# bK>Lc;Q~)* |S_o.&D3PEZzV/3 U rxu\HMY vfzB2a2!"5T "FVȄL(# di( OJF|<`㜋v.ZѲ25.=V* 'uLr!SYiJb{k$0a,X=Fems_$jcs:90:fhJC F?z3= FnI(&Tl OnsLxJLH"!7ZQmJB!(2HmDl"QlpM^eݢB#F;EM.J}Q$$  d:t1Gټ.r_&91}OGnO:ʍ6PdT6Cg$4:g1E:6^ L;xdǡ auUB6Z̓ 1CbI($A$"4eЅP`'㖄 C4T,Tu}7ӖHݩ%ϒY@(oO$B՗á5ؚ'%Z KP{L RM8zP<|95bwԞIܗ!Vqo(4*$ ʄBAF< FBa1mE(b:z!T"d*PX&LO6 R6*aɄHa%KDtRɗuF35ɟ%߰. nAxߗYüdEߩ6i aad:-5U2zHAф.ՠ9p^F уTR* KD !V.sX|VLkT2[ {\.@M(we؃.Q&<fЄ C"!(P '(8`[Ex8hB<,Ԥ{'\ !?i"ltKzgHzAp~ Ձ#?gS aA>}ᝈ ל<BmBBpgBA}Q~" 2 ;FX̠ BIF912v[_maT6 VǕ$fX(=fkT܍y(HD asVQ9FAΟ%D #y "|yBKƄVMfBpA 04%QY9QsB8XUeLxf0ބAj h"T KEHN'Nּ.كz$ek|bIF-܂`%pKxeUÂ|skl07'@k\mQ!yY= ֩I4٨au@ 3@kj Ohf@aM>~Pohp(4%~]JIܟ'=ub<#Ǟhxջ J0eUj $_|" 5G?E%AIG{;mjB=!I$օ $n6!"x*H`DEh"Zm0TrW&Ƅ쮌66F'\_I0psd/MGow&~0d_;&| {df&c!C7zL,ut|J壑*RhNny74?y2f %2n7ે L)џqAF#X ?QH p(`ݗƌPJGɂ;qc2 &T"$v,8CxDPeЃmj !]z)ty=OAT-p'9oP5;IENDB`hugo-0.92.2/resources/testdata/golden/000077500000000000000000000000001420147000300176305ustar00rootroot00000000000000gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_100x100_fill_box_center_3.png000066400000000000000000000253721420147000300343400ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRdd*IDATxĽ %Y~sofӼ4#ZF^d,P?@S*C0*R$)pQ1 `Ja &ƶ,>Uh߷ܭs9ݧI$5u/b A1@ bк% QuɸYJ <+$>V/FC3"Ldb,Ѯ+v=w5_ (唿Ouo5XzCP@V,)%@e9(lٟ vηs@(b F2'MvP7Oj, cdmW]D6r"PGZUiWU, +Ҕ+'ŁJ SX ,Vr冬T1FgT ;UMp[u`y#V`E3j8ok {dZ͢-L39k#)2j/Sl+=*Dn%D{f581E`aIpXN9\*FMa!X eб0)z=`MѬ0+b^P^b/# ӈ|{TdWHmlڬ$b-XY\4LBi1gs(㽳KG>k?\3tN=lt(Xw)RQU.C݇y( r5:*V|SIPV T#e"O,G)&3F8 Yw9@8qJ҇tA;g./L!`)+|ތ"ތ9l)4%3 V I|(1`e)a2ŸYEQ:u(+}"IT2#;i`*F*s-|z3htOQH :ZRU8q' 琋;HӥV}Z 3_ f]L))H7RUpn{*? G?vt8f2]J  T`],mRz׋y('m!]IӮQq׳IF@La4w`σSG r+O5jӵ L(K[%ZH(kn{xnqarW(TΠjɕԐ)ʷ9jZ!_;zC!~jt I*ZB:Чh&|ɏ*dQo]O>r$ۻMoy&{kё[>x3`J"m_}LqtHm.}܌VjԈԱqVc͕} `+5Q@AHQ1ȂURXo"5$ IWS~"CogOiGcxmL"=y׿_|ֻhKSYD|n~HX[f s0c1J,1ʑґ)xvg+ ~7n{?^\gX}'{!_o*J(,ȃ%=VyӟOpkkYHA&CVy?yo~4GxmM͠t"ss?M??<}<^e H)adH,iBܑefDk!kOmwSޟzoծܪ!hV7;?;(|wݓ;Nogyaʍ>$$.4|{35ń/*js1;>&H4lkk,CY^ZuRkh66ӹaSݕmoYuԃ\67(8%+y0i)5foجU +%MȊ[[_a/z% ^}JbQ/{?:[|HkS]?TvhX5so=ܫA<079왙\ۂX w׽?PuqnɦG) ToВt* u7;V%"k톧n߿|ۿQ$7ok뫕N96Ӟ\u`.XL|}|>sk(~\}Fo F2@1,F|} a{g# "xϻ~w*lW7VI\vk?;1זIIpCi- @c :C¬X2SpnFF:V}^7D/<>wVbcOnlj2q{Ȇk*p) .,hFbGH1/႙ ΜW^ _Ͽ,uInJC-=y/C.yNp`"L/ j`\//s~!lWqnBL٪ N}JNrqusg?O?PSVg :gDYXrbEQzJ6u/?޿7B43wմD+u`хi+]FXhO2fNKZsN]V{ՋXY;  bo{0k_+NU*{T<@*H3 TE\"|ף?^~A@iWJKgSTB.$BrA#0 9 Yh Jɗz3HFȹ1EF B [\IJfN&Bj0܌VIHf~wO?gזM0jN>pwʬ4@]XB/˶;s A@2vG6d2k3FJ-)AbTt3EAfY9h=BS6ސ kW 9hp.LkPH捥Ў8ww,}V5f Te]^鬠=laJ Ȓ= 4.,,7̫p|EF#El4V?EFw,Lbse8rDX;=& 'Z~!^ËI] A9ɂfK Z[HnVv^DGs#YM$SsaN<(Gan101|\gOFJ=sbRq+t%Hd׈Q\6ˁ~\ӺƊ1#Z7Bqeʒ *!Cm0[3&U`g>bv`Nhi1*1Q=ImYKܵ2:䱨èeNӔ{;bt@O5nQo2y*KER<`A4]Ӈpm޿kfoq\9w/>W61P*QO̘jwIS_s8M#~-g dh67[6;41w=a 9~I,e;p.ifKM,d(ŒT/ӄqݜm5f8,[F!B!  Gc60Pe9LpMKEXhjPxLe2j#nFIBk5蝕 eA;- ֆЙPd]1 $+N9eT`bcjbiGs2-+痲Pâ'Q<|'~e` (%P *3PK5dLC1/4y^2# ,/u lʉs"~| "k\K}Y@y>9ءPfE(sF;Z$^lShJ&$vbݿ15jiO Mg,J<9KcQ,_l \W!%Rz1~Nqf^O@V Q+D`c;uڹy%Ht9Bh-Z@WP5" U$HĵlҌXY{4xChT l&ӐIktB?UXIPCd {5S &a:uV,+^#d4Rzz6WvIޯxcz|R KrbgI֎;tZBggW "ը& O‥ >hbty6 IyŀzNeovc  eb+lgtH°[lX,eIax 8ǻ 1gZ`\ dN,㴝Sí{6Otw(.RV bl\L=3wCtDձ1BğˌSB!KЛ :{WX yUl6WLhntS\eI 9~Y/:/i ʗ׎yna=њ?25B7_@Pawzcxz~}˃v\Uy7ɹm5bEuGL^0q"T s<\"OȆh%vj DTaJ c;Z4uA)3\utP$Ե]`i6[!vլ=rLuy3(880O_MD;k"Soq_;PDhiZ8 * /d.MC%rɰV}:O'wV#QJȏt&pQS\;@y/2֜-N8{asirؖCV"fqS5k(5n~0X)eO%5)^% RX?q~+Hc_=oĩ(EwOmQL| (u8nL.V.tx& H|MDtwGkmk~߽ܡ_:thvӁ71#bb V|NX8\ex@SE|Uɂ.֭l9ܜyӌm ĥoF?Y>}; iqkE#l#o-MCSSqG-= L.̞}fpV E dT-8O(ҙOA`4Sas;内Gѷ= >_9#M Nxøz?{qmywOer|\_gzӖS\we铹Θr-`sr@ʨ^e1<_Ce遅 dygMR&=Ϧ'3ȝ,ɒ~xT,ّt7yv /~Q=G8jA (M1ͫWO3_Vn[9βr>;ȔWrfW Ce5,̮iVvK:?ž{ֵ̎玵猆(߹ukZY;('4ęq*Z7LË 3"Y*q|G e:!8 0 YƉ 8E3+?c ͧg_o,Ҍc`CV)8SD CլЪn'w̾s{2ӛÏ{6,R Xs,`\gUHikt0TN6d>j51!3ݵ }rk XD/taʁe*?a"fvM쟌!8gZ)d+kۃdev9~2)Taf}6[T]NzkO2\eKLlp504ee 3)HSVv6j VӰ^GS )d2jXNm>~(Xm[ F3fMbk۽0md֡V7V!!F B 헓:r&ztYYR !W2`II97!8YDKAdJ8|!wS\Aabq$~#`3imfJlأ$wJvoǷs4`zkðFd0[r3dpz7o^L%Mt*ûWnX8;V"!Tx'/B?aIȆm3̈%R"ȅ92oYʣ8KDNCMXG)>+]e ؞d x[zA\Gh2 ~!8 ̷xiWUzQ#Ta2s[W62š/P(f84Ʒ[)B"H)XB1Wi::7L R+f: +Ut C*$Hk^f3Rtm4`⇿+[FpTɢFz댔M@H\J,aiN{>vGGEJ@gjCRZB٠SP՘͌,3$2"T-H%*̴k12·P04$'`,ؚ;Mv4402X`$K$$K7&ٙj3fv8 7\6Ԫm IPmHV>;jzp!\YOGXfV(tje gif֫#sLdʙW"q(wShsN[]wU#=^iM&LDؑ;̨?ht=^X@n~m*ˈ Т?Lu]Oc\}Yo7-2(D.ZT20)!)t916Ҵ:IHM\/(_A5 AN TX0 ?%zOa>+$ʶDI'&w5RױȱZC\Kx1$ a^wh.b9o:I#mT#҇pAf0$dS1.rękUyGJO!x"G_S Y OsA'v `( Dɾ!;mt㱍NHr-N@`#[W7陗9|1 < scnnJ?8]79/xvX8/wbCs{o_PsR(S9ekJUZ_I ^VS"܀u˻WY^:()N|h{-&r;{ۛtToQ 0?淡pYe=mw1p -}@E5F > {eOƒGU$v^E5”t_QSU3qfXv[>ևE#:90&"xWO8p_-&=rgϋ8f|t'"4f屆OH nېUr{ĒeU)dձxN8|0p 8 rJ϶"\CZ_#lWl-W )乘`$x%^I<0ql+iQPUnw`핝*z.mYahBw\bB@c&G("E"7@ݝ0&~am-y s~xX~[#f]ǰhk 5 Bk%PG r:T׋q*d,i y#0.@h@|r-vf WʰP/e|a&;'-{->f3z @ 0 аE դf&}֢d<&%wQ/ ΀O"MeE+$㙳 /{W95mMƒ .Ԯr$HKDBX8bM& ut Z 5,,̅Su@gXFrD9gK"g-ިXoR~mpL.l_ |m{f $~0PA~e 0ĻU3ݔ T8SpCT n0%wA+{)Y̪,>5in6n4!"Wǀ$ LGtFx4a:&>ڀ.9*q&"k5M6,9dmƪ2kXx=x*>g">ӛ'Qü:cʰHaV[5,pdO(]y%CӏA I^t3ZǸQf F-4T zyט:7=XoRXP_)N5ԙnټo PTB[~$椥ThŕeHoՑby*Y$ 0 ZO}'[\xf%`#y=/%DJXjUƪcdBk1`O40L|H݈<ѕUyHp!'|D]A͌ ܮ"m Y*Vzi^>OPɺ`ъGH5L35kȔ[q3,nLaAa )&"D1ט͈rQT;%#EyT͓$t3XA4a<6 e.?fìͧ \#oM|:_3KX- 5rtb΅,{J es$37|Z+&A 3Hy\*&*HG$ց'O] ^-8q*sSVQ9[W]"N5+Bmj)[b f}\ʦ[5&pJ1'x[V.!GX)-S;O^,'>vvç^(8A(+(iTc ce~Hz2D2kŲ5}jsTOQBdx,b^8AU"+Wq7!<;GU^ȨllbAc#^OZj/U?MGfI7 ksS+v Nl5ۆ `dx)02wV8C0v zƘBvVQӽhEip V*>Df>{$+Z-Le)BeV$Vm]KUwIoNyEu i \^r޴u^^u75보}0Ч J$P%C21ҧ<lt6+S|B>'ΟȦ‡+頊$/ma ;7 դ^.v4j/v XJOqxASp?YI nA,@^z,"}9/_Yos`vq%,(gUʳVfư K-tk)kC+BȆ(LZc! UE;fTu^tx$C.ڃeCX4AT7yB ߵcdp:L 5* cr9 9ۈhy{ƾI ędٹS̪="YH { ݷh*!*ד5[駼4ӫf;5Qr+I“CR&ՇG±$d;Nl8>QIZVU}tf?h1_HiXe$0)BQ ӹ=׫'~%ʦpL6ՙ,6}Cn`o*|aXY-_lccZ)rͥ Y vǒU/\=g웱&NbQi,X_^}:-gjkTY+7˓| ҦN)|^*ҨSxPx8ܬ96J I3q)K-Q-~[| &ɒJᒢ6N(8KȹQ;v]q7ps 6OHnSBv)"bk0 ([F'Ã%vP2Kgg\p3fqnC&&=a*!6b19C} q#˿os^U?//  uxfBd1Bݫ{S_iW`eص-bx̺EVZ&h=e"(t"- ̯'O_Xs /4RH*(K\F`YntAӰ{!G;($+x2P8I8څ F4, IkF;zye0g/*ETjOUGN̪Qn{D [׀Y XًplG=mǡoBy"CkUy\s(v+B3)E_vdEOkBAڒb h"|K2q ҤX'2^ħqa? ?3lOyv5g{ګnى~7(Ta۞FI¾;;qO'wl\ӫZ//+0s;y#]8}Cê  ֨e2כ^2łkr!Ff7o?r4r`gl3/#w-NaG|Yu]~}V.b5DҜn9tƛwnHoW&-`)l;2`EwU8AaZ3 UxqWzR7Zt*SHg>t*t a=BxܸET*8G|ֿx1ԦxK9'Fm#` XƂWfRtquYMSx.?&|h01|gػ07H[^Q(DA `Ad5,$CWV|Ga+)cu?Wc3ڸ|*](Ĭx ;򗀿umrx- Dqd5S#(*Q a|m_ψ0R40wǞAR}D)QY%;;[m*WUAUu BQl7}׆V |+t6hhQM,Dx]D<߱ EI%sAނ?rW_<|P\ ^6X[m( x5\߶3X L,s*fdI[M TA Iw~JDE'@[&I8c.嘉!dEpora&Lc O!AwbIV,}]-rw-DŽ$ziXҴ,K!2tTfDy#ƌvи%N^E &rUbXε~{ݝ * f+GiE՗:EVlI>?tEnVk5`qaʎRb2IR G2 fw#]Ień2o 66 Pn R;H vǏޟ7?-ߵRZ@M.L1+/=KQΟyu~W/\4qq?z(cDh ;ڙdm.BQ.ʢ%z?"~RՁoG処.wlVvTkVjy<0 ^ VM=>rCD2ˊqשMB'(4E%}|3 P*43j`饕Oi_ >OQ5,򯛘N*G^tQ}XϵV3,ϲmO&xqg tI!%q#{\Fla#yszQÑKOثSב `,,kxS]:fa./F}_v X")]CԕLJnFz)Jcy)Q,ϵ7*5ݝqr kH۫cwGA☴_e΃hNp6 lCĪM`h>6;ΊD IcuaXy/ 5nyV5lWk{LGS Nqƫ)2-6%j'VvqEhh*ae* 223ֆ(O,ՠF^x3lZu 2D}#,g٤6y-Ǒj^b9??D=`ǻ;5_ZoH#&jA 3ɴ`Ih?G>6 ;hks) F*T.fYlynuTC-}_( ]}(66l0;Ս]7wKO&+y=pEUṛ:l,Ci}R PBGH!TlR"iKĤhRs`H3hb)N%" +hc[ Iit7UR:)"ZX=:ks".@/汦G&{0=:юɄ7-4Π熚$ qԶjF}mOwYK퉒m7}ӮOshPM92mG5UkӍE _syͺJc#㶞i^T'p{V<Rm}eM~S}ZL6 4&Ɍ6 5{hva"#V̕ !|a)N6/אyfy3lBCwZÚycItOcnIMK\N?fkC&B[չ{5F3֞U_NLjBS6&8|G- /c;۝ V2g۶:cpa/o _y̜='ZVeУNy Uo1vrꛟm7x:[ |ecQt2jd%G|M϶?7jS5Oa6tevJ.NVLHNT5)+8-=9Z:=xny'!Z-eZ[N11-#[o;Xpw,Yy_٬6UHOs,ؕR\<% e㓭j8t@[U)%m_h9w75Y Wžs (ѭª6ƿqog-mMqh.nSǩ;л0ss,ۤ/ ^o||):ZvJfIp1 WqN{Kþ'9<$I PdB1*u(No}+Kw'+kYnqG8l(^G*k7#ѰV?U'+~B97וDH߮EtO8BHWIf;y`IڌP!W>m|fU~{_7;C-S=z0ۀ_ulXBZ("}}w]^V=xv)Lh%XBӵ@~ 0ۢno݀jJ}f[k*b4QlmCկ>53*@qr,zD)GMLm|چ/$hu xe.J$VߌMD km᳨ͯւTh>qfV&l+]9nt?!Ćݡ-*8%{p2a7uƈg-.ڷ ߁ ♭vS,({wmAdlgODhB,m /ʧ򫻉-,/DgT>:b៴0ue+ݳ^  |!Gdg9?3;?d* -KW_ƅW[u>6ٶ<;}SB,2_Zn|7 խY_{;rG˫@z M*dmz]m㋁ai.>ʎƧ+cpÇq; 5& w䧠Dzx_Qv %ujhgy_8!DS@}^F%WO䬿:@6鹭~vqі~u6;wa^߿;k Iom) ҪI?ckm\_o+]heX0>/^y?{ KԫknQv\vά N_"|aSm/A9Vզo{cGE26!n%_Zz { qcБraB|/|?{{mؓ- XϤH}E\$8 ?KO_hNbad,fkUks$&:Y{z v䶾M H6X =*~\, W =Kɛ+g. ؒlrS>O½?woSX4.~e@RCsM*N}͔_DZ\p sco]_`r ~.M;_+2Ժ0b8//>s&[vsLᓯ{ $$ WI8\B/H̴&+W㶇gvݦ+^~k8{3~Pwt WOzD8<;69NbڅJZq)=X>JI>L<<=<+/,ADQ@<6zS+k_S0mD@8[>2gE㯮cOl,%}j,c6 `F-g$4N?}mX8t!+ظ+\D|Yx+0~3NG\|r5HUh T)sƢ=c +;VԳBaS~${Vzc߂m*j⥧ 0fMI֫SqBϢ8Ts8(I FW2i^֍}}W EL ٿO<azҁWV_dIA!T]ïCA2[̼}ǧ1O4 =Ǵ9iާ6Kpn'u"f@~ԧ'}'< pn ?)),Z f](Jʰ(Q%2 ha9`˚T酠0YO[uGO1PuSI2s+Òlъ'V,|IwjSQ 8]XI5q?S+a RQ) Tu: sG/^y,/3-^ËM]~᫿F6˳Ʃ7-?7i-⁻2I+$x݂J;q =>B/[0' /y *vV!8?"X_C^?8HJpCoяL.鲵yW^(aRQ&Qja !r³[2C GOIcy2هGfmCL'k0㯬,, ky #G Nl3j4'Qwwi`O||}sq%E?P+OEΑ/XFYrr=&ӱW] vm#;DCAc|:鉅x\. ed&<}[@͌ABp-ɺ(l|<7CrPEpG,@6cV6ʪfѼF&u`_|WBa+zr;J6HIsF4gJ; lv?. fEdʟL>hν%Y`2s)UI-r9V" 0rUa-"?XeW:~MhaKlO_tđa>8lQ+1\OZJ Z )>" aKX)n?" h[ZvbԮ q+%E!whR D0Ha"/N%~B7l4& =INZ˧P"j -9͉_,זsP+Q5}NYkN,H2;{E==N9]B ^(ӏy Kgh-Hp8Ayu_EnX}Dպ> KBgxcaYUg!SeS;m&l{;T'R)(\^}rMc%hHt豈LE{ F7/vXD+}, Rv~K-xf0JVaf̷dBeEp'zc l>c:G!n]xRwԓA8{-)!S8( ,Y0'i]ܪhپ3yڈ4}Xò_L-i+ W*B(Se^{s%+6d_LW!evQDdĦmL┰˙Hʎ%*{ bd8bL-#aWlU~.._Aqj+390*ui#D^7ff'Fz[׳\sHl&aƠ=dC7Ψ-&;lUyX5`KVӴae_S 2Hh]NJƅV}4Ѱ©d n_!H`"0IP=w#'>;Ysk JWX%V6l$^6)[R?`*fe|6ĝOtբquCڅlMB;PYpԚ'Nӧ23"eFX=бﭿ8c#勯¦6JDAi\rScPTS6m)c^:ɈNSױ;&pPNK؍`jkcP>ew-gѪY%uhպZj6YOq,6_)N׺ ZBKZODrbdY.kx&bx@6< SÉBB=jG5$di<(%f}[Z__O2NejKT ",:*[CG2`lE$LB nhiZg| v 7Y*~6Fff1utv~pח:#em:r%~;N͚2I̡궩#Yf3śK PK/ͩH΃)uO=yISB{B'(%ea6TbWK\@?( =LO ZmZ(YXXzH^wf-OgN#YnlmnV/._n;6"T\r>OYT">wq`*WH}HtN6_m`ul.c݀ge S26X8wa2~'(¯b|M-ߪ-+o,M–|az+ZLBTO )P Dh+>&h0E|r, >}:I5`q46Q4Z )5ڼ˯< 0R$.l8;Dܧ`G )B93y~ K#M&Υjj/7r>Jmv%9ؚ4& -Kđ.YQ8dx w8'^%qI}*%%Yѹ[(6ZO&IJ4|`#,|ŶM\Ksd@ (zRBkk'QarQ'LGcKY+coYBHq/0@GP `hxX[(ԉ߉)+}7+Aq֥IR\oelUm.Xnd ~57x1#$KyuW`0KbAD.%X.@犴S*vMg֘J|ʆ2LUEl*5&r1?GO_֥wvBrqw8;˷z ZH)GK+#ul{ƖIl fVw G11 х+J60jREcK9Q0E6Mڕ(Ď\I_WzjzWaﻲlW ~`3T&6LV2?YB#\*X00xB#2"l<1,5n{IImĜceJ=cQizbF Y N@f޼ѻgw٦׎tg _(6 /Sx,re_8JY3nbK0-mX6)GKGk)x Np&P75`2Ta*_Vڼwf וU8@yPT\zvyAV_EAaVf}C_>Yu5u?E̫Hh8!fuㆦ8[0w. xlGOۨwzV@8=~O`xN0€*M։age'DUNeL~&'%[]PCZr85)j"x2Z%"ߌUy#Kpg .!|>ODCO_>,4,^qS"Af>/2$zHQ7ڜӼ ɗn%O Q0"KuNҎ*7# Pu\WmLTe#\lm@Pjt|J}!s\;}"k\bkZ$1Y2Uxeo[ A!D1)Ve-~6TyѤΡ#e9Ug"i̸^4,0C9;~"X6zQ\XXXŹ0̜avR.aU~M%k7g#~[a"kZĠ (.hg-c&2zz"-@g@iL|Ǝ! +"cZT7flYÓեܥ-xY6X}̕!b꾠X)2̋qUXbXbV\ռWvnݚTt/bRcqlf) -򋽥)'jr8SaF|ٙ Dih%ن'm w 6Uߙl$J2PgK%٩RէY2 ߩ~@5ra LfAmMZ2s2۱gI kц]ث&@UwC|2\b]u__$uiݳ9V{1h^EZ-_xv)lE(::LQ /^G5 m.9xi{4A%ܲBH6g*#}ggc6^fVgų4#;aTl1T8lVCMiGŽTÞ:;;26ٱfHUr3*.!w9ݜtV32ز7Ck$/LZb5ֳM(=$='Tlj5mе_w Xl0Ket9.M(VRkڢɹ3,XJC~jhFjI+RW-X/S, [zG!L|s^eu+ʭaӦf坅QwN 1t_ ?jnNmLgLH3\eiڊ쾐O92TKCX`F84U彀F#n.)\xVe^,`26ᅡKs,ۗn=%OজѬX+r(HcR(lƫ@J@ѸP'0o†`,a< Btg^s_*_X(M~Ru;X [Y1~:{V+W=ON߯Z[ngOeǨaLJh_?3C?3謓 M;TCyBB@EIx 3 xq3[GԦTmKiPTUl^mbyczÐ0ncպT )T_E5W\GUʾJ[}J\e1UWgq#SY '2Rٯs0V*@ŭ^yBaV *C?w?tԄ \z9G:{gW^e 5:RSn7]̯Y#`u)AX+t܄xXáÓ/lݺ^lʙ;J+?tlw6o/<|A0IAkX0`iwC):#:TOj#:(JQbz4[*NYc^Zf5tuG 9bw~Ņ(Pj,A]EX*̚Rzg;~컞\:1a*W$6voɩ3WAuN>:p8|Ms_RaOcNVJc-<+1VD:AUYcdA3ɚy<ݗrfH:EŦ,f 1N>D]1ҹs$i,,aMHJʮiSl Z)beg\Ot:ɱ&iPiAZ-n_O 䝞zYMQ{`EZt97=w Ti3P>ePU5 I̽\y'ν֜,0+,m #oTeuphۺ[qP "~Knr4x ZFieADuniDŧ 6ǰABqxִʿ38a+UbZ֠lsJS+NX4,8_a-_arY 9MmRc J[R(p\JOL`mك `tC/RAպB-Ūt' TL?\WȥM¬)`Yܕo2Yi0k_HWI:8t|~2 -}՟#bV2ēĞA#5Y}x)l*V5TPEGq~LuQ-`)VyqQaZؚRb|[[Wt~0AVr TJ @a,m 8W)H=5x뙭rn􈊡~jkDH;AChPap[a9haDnjU=g҂dyGz{VJue!Ȣzhn0 \@YPC(U #13Oo͖Z8p9$'Z |O}Gob5é[Yc"'(Yؚ0_z=_r,L=VYGY0Kx[-WRs[]y6CZI~&\dJr- /yTjakO߁3f{Uu Md {(7G8+( z%z 4llyi͹5&bWcTIŃ(B gbߋ{__oRwUަ2%Wa_ qEM5~Fzcs CpTLY+J1ʡU{a=0s_P Y`BQ**b?(M--٨);(?Ol)з{G~St U"NK<9) pΚR=װ?X+ȋY/F,f5k/{d祲yt>KC n&]*؜~׾30o૨*C>p>/߅'Vg>UfqjNL$C4f{a[JןNMa8;,+a[1%2G(-xfn])7hnf3"vA/+&˭Kg,+패VlanC}1. ,1pkn. +ӴݡQWUTbtX;BU3*˲uLb$F!(uU#>L:pC'GbI:3;1~7;Iz6=רV'8눥.7Q$jز=m/\"}{U+&knUjMO_}1,#$5߉*da[}l0V)}8ƚ#"2?]uXp 1S-ylp=V-2USCc $nb C[rzf45 Q:b%@3" gyt-۪d1Xn"LpзS"lFu d~y{;*V3STq[0 5|R9s̭ {H>R˫[hغuvC'{'a]`U1#!f?reKdz71Ôznce,_umra kpwwlt3Q-Xuc_ $$DN⺚VYm*`Un .i %J2Td#QY)83؂W"cYѳ?x(.aE)꺘R]7+}}Ғ/2]"[w,*ژ2~@u'|bտF^]٪0:Hafo-=1 v3/o޿Zίmަ4%W6`K}B)8zbpq4˥l 4,1տ8_w1T8U@Lv~gNcj5ul!6K>b%CŰۚKS Jμ:=.ݏ;ڡ[ڶPNèA^Qִ-1ͮÔdV79|x\4 FpqgW12+1p'q惵,ȫV_AwŠ(0h~ &(3f*ױwGScLQwp{9GOXb[}n X?w`|ik r=1,a0Åul TFub{nxT҉&<;޼gif7hnZBAUw^2=P UOEjXѓaYPx^k ӝM&>{qAt2kT=Bx .lh/1&ψQ5PI:JLmOol;G4}z0f6 Y8_M'm>Ltt>먮᭠k'~7/fឈl2񷴮/I|<:S5oQM&-| s:X҃#lHH\` } lcKOkMp0#K?)Ge#\(Bs=,*Lu o<\ƴ1K5q|NMI;\O3Wnv,˯2WWfym2KeX n8) Il~g[V 3Ĉ\峫eb۰yQ[YQ.EL*:b+T /:LF!Ф:߉]> |l@O"3aйtf6f7/uR3[ /eM<ܧa]?W˶?^϶/)=cUy`9>zӛYY%*3A;ۛ_{Ͽ'?޲ſkx硪nU@HBB 6(Q 8`m(5CAE`@Igkw}-|ixJ4{cŜ5y 㟝gb*>vބABB:׃zx; 5L WX;h惗ϛ// X7oqL{ocA0::u˖韺+^SknQO0x(@ eVY,U/Q,LF[ĵ.Sc96j%v-/TU;,t% 9!ClA% UzX(3؁Yal%\9*0^x^DXq;-W58sgYs^Q_XWܰemiud'Shr><7> P9uz^/m*ԣn%¬Bԥ5Wѫ1~ &,O\~ C0ae+-_ھ, =tu:YyM=6.&h/5t@KB)?ɭcSYPc78Ւqֶzđ].E,Pld=!z҅ u=cJȇ?|ҿ<WI5pJ7LL㲿^(?bvطD /c{x cȾ?z$Di,`ۀTJjgBey=8 $S$\@G+Ґ[LV Ԓ1daPHµгh*7|.?1,=V1ǃy6<7~5#O[Ǭ.AF]w)ڼ]%4] W DVZ~[r^&`ٶ=d΁QA9{YO ܒX}h%Bn.(::NA4UtHKNU.rVx{~˒Z__Ez[wǏ%)}1bրL}x$(6±C\UNLV7];~RXE 2;e8*r(®! Fe4;]c`l㇘E]n9~pG\xU<[VYLKyI4`ֺg hPrgy*w~YFJil[K6RPfY!UhV Te9w#.E) 9E}j1ʌ~}@ P,ff(̃=z2778/?Wٗ%)OWl{- 8a硼Y / n¸m݇s~lw\WT"/.!M4J(LCc|ʠ-u (*<$f^-''%\FIǝ ܋m,9QG'2ئ[r"ۦ=YW Xg5#-VZKXr-',`2m!WOS 8|$~f2qS=+YYYyom}mTw6|mck  7mNj%>pX άwGYE㯖*IR/i}O:aLuNDb@}κL\%-2~ŝ0Ñ2m@bJNd_%pF!E8[Vb"#L17)zGʓ7x 3j /yGؔ{q被$jj`X ޤ rF!q(uE) ?ʫoJy1ҫ3(7Od m$)Ei15-dBVVVcZEwq wSwZ{o [:pxy^BT )l0^he.|f,$kX|y9v٭GpnbH1`_P}<\$͍?|bMZ1 ,< 6G8M(CN [`\ץEI.n`,.]~󊄐RI2Cؾ=sݐ 2l]U׾{J\~ɋ_tkxh{4kk&9'F C= 1<+CcOkY'42O1"ډfq$-&H`Q0^u$]& ~-7o$7x @Y_AtЛ^eUԫufhr?C8k22}D8j->h wdz'vq~[D}%?Fব+TQH<)-4yBWNXujS!BJD!/u˰: Z$UvCLjsjSh>ì2ƽ QsdFBC5*qGNǟ+u]ߗVkƘy|ĂHMw(,\1ٺu/z[o}~ZWw#_݁J>*4&z l?X']dQ=3A3&3e2ۦA),c}y95x:XT-eh.M8'ja: -9'_b[NCUؾmCgΜLf Fc|;2 c&y<~ZzICq7w]}98?|,%cؚcnGŵ,,ҹ}og>-|\=P a/>a*fD*b0V#V.]UZ SlhOOⷒ N2P{dYV6Zή%dO.X%trDB`TAؼ㰕2cE=$NԁzV&4D۫SE/(JZ1Z-t'#p[{t,߂^|kyɱ$iUP$"qިR_bD`Md)2,q ۶_ jQja-aQi^ {EÝhk!ţ8ۓ~>O[9A^A\}Uwaͣnӎsr0HKyMY=Ơ 9D9$:s]Ƌ4%v`%׍fLjw%=b ! NJdek&et+?XdDIHNW c=wȼmK]MBe5H_8m1\E S)cb|̟\5 8k~'Cy;o۞ cؾ~t_<SH A73 |$eN{sYV7NEq[iNq_ɺls!/Q*Ql0sFoږ *8ӰrdÐGi3_<⒖or8NmYo% ? [Һ{cU䲍z C67:6ty<ՠoiaT?oɟxOy|Ѧ*ie$Lhsy]٧" +, X ؂i!0+ZR9(/W7ĝ6L[lpv&"v&Y}7^s egMWkq+e612v6>_"cJC{#UV u5 ꛍ)3E2 \6 . B2GOXRLهXmVֹpŨ,agڛ꼳%-.~EMrѣCЙ;(Ǻy/f}1/bKc3OO?kk:ʾw_\82D"w={-xDҔr/'ɈDlf_]!F1m'ƔGd /:Ab}1H~Ox3e"fFKJiXRK9:*f,dJ'|;F177'z\0Z_$]ht3+LsBm$өN{V/߆l"Zx-'hsj5O'*ęn=>S[p]{q;ϵpq|XHLJ<=/DUBZ޲?knw&tØ/}&,T3ӡ+i;+Yzq$.?@JfEC8(Sd+-|$>UDa+!A[r܏$YQysRXiڰlx*jq!)nUXKN?&_mdva+俹>?}O74Vi #Q¦2AJsW8Ѷɍ/ySBb6Yȼ顆+q='~0T nb0ɂ=AF]7|wlT3v Tm9[ 5]/ka곰@' {3d m!]zzL" 4$>ĹZOi ɐTKʣBi][9ful 9Z`x6t)e ͚rg} Aߴal$`~|^C?A>8taF^Ce8!ES Fl zJ(Kõ S)ܜs7p;36Ľ]'~HȚ*d @ՐccO}1_qr)"lntWB-@I*%ETZp{YO+@Nj .OU3`& QrFؔ&V,@DžĜ2:L8&g$L"1# ֓EEDZD $ 'x4=~{pw FDd=4zC`yXx{v–Pn?;Y>“%e?7Xu3Vp1T|DO*-27̿ZeCJS]j`,ɭ6{?e <|C-5K׆܏{ԡ csOcTͺ-ik䮙,\n8iS2|/ }fL ChfD( .h_)1Kjv٧ͬ!`yXVf|R ^Q9|,1:{w8ƶ^?W\6 jy,.ʯ_v7Vr )Πy*y>X}8ԔP\ByOoR7p®γY?o{`|ۑ,>~[@n@;J@UB !bNbg쟽f8&Y}q9?R5h[^Ȏ+eأ0fq W10v~rwz5HJOd3Y+Kحt&)̀Ǐ0-lD5).Hڎ[lq#}50|UF(7 M+UǍ9]{/ KoP֬d00Xa'(|(Z,-gsBG?0#̊|{~#p"^D;#6F,kv'y-ۼ}ΰ8`%⸅%S}i|.VaFi azpvw%>F!rل?4cq//`~yf8no\5ʑsC 6S@]:jV- tʤV^ ϫK\Wv/jL"6V\t<|IYJ.JRp+VpG(20JJtw)蹬d;v>X9ilug;3C3@:S_gsgK5YRiͥÂcUtɷ0-?o gxh 3*ԗ ZӋImlUZ̓څ~1./iѿK@_!=ݎwPm&V70S!ڸeQ<[{paHP!C!Nl# 'Z\^I_/ӥ!t>lJ@?Rc[;Ikנ[bOGs5xVX1t|Tl-y_pe\54Moiw53d4-c#*~omnw_*BMׂZۇ#͖/Ƹ,8 7ϴϩ%ZrAސ$*w> ,!C7aXj]2s/ S~ŒZ7h%w-xm@d(_31=.5˗pNgi- 2gNQ~3};<WilWv b9mSeQ쵃gZp(پc;ȸlᔖ;#HNj9VylX0$3+px$V>mj +P7= ʾW$, ZyNbvww'@C {!w+ T&,p9|&D:=Vԝ\ěV𩼅]rsS@z(BrkWêO#}\i+|"4pؼ-;|K>Oغ*3=3,*urǓ+lãSk[QJ{Zz|҈?.5gxD{Zq]O2$1Uó6o,qz?c#qzog'i;ccmI~D9P%#>Ͼ6f0,k #)>%I#CH􁙥O)%C%+,bz)d[ Pd<Qn:K0:~%,CtJ>^0v[ڋ#+XI$,vK( hN( ΠZ>?b`>SZBuD+L!"Mz#"uB([Q& }Kq /T'-`031ҧ1wkA9w|V Kn[vOYuv :E5/Q?y\g <_i LPzpE ז1?zHl9Mf-Z^{(YWj)p;T+;^Pi>b/J3, j -J̢oCs;JVg3hVFÖg [?fL04+^Of ӫa8Z9z垺yin bµ?>=?}Y:ddox;↰[cD[teEjo7\WPN ۼ5a3ǶATn l.R!;KL!̯qpr*}@w`5K!Jt:#۾=6g[$sFhCfd,giѪԚOvQ5FHh sXL==F;,5O掖[:" Z^G4X XnbϗGzMyyUw( U#5L ;{˭hO#̨>K<E0LW0187)ރ'1[ V9d[]Ö\)aj^%̘,3yܸ xlܹ[o[qY {nOD-d ihz K]C^МfG-QMzmqH?*E $1'pjVlWQ-ƄEQ1R%tbDtx^DF+ςO+Q깪r2^&YG߸*džBn]0 $✚- Y=n%W} -a[7| K=GKT?`zKFaqx.,US޴}mlg5JjmM{ZΩ0P`#U U_-HP_MPnl86Yj k:.gJر'+ niVHpq ژeRb(jJV݂*pup #lDj3htXSN 'Vu3᝿gcD)VJ"l%y(Ƭv̹[ݠzLvqrgU^T9ĭZ!k m ԒL,_G*zUB (w0pز-2\clÌE"l;`} 䘤UHԮRmՃ KO^69]_?2pc–gTRv~PPUc\ח¡k#ƻL2xARIg`f9!6F׃!01z;$o>O{HV񱴄=g~ 8!t ,F,Y|EV-*[J1_81 g[%|+- SCZύg C܃&'dX xϼr˓1oCo qLB+}mUǸ*0B{_w* [Ы0`|nH&wc`h=e).aᕏD561P)nb0@#)hW:p q=\wf*hTlг8lq"#=jkU4tXU|]VZys/^l 4t'q8RIቶ[RLG@#j XrVuYl [Tf nZ4T Ns.~ H2 5@*Dw߉-yAl~n6 1D֤eUT,w}ϏCU@ᅀejk٠AU_JVzXOͣۆ*}8l Ujr Tll UO_+gҪ J3\j`1gXPRՓ.) ;܏%K0R05uj9nJV&x#לs/F =Qvxx]=V,&|N[-frx-$e^f+ɪ,1C9@Es'kqP%ckh$ "zELe RZ3=V9.9 xs}sED[Ty,zA٪"X5Nہibz(yd*լ@ky0+ SC,XצũW<ԫzcI7a!՚ UgE-؁_+;sá~>.*m[(& ݊ilcSh'zTBa:gP=r2%ݏ2[?$g|M+iFDe1ՙ Z! UKE;̸V,V=>G LMD[ܕ NO1PA$+pn2"V1q+Qx `~Λu{.+{!lũz_8bV{j %T #nHvq1KDB)!֩wV|dF [G ˺@+Uk^2@ I'KKKXWYt9/mCJ3C!ll-3]U:`Usl^w|m$IH<CĪOzy<ʑxz|DZ7])v ܽH0fĿs _MKQ1#jgly[;6^A)*#4* =kWFEZKjDb>"F"=P<&#ů6S05 u&5mXqb,MT:EBvB9 LäK(Ɵ 1ڍd W/kWN!r*,DvKYg u`3bHaɯ{`ql{즉~haO>DJGךaS_P>+ϥXϏ_^~/nU) VlHMu@#}PI"J bHΥDRb 屁GZzv az̯%P>%lX!*,m(uIx@/$(Ş.?۱Ы!+yqh, 9)gZZ Qb[IoGŎQ$  (ĮPp*Pi:g={=(&YT?uIKTa~Bv:ŠA %._|p. g#woLTVU+NtiO( b=3h@i0gaC!Wk./[01j Ұ" bFtQ*H@X a4z( GDv/iM9|x6vUxPm2B-e8T3 ł .VF %ƑEkZ]ڃԤHnX5w XLZ=$XQ{XMfV,ƉN95AOTVUZ3ןjJgL*Ⱦ)U~KX<'9kڇmTXp(lZݵ`Ŋ]y CtXp^}'²-Ǿ0u}C.%Vq;5ԴJ( ѱq [Y2\ )* '#A,pyCkkڵJ0)nzvkais2?ʝ'erZ aפU-o^|*it Mw!U.MQg | 9)#1ؔU7(=˯ hŭSnOYVܿ1f-\XM~e zZxKM:b~Ta+S"T%f;}գxfK-BXRV<`,#Wgwg|m=T.y<6m_¡#H3+N" h#:W:mQRc#-Y+- uU7tXKp4HJ9 /VSvMOTdS :Ғ-5Y&c*d!]6e|jʵIvxhB,-p@yY 6ZPatG*=QlвР\ Z3fvbQ>LHJldBd[Xwpxyun,:4vtx\E,@(sH<`7S6 Xv=^R'QeJVVZ(c8 yy󖺯}4e|_nk26 11 "%&IzYt;JS 0b 0 cJC۪H&"(KN{ցTy׺anE S_5Ɋ&!̀W8QBQCۊ]Yѫ 3]8 U,)zqQy dH!ZI8˳d/ fЪKȀQ) U!H (Qn|cbakQdX| =N3G͑xbō.=%̣f\J#MG#If%t["Ph F`(gDYJaa̲h[\i"O!}cP= Ca Ct }01mf v&&P4ˤZ4bƦե 6,rx.|KK3+َR*icXpܴL=@V^K8BFЮ% Tҍ%PbHݥ ud*Ly݌FoFvHJ$QWun$H/Et3'rY $&*ƌ}DxՏ&-\q͈ʁ#P"c_EVN@D+Mr9a=L~$P.wOh/6\G|%O?BjJb6`3Ld?Uzq綛*!+)/7Rk_g)er6j1Yodʷ<"4* iJEIq ˅F1 SD<h 1St%2 "A!VИT."M$/;0 x aB7TiѽTY,Q G3 RXDpF-T f%4p_>!8}H6`ՄO͢(g#d~lDq<S+󳝌 gdȐ tVT s\hG7+]Œ FjL:er~Y"Ö"*! 2&(.qAEĕ *VA,*"g[*0'xurl#_GG0ڑ1 YTB8<# eS]yb} T릈*0poY$[%H~j,eX\^aSd\js"緷W.~NT[IkD7'@:!!)ͪxd+bDiR R!Tm;,fHAQTHN`^B9B3V+ڎMxD0Z!\B̰c *RÉD#|!eOI[7š|eBL7$T 'މMϡ!>_N/'NH7%oXR6b^V'R$71Wƚ,"y+'! F&L2S3v3cΝy(\%4R2sN 5#2+ceڳHMQSs&CI`⩈Գ&&\M?6G]4,A3~b=1(Ą-#pn^ΛҒӿم!c dQxKҀ51ɋ˳6ңvi-cO*K(>Cr6bY6 LD(&Ӱ L)"M~mH"%Vh#ѓoP=O`HLeY#zqb& l8<7x-~'jJWQ~.aW3}T<\ |J@cߔP|م GX\MT!cǘʈV@{"H20${7Ifq 0_K!I@xCNʱҀph[gWq:`؞hö2I }ơK {e /w"eghI i_! g;eZt/%: 10N,dJ kEcf^JEQ%F9U,3ו`2E:`Pe=r_x?$*ԅտ<7P%$W|&`=A<z1BULWv2-_!Oeqսq6~% ;Ӊc ) Rg]MW2>cԒVȘYFeVKKga 8a@nШB&JZԍEN,LnV?nQP*I S躘bF%ab•}Rvʣ`.]{Ҧ sJ(atm*[jW|dk9$MT ЉJ@cEbD͐4k' s}Tc&#H)VKu`\^Wbؤ.C Yc% FK"cMIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_200x0_resize_q50_r90_box_3.png000066400000000000000000001711021420147000300343630ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRdIDATx %Ux΍^YKfmj%$@`Fkgl1[3``F ̀g$,-^K]UY5^=۹2]Rçeeˍ{==oo/u|l'﷋uX#wGy{}wQ @}.FI/ ٭I:t}Iɨđ$Qk9;%"E} 'ʭ8G7bXl_=",]$Uc-*/}ƒh {#w^ZxIjN4TrHꃒ> ")Q/FwH*wa m}u/d}QFNT<Sw.9gĨM=/J@*ɓ^%L@p'ɥt&rJ w/z.dվIj1EEJn:Uy_W|J/Y[41 $<^+OI(;g=/b/SFB˕FQU@_4#'1)8Uq)ql aO3"yyk^{:$eJahd!8EdNOK *F1%$Lq{1s`[g*,!c]˿k]"4~3x< Q߼uqHNUDRR~\>;'s H^/m")u>p7#GےT6j0-%߅1*GRv=,ѭɶd-g%/4tc )mȮJ#5!¼ cq)Y$wdU$eN[NJ+7ʉBo?hъZ [$ Gɩ\hkt{yV)Ĩ碤 Ȗ5>#c]rF[~w2^UNU,Jvebr,JdNjyM'REkmfZ/*)Rch5Y ؄[^GR . U8:O]kӲtAdoa'̟QfKm@l@GOȮD6V/҄匊ZTFLy5CkvvԎ(QJ*b)N?ɥ˃PK|@Np߂;?8z4TeTz˯fD-z1}1Oa Cag-Wrh܋yS䃜zoOo.7^=쇘fq6\>F@ LcJb ÞVWn多)QFrzX\#Wzۚ[wΆ1gOچ-2I'FU6Ȝ!-F $gt}ܷ^Luk T !7vk> G5˘,T{Sʵxyly l{kO=wz8iЌDZ%c<xjU[ejߖJg,V$TUyĺ?heMH "TDHU# Oզ%CR.o&Gw@Ь }u5&㪩|޼߼yM[ 03&u >W *0}/n/n/T[caCՊhݘ'H6| 5Ae5j fIݤG8cf[*e4!CC!ϴBaa]de?Nջ.T ԋ7OK;¨S;~QXnMNF#oANo$sÁ JHIg2n]ƃ9UD ibe5HdR]m.2Ya_vGH?Y ]F>g1?y1˃ӷ2˷@U4T9nu=򖙣oTnq%Hd\{E:V|= ,x򈰿CHA#OU˯}d 9v=¡^B? :+2èsZ~{Qʅs;q{mMg/f*ZWx޽qϖى  {˗vR(*AcbĠ$e,+s,mIۇ>6cʎՌ&+uc;zRD *MXr9DDHsKDdywq]Ol=f..jdݷ]~k6ԬEұ5,|}1NA9ͣ fN:d Dҝqpe?N]v1s Ck}J݀x2jk7=z3SWgmKR|s>Dm敐ڕv "sG97!&kyo~ Ol9<{W݋׸T9m3 } Tn#WD$-ը[-N]n1ɻ5JCΥ"v +"iDԝz^ abn&Rtcսdgu/}GMwq/9 c5fe0,Ѯ 1Ϗ|pwLuu2A$vŮ-Qi^3~4} !y͍M0 !?v7ZWOz-Y'ޢ/:&/G0-Edtmx` ) ,kTZnqBe$>T |js?kfƣn=#LhcS5.hl:_Ӽ_auDAk+%Ha<v+7oyd*(0i*C% `Ңx--]YW1UO.>w;=WP2ii"j; `p; hn~i<3X &jƉ'^z9"ÞcZϤK'|'S Ns;6䏎xp3 .Y!v ˩ :y잩ٕH)u9@T4DP[,Q?at!DR㱨;]i_?q`GdžJZZvB"5֢btF3teNGGy!mc}^㣣>_>z`Y~Mʿ~+r5|nm> <;j]fßmƣ^5 ; m{Y)mr/m=O6Ec>)=2ݼ}xYs66xԛziUa{wA t31.r咑~FUt2%M#̻5uts9꺝wMǟ9tvӋtȀC!ƪxMmhM6$039{'Jޮ:sJ{,C7.Ӷ`P6U X8#;'6L&-Zٟ]7ce2wuU}MsIHTւxԛtn:AV3ӫS*UW @VHj(FiflaOk߽sf+QvѺ7H;~>9)>hpd-JAk.*?Ql-c Q.;<$K@/ h) QW$h"V̯+Aỗ}[/t.[fncթJ xZtPWuޱϦS@g(殭nym9h4sD3[]eNA;s3@ ppU%?ZQ!q|ո3I .X_>8ٕ?y xhJ[ω?Ň;1w +b";ZGAcxdioż B}de` s*WBV3XkwJ`:;vX3 e)]Z,6~_~How${3N]euv,SAvOԃ.04@/TsJ#-A^JZ/OO? 1IF^Mֈw@ C%4K/ë%::Q* !0C[ٷΫ 4pŽ;p?v!η{>plɤ+4g湢 bWIE$R"QZ1@*̬xu?7lJJ1rM)@ux&*3^nM6XE %FF%XMHVH[2ey'_癓z}{TP ekҏZcKJ}l.HqV\wcB9|C#Zhr".É@E`|`]5k3ɼ#s<|ۦ_:K7^ybn!:+Jg>w;rV. ¼TqPJ 'j oBlt.-M~)żs%$cv9\Pb rwxeiѫ1dy}k߂ +RE'-I`cvĐ=|jKз8vņFYDIڍ˝3ϞY9ю 3a %冘uG8K+}iB a}DsW2i[5\y1se,k˟)eK+yyuɶPX)Xmp Y>ҠVڃŞI$34s,MY rTLUGdEB is!.ǵ>7NRPN~Ud] pu }754Xz/zرĀv&ϟcphc>=sY2#Rd4vҒ.Uq$Jtjjtib/[+AAzqD>|r蛐3!|++z+#Dy$Jm۬ϣ]?L.$^x0/vkb9H$+w4ZR3ouV+})4dFKJW&H+2z.´u(4%0lTA[Ys&EN][ֱk~.حdeP̵Xkh9n,cG;]ʊ ]z&oPmybʮ !/Vg^ %xOQL:l4Ft9铊n8c؇&=.UP&6ɰ(,Ot@Dӻ޸iX؝t"AR/_`ˡ,O`y M.iXc{|o_Ebԇ+6O!^IqW)o;QIyGGsO>W ͬ{( 5do˱k!edo{#yEخLNdK•A}?v;oH_%wItz. Yp)A?Xa,wz֙} **a^hRnj^!ҵJ0*TĜ9lO&;QB 1$]9X4cuNW&ӨVG >sbIJ+#y=˽%*Ls뱴J4+tG M Ps~6.抿@^x ܐE@^d؄ VP}09FT}.Sa3Gru_.~i`W@Jfyv/V-޿p~TiRx}z/19>1ug9qQ=RȾZbЛW=rv5v12zBe,4*蹝ݬ M,~dW1ßBk5lc; $݆Gh{TxfW\3ytҪe }"<2~\D7'dZ܇WDAԉ'Z'b ncM{J!9(196) E O# kJ+N6>s-=t俻vf+J?\V;B^UC{ &! f6':;?%PF"\HEuR[-W܃}-qf {yՉOܰ:y +'K=Uï}o;_˖ o??xx_Y߆\#c_uf?>yke2qCdC 5r)l!2&rT3oaR H wNq|_R$:Iv&X=SG% h'V3*R{B=z^\s惎s:$U/onh"ٕs+8!1TJG΄ {_:U>UCRzqһDvquD@}ӀP R;p 7n{|;almunP*=*޴!ʡԖSݩo~OtZٗ~t{8z#Le$|6rKMDZ_bUE!&3ˠcPdUBTą*r_Uj[C*1D.fȽ p* Us00HW@W6|НwhUͰ_ \lyG~UIȠ/A}9n<74s6\Pڎ])$dՂ5Xc }z]_vԲ$n'fB]JC&mYc!(m5ȃ!@ \3?J7Ch)oYto?k8|}BPlƄ=R* #bЫAdԓo[gvy@T0/ְG 6*bV61NlD!7|5bșX.)rg,3b^yoh0 J֩;lb rVPFi@MXQ6Rice'!ytQWl#4vwo1 |wCpےrͨSb^]B&qQhnrګ6smm#4dI4۲[QP3nnm OR`9sjFdEp9tu<-ͳ?wH9ZM(Iy~k פ6Vy Fb ^-Aq)M0z)"ɖp,g:)wCˋ؝Mִ 4#O.y9){|U"U9T MsޘC}#&x؂ߌ[7Qd ҙEVq!'.ܱY0$e$WX ZTMd@4Dby]jA*0JjgW|1> OFB2mbb )2 0nI`aKVÜۣSCf>S N *a&".h,>$iwllԖzW3Gz1,[0_(I83Ɛ~C68p[6p&V;C+d"kin䄕ӁXa*F_6n;$ 9B+EXCVZ3lLѥ Ti!WH_WPc `EswJZK~&]xk$,ZIò vH31a;Iu EwQYDܩw H3Rхvl%BJRG¨`*r^UAO,o%ڭo"/%5W8c)Nd {k )o@h7:@T3-6d󞏭A W^u?Qz%y?xΒPv(s'. (WBd,t&)=RLZ" v_6!)J,ѩL \$ΤayF4clUu -BɴS)Mlҹ}bjmY&grtdŀ\F ^}mWJ@w\{[zsO-ul-B_ `O@F`P I*]Tq4tKp&t `{h}'XQkv!)'vik ݺ&S"Z= ǜ6F۱+k FkUÛo Lc ;?t׽&_pT1LӲ|ع*%X .Wl d @LwefJ ĩ=-Ǻ#|Iq!@&Sԧrtq#Ϲ/YR /DloYpXhf?_CU:L:C8vy ϝj`5z5Ho:0ӆn_avm_:`EM~̀]jUpH=1Cī *MʕPTy C 'B^mUtyz,|lcyR=NyBSltyyRɟ@y GhF' aMaT{n<<4vϠ״%]Z"5Д_VgdDsuJ+|i&]<& Ɇ mfRkW Ji0VQ$#l-}S<~0ϙ8IW{ ̒e2Z'JCܵ4LpB=ˑX A4Іn3EG>ԅ /RZQ +^u2 ~M0h1~` cϜR!95$f$g*6ւ˕FȈOc "zD &bX0FŰSz&zBfD/)*؀imꭖcNskzYcКl hKz)фX@S *=.]7N_1CN1UKE 6(‹b0&2ϖڒ9㳲ҠXB(1c!z7\lz_s+Y:C.Չ!Fg!mث*gv J 4BjX34x`yNSÐsAX 4A3X.sCi'0!|}nqI?c$)&(hB8ѢoacQ)5!?ljH@O al3|"Ld!mI)qЯm` [В΍h_9H hL]h!M誛5'DUVZAIbH5K?nnm}v[{u t^^&i@ jc\**CV}P:}X-R+vE{kwo@N4Vd^lMB4zB(EnjiRҵpAkkV#`'HS^[! [ tA?z۷oz(:p=M^5T@0oGX#1!P{0Y Ч\6~`&]w^;֩~ֹsOJraZ$E"= %gy6D5\krsUY l2ِ=W0?\9/"0VfԵLgڝ}~7ooZ_?{߹^\$/|6mwHaI1a04U+h߿=dm|mL:9oǞLrDDgPo|`"8H< hYMp?z ds 2lOaQì(<6d85=LC\?  kA*+M)?ť+g':|WN?{hBе}^s;r2tIG(Qc li^ǂ_ovֿ9l;ѫl޽^^p,ܽa.t)*8Tf&Ez6%~j.QÄ?WM*ݒl-;CKEȝr|&GiJv3tRY`>a8YR?vd=WCB˲ m! zDr+;eR> uL_Z͎$rhlIvIc6u3{:Jw[mI??wǎ?m%) =y ! *b3۞DelJ](l%hz(aoɢ弡KN$=^Wcɜlp.儭ţilUlr̜lA*W㸗Hd i Y`xMW 쥑 aRU|3h_7U?Ulc +LAO˶S\F) e5)/KZj`>5ߐO346;N>Ol֓Krb]kFveuMec N fddHMg`wSHGmj v1w%]D)W xh^]N.gS62рBIv6oa7}˕9҉sqg( m_ ڰDoe' a;B*eI8]aR fg9TKL71jLǼ~Ҟh``9_`AcnV&Ge40 \e3 GX(Z iix<ʂ1ZcdDb)g^J0xTu6_QJ"=Է;`hw,TREq ƕnVH6ə{kBd @1*iY"JSKUՒɎUy˕X%-vaƊS?(WG 2ELyTmfðLzJAI_k^6kxkmibٟY %)"߆.`s>Իƀ:v#[0{1p"2koxYAh%Wwi>/3EںnbS_ج8dZ2J3qQZoc!P`ؕäρ4)ÀS% ,AKgKl{DsKXRdd)'}#X2b+M[0S9͍ࡇ|y;<`h_.-@WM4;XP闠VT$b֒{EX39B)CW4ddƝuDKC E#rf66BD0|$aqka+֥iK*cie#ȣE#*Zq9SbxX{“jN=DS^SvGj;{8HӱmxNJKO|/}KȬ8Y m8Q>5B *XM'\ L;De[]縛%`a- JeXvt#CYdy tz['&7OLl'jjBdhI)W^J=u湅s&?iT3ըQ)T ?Wk dHT{ʀ?7׭Ү-Iر] ML}qNz9Gn]zaC?GٴN~2{{&BUn0&.9l48"u!NR$"ULXKzn`a VYg޻p[rhƩ9Q0Va )QYQT/'2Qsïc (4I:qY O.LU:XdP8j)\\qo?iV%- ˶ll˦>wKShIT*q dQb"\Z~=nԂ,AEXQTͿѡ36 u uta]if+bz3J*bT5#Ȗ-x!!q);}JdmIS#Xv?f#hsL!+8 v5?sk'ml~Zr'U4'+e8a$Ӿ0:5FYL.KB!TY#\j4 X>J%7QLY zU7oDY3_{\-HGz@q!i5AIO NʒPYHFTtһb<7ѿ'֫P뚷ɰDԔB-bV&MX)]P[XUI#:"|M{Lvj.r׾TTxKog^\Lq`hs[`]l"Bp*?{W#9jA6t=ʹ!)$Ϙ+Xaqd!),J# Tep'hl p;:^=]? K9Y~?ܬ}lmQ;޲ub, 2$]cf7-RMAtC$)ڶl_;s}ˢ{EJb1.Wl`$2n.R?:úϐ#;")ZhQ!89PQlAtW4*%۱$KvM %[̼aPv5!҅d"@Jj5*Naug}[g/x;S";_I|PHۡϲJ2 Gu0HG؉q ;=9"lZ8#hrd|D#\P󚚥gb‚n @{ {7H K(G)?LlcY*w`&xBc^6_r;zzWn׈?2ͫ6m5v`H u}EHEUVD725\ӷܶr@پJْ*6|(P-qZX-l kI$M\av%hgF=WV2j53P`!RIz"1:FL;aqZgȱ'{5L[R0aY0x @_>yb__&\N3;*8#N#/ #@b=lb]λZWAB]a]/a˱ˤ1*@ 6]Y*yJOX2z߷ťN{he e$ &&.K_Mkpfʍ; *LR[/A/d\xBاZ5\LEp;4|/?67|u?( A#,v_&XATcԅFem̥c֭afNJv8J2 MY6F41+')`\"rhUP ~_gRIK'/>uwD'茥 3tܓc R=["^Z{V ৶7%=g,m~XIP) E|2<Ȇ挖YZ4 PJ6_躀s+\E!qzz,AL=mЏ*1f2I'~fJVn7s M󟝟yݍ7Ɖq.g$JśC2*ɆJt&SgY/h{ߕCc2zB$'GjBS;HǐX|fٳ609:ɤə2uz1lqڲV]2rsC)z?1=Ol'Mճq!Re[J~\'iZSJg7_n,7jVYA.p9is.sҺJB-?aA:7tE;SIʉUM`ȦI#7Nn٘T-AX:Nce\9Ʌ~j8QHZļ6j9Pr:ƶFoj 9dS=S@ں$4 } =~fFH/IBruR \iMzSM2x(u2CfP[474R_0|^:S̬lÀ䳭MC`=<,EOj!O " ADŽ1:),4gc9@G!Vqf _:_Yؐ@ :@ػOT :SSݝN~_z1eh/lnet4#((Opheb6[:ێm80`4T}lɕ3D(2 &[N6gÚ4VJ*/0'!{mh{5\ AmҘ΁zLnv<@| <}"@f]*EVwdca6AxЙgxѕYR,ScΉőwJЅL- bfݬ?"k`!te!XRtgX6i<$tu(!E!vT8l4z,w/U-C,^!6&V8Ʋ"{B-6X&/p@UWՋlֹNNHC0%>Yn2nQH%'zKZO pKm?yCnhX( 7Z%b &dpPbWj-, L0ƮM>O|u15`c]E,Bn(4.ҨZ飔xEnXt(H>7~C}J*U%bC楲hpȂ x;梵P+9Oib" 1^h:fIĔwqr6ѵ ! ȃؾaʹ/!U=S<2?)Osv\G:m/ώ 9CU 99JdiS)#ݤɪ pY*FC7d]R썥ʓ =4;Le*2`BcMcFIY c#$0 ?L,"\:6\h,I\2NM)S|.RSWAzd[n3.l{M^@IW k6@;fǙZچnP 7Ph4]C &N;NB!L<+Ɇ'hky:tt>XT6*WU yd5R=0+V+PZ A;U>23dTOa pRw|!UYSKZut|li7STA=\Yqg8)D>nu*07ىdWhid72;Z;QϷ$d5Ǎ#2E1ʕ-kJPe|>9n_I2Me-8]: 6W Q1ԆȖk39d.1 +QSi4׾Eޝ=.lVr1AH2;7Yΐ=ZmiBRgx5d4{ZsjSMYL£¬-jԺF68pV gO,ˎ08ڷ{{`P )"%0K$Ӣò&KIa)lѶly %%)R4 CJo=wu{O:9yz3ӎEի%o/ҩr iE^+`>!9F(%HP1U=)D(| S( J%hL|ufIdOɞ"ywHzKM PG^#$ox^1ҒE=0"I?bO)6%`cXPH؍G( ̓kO2! G-D/OR \CMT]1,Q0vs>#z !nP#V= -J%q*f4IejYaeMjpeHz@ܹ'LnVJ$^PaGSx 8Tr5{+:68i;VnUn€ăb\SfϾ0ۢGuGS2&m>e_(=7:̓@hWnxc#Jw#pju;#jP,(ʼ>hL5T5tfBWhs='xHú7^9̜(RI D8Ҩ'Gp=iG?;)=Nn^Ζ}= vv/_>{^yK1@]"bIMG)qp?FfXǐ چ#GG43N-Es(M`yS0ҪOߒs副^/.Gn JV P/G }B2TDYveFX'/Ey3|שJE^]8~yO|omK[F j.сQKŠ`0-h#eQAw Z5Ʀ.AzҺ$g0=rcSb 6Cв55DqV]HK8'%%2>0YPYZ%̔w mL8|V$OpH 9&[f?{_k7H7>˵%A8Hl {pkzvHtjAD ont_Ϳ'Y x.rޭ}Wf;-$+6_.'I"P0 |JZ"A)c$[aBy X aʢi07a;aUu??pK+rF 0 |$#LAƻ냥ShzG1T*`l@Z~nh m48xSvCJE`Cſ83=IX n5{L[,F-shKᜏ txĻNv.nk/y eQ0nh-P;W=[[C0),a mm~&p vj/v6 G2{2;#zzD T/I15"F[&uDm#K V%SPNoGVp`a& }qа8HG6,mW 5q=9sH:obox2s*8J5L%,7(E5DP VSmE@ZÈJ_t0(i~&VpF\̆rj$ZV/ZbI7,?O"S-cZPj;p:y :]fVGF{1 c&]YA cSf۫m 0=*͜. |HϞ8 ;!_= "M;ƩڗQq=RA6ʹѰxl,|DQ@U3݈PzꙶfrG3JlB.{t&J`^l.%3HC-`H_7^^8rqʹ/߸< +gsV̄ιLs AfT&|!wpZu iuRʐ)v-tW? OOu|ۥ='y}~훟'r?r{k9rj pGK-a1$H6!u  hUp?DtZ`be cxBx|w9%?oDprمN*dY/jeV ~Ur&g|: iq.5Gi o9~/g>A_~|;{ <3O>?7Z:txiľt>ˑ, Kλ#A89m5Cu⭮gO_|u0_E0)8k]߹Q*5%I7SA,+.jO?wU"'_HqڍLz/J[\ ࣟ8r3ɟP}YˇG.N.|/-~+E=PcJ4>jF0Xmn&+>1zt}ܖ;˝?vҿk@( 0`ҵ97۝ SID u#0ƶbz}N=3)`vro}[??p*{6yXܯ[lk t΃#37^Pl7WM/b|=ZWCIO !Z5C  e'kZpV 3:x HL( ڿ戈zXk|GUV"(RÆnrqӎ[%&O=G2x"'mh,g2ND~Q嫓wVfhfs1vOFT/C樤(3>\QDlslfфG~f;X2̴mvm}?rεXM.TTЪuit6:?ӌS R& Y~ D He&6Q|nމEwUx(Q\#I~j&0ω,w?3?xr[k3{f_!_mE衦я}춧H((u$>9A6LNNDR Z6ˢ^LkKvz;{WޢѼmgmcGME`KP"9ֵ>:5*Df:9 N}er_}ڔS{tHVd=ܩ9;m&y[v[臁 a iTUnsGC1`_wo`FϾ 4;|^Y 3MQ.W0ke1tf<}W'-8 fnP7^csgs9ZqQ-yi/xOG Kzp'S0HBNJiuiވ?Ʈ^?zs&vvE}sЋm\7)Mw|G C'qZ4+O "Q5>~1XCbn^]VAF925q,;UIyOHT>ҐKJ)~F"c+a!]7}a`( o}3t!RrN&;EB{4|BO d[clb0˟pJnUTVpRm {>xY c&k"5#cMUg[QH&!*dpY/Mtm _oAWO<GW?A0N4ZRQ~amjr[;EѮ:.{L4J2֫HM 81Ʊ6xdfY^3!c<lm[ߌf7_?ze9޽܋sZUW^:bn/Z4J04eN|V߆:;7W^ncLfT|y;CU_V8'P7hAZ7nآQYWXUDqiҌT?{ a^r=1&ʑe4J7F'5Cȡln&Jyg[Ţ_dɩnɀB#Dz}ճ^^9VZX7nel"z_~>dOp'GniAf+K#[3I}>iϳ~.Ϭ{2aU 8l΍b=4p2N\3 I;h!{ퟲ`_ﲿ[Oe" <,^=F]0&_;S|C9V`K]칯; Qee@~27m#~^HDEnƻjr!T3ԇ08`V]haxY=˝?zȏщAij7=./j`͗Gf^p0DMzǸ8gpB-"q5,v[25&1$C~es*hhۛcem+Eb Oi0 ?™s'ffV;h;W":q0 k;׮_?};),/h2R$ܗ+7^[߼eZ03FD%3* lh_>ZBCNb O]|rxJ}fB1ޫ.pwn D5lM>K1)GE"lrz'A$9O# 1;#>Mᯉ; T>BUj67_ٸrw;D G"u6SpL8h({]U~%dA$xĖ0{Zֺ#h#괠, Nfw ^Ϊwqz訩%NQ\FKI@"7SAn؂X&yq<$:TLF:O&"[Ith;)39Jzqῒf 2IF&Ofp2E =?*0) :wϝVO*ꈜVT۶٭F X`]⨃ Da,hb(kF%𳔔92G\DL:rNAEq\'MNnEN}ȀH7qIFsJR2E19-6`xӈF0}RD_xCҠש}QQ(FT>;A셝W̥UѪZ0XgCؤSР`$Gzfvȴ@"+TZMVFə{ oI Qa\3|ypc*Axʙ lUbQyt+8 w^8<4;[ఢ06yio~аboơ|;T^D2$% ?JnzY(Hbhod&[1(hZdA dre¥,/ EAM!L/80ɥ0@ Dx#‹41t/>R;hPAp1\l!upW:ueU+ S_ł%MHcQ|c,W"Ija*G[/V4u11M?,9x3b0g0|q ~ujkgF.G 9ozqcS/vusP7O!fp( GkG>Hz/4S؁UFFIIsxl`/il%{ő%'~SwPz`N<Ɖ#CiZuޤݧ!rvoȕK(*/ƪEw"ˇry`ʪ.J|o|ߟi"OojԴޯ o,RD {t"10%C0'|!KN%1ن9۝ 3bύGFW읜 Sxs ,41"c"'4#S^jux1DZ%3=qґJ=v EME= >~ |\Q%8\m.%oz,-F]NsLA)2 wa91.-z:]GV. 1,%sء:IX$БܺAMq :u=Pg蒸ޑИ*xǷ#5,ƒ'{z|iEl7_ 17<&8aU {CP?|bDVPPtaPj;]yikKPf[0vJ:n dI\gjJM:uS'B Q:EKǠNf>zQǕsCI!8T=.1 2h.ۛ!4ʕjoɻ&#jjh{XG6upN3(|~vscMKT&eit!d[c|J;@x}yƭ6OQӿW.^*A |]/ats{m0nrHr=*Gb?`Yo~ǘRZ{G.犽1G8Ke} 2ab,0]<)ꨁV4bX;l` u0֖Do.13,u!E^Ҿ1 gGqzQD@T$)f11uupuH!u<co3RMu`6 8 H}tN`I ҘW]fCur;Ԃ̙bp6qbVO2UW3ҮJ0 eܡL~1㜦[VG CFPe`X"NJIVV~?珵O׃b4ѓk>tۆРH晰yL0RVLD{Dž.RPi g֗aK7}J=@aw[t+mLvyy8~M}=ճ@Ji"#`)+񺀛bC$S]7|wv4&H &ay +VXʍ`m TzX,'Y`$(elęL@k"2QF$Hy8\"33}l CB ϡ9ok-Rۊi睏dHǨ-i=:n{ wV'h=:Lpf{ƺjSCM0VwoRn@+Y !EW`vfC1Nu0ef0Ҋfc'O`\$gA[N1Tϲ"l"3UyqaKCq< $Lx01"<~ƹaƬ4` 9-*.Vʝ%Ѣ"JٍaRb> ")ˆ:L`M\aQcJ2'܉L"Vo!btRf W )|:E^Z[O>f^xTԢQT^_D>t3nK~=U^LB)[BWA*5$5Ԭ N;ݐr,Eך^CԳ#)0qĝ|=B-4b,23%D:=2NGIQYє`!rv@G,`W T㖧 ϙ?{J st/?B<)1"i&tcqc,1ҌfqTWJdRH-%9e&n[[ɭG~߻Wl3N04bѴHdJ&%KZdB>hI +U6#g8 3Cքϴ i8?ǿc 56f2uHi01VJz^+g~鹹 'VQOU |=1Q:4lpW:W>9kic/Qbs%~Bx͞!3l{Ә(_8HZEJSm W*.3#œh,9``&%Hyd$5,'H3WE(v6νԿ8.|ՙY .~Y\ğ|DI ΄$P")Q0(+L܌(enED^FM$.'`%7>3 5>h6ӄ*x8K .2 f>ZTJOaH-o_{hv(lx=?DrY/~ ML-=*SZ{PidׯHgvZy3JW;걡2 *$ fy@x}))qo$,c7Zi;['UtQJ$& Y)N~ 9lT~]˛"iV:nZ,Z9߄.7Fϲ*j^oHYCKA 8N .&Ad{I<7mM8 lP @ANv\= 7cq1CøiHVI9?f(yY!S4̟Qn 45O.>ܞo6Buj֬ \t.z?vmz`75zL"xV 0ѧ[mVkP2 Ron{c(2tJf)K@s6IK:R b" 3Rz X C7=Gkn+alT;9fH1Fy(E drj*X@wV֞Z\.ݠpf"6I'rrpFݺ>p3s8 3j=cF(E,@ZJ0Ehp Q)^W #9ą3q_4p5Y,ۋѠd+" 8 E4o:и4}Ϣ^N &MGn* oa"iID&# ӫ;W><{ȵh?)|O %4ۤe?Ȼ+1PR&d!t&J>-{~NW<1ߨDUB< U |(f2 dMҷM VW.?ҽmʽV1vWEm,SNk::%kKN!Qn\IGY~r3D aQTW(ݹ&B[ql1!瘺ŁWiDHf X]A<(ZcP%*)UأK5whz=L3 wŕi̸f$t@V!=Rf.{rPbtϾs0䨮+:\y;ߋcrE3]$b\|r:XJYJK *43R "hBB-GN3OxLHvn^"DCA"+]Gj"u](^%)I=w3n{] bT`Lf;FpeW>4͹]sta 8gF6`bE/]XYT()وI3:39Ys o!X|*ʜ.Xhc]B;]x15 57CIT0E֠D-aC [uV+aFkY\:6W 9ۑDTW׷s4(j^z3nk7d1,.D:*#9'yO6O%Lk/v91ftWzX$)J Wc,`۸_,Ⲇ#1`RjbKTN/ OaònNgZ V[<2zj=bp/9兛b/:o_X};5Q/"9\ndg-#QDTL+>BHI;'Q,, 6I@!ݳ EӨ8¼۾7M%;ـPS!0g )⣞ԹG V՝k3f$l4f2*Vq7/>p"y"@ĮE9#(4+!2ʌ6JHߠ^}von˭v phݹ =ՎTPvDlty8SvޥŰhJ_,ֆ[[qv{UxeM0*^+'8ahjK.nWΔe+.ՙL6aF@8%c}| er,Ih*>_Wը7ػ= \Pc#c ${rhmKKW*46XʍFcw-3*b IxVи(+ڽKuXez&D1+R2IԹ|1cS4wI"!J|ⱀ`lY& qk4T%8bviJhLJD;ICm,q p'RX| %kxdnĂq5t!H7h 'ߵq833.n/lE R[¤)CG'V,SLi!f=daԙhLoڲ>.F%#%vD3e`*^Ո]`K:d1L%5'N)/&f'Pym҅E<,S d52b}4Jѹ\1*~+}}Mcp S;Ϣk:3p2a QʖIA]/̄9]+b Z_Vegcxvrd gK48sBPȮ.Se\ |lIڭhXb쮎,vt8Vш 2y#H`ZXͮoq[ٗǏ]zpQSi-ߕb;QpeD4c}7^MN"③=IY`W=L}cDzWGEoO J2Ngea1&b_/+bI-(' )Zawf_X-wn]U^맗wX(S5wk?|} jF+q= % .iziS&%`M,ET>Գ(%ǖdSY d%gR3D<.O$Mj0'Zr_ 8=~}mVtWGZiuηMoϼrrX#W cW`̓i[BthFx:0 +S̹DiܤSӌpdЪG HQB\3YU.7JG7"px3ϠVl,Kn 8̶MToOɅ]QQr\~q~Bv\π>x ;";H`51d@ǤNQc{aT__&ʤ-R-e-;$k M k'+  A 0[s>w)v;_b劢X=Dro&t́s+e{չZ{zdP*9|dt0baߒafZ i jL; <N,I~~gDRZxJKWf9O %kay3#u^+z]}~ufne+u3\1pe;۝ߜM{6&U8@0Px{l'иMj;;^ޙiB_~IjOҧq?/>#]夸jǪh'6/PMհ,[;vOl z;adz6xJa8" b1!GSaUQ$ )ʒB !Bm],$DEJ|9BJ گrW;E[U5^%V,B 7Lf)h_nb_å,[svܩ-GuZ?1?@M}No2):2;M&.+ZJZZ fzF;|d楛qE8$ 9"e؆QV%*ȗ5`bEj2FHr{6[POz^B cd}#a,I#d 7ʥ!m 58~m=kS\mI BN;kBdSYX-&@jTTz߮|U C݌”x+$wYTRi038g6afDTѰڽ);0v|ZWe%.mm^ܮktiaT3Ss- ,(ǎ\r;*ߖqPP4MV VI^8Pw]tWiKÂF%zwBl\)­h> E\LBᱍ?|ԫn$}ݪ݇V.{N9 ǟ̹"ea~ǂmc3b*U9AhШDUۨg_+!yUp;kތb@R]>I\Iue8v]wFhͺ؋3щ&0O|7NM~+6iÍ;h{YA*ȤR C8'NeUHaTit%wQ jܺ}3?on~^zs_{Auf`pփ\-D9  62L63"  uf66FdVu*ha箨NcVdIJ[5'fMlde2UT&ś8E4j*=vfQYAYmwi'd]zIu}NH!O 8wj*ǙۮfD{!M|}l%*|;BF3g[x3J: i&WHEEzZB}1ņ^:c^t-Ө~ x}kuL[H.=V%8TU}Tx_}vP{!(|7Ϊ-ФVYRa"%;nP ZGx&a &!- G ϶/oXbo}p{kWx5]hsz) hŝqn5qN!ll(HEjKrfة޶Y o}dz3-`9;O]7blh^2z(WTPE,jD`>/1zDﷰB?k<ء"0jhDX$?ظj S Ge?jl_Qz'fNhXv7j]agjSP|_%k"H<(*"F JHu\xW:j*'B Rt |ԯ/~h8׏n9ʂƒPeP竫O$dw+@`AQQ5ݻ*&D 1^a`pqV z .=B0o^[9tdε`!%zJb { K{j*ơt O `Vgn-3&iԘ,tIٌX&;N[mqSϯBhă*"Q߫v[.O0CZ!jԮ܀n}ҁT ʊј >L}Vl -C1$f:wfh}AҭzN Wb69о;mgwOΈZ]P;Y*`dShctfiC-R''P>{^O+P,$⺽>)&x}{jmKaSJ2xꦧ SoەZ'}-]AD)Ot[7 =/scK5U "<෻UG(摑BUW#jdfeA݉z~*g!$%Q F ,QƖ(/QbL>jb8T%RK8(F SȃL2mBif ]?H^h$8KD QSy4'bPR֐7B'I!u)CUJW dID&>i46,͚̾ @_KFV DIK~)$L/zmm0#!b~Q#}DdR6!~= C*@Qe3 t8Vm4Te 9tȩ2#8, 8/^rXXk0[%yE{V:ȃz` Yg vZ".} Yy{N q+ )=i<6H1 UuM!M eb^ސ?]X |$@eIŗn[5e'@0/}1} b^<0x,f",{'JVS~zPYQ s2 b OD V'3g}H"15X*(YJGWCDYk|+SӉHTI' XLJ?FoRE޳p; v{FmaIj9/pVCA2 ^9Hh$d^N|y(yw?C 1,K7te\p ::=߰dx.(ºg*&;e1&Q)ktDv sd^A&k\EE[MP8mP϶2zGp " DRC$`L=$~8S%IDa!$`%-aqDyE Xx0)м'W=4:In*^& KkrKLyA8#Jij,131KPR'4Th}/iŇx,gYYif~B-'1 :l'O\O$&cp혰=W{TZ5N蒒VOIKY,fBxTfQ#4{ . v; gӶ`Bј"M}"q z~>&',L}*V@4c%m.3⋘v#i4s)ݝk_%L$!$km$fԂ9}[I,%1?W2Pk~\*eu'1kP=ڵNO@KT [t\nJڡ X '"YR f7R|$RfE@iJn_?H-ck&VbWw9p0z4ꭏv[O]}3fa%!lRq f%sZvP$itbv_Qg[58˸F{ň :|zN 1;BL7.fd?YPg#3*bR=^_JC.l: ۡi>%B| Cް,?s>db{=rԁ?$C[7F.S+! 3_'ŝ.'DWneouƢ@Habmdzd93'hӛo7hr}QO4U 4WIk>0;-$P. hGhIE- MiS-lDRv5%נd,{6, ՟5Py|ѿ5wOŝ޵կMЩa(WPP4CXާ"1mMɿ /s, S!Li؍u pO&KN2*re.KG2grso}g\k"տO$F#"oy20)^66)fȘ1i~B%vԙ(ꗲDC|fJU$IAv_wcs9-f/pL~scolE.W3l I[*33QJAHϧ4jha5ĦwԷZ]D0_}ۭ C|2̼L+M6҅iUxHo2G5N^Q.P*`2n و1q`%AbdG|dEw6cQM4Z}mڟ՝?~-]AϱT'!2W$MR>BɡWx^8D@@ 4 g9G霧]DO%3|.)`! T90FZZݽt5oVtV7%* @$&8/jv%Ab$! '\k%)A2kXTf[?~[wf˹q8f7i 5uDj[S*,:Ej|4eVA0!9[}%Lkut jT6> %:F+foxN ;v2 ja[l_t̟ɏcsЕ޻Xsy0;!h&ԴT67ʚ]LzwPhK6M5j`dμE/eJnqIW/^L,&BeW7^z{^g>5wt82fDvAp4a+Az(W!QTä{~|'3 6DB3~+;G=طգ_MYkEIhgJ(֒|eU gm յ+k{Ƽą5M4q{L, 4tBs5X+Y]dXvS:MU{X֯۹5h$*%͆dUƪ9Z_Z..BٚU{C?2!1QQBoM[*-iwV e;ڲƯ v3?Lm&Ń}*S3 Vg ?!,_9n~C}7c"|DէAfV[ M个{G%YdYe @X @H^^^b@Blx``v+ٲ%kF3}zk}ݵ{z$|I=UnU:ܳך1s2e=ZN'~Z %tq87-d6s.7RפoXEZ=N&X<|ddqk ܿ|zހj3Qš7ClF;\CDYVwl8^M߫=HrqcH,v@LK{l&ӿXi30Z,C369-]WJ~D#tޕ}@8ܾޚNEORJ;ꌾ\(leefBSff6~~!EÙg܈K-{r}̑Y^;̽f0S汓>{ }4v 7ns#{:YSY"x; H+Ͽ'T-^PrV ǭS4_$^!q/^bG .(:ޣy#+ʓt#\+vb-ug텸uiޯ(cyǷ[lfeSO6DG6Ӡz~w)Mq~`# f˱0UW rzQ$QBeU?*Z 8`fb˧V@XTt d&F[$+ m*xK+Ohpã#Ѕ_).jZjT -q{^ d.aG,ף;jl 7(rg>=!j9oyΙ .?5k16h%tKqɫrX%&n|B7KyCwg2nFQÂ7dK\+ڿҦB OmJXy4I0Pt'ठ ZVRde&\: Zڢ?J5WTQ6rqNBB0|=.V8݂?KWq6l9$0 ZyUYWd2_t źVЎ\8$tD@olIT2*GKj)ɼ/NP>zl?ZA:')RG<`%s:Z*]x'XN :=;)V[̌XӎݠF^W;uڋ̭뿥M#88FΤz"mCc Fktj}r,0ݼt7:@7 AE`,r퍺Hx4c߈{2.#a#lg]!=witqRNNߺ'{0/=jD\6L٪vqMÚN*b^rDJ0\u1zDfU:~~j^VQzT uH&ƎKѝNx_p|j9ch#>Lx^TB.>pa}\w hK[Hri4 : X`ܺr&WkNLJmUmėTPT"/g; `GYe*-\ TsET1;*z410E09Y..C: 3=6OwWgH ˛7^䖔 j].z.+U %= L>͜ {k"cǒ#_b1NGn^Kb v7jԜ*C7`K"&0c`7 \FPF_4V8 )רsik0o[NeAh T؅JW5vmd67}JX] Uh[W2dQH\gWbAmc9s< eO8 omqlT~}RwRq窺Hh<\ J5 5\سS84a(蝈&weN R-Jṁ]p1=c4-,/cx c.msdo33kǚL}.rCg^tV4tQ-Q2;L~>E'C-|:Űc DXESm"׌X;O󣕁8yah@%m}YM즘Qi3剮HOpEMWgΨ h'Ў(ꍡ+r iFǫ\2u}|N&#*bYAwo G4()RS;n<" /0M"X~SrdX2,u_qgbW hV}9&!\oO&ƝO|ς9=B& $~hTSgҞU\2jA;nsz?1&m y5*媫[vbo4t.jBN[l.ܜ-(ܿZxBEeXYJ&?ûj1(gTB?{IN-+.wJH,;f/$)UoQޑ*C^"l.iQxG8(.l&|tN6cCLp>n*l.@?#CQ2\a{tfkjhXq>rϻlHrjuo;8t1S< r* >s0Kc?p=t$[Xώt6P o?I*Vu5pd,ϳEk &eÃ5l5\`0 msx-[*d>9 R k-_#7n1& 2֨ $cX$TV^攔aWS*4w!|U'0Xj2qKeRີLi4*_Gm!Pex@^Z~U4d$Mnt`[\KR@B~Q;cD?L*OS uጃ {B ~$in~ŗ^;s.<⇦|L*a]Wc{ mn`Hnw1]M+xI$ę3)n|#gpƧօf.oi3sFqD$33/hFv%_ ꚎxIz8,i U,FߧiYkpQf_2je^ 3? <.߰ۤHO Y}/Fp|)M&n*X73310ƊW?A7w;@ +*Ϝ`o E :!.b&q_dxa*ʼnjDCPfy|kaUKWP2a}B~ `lSO?1B%0F* 2.,]TP _B9iC^+=m̑qH+CƕC1uR rfg(#=!?Aj r(©SEQK]]k,lv\!a^S-*GDtD{ PA:}KΖ`Qd]BU՗կ~_z(w!kV!c, reQq#\"qckj4p[wFOی&#πr9<>:R"@)v-xG};Eف2 1Ƭ!6CZXB- 5-eQ>*_ kT!OJcv/۹ge"CHtmNђ;t1BɮĮ]C022q:<<\tqUD%0Dז\@9-bf$/""GE?7c~"bn1;3{f"%T8~ 4Z٩CbB\{ws7;SL4]߹RM׵SY^`*=`DTTZfj-hhPr[- TEiOx" e+CekM RVINVr6p9‹NnTgCk?3gS584M_Xn]RV!Xrڙ\3ٷlns6`eR ˦ /ªFi"V{b14t]-M3N({vo٭fZ e̳t+0Tl Zi19_1RFѭQ}׽oy* zz{Rgxіz8]$HEY­\"cwŃZ +_5SUR+WrFdZjU\,A1B 1ݛֿ=Ӳ͓AS5QelT$hwR*1w̔TqyRohS@ig @C4cUy4 j;J+DE"fXݩm/64U^ З;qܢlI3z ].J&}:/VZ^ L/3Y^%@@qBK@Cܙ8C> f ͫ\hQ(ݗ153B x>Y)OՎ7+FgߺqqܤD*1_5(`?2^KKP:WBzP4൜iGh+O\OI<#ruI߂Z)s⿜\nC-6 35R[fKXR_;ׁKE8lE(:d,]6CAMcMM԰\J.o@ J&ùejMKO!Vpr;?ȁWXUҲ[g'DRGN7_E/ѲGyXtT׃fXԖ@.j-YԂgX .\KF0EL`D4\!J3DF~KZ0[B-.nnm_2pl{Ӧf Cg޸'8PuN_U@uQ)2,(RKoƪxZVD0/w :Ej ZUhL j̲3VSBxn̐ ;%\@ʜ| mtd{Іb׃NoQteP|L_ c=HQ P}T82Jn4ca(.vm}]JU9]\D\H=N1`L"귂 Lg h /´v9-DTW'seL? Bf<)ZEeCd sr 0hҩwW;G$t؏yD&޷KͯϜk@y~͉;(+tcURE^J} 1_!F$g!< H[F+!k -N9voR4П*l(g'bZV< (Kk2X&޻k,'X_>|ytr^Xo\XK~@8Z\4c Đ*Q`'=z\gi$JزI,kt0!T+1!^+RX?;1瀱NvZ/,QA@oX_rڙ|C 9P|k,3fa"pbRVA/Jcš;a E@]$Ń֏jo_zu~f&\ķ& C/x"4ڼX#M/3?3|!ƨ,ki8(/86lRVUYJR (II p_XϳB6㌵!RGJu߈m;w["&?p,8(o3y:D5BR)6A,;/U*Y8UMPM͟y-{1셐Ï탹X⮧"]HUᖿGED>g͛w)ǩ4`߶ZJ%/$6F˃āBe(O3M_~XH2&&Ɲ]2e)4C'\͠b U"jbcYƸ/[oR}:]6]QXKCX ! aB@dt |RkTRUZeZ-+)pYY2S8dGB~̊S$4KSp1kp;<{Mp̵[gӧ_~gd@DD-#Q5D Й(bh7=gcnbMftXv q;P~ Әw/(2+-^N6t$0R p]tk;UI gID[d[?xi⽗ t@jeaUb0h]{PUȉQC!R=vH$[b:l2OA鍢9Ρ4z̊&wY !n%IPz/5,E F*l 䅒gFx!{LkeA\^2mDat~Tn$)\)3}S,lT⧫sEZT̘ȹ/=cJv"ZS\iC:-VsP=14Ild`Z[԰n]*``kpp:GEa[4|{Up7ZUH1Bn jvSfB5FYc f*J7ي8r³U-zv*Oʖ\ո;6Hd5M}izYu)|lg#pdwQѹI (2հTEd5VXB|al7vPl}麙H$(DCR c9fҊ缷-MG(6CNv lFЮpB8f'X9EXcg;Ƣu¦$Q{x' D:6aR0TH޺F;UƄP0 kMWl< zHL0jKK9mS PUF% NlUh8+XVe n9va|1e=luكpƔm̹u\ypAmө7w(7mUL~[ hu߾Lͧضq]J,!&!~5 +* eʯ|F]Jkj4еΘc8FϝB/_tDh3H㭦1"1~$ ucˠ\]5J딫(f)#>B׿ C܂bc#o;`9b1)4!ׯ ޸O\>n]:D4d&%d#eīe:B9߈<_X,Ҁ $vxQC$I]w_W_}ûuûޥ[ј陙{@rκM; d?t,8[ػbf߶6Pkhjy{0l(z_:Ʋɿݱ~tup'r}~!eKŪQ:cΦfga+UQۍN9v$M{N#{FǪpZ$@3"Ϡ/<} m;_U>v\cLm+lG<3qP@)c&3\"am38+lƖ[O8﷑ Jt!]-}dx<=͹- `c Ų~3oG@ ^EP_E"ok)8nî-س{&*:e,dHA P.1Ə>G>򑙙l6˻Q0YGI+HwU@ZGevO zGh&O3)`[Suh0Vu,c-v_og[;9/%8qp5Ȃ*@IGu9Hu]*Tp ࢌNiA){=WaUX:+:DxS _ע3H&(B~sXC!}0Z="Т#!|&ŜY8(tM$1)RJ/yiէ vB)0Ăb?*۷Y X]h_ \࢙H/Ts'zx?/js78FVֳY"#Kѣq"j^{%ӥ;vQ`''4ި1lɓTZ۾/ *&[B霶 $ izMrQal΃Xr`E%w1$BD2~@!cz*HGǁK]O?T\ՕUN$. }\aq.lESj涷W-O^i]|\~ar$jqX񴯹o7GG>rJetd;wַET90[)VNFr $>~B(V|P4kPn]|>JR5lNGjs"Aʖ> GTQݣǎ>}zpp`wCi W^p cD~c_Dہ;)%3HG8(cI(kI /-)E$;e8nIF-oXP`:GEДJecuKn!ڣgBi~`#8xp*;Tľ2E=ZH S 1"$d,׿` ܌!#-DX.r/+/ ZŒŧ0S) 19S_J]֧46صZcM3e)iOɐ /מvrU#)yW/g"ie3';kZ~ˀZFTa\NFgax:rr.dx,+UJ!54eg B\ b0*=;w:AO_$ZTkOH{+(5/*'>AQOS$]"nIϋ]c:cNgŸ GFv,]+N'>q FJrx"H`0fiAI[-tm/EÊFkޏh>ޏ}p\/DVe@)nڣ㬤>?SaS ̾Krۆd0bE[سNNGVuD eSFqsv{ eɄ}!h[EE{w}|,vlt:w NyVr-\hKʂx- Jbڞÿ]D^2G.^kxꝌec'+8Uܴ<f8[jBi_jGC޹coD |q\o[4If PIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_200x100_resize_box_3.png000066400000000000000000000507631420147000300333560ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRdL\QIDATx%G}'ZO>07̝(4#FB("y F鱻 N 0&ؘ,$!4hrn:TBwus'pgzӡW\aɀ`2) @ ‚cH 'L$Sy_,O؋|ϟ°Ǜ!R o72| . &o/9tYyygxcGlPɴ/1L]~ Y爱 'z[}nUKhW1^PaCKt7 E6mKL@Bo$ 7G|ьΌӞnOcE&@^בs \>gF{{gf||e.DKtY7ƿD,@1a P3Z4W B PrX1Υ~0c ͠ 1)Xxa#R2M  [148:b|.^`%Wl1fbYu%!>4*Ki "o8 2tb:=0}N~ցu_rEgNB F$-&&Ud 鴍bҞR8(@|n(m? ;:0] K f" jSI /]Nҥ ^>(i`AqJa(6,AMeCȅN3o9B,tAlMiGdHd `g]Qt`8j>B7 h{v^;'fG5\*kAJ맩^]D "8 Z'Hy D " oWWyE?El>x2q$ҌSDA4jf,B~JŸ (3EE16Al|.`1267]7~7eJC CeVMxYa LT5-wpz/ⱡ0x/W!%-nv`/Kة$>(Zۿ`~1DFvݔ{[~~>3`@yNHǴl:;;8sUR9R7&Es".ePQ%4$D @A18p @R7!m[Ee\Q_s0܁ # l00s!YKP.t-i%aUTE7g5|Ƣ|M53x %Udsh9A;("!!@ D)K( V܊R8^VBF_ks\A3/Fi`CScaw]b@a3]*S~~/@gRQbnAXᚎ X8Œxs(˸*ҒOK2/I08݂1RDQ)Ljq^t\.H0;'av ~RN>G#S$]Fܸ p(᳟?M.;,,v&zUKs&%_7'ҏG&"g>XFjsh*D ᫐SOE FE`4h1S0"!~~@0\ T1q̕6 DM) !ׅy[Pުà3C̓gv(:_ F$(Z4c 2!@P!~Ӎ%vN+$Ԟ?x rSo*{Ws3 !Jlɬea{[y0#:ĔQ g8Wj{[N*LJ垫 fGA|9OF gfnօoФP:9kr!L2=)-P>~T'e)D9$ݒt1HL㽣'&\JKCMË"F)@Oh#̡<6V0 iZi<& flc!u}ɌebgK |5BnC\ױ\d\TWץ+! pQ=\w!vpkdS Xc'9KA=Id `nz>P7V# o ̺mXD=g9eLPo'葿 djOw]\vTֱOadM2L|!$įtnu ӊ>Gg>_V-BnŘzsB2駎Dwq^O[6޻ud0czO=cKЇ(:n0c|sJ$B)g{"O}WRN| V]>M5b$Bgd7uml({+'F\X`mlᝳBu(9l^"\plO,Bfps$_޹} kB'o}42ebG]D#md⣯}˿{O?Nŭ$+_uAgqL!][:s\Jc5Z=7gM=7\?V2.`ExC'Ɛi*9y&(@C\^ _sʛmj ѷ5|V hjMX:_ʗ$.)Å$';U%_?#>"PQ#1 pD Z#6@n^@Юb2H%Y`V!dG5w69hs\|05rwt>0z^pv9I5  w$8Aj*t=R#;c眚{̾MWm9O2fձs9ylڡS6`׌O++W݁cK:NULhժ\A!}ݖ*;:;I)0ս+-zdhj_s;pULg!%j&oޅkyu=ro?Zp>2Pȿ,4GͭO*eu ŕ[ ЛΫ_{ ,@]?KExR|ܡ @oyW\2ͭCGe9 LY ZrGCjpڈtx\ &9ۻT HP<` Re?L Q AowK0&91c}qrM`"WS70*wX49lxdr &]f8== ]aЗ鍝p|y0ϣggb2W# Y.L򹕺x+.XR$C=ю])79+(Cƅ IH8kwjgOknEF֧msI# Ts1HqݛF)aąVcFǥϊVN).K)[TbM> GV{BSVPA5B,U|;_n~YDk€FJ8ҁᒒq>–2lzNU#לUB @b;:FKQ,}#:~^dn\ 3dnXDS3D\CK9ŔGQRN \]0tZ 9}ɸvb".%qwk" ɖvL7?Ad>#PSoݪ€gɞ Bد^{9$TQR+YN;m2`& ^q5{jb'd|L-qDPec' %}/J 20m]k< s3U71Oks_v(t_p3$|,k!ѩ= 06fa44sɔyH3% cћsOсr(B;,ĩ hr/wTAr6޹u}q%.⃗gZjJcyc[nj|oH%"˓>RSzZ۷G|KJy5_v{XH*9n5fHnݼC^\Ok,Tth` Ibwl*.D~~tm@dXTT[Yk-D@[/ͥd7r-SAjEP= b=9u+;e5Z[?:>Lw֖ͬ,;iS+|~}Xܸf/.H񜂝ck_l8ַj) 瑥ҋI~]w?_\?)D&fev RD h@JVj ~ v;lrc;6w$Sx318ºc|$ tՈC@A\{8ۍjЅIA f0o/Z W% "Ї=;g|`-[c㻫CczB;آSO1OqP\3ʎ ɂ0(hh"4hnp<˗>$@zL !(Jk,D,̡/1D-A3+^a;rܥ^T>N#3 wAGvڮT*cDDx'^ rC_So}W[%WHte],?7[ĒɮwP+9x+>SնVzuHu.Ce -3hy߮(̜[nFoO#(Bbi!d̩LϮ3FO#2rtKsOk’)rNp%u^sN| O6'(tw^rP>Fi,AbA+5Y'2JܓHS6ˍR4}c b VѧZns?h7v\ x)$nGp7Lr!t_|r_њ K窍/o+~{ϔzrMl5SmV[r!r֡%)s( @(;XG}ۮ? CBE]p1J&u0Tі< H `3ɍJmbW ) #BqpRff @̼bxE̍ХY)*L.#<\&S!%@Q^Qqv=Z.:NI΄"׃B׃!%[a;;ߢ_PdP QDj#i&KkG b0o$%{]Ža i}(#ӃMeAGrI@GWZ5BeRfǒIlEePPNXADGnqJ U= Š ِ֏X>BPL3"kɅPBS& sr7BH䫸^ծ<(АR=I <13|ɽO}`ayA2~% EESM lx^">1Z~,Jy1GU*&\`.S1n0QҗEȉu=Z^iJI=] Klꇣ; i܈XAi‡ քG.Ro,Ri2U˜i qqw>#/| F!_v!H@?{zؖɱ-/?ꍊe{L#[(-/-2M$\|`)*0͘ A`?Q Tn-%=eZD$RQ@PH R$) 8fz01+ n$|(j* O9zW n$ ĕ)4 K>8O\o%SNbarB‡HHd1vGС}=}= xӾԯdg. 17s- -~ Rx*E4G,к#Jv5` 80D$}%DnAItłPR-R$vBCm0X!twS2 A2AWr!=_;.(h rZEaeTX ka1 sU9g0_ Sė Q$?O$J\ %ȒhT) tKX@T>dKR!V,!WA]MϢ0=wG 4 4ePxjXL<4Oo 29%Li6AiwRS#IxQR9r|#{;}" e:v]F{|˨/6^tR̭$HXPRM2E̠‚ԣ0ГKiTB̻ ^;W/BB[ZPCy(+c901{ };DYahR#A T@EZZtX\c."A% 0#c'r5yRA$9VAFZU!$Av&3, 0_ >AI0W 0*_q"CAo*DB@!@ĩnOH*`:% `'}B+XE 2ɩfrj)Rh>|f̚Jy(G8椕 A6T%*T0&Sid(PȬ/LT'dʀTG$S=DrHOj J<4! `T? "U>#VR$J?u I1(tFk XF;GjHWa̞swxNKWx }٤7G+i \ 0©l9` &B'Id*sr @  gByC#KD i'ZR(e&~%D sޟ;~* e!bkU%8>H {67Jr*v]'7ĒNk [HZ$*hX؂}|7K7YEV+B8!%aHX>=\B>9a0s42au֗e/ kX FvE(B 8n{5ޠiHQ 0­ bb DAI^BbV985~gn*.LL *$wxmfPte'7j^=<QJY9 ']|s{EyD:En3H~ TL$UX|hNcS-! Gkkr#AGfRSYI=<=8no<՞,yP˱Gqk&*2&$J.*T+DR?C$>2$d<`TĵFmCH@w(S[eԄ^{[LlQ+N#<ѥ-pfQ>jT5!E#Z>m-LjkmOe3IyG'V&XqhX0LmѐP)&NkG7<.g`23=vz{S3:2[ɔc!tux=hʡ:0 NXb~ԘM:XB"Ac n5M2Tg X2ۤ\ueV5Mm-XFrIs' />NUzXqG}ՂdTe׭&dKY@6z#~?KMj\stw,8T_'E4w t(BffSBch+>69L$t~,keLFXԪċ5 L傯#a=ʈ?7r=Q6MyȤ)0y1\pĒ7:Ӌ﹌$V֋ܞNo@$]dA-A\ {(atiݦ6v<%;% H-$ 2ŻǞg쩱pBG=7 0pf!gFk[̿}s;DA~тOnpH9[r}>5S!fyS9 pA%B9%Br%\>9܃ RW}pFMqFõ7YolLcgn}paGik c!Y(Fdo6| cf)9;\$UL,T̵$idf64:+'%x&ط=|%:8Wr#[2)q O'RB@ẕ%-HH͒ O5?WhODS1Vd3_u0|dRKL/K)5R>mcbd &jS0#oDur^Z1tn8+5?ޔJVn)mkn=d*Q%k\gNwB}X8l30e0Ckob\[~jNW  ea1Oi#c"1[Pѭ`ј0ҕ'*'3S Q;ez@T \:Sfm]}83duˤJ.<+ɒ"+OwNUZz$Z&)#nu+`$ F T/ׇm=se˃;zOOf VtSnu׎/H?k#dCWWi hq,2 VQZuۮ2.57\9Q"'Ks@g3=Q${j){b10+-D(5OۆrBsː!]2/\ʶ9םw2RЧI +|/,gLXߗH'؄7Cٲc:dyf 6D*UlY;=$#kw^4GF[4$KX,OJ1i4iR`ML\I1gyi_Ls>ZtM0Ojn ÛO qN7J,x:O+X(iR`ymo>6fG#crQrľkQ׫=9>ZNb7o`uuv ?ma{<-zVX)}_{nϞt:ʻz^ tvvw L,w7֫FpXW/7՘CDompmPyА端l:wnhZz~?f޹]^\ 7TM|dz{`'Ƌ6@|`inS4Kj8:d͑M}"X"֞yoJLmO<3S=mB}v?@e̳z0LMnE,n&kTd KwoƮΛڝPmBp8 4[@`F xӷO=vɵeK )dRMNt8+nycZmh=.i ׄˡH3F"_ēO?Gg?+xɸmgO)\'VFݖL~# Biay]Sv7}ԗЀ:]աL74Orl> [Zx@,'\aDP*ɵA`1.$O $~lbm3%,"aB—g@ wokMmS??9,b8]`.P2؆\o] D.Y[!qHTD´diQ,?8zf?0vO}{[z=x_eL+AdIc"  d,3Zj1Y=xbwiMܑdɗ nI?㞷<#%@D}0 n'5d6qcȘee}򓟄F0M'Im"ɼX({R׿vFK[zal?_{tl+&1e^0x+Uj VT ^2:#M# \0T]p㱰.L(=?rאLuUyϾo/Wgچ9Dtse# ۻ*ߋMt2Y|yӤLNܓN}l7Buo(IC@Fy@8#>GB_wr>@(HݿHH.wwL= O7/|Wݏ$X^YeDZ&?* %ADʢXKt5 =Tg$?5oR)bb Fkp }MG/S3O|ߘ==_/eP5R$IK{"^yʿZ:ٿ2?AXNy`wV(m}kʇ~#]v.VSgYÍ83&L7۶?/zvBXV?W!M?lOx*Wl,.3چ%+:RaxD rjI/J`dƿמ"dUd[Wܙ=jק`ď]AFa Dמ c*>oЋ!oCDm3;SccԮ}?~[wތGH8L;Ή|"Yl:+yz@ܥ\ fa*hyx}d {5=^, aw ?(b]Kz ~s,HZi43Uac?X<_lBb".ZL-V(jAݚ " /b`''n?pnl^ eͱRz@X݆l[oyT+n)l~HAR7_'aHB)-^del!TeOXX5 YAsh{6ܤi%StұpBCNKn{m#m9(ЌxUt0<}Mڿʽk?gyЧXڶs ׿cFwd{(oKR5**8cNF;6cŦwp^}Ã$3؉QLPErDUlJWl]tOnl`= ?)'FPՁyb[yĹ7]w;zzWBF^&LXpO?ommjۭLƉ}ڕʑ䫦vݫ?|'0tt)K[*0;2^.!Y33|أT჋'? 8Xi (#MqKN%_:3 W$FerwP_2 .@/IEXx2fiZs|uM߽x:4y̡*Bxwᝳ~Ȍ 1t/>.C_ @4`!H:;߸tip8w׎n UVFb{aXH`dd5)iΐYqZL04F=w92Z[m3zm&)sM=v^{Jf涩Dm~g~Ei8H\rlѬ FLuH1/0iTX)EfWb@ԅ\}BE3e{)~W|LKTͿ4W[u -p, (g0ȁ˚!{oAfp_~uk kuyimi/qqC#lfmc?=\Ra}iD5kp~O_F(  "lb$F*W1$*xCA4Ǻ,d" U(OyrV @t<×*k!,!>x2QIpFxHQ_K'#%{$mckG3=V#fZN _|ꃛo5߉{+-mo K̙ʮ7e!LbG1e'*|yxwywk__.筑I .NA_(QCxY5h{^?3=͟|ihᎭmkod'{ήc`bRn5gϝĵr+ۈ I0v'+M>< " Yf Qn5v7Y4bs(a'KS7I=.1$lumM;U?߸vh= ͕д!z ;(~ihWTra:`5o&&iX^&-Wq޸, ?HGTK.ȳhx!kTرzcy+e\bcerN4ڥB@}Jdr5m<-zmrE-2 $ntilD=8p +D 5&CMZ8%/ed}:tEc;K2"3cwz3/?1Y f^Ȥn$VcvnoV%cCٱ"ҶgGpW_]f*5D$jɹ*n9A/p)/e҄ɄZ ݶW,T=ӳvsОU\XuD[<U{޼7XaKZ 0`ˁk'JqH aXjNkmj0fb "GA&+M.Ƶ%( 3X-%iHI}̭ #D?2 ub.5_3/)YYjF_FYT`1f\uݟK뭶u{+: IR̂ X>ˠ_ Ɛq~0wMYI L+eR~{~WqiKh ,1eXAD,9BkT}^oe\fh 3F^R@K~7g0, W3_ְuک65).6YVOU^xb] SxbHcz)B(Gv|KBdtUZTx >J;g=s&[iO͕+G_Qkh" D@Z.IUn"?`< Jqmf 'gs9 9k:,l Yȓ:2QI_GU*K 3re7:mO6iڦIaKv׆9"Q;LME'Q$aQtL'.ΠZITːf#0n+>ӭ~Wܷ፹T)e8F0;T;[Y2C&v/ ql]4vsCs}LVjK ֤ʕ{9kEq1 㠙&ˡ,^t2J#x(L$X$`Zuvbc#jQĚ핫VʓUFYA~2 JyH^RĔ  9C.5d2Lϱ%ϏH- <<*Q9Hņi68k{6BlFRiztK4 +6~`qS+[o<'l+^_H@ mf5`!{b55z2(!e00 Lڛ?uaTKk=1gsX dа0M $]BiF+C)P&*>ÌRJ(Kp3RRT% >(QD)OIđcÄ汄h ޼+VAUXɹ@2hPbH"2))#CAxM b8P%T6%sdo(JTJ/$jo2vTUҫv0Apɼ/uS\% 0-ZZYlTd,,8k9ԶI}CzUӉC OŞ|oMQҔ SȚazm$ RǫKb9,,O{I"u@VV%CJlP/cTkhYMT-/y aгaņ>@*(WXLK6Jq* NI>KU'iCdUY+N-VfkzĂDYw#)>0.Ht0r.7|2kaIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_300x100_fill_nearestneighbor_topleft_3.png000066400000000000000000000547731420147000300371350ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDR,dcYIDATx fGU7S}zf23IBVHĐ (Ȣ "/""ʾ@Lf^[u:KU,= ğTy{ֽu:WLځo@=Y@?WBBH@=8=~#.~%p>^y@>L$@O BW8TJi^.vzӋr:h8>\J˗ -='3py7?WJƏڰS#3 C(cKt<ʝz.h+fA?tX=.W(5<*-DqGbHċ"v = {*'AG}D(1do࿻{8P?h@E if1K2I'!ʔ54<:ϛ(9t;x09dS;0I`P`Hj9p?$}u$ANt!Rڀd([M%A)Jr LGeK_g%^Ӏyk*lzM>ReJM殈x :It5RdcZrnG<i})Vm#[ou&+Gϡ0r)W9VAaHI$ Iih:jJ:gw˷.GٷxOhﻰ| dAgiD?i&:W ֧3MJ`[%dr!ٲىF$mRuIL~"]MJy h]ݨPnQg{UdO_΢ \!EWe1 wYґ q"g_C=#-L/d]!j٤W@H)hR#')LRk %7#d #i4o铲蔂N9*cPi'͐YDA&Vk̘ $}f~-@@.3 uU\4J/Xa:bCg_8Z!6PI4TJPX`kJ|uwoz]lh3ߤ_ \Fe))SӅX:F':JiJ{`E@ņ JGyf<*RnQ W!6:en4.1l1j4OYe["G>AT]IDu ߆`v~oo33k0K.%*S  2ˍO4_iHˤ*™aNLCr&W[h['e/.u!Ai6IZwjw$mFY˞L3QbY=X,;I?n¹,?d@!T.Ao⿒z٘ ,`5)@AbmmkhIsKxJZ B qKul&b9WyŜ]ev) T˧p'&]58xG6CV8i@0LLjXjS-4lΥPXj3_(udK-Mݲ̫4KṣPؓpx4L]qe}OJaKAMc-+hu L8pG !4EZ1&-Aа4 r 'f}hF?ͤbڝVp*@.ЅKkq)K+%B쁌WUHAT,LX,򵊟E_D?s6mDUF*N(D![>b FZdΓ|'kI*ٖr̫L6rHNeM)W,:1q*@IFhY^'G>='~pU$>;~ K$h9C 0>;֨_-5tL+JCJ.MK# 55쬔أ%jZp! (KcM'Qag&B̟$aY̦0Ȝ}IOf'KŮU! <W!cs AY6鑙w,#Ҳ= +d ʨ,բzE3CrR F!0MҎ,%-}C |ENe'¦YvVIԿ/uZT+@.AmC@oOeZM#c@?}s"ǛT~ӌm$8֐N-% PZVP_f^Xm2sI elZU2 iHd5N3ץLt_0y@&PDt @STw21} lfjfpy1eC@あ`<$D_SͲk%RP3ÞLfU&9 qGM1`N/8L@م"!|S9 *:6L*Jmn(v/Y-c5[p,Тp+LӐBh$6Ef|%(N4%S=TT:ըh\b .uKX`VK7k_eA b?Xd? țxԬ|A,qK?焴a\"OYa[Rq?pA}=lOuDSZ`=,[E{C[Op*PBP)A=yAN_%˗R&Bo\سtN(JEIPegyhf߂+ZVeKI"ʶ <,LPg%0СA}H~ϥW^t̂fQz>l T/H9pB}a_RhcF\`P1RVE g(N4q24"U Aौܣ쥰CCY9CbCײ( $G \<.5TK9S*+"@Q -ʙH 3XJ| /wgU<;gxΈwe *hB`|jR`O0N)'qK f [œJ#O=7GbB(hY\K;GzB^WQ`$@UgwQd@3T2G/Cݖ|Cj?ZMK[Ko@C}u/" ?}YT-J;uO_5HU: hʴMțG#F`9$sA6yܳv37]s" Y9Gl}6N]8d<L>]z2WZs3IXURRt$j%5rԍj*+,ƾH-eJm_4<9%( )%@ab$*Xb€v|-Lbpo={mƱ-Fx3h5*e9?Wư9]t$LP@džC`ݙn:kxndzWM*7ګ8} i氛[>?gv&Rzgf]b2p#| 2UtĒU 6u# PDrU\ s9Wu]hg!Y~4NP%<u7*NT a 9k)q2!x:ӥb'8Bs:}weZ,–pv`W7v}kW{>o_3ro8f!dcx+-MCٱa rVH+|H.~F2mW26 b]ǎB֚rjgP̹LՔ+FHK؃ZHNT]S<MNZ&k|rSl@rB*}D Y81J@爡"DwG;_&=+5m@9x۫M|@=sD  r*49Jy\; $a&:yʪ\3ʘc'ANgb$h= x.a" \gA]Ȕxe$ 5W+UQ,',d(<_>? }o6݆*Ѐ` 墏bt0ݙ>nvͩy&=J`An|Mvת2]qJ((WݣЈ~"׬)MP&±~fX-PRꮨQWd C+[*)TA Z&/v&ռ.j$rq&0$H7=g'z^4[Bj$z45Y:[M/'@Hv E $3q0BKvקJVIQ ŨJl@ ʤ]F$4bE)e4h~"G0 .m *v}ZE9Ҳ9R- b/`s%0~!J(bgg\7DT\ʦSS;TSҜxIC)@'}O}lz캗|J^BQw" 9-LVa_=Pċ`l}ӡmu lx& ڪaP >sU=m/zFP-cbC}W+hF*I{XaLBF;l)JY x@ cHAE)$y@%W[0&\҆gl90U}E"OuQ^87^K/xh "\d#Qxeӷ7'$ a4dbVbnB.' W Pg0(~O<w7yM_nҮ/C̛R1 Ep90u@013l(naT(@PG8-ktF@EKYʕ01hG [Xb98Aŗ%N]Pe&,"X$-H r-mo3i=( W AckHD΁.#\aK9v1Ge=cIJlq9H@SEԈgU4PlF%TaTk̆Ә}ZX5RpH(q6|?AϿ*j aѹP11YgàKS=M-SO@~aݲam]BX}Bx7.|xxӮ= s$yՁt@6F^;>yn_A>"*E\3~/|ĉzt/4z(4 ΎPd;6ߏ$6*!lySUg~kG/s7;( FvSs)˧VpOI 1XQ ?sP7Wݤys#e\3#JxMO oe˅.Q$>Ydӯ}d-7i/tk߿o& Ck_?67 0ҏ/u}>ɳw(rIgc$~~TaRwatd|=V,(KAz!Q'2ԮW|*jUŞÊбZq | l&&j >&QoO޵+8!Ir3/;%^}JOo}mׂRs2qu[MmmXZftyuuyאOfџBP ӿrONzHFڄLv vW[ 3=xxdPjG/z}h9ş$2x"+B<+/=3' Id|ڣF8Usܛ<%f^R}hN9x 6|*_}c/}l: 6BoÒip֞sKW$XXlil%ҽkN[vS7{ȋ`R׹G6 Լ:(ZzZ< H{dID s ɐؿ\ſFC=/}>tW\ HA ,F:6F[yhnB5uA`5I^,$o}a"h k~P PRȒ @}z-_M_VM9%qbqZpz؟Z+>{'2 p$w?+Y.wyS\~_MZyvRDJS_36>]rK9Ud"+@;*"{pɻ2轛VjJlJ4y#BUv5{Wʆe!&˅LmoYĊhG{JB:3 :jT̩F^<79O}#ktXpIj & iV& նy1ܪ;x~b'!/mǜ'~̠]?݋ A(!hU_%r}h~0"bH :Ȳes+'I̋с{0ψpD̘BIƶ"i81!rsEHKd֗=o} *?2B\&._)t_!GfBdc^kjR$s aMMHa*Vz B\*"y73ȷ=!"UwY7J7 o-k(#|pZ~ =h~MY*UwD(|@' -LAS(@Iu f +>rO▻`ׅza(\y!xYP qJ%d2cWb]}}jܑj֗8dO)fa,05в'w8 GG8+n4"W@cdȠĆUvAhRPc*=Z l75{CNiBF:~ouZkX6ጙ?c-xR;rŽ;'LHv#kB3vYM 8'.tA U-h`M#iatVA3< Cmjz?촀Vc_\kg.*㜺$$~-R(u%}(ho \a {@aچL)ZϨT'`ecsGd/l1P C=܃27* ,r֫u9C@(ڨh`~L'1i*իbXj'и E%z"J D;̓$= Y'4, dKR[%谬Ab>b)\(HjP`fȸ7=2Z(0T'<1k7YAww+0cF!-6v9=0g:ͩ9~`0gVC~p$ MYŅ!!@1U``"HbBy"ςx pk}Yhɧ]ζq 0˔.ӛ-ۯC&7pQ՗1ZfWi{Wrk,ֲ" -0] E=CVV>M˵2#m%`AK<yH8X]ep ió&'%QӒowr_zO@ \wQb1׼yxg/esS*qf@rZ ʍxYM;bpaEӐVPc5IԢfKXFx *G]KYd-c[%> .{>t ߋ9aMǤuj;{ .Q$0 =e-@x)n~/Tv \_ywe2K[q}\lMzہat[?\8_KxGy)p*(ۣ/ɵ` 5Z+8&qp*b1D {:녯EEvaS;x鷾o{Åg_XT^1pKG?{E}G|V;-.<%f?[.xO[]PyCvHg:_R\:4φ:tmoW䙿1l?9oXifP/k?鴟p>z؛rm22Sb6y+p_#Bq˭XwJ3bu_|׭q ^[lϿsFG3@UJM_ן|CGn10Ո5ZPh5(Ӡ|f/;CoT?g?{gc-)=C*h0 Z\T7?!VrxF_zz3&;V*@yiI zLjO  WAmo*%60{ms"4Cۧv;F-&af~/M29!3 n3ɧJ%\tPI]Eܲ @ʆنr{@xw]n+dC}C^gYPV6L@ FlV ;~[;ewonᕗPU=XORjƽ%2Zg\17+ Xt.tSۿ\Biթ eEN8J1ef;1ɣHX%ln|:ZwNs&i}_XŸSE]fԍ {VL#ҐI:Cb׍5xF\+h:qo F.W 7p[Q U*1&_"ryd≔phPV VթDA_{4rG(fmӿlu* Oem9/eջn}?o\&+iur;?a2;[edl\Fuw};V{ YEϭ )Zx*^Y9i XVʝޯL2e9q%;֝u;'ʨ>Fփ[ᪿ\=o}wO6^D:JBEEEW2%A+5 <|yz(';($Y~b0_edy:L؇_s‹nv@ֻ{?h(ipI(/'oݝ/]_Z_AŰ!|e_\bmMʌb;4KJ{ZԧcЍ}gteor]xz\.I*(UğcnEz>r勵(20“Wzu$.b ^B>wtGնN*vz_&ֵN+_pk}ί|wO(w{ŢϨ 7_ź+~wSێ~0=Z.R\SW^a?xc5X%x;m#VT "C}ګ~c٠[i(*Gk^6*k:ϟ{Π߻soT_U*ʪ1_l@4qSF!MpQ͌I)liC5W&ZݕR@DHvY'赲_Gަ륈-@qSC|t)S Ŗ> i?'zM⺺>f1}K`V5xt\[;7AٜEq n7:}w3ĚgaAAd`t܋eyb& -o[/tAO.m{[~RPP,2Rqsh?T%ڲSII>)ml7~Zw N)REI(*l`.ӧݑLxS??_ k~\P8Ə %7l-^Դ/)[Md)^mD肬"bu dK"?R-o&Em}Q@*`]9Xw~y曆pBk(I9Wm}aci+u,:-NvL &l]+5R])ZEu2ĺHTVkd;%'}qu8OJjNnq=\̩6'pKI-;#֣3uPggw%q;&t`%H٩cOy|^\\_`@e >Z^gRX !^D*Up-G#l!mWu-~ڡb1Xi׶U|ylPZ[d|SSX5%P,ϕtB޷Bʯ°Xr=8mqr!7V:W2nQo$bu6+˜mY3_y!vݟ;JF#o{Ws !]ᘱAc.4[B^ٜZbGv݂ WNu+A/ TюX⋲ w $2rWffj< x "MTըb "9i)˿xNqmD̗)ih[!CX\^CE'- [ ERf TswrC,&U(,e8{"Ō[`;V(%RSγÌ@~j(S ^Z쇅5(`QBO-&+!l(TH{¸uWU&Rfp9BC/mNT=62l4mr!CYL{UDI< C}j1>DSA@+;R"NYhݚ4>7K8Q$87ڟXv jo;f"ʫ(8i- {ߚvQw%@A[W J0)fBRy^W5%aVĴgsuJiKU+!К} (%ej?2埚 eH&})ޘxPK``zDgEf\7$J9-4 G=w }QRcQjoHoPܾ}yo91̗R`eAB `%يTsI\jA9Ci8ZeHGִ˯\sJnѩ^^j1o b 1t$w| J$j¡=IL&Ii*q,AO2Q=J#['o/{TU( ξqOR孆'X'cSS/^;K rE!F;X휊όUYiELhJx+f|Iɲ\S>TF"jx'Jm<#6:jNEjy꥙`G(?bD"䧞]tIwSM$hE)-k.+Z!(,\ҭk$ݑd!^l)Ǔ`v 46j|ꔕ9R?xu$~P uDc-h Г~ prڴpW^w򁹥B LF(V^cϪr/*iccI0ނ( l W@Xd{`PR{ 4D Ŧ<ِ`Sfsrfne/]c[R6pYeøFaAb9R^)PPa}+L4lA ٞ-Q+~Nz/X|;Ye % :TbߜuQGDRIMA±Zi ~*$oY6eR$\+nl;!sS>Ǜ:d-02a%Yu_*gi"߆ڊlLGiOvYf I w}#5H;H1pK4@%5%<|p9]6ԭt 5S$뇢n7-?Z}#GoAॴ=ʏj(D\vgTR\FLX,ڮqI(0 -2p-bH,@LHuE!؋' #@ljhLͭTlvk@i+첊C*N4vǡYzN}J|K+«&$$ Ndc`Z({D.(8qgsQ#-"T͞Q }bC-CʋUmE{.vE: j^=ps,N`!8Pd9XG)v]al\.ouI5TbVHqev9"BH!%CqĤY5-@* H,5vRmz˅n8[_Mz=c'~l!.]?xu ;aolCFކb M+Ti&wώL2(#D%fx*N"K*v%HNuiލlOQH=BomcC*DV ul DAhI4IŨ:1NNJB | 8d(v=@B7`oȆ Tv 2I,KN df{ԍ.=WwEm)4R,WP"F!C kF!usTeK:o$ A jA'x7aD:繒VTU79g.5e獗A^s:ը0a͜wϜ'F(H~(A&?9 ؀eo< ҶlЕ' e˴{Z_o>ٛy6B8>`燓h`@ۑҷvJt,!, I;I(ZQNHcf^t꥔RBu2oR4#̸ @/.lA^oLkK.F(A-yԴP%}8/=\픤uQ|\^UO+biFLN'& ]#5L$bt!UVRk3G/<KI2F._+ٍRq,Qx?:pۍGm 2֎{t@+aF(uDY\C6^L rLQbS/SZ!Z#EH6Wj98yrni O@#HL/U#PD#0 X˶j-58_ؤPMR9q΄(r*U-XLAR!P%P.eeaw$/RʴT]@\WMG)L *CF2>R~y2}=J)_=Pގ$sa[b9PZcBAPŏ\ēEY'qlZ%TerOF l{T@zĆswK$dh9  pqPOQ: o%([#o*h9jqÚh~%i,pjHf 1JI:lcI;|t70{n9k1y0e~H.haIB1o( S hd"GĖ6PwߢhJ)W煜U;-U (Lqˏ;&pv 9&i$_$MM $42UAE܄D4d8kJM86ϘK49רKcxa.YȘf'*`aJ93qXRkۉʬ߸F <1nbBJ4rbF-NW4_]S,Q0iř~؞UΥ{g$Br=g |eN{-^{p MGnn9H@⪣ƎxSMÇI73Xs a,us۟]1~Щ $ jQJj%+Hû-c1VkڄTIa/<~oX3XF( uG;s+FC*ZS*?Sp- Mq c3kFFӴXNl_<ؘEB;>;~++}MĶ<,SςWtʾ0l" M|v5' 0 =3`X]O,g옺^/ERsU%u߫Iɱ/H'$nKٹV ؑT҈`aĹǮm\TH D&@h$<%)&?IDn`/,y]X0[-W/'Ytl|Q{^pqk: cU]qABY߾f6wuR97~0$\eLޱ7M/vﭚI6ֽq>J Ğ:*QХ:@A"Tw+t~; v<=nf-D-늷0rU%۝Y¬JB!!xpR)X\^S]'eOjl6|ޓ9Zn1ˬUɁw;GΏaSsAhe^aLH"ɸK* h o,./@RCA٫#]NX: `I [UJa\*Sz\i¿<0ݛFg֎OtF$ :%ߙc&.w>B񕗿 Fx,YCA"s}gvK0Z<{|G0{좫먊Pd Oim&D*Ql g^cͼ׉~$}{۽1X8q㜙07L-%5E@0B㲀CK Ņq?wfT0Yi{UFs|h A|Qnڰ{՞8+Ϋ3Ya̿|~Cf֏M,Uu;s[33}e50;sqjs|oϱo@X^OTZ@_mؙ_zbt̳{)n[-?`4"'}:ZWÂB \&g4P{Ԩ1m#oǸ]Sn΍\φcoz:fSfKK +G~[]ZZ;g_iA.13 VwYŦfڽf.L.X:hDmX>1]sRV֣8 nkOŇ!`r6ά =*1a`VuRYn Km&;S'CoR xT#Oιynn/0Vè'˖`k)?X_E4 Q$5}𗨫0h ]5:`<izdJ,WІbXN>qP\i-Aw(g}SێycsSlS[)[:{܂[XZua]tW}]8,ؠ.,{/Þő6L!mt}߶{=Wl[nj:nPno|חO 4ѪC0sD/a S>kO]wB>lD&S0QKp6(PK`AX{ lY ;qÚ&:P)q,)rX)l@@6EeQ~w-m7Sٱ~eI0@]^fd_٨q^`n8<o"6Ro!{6.V%(wMiWA,n"0뵃[< X;q͖vnۻfdquG*?Tpt9Y"B$Ol3 zd䶥68sk.سQB$ uuuܚoܹ篾ϻqzW)}_oY\z4ua ]:T;v*G4L#7c/ 3߁-ޓv5Ufu_quY8S,5xiQ}7\I"ֺAB k|k6[o>nzQj?Os[$`soq߲/7sQNǷ.N6{5{{/B ÖƎRa\kƣm۶߹z/}K|wN|Y޼Gܩu8*N S'Cy;_ [Niy[# ~a'Fv͵X!EKyMԇGֻq#u --J9AJD!.}kDȹ ~4n=0s£\bP>83{=Z'mׯw{m_܂@@ONj;ۢ5?_%|gP꣊W>\l!ɋO}f2ܙFiLBc֫~ _bk 0á]Ht`sH?HPc-**rJ+@UHg^L# L:5h`Oq)1)Hީ > Zf`C˓f؍p~Hk BţAS>68{El5LD5r:5r1, TjT!ȌO_eء\>/nXf%z%ݩ r42%0ԮUzoySivcJ~侯h} r d˙NКrs'|P~Qm'N_ikvpz'0eGu\І[~;3E/ܛbY1@p0Pi|ܝ72Y?2WJh1 r-cݐ(;ҫTh]Lx) >w޹1*<ȤxA'DK!J~Ё+؀%L†K5d' K4 XXD" `n*! r?-Y5]J=l*Nu)(/G?x: J?Cz ;!JPA0ml.r ?b}PŜ5 }3NHMx)y#+uӏيۀzݡi0D z CP7zqN3Kn,wwz}*NOt!B9GA\.z u~ H~ `}h~ "\Uz6Rxj,- ۺg"*I%P,9)2$B͖B&-1Bj!% ʃKbl}&%0и} ZzNp>sЀ~"$]mOŮJaйd3wRP- XlEEH}jt̹RyJB!wtW%m%JGq .Tj-;D 8'X'n y }&ٳES43`Hah`V b}~`d6}t*[ L7dbGAGRrobUsюFe_Lk{ɀTE0 rY%POC adv>*! PhK@uBi"T cb^~L-G>\Xaw2{ȍ$y4ȁMxoU{_+W?ZXdmDޡs ?&C̿_,'Y W囁К|Xj<ٜ+Udxd4#3<\J"ߕ郹pŧe!mRg|&/5{TKY荡8iO.Xk %XQa#s8a{ ?H ~}(8h B92ۙ@BjdžuIAsuo(5fdHfSк53jaϢ+v ͜>ahi|-B*.*O39Y *];AydX(2!ѻ9 x41慶ST-.1VtPЦ2~b5*s2 7 7 Ї`)T1wAnh^/[zc0t?r;PYum%woT^%Ģy؏D Þe -qpvkuC󎎫ﺎ gCGx fhя_tx#ZR^Ce>IJ U),IЪP+M;TL K RC*ȹBHgXn* 燅Ƒc|/(kuòT{*kKG\jue"Pۖ[_ CH y ^VLq (>Q+SEU*~c[~,&Kh@q͎.ƃR)t%Gcİc>?G }XaA~<5{ZW~灟RU*!ƐjGua{bAfh|8@!ۜȏSy!tN8;LJYh| ͣ0`@wbwL0A-Md<6W #P? UGWQQ&WpFP|wͨcuyǔ0?(̈́.}AE]:0vSoGaa?m<rU<5 ];LpoϡkWk5񢍳bA 5J(ĪG{VS67yFuNkQCbf*|3:o *fV*xFBLwsP (tc)2ae% WITiYB'r&JpAzޙiB8+:=Y< ilǥtޫ%SJT9s~|XђxCMC`<H {6B9`󾀰\UH\M. XE4?kN@ L81qM5ECm&ob3DM_!8so-lUr=#p2{e9jΤMQk,FRncH%2ciњ7+PK.PIe&ѥU茹fG^t? #Φh E?VAtyv5oƉC~ln_AR%#A)vh* E҉Lj?2W=xu1%"V5-ԊmΠv@R1ЧwÑi߿bϪB<+135O D;'9zatђ?6pwKw](`Q_Q&iH)P+38ȡ&aT8x= :xF`U@_Uʼn,sal;+ɢRP}ELJNpNG5:PB؇:])\cC&t|u_3?@rYo1 j㒏]lg^N!n$ V r`>>5=(VEQJ"^;" D֎Q[Ƹ^@fwe'E6hp=T!aMJq?׈_9ځhֈB !Qp!DkY*ᖌdWWr'UHz¤T8.=+H=A+ȉJ;%,^lQcĭ5 Ӵ` r 09kPj ^LjJG ^"` c'ǣ)؋D!25,(#[yl +m +TNejHGn@iAXhdv/ų5O+函4"PJ tE4L_2LU)Υ_+yRF|+uOKl䨎|hp73Q!ÿQ6Y> y&yw !h`'(?mo‘ Jl+ |9E O~KPhS~< .߷`o)JC^JN>8 E|NP2H__7pjCnd%K"C2! B0PT6D c:EȘ34rnk)3K1ġteMT[8dڛ5@crg7&Gɐ\*3}2T*}wAdD,EnVILDŭa$R4߰I9,1 ဎdHJEAY,%/OpB@uS(6i#ϵm?[+l|/cBkY*xd=Q4"]WrT5='0!WRޜN>LX4@*ʵ(:VMwBmPFZ:<%xuݫ)9\,~AùR}*c֦).ZW!vfs`闵As'uPĴ#Rs4Oq#dzp/e( PNP KUQw7Y ze {>Os9TW'+SP cL5襟ƒ'D9 d -PJ/ɿ.(-q*+8 C5pkQ򼯦]Cf'[PgeްuD# W! Zjه߇(9H`KIҁlŠ[q@ty9%R SHpOLX*!+ ;ijhVSެ 2p2wd5NQt]&V .SfLfV4%n 2+c]nY@rbx+P&X2-~Y˜:J?)0o@է"b2W-1S0 1ml'PJ A$L.zv3oZ(qJkuAݧdG)Y +Z4ՠhH3IgV6ًrVt/K#_>IJ!iTo 7UERS # <(Wr5t30ֹ8 gIp 0y8ާDjj8 x 2<,n%Hƹ"^0!oQ$IBAgkKqwU{BijC#5V>Hu׿{ᗲ;M=Uu;0AhfQZ-mI)?lWR(+gXs]A:"UUwQzr4&IP9SÒ9|-I=F5+ j4&qJ(jF0˳~ y*%Ybh0 >J e9dkok"F҈u9A*e/n G6ybLM3"Ǎf).jy#+DZ>D:1^UR>{w^[(oTDǻ̩ 7w^+9zF % b/9??̙9ryr|ż{=ܿI_icNU)GζJJIs" /jI|X#+O^4 ;݃2H֮cl=%sZųvvM:*ݒDI<;? ͵Z-D i_ {z2pERˉuwxrif^j+3˧]>6<טiꑈQJaٿ@xM70uJ R'?Qkz;_;͗ImދNv[ydvo@ն`Ij,'埮}.} \Ϊ+^i{yf_Ow 6 }Y,VHJ; ƏjB).(IŞmdEgU>ܘ{wx+sER5ŕ>ʭknDX|0///~3?q|R$?G:[_}F]~ _//iϩS$cyZ>ԱxWj'N<{ǎ?;2Gʉ(^hֹϞ:׾k?2=HӝM;[cuź q||Yo`ys7 HDТN"0GOx2y.&DD33(g/_랙,#գ҃官P !LRC%-ְ&AvUd^j0cvkD<3vsaWW֠!JO=gh֜$ت՟LDm~]APxq +5&/.2Cs_/D1j~}ǭ36n4hIAYr5&I]Ufvy$Z9C+ 6?f<.,s$wV7ѽkDaB**&?vS'?A lf (4d4 ;=seaKAӟ]^SPNѤ Ks.,h*9J&tBF0?O]OM& :X]#ͷf5#!?v㧾RgDվ&|7:4i+ m!(ɼb>#Ok8MmKCFR8.qys"ng0rt2d~7QȁلB~MSp-( Q}!u?+sL*XOs kĒZqf}s){n'y֘kIuE-Ckf綺:7C0WeɎţ튓PvC0HJh :FEQ1&] @5KxB[o7,{(SK͕ER[xyui4~`69P´ErLbC[873Iب/ϝOnY~/|_o?gg,˴pG-NOit¿nnR4۟?fKKYU#Sa3SV /͒JЪf䨊 G- /$jc2n+]tѱO00ĸ}J$YTESLF`r&Q 'ń_\k(RTfsZ齽o7n|3/8mgos}Ve|sB҅ŭ8х#scAqWo\iQ-nno]\~DŽZ^XCTPBZQ V2 EQLCgT*ɻX\_uJ=Y|)\JI2y=&KTuH~PS+\IRX )-E;,xX1[͵8n+9+y.ypWy}r "i%2R+k^t,ϕUrco;g٘#!ffcD3dKٯ&QpX 6(y;{# &u$qύ={WWzvwǸՎ3!GPBGS岒 ct4)Cj 1[N$w6v.!bnqiD/, M/߼gW [cԂf35J:] \*Vo\B@"rvNW1Gv;RwqXhN"!4nyb/hzQ)] x4yΊ2*FD#20u.Q)]x 1^MKS-t|Lxc֢w&Q FvP'k>E41;tOb2eeiq4,/O2a"dO ui`ԁ ߸^Ȋ*+LjvE,pD2;RΫqk3UԿim4v#CFF+v rG7M!:`*wSu?5kҊL<]&]"ӖG ˓ѽ] %^jc1!h7g'J-,Ge`\d}cէW=+=LK2@(&--7DЕ5OxɈp {) ?%3I1#ߧaBv^{;A.FYosJnNM" 4zkvmb§AibBhИgY=!! k@hVI2C|&iADTŲAϡ/FEh=#ma 8n#O{$Ǿy &l4mXӇ*JnOx㈖a +Ս-'g5ZQv]ݡV )?qElTm=_{7uPӐeОᓮ'43jL8=i!=KSDfڡt Bz{?w! ɐˌ jsEm֯7';0ݲ]vAbf@5^|,K miL0^:s&yա܎%jLlȱM!X_ZfC~tAoW\wפz_^5PDtzu=hM35cO~*JQyQ*7A2=쮿LR僟9c6nxsY*Jd'!rp03yW;Ys'reͼ!SӘ6ylJ坚+AkэA2ƳK碤-꣏}/-|'xȌ.'M{cBXY=/,?3yd"j9_kOx VVU׼z}1A6WǺ[onZjypvBG묿(sG|ﻃ";t$6p93C=i&<' @P kյƜ0уg?}a}To񺱕8D6nwڍqť_3(N[ΥϷ=V] Pč`u "X vx[$Wm{33Ǟ*^ueBpp{ Sd=m~ $!hƴI?S*'{OƖ/MxzšX-#`н~s>WeBĻ4'ݼr.qmaqe~ińǞWݷ>I$<{bcF(L>Z&9'Rm2=}us.Úac ?E4G(?BodL w{w S,zv"0,zp/C7᭯~7WVΥ_?½|Y{¯7 Ջ>=XNSz5P)|t9nR8sG1v~ܽYtTL} o߾sy¶lBgon}olݓZ(|_{>9784gLGjK+F@[/ݾ>-]y#;;ݍ׈&OMX[l_%9q; 9ˁ0cƶh Jvn4Gzjl^=PWC0[_K/t;Z?7/PS8n pMaS Š-2Rc, }5l_^aR8)h1IYWoꮿ/b gϲ48Ď>u"itLLh4pe߼unLmQ: `wmY^xk/|֧CIrw{wgY= yWmsy|7_nr)߾}_x& U^y뗯]H|8Wz+ĥtb,N8+>݅|sUIkEL9y)&ڿ񍝋y!(最`qHZ"aHf+í^޹Hu BN's̝3 ._<ɾĠ OC3G!\Rw 3N]N$fqwM=ܸ%#[uxe5E?OWwfgVZY!] *:'ǴC{[|z B;\}7/) Q ߹_˽\j ^0@N_^88:wUy{ ̈Rx(dٿlf?[98T2^gݬ۾xpo~z LnnH¹gDҚ`r$Ûعt|}@!#͍4[CܢE7%#G^{E΀ Yvp?2;iϟ*a(.] O>׎?V'uw|`M#/I:i0_w.=ϟ}jiHSs _ps{koo|{gӏ|;*gBJk9[TuC# UTnw>_u?~'Ϝ[MBUG _𛯾qeg7osm{'սÿI$_hG+TB 8'A[^!bQ[?4s6fV,F;ȄՀdFyYw{sfoLH%-nXpܹcn}p\QiT_25`jwÛ_m}W64 Gn~i|D<>3Y,v}⦳9H$|.n$ѯuod-=Ejb@5- G>SGnע!DT$ fp+߼r;[oK/>r܏'I,/IYʕogjbmRseH):a5fK'7CVLt`ƍ;[wyV5W?ԏND;e(T$a$Q F'Ϟ{ 3F'EY4>8k/^zekrle]"u1ե??{oۖ"TrW%cRwg R!6'"n\\_NB4E4Y*N˺`[f2;(,JCM]#NA1lT_'暨(:t;ռwGۅV|F؋Dž1 A=D":6HRheПStE,j?&$D"jZGZgץAs{je-bQ`87z]I˸&}4MoİNKݓ0EAݚ }"+I / E ̄jP"1|kfuv~ժ%# f<8LzoQW euDljfq W`14x;h۸|D惝3ؿ /{V9rax@.G07&\ [`k)85KP! t3A:1! V͢tct)5 b>>oY~0=yaF;&֢I©V 4mF!!36sNXu0hٙqýTEm$XWwx~px`)I۔5OxU$Aܓpwcx $h,m n(<; W#3ozF! Yl3L&ܙpPT#~]7˷ы{j4-6aHIa\jhmMC&FATZb:ER}th>iFӗδ>ܟ9q7/}{@}`AbVWgKy{g#gR. ajFᔑ$'ؤ\{_458A{f $[ \bB HrUl2@:?O&kx*t 2_MR4 -8 ~xGu3=A;r5iZ{bEMw!tCTM?F,dV4 !ڴO ˖dF*Bqd3Od9Z3<̓~eQ̶V-k5\Dwv6oޒnskcѮU:@X2HP!qfa lv' VXX"gXyNhU}G`Z#<>hذDf6;~W+^+Oq V񩅽AbimVeV,]ē R9֥3mO"[ɚ3.nF}Quc,uԒمofXkQ(KJşɆM,i;f#t@G!ޕI#Aݕ)[& :dSNٳp<5( w<N;|`h6͍4d` d WXo#IAvgmoDoQBky5E} |EڏEz]K~OҐ ]oO8DQT{b?vS/T_z~W"@tRhKəXlD^T'(cD\.,Q&B(+[gbN~U"ebl e8Qw mBkj68_e=*.ʯeq͚7$vZ·<`$jS!ѫ- JqQ#¯X)2+u^kckR+~ڭɓ N .t5&4Yq3Oe- !A)j ujQ734Jy|+%8ӷxtS 6Ū: 0 bÿ,ɽ#h40;s6~d @2;̣S3 =+:. BAbΒgRLJe*Kx#ıkYrq}ngz:qVlځ@p.Pe4;#FvqW\G*4g!+|T42$C00Df29iG( 5gȍa+9U eW]W 3؆t.*tSb.GV=Ǧz%7W/u@ '?Z -\B FAwމy(%Q:&|\G(5[8ʹSˀ#0ՌaC&MVǂsKe% i<̕ţDowY k͙pٰkZ߉cs=dFQ@T EKIyA9M㍪Kg_wyVcQoVɆXշ>/yR8ExN i<QL g2fJ_dJfsFzA]e)}Xn#h-ґB/~hQ%2KJQ2 ?Xj#<WڎaDִ[=%+7V [i]ɛ ?>oC%qPԆI'$A> j@`gR4ᨭݛ{cZ\2>ql{^ͭS\ އ{sY,΋k3r{J ' }0ԟ!&,T>30+ݛ513QcSm|*HĘ +5rUS"gig91;8֬*5]Х6u}sPO9]НصS$wT٘h^o_}s?pZgk*i Wߺu3"6EBK|XkH}lʰdyh܄pھP2 9a uqrؔw';j @Z2qoqz?,NhqN4@#ǡukX3 /݉ݦ8p(Sɵ zV T)N8ߦ1gÏI> ^vݣ(^i;9Hm4M⒰ƞ[1{4,1<.`ґUkSӣPpsur*eߌ?U*1fߎ0$(j6K( 9͵JDn>B,q;]$r'!Gm-^.Yt`8!Q$, 2TG<FQ:ڶm'9͠)klWr\yˉ:lK'YV?ˡ`{5Ɯ aQ9rg2- }2t߬pZ `r34(@酠[á/G'BĬcڠ܃^#'r mW"c\2gbN;>S8 B>RMuz {,+Q=0&LrKQbX9R.(C9"eHF>vxvfv[iٽbSMޡi9ųzn,9țee&!3!ݝTmˇ4Yeȍs ֝-GDI&օG:C<y$܇D ~+z7BppGo^B+2*WzMFn)P'E#x%~ƋE3 „ܫ$xn$;a6="!Zg S_Xr+=z x5`ռUjL7\B6M^\ѾB^y IeQ=r w- TF 0\^-J!um1XOnAACɑ4ESbm9DߤKEViIL ɷfz^k 7l#{*-_wf`<@{{\cY 8uZt5sONאQʱݓ*rz ! (Wɴd5)P=yZE.D Y bbzݭʂm"WfӚ}ly1 }J㕃û5%)RO2b} &K H5{%BOaFÞY<#<8o sœi$.H.aRt,T{_c= 梵|S;_[>J-ԀHjheUJ'3e;PG=rΊ:#*Lצ0fNzދLɖ2< O,zRz1 Ed8\Ai!,P-{'z[f2zG %OiO̱Ri"sfl8dr`5HFt{9z2/vxX"pAۥHRAފݑL?K sHkG6]r56󵫃caS-$X!#cl^>/mh''i,nD)葇^.񤲫kې$D$InL +%JA8k؋(UU)2T#H)?h T>~vmvkά˂vZ=p*J`}`=I%\n뷙$lhm-ˋbu-80 : C増`&kV+>=_˓ =' 5*;'6V+7SJv[ݕle$ڀ]j+rQaEiJ #U"!C;Aގ>ck@#ۺ"#ΙdB{BQ$IKD//&~n[4L rr%QdQ8H ê0 梽1Atv,|5.bN} h"}:\CQ-)=a-NsBBTk(Bm6pPm$?~$ Q& Qְ$G+[@vME=*}dizrB1,E/γboTBD^v}/f;'zGGҹ?$ +go#&`%:iNj? 3`8!a%5߲J9~& >o/FXb-@$Yjͭ<Ȳ<}[UwuWRZh"%a a7CD03l1X#-($!UWW֒YgM^feuξサ{;}+0n `R\BX`sNZD_0Jދ( ɍ.ގ99[g;H#b1(:Cx5:!!Q$bBױ_!Δn= #唤.|Z [*) 8SQEP`1K# ،q3z2;c Z3G.=4S!ҽ`isH;[_HV+6LYN$AIA 36(dRD,;CD? Urm_55BձXPJXagmnFe*K^nmRR xgnoP5_TB` B@1o[Dc(-Og `,FZ*!.`1 Ȱo`JSU-^hYQO` B%$ Pv. 4rK"j1 -nz\TN:JF;dʶ! ic/YlDNp^iTc⿸{]p4'+ 0~Rbp*dy~uoqǎJfU͉摚ib( fM@ *2m)72M3R/q$ $c₽/zgyGDs T<0#Tc`j+ղPRJ@(J\BMF2*AȊ*y<"T_|! &23 7h& pC2@@tbU-|yKFp0OSnNH)x ̯]THWw&_^fE&l1N L:i_NR(xTkqG0)#8&e,+Q[ƔA ~ix6H&= ~F$5 1WzaCqCFNJD^xd 3RsU 0!cB]2<~13A7]zjl0Fxr:pPTJeh(rvVv@BEQhW8N\}0pineiO#@hܯ njR/R-="QlrEQR)  d0AvMԁXSBZrH6 02T4 7tRգG>~r`0L]'E% W@ E>R D~,[) 9 |Pn Z_n G\677>q7]yK >NzqzMbajE f`KE@` as1Fю5~ڹW ǽpB](ɳd)#Ә)6/P ݘ.AԨ=ij:#=5܅۰3@0ҥ 2m#%[بj=5pp( *>-8ŋ>9ۅ%e33-mؑ10|.$T@I( -C1L=¸1ŸByv\4j;Ӿ2hp] ȐA@W\H0SwLXt,WdJsN wb\ ^WrA|Lx |UW?7S-Z+[C6I1M ^J@҂Լ;loQх 3)ϯwZB #u3^v6>OUCj Q2jK)RSLzIX[-*%CdA{Mxm6k![ȉBRjSvu[ZL099i{pęw{}6xd9/iL9GNj-7vTv`Wbc# `Ag+h阇eoiOeu Xt9tȓzT( H>`kRP}B؅5`|}!c AxIZ^ IF;&Ix `'WBV]:"þ 9jQF}E I/v{ۏȄD(FuX Ub[|6Ι_^|AB[rkn0c'O95c4Lq=?ʯt3_<&r'^)+SO_찾G<9Vo)5"*zP3;WwѦ7]'*Ԁ[rmyVsӕsݯW @HK4T4g)d-6@YE] M4q00n6͚Ah҃%\ 0qV\#HOGS–y$i &֬^[8s[Ԯ{Ukl#8'i;P!0?M L _sd:( W3͟>`8wo }jGC(z.Bf7;tf3T]?qUb[ ̣g}o3ӾG" :3 #Ԃi NLuNNJ sՁZ;C?! <6k=RA(Ŋ¢NRZ#Ϛɥfž kux#W y9yaz5 T6YvN9Sl PImYq&$P}O #=Q5,6RV{z5ܡB!wL[j v1bN#ǪD\ an'&P` OGx2ނY;jܜQP%) |i{B}Y}i(nEO.//Kl>po|cee6Xz sHH<>@Iuyu*FFuKX߳^1<}C:(aj6'֌]#HOŲc 8/P-2BbܫB@ lfh#5Sd#Tj?g3챥H#NOǴfM%Nk`҃@X>ACf酢,ʜHP<(Kb$25t@>2tkȥĝ"0\à 3"9Wեw}xd~g SG\0kx;rfBZ(~O޼|R*[o~WwK)O 5;G~{2zfo<9k^+\JIDB j qˆ؊E`Eq0:X$FΐPJIPcHHz5$:'%VWzhr'>}{ PC'uB`z?j]6 |^EbW^=<Ƹjo7%䙝Nq#6}L(ߖFؤ\\.8AH@__?9W}ױ*(ai|w #X.mwO6S5ͫ*B 85iԞ0c]#S1<1_0pgR2av!ˋ4˨L9(ۈ$ɸ^Qv,=* 0nH.̂H] FmYgK@@Fu )uhӹqnll͕vvؼrGi~,;?Mg+y) IKzr7zbȖ }(mFkOp;X]@[.2̡iNp.:*m|X8^@Q ]l*S|UXr8&?EKh,y~rD:k!cA;r|i t(frM0u>YB wm=OpՌrw}g\2C=N~z'/b?«tJ0n6#/pʕkW"85bT3|"b{ʧo#MX OTSD@~/{F_|$D#7@]gky&OLw]s_g$^@QE2"Ե#Qf!LeTc`QU41)N*FS7ߢPzy*4MDZhCSr ӋMwjK^-zw{V?6wSGG5xUyӝF~9$ gDfs'o5l\<ۺW77% 78X|loCR1"_8f|2m!fgg??zc\OǧD\.vp#V.s? ï~kկ^{޵/}K+_y/|… lP`~io{[}RY+^_6|JBrSʬɌj2\XG !&U&S??no`4+NgP#oE/?@=`֘竇RqM1yy| ڳ_x}5Hˀ7OwëO>ܑ΀`\r /ʮgҝh#_峟)s466~xlַ?c7~ܹsضtlnn/qGIfj URӝ\ uő)yՠQ?T'n~m"6UU ƌ8._,P0 ʻD5־q3Zꖢ̩eF.K;'Cg%r4k™h*[2Kux}l1M*swcA4y'.w,V{Oݦ=xDϜ9#9Fm>q1-!;+r9xibBh{{ݽn'BH>!˯gKTڅN['zOH O{e7sZTs񪉕% gMmu<*xR٣b֩ɍET O[:fXG~̥P,,9 >boͪl\}yN|ڷ7>b$O]%KM~c{ʰugP{=̦Μͫyx V"M&N28?8yP>9"xFk^%޲8BGtQ孞0j ·aik3LNۓ&-mx>COx_~gk$A8yic5:obaA}]q#֙s^g&I=g0==l6z^1ѣu],stb_ڟl<|WIƻXAxDZtWu,"/K% >҆KOu|>8|㖬'f8:V,[ԕ"}5tgɞ:d4@+N b2Y:9T:;lp|rfwIo M b'V{ȻI# N\M"{+̄sPz|qG?/_n;wb%y΅p#Qwvx#$g_ NQgx쪜~f~L*Az79Ág{ .8C;,iM3JE[3cYΌ:){ :?X~bll?zwvn.mRo9-j\#, -}pbwvn+z{|gԆ,}S7~^ ? {3 u7Kɐ3 Po&o!Ue*+*C`A#%+J]A!U7b-Zm 3ow%47x BCRjr6uW}/ LBq3Ss]~lپިx؁, ͟tͷ[잟sB@uX?{- ॥֟;~o+2ɢ(:bYwy?rG|{K o3 J42`Q Xԝ*)ƭ73ގ ayDFkOƪU&saAU,}J1;̟ ƒPȈٚ`ow>xҾ[uze='䍾@jp.֜c w !@8K<~/ŋ;O\ s6fd_~䥗_^[[\91q왻kvf&.b=v#y_P$Aw o{헦TgOJ7 $0re]'oa/ś;F^S-A9mQ8lcMᴟDNFQ+- Dv8L2<"duEnIf4{ foVR/{n;⾇x/r b r1-=D>w1{²UbA`5[R#Y R"hcpzP`zHAÁe`e7tJeG8|eRY΢KRGWv"ڰP|7yW}ա(ps)}) Ƭ=a7.VFՈ"k¯]n]2=*ݽoW/]J)xx޾|g~%{?pG.;r53Xؤ`H#If'{-4IDATy况*%"+g:\)c,sT+B^Y@-Ջ9oyq~,_搖L3s/]PX+PhW\vצ1O'SK浈쬀P{_X}qڰ/|:3Q8~ezݘ\^GuxxG˿r_}}bUr( Pֺwq>Z5ީ /4z;-/SqI4Z[`_xRM2j5clM:v9m ⨒4_@~FJt68Akިe'Qϭ;"7J絨k'] .`/ ul]6ΟǕ#$ \]Y}ܽ;OO.nN?q⪱k&Ydxlb;?M{놷+z I/a[sBȾLe21*`A ,o”nŬ4\ExcT3~Lؗ)A'xbqv:咭 4-Vʯ0ڴ3yGX#pVo\#w\w^eRtRG(&>n;F7G΀Luc/3p7M5$LmsHe|q .{xSUci0g;iP0V+ΛZ;en  QwKTn(ؙ>zP+.?B.:GT|o(j{bȆ1s àK9?7;VJcQK֍@ [R/w Ytjډ#W" JwҞTxc<؋-* y0ffqfe0SO}s~es^?tuMkN"h~v1i͇[kVvemǁڋ-͟':ޱՁћ"{moX&;\*? jCQ^{dZ evѿz(f3ݳslUX!3ښ]mrً+נj:-&F M͝흋ƹ4qF|Ki9WMoC#_ MH2ڀ˵Ȩ eGYGGoP\#Ɛ8NիTq\/ YwU ]ӽ@|yFNǫگ9' eBtRw+ʋ%hziW9bȡVJ`n#VBmV5`3'k.,. 6ܞ#Ǭʄ4\^C՗6~6av^ٮ=Jtcs\]˧$Z{au^M!H@x=xs2IuǞ8ܲ}sU$Kqp8^J{h\\jP22[xsI] Q}xJ כvI; 4E}g& OՍ/Z_zM]4?Thޮ$|F]g3+*'q8pG4 dc:ɨNzIɔ^ԭGD,LƄB+?ӾAk@|a +;7/N>{-hT͵>=7TF<`;s5*;]봶a/BcP$؝ؠ[LҎ8$L M+U O4b"àV&Li8f#c 4` t,Hj 01)pD>Gˋ^ocD}~PEP'&d!Aq]H;x@h};VE*N4Ҡ:ʢ|D$*rӲ\O4+6Z_^>Sqa|7` #uQdiq,4޽K77&6Uwֹ}}blP7oj!4*c<B2LݮS(ի[;{QA@yО`s8/,Sx(j*Z*ZSDmIgQ6us14Zi4_ C gwx{;L ]rCU>:E> I+! u qK|i0 v@ ȊKXݤdű`(`ȏJfJq 4|mQ&uNp֋B ur'pew5T%)*_ۼ +uzEjZmc.!=K;]g8Z28*P'ȏukAX &!S6êjY 'Y'k>28dmdhLE!Aoۚ0/֬}Z" & 0qb8E".C2|IX.`ڕ)O'Z^ ?2{vur?]}+4Wu]>.dDpq}džXHn]Qѥ͎ESϑg{Kطg'<ٺoљc:CM"< ZHS|߲h5\(N1N:8dJ#9Ewl!g!Q.|x:Y *>Kqq Ew.׷ =/Iɤd`j0wn' E>CGՀeHRJOEאF#(&LZzmןvmOFZÞ'~1vjHl pqp#7k6J DpBxQl@JCU'So}?^}yĬ͜,Z) c _w{˃{[˃r 0d /C\kӏ_Ɇ;]k{NNLGyɕ(F:6Ft[><Ԝr 'Z>s4-rK4@YOL=墈,Qm c$`Xif碞:UzN\t]pH!»[ABH I n ½{g; Pwn'k^#}V{9'^lQQYni}htC{!Q?C͕ޣaKPs):Uܡ.!oUA ru0 6&kJd:!''9r4Art<1C :$[rWw_xaUѾ흙dD 8TcٓҊ\Z[..DzGŕgraEqԥNRGp.&h#g7^bQl,c[h^^oN dO>#bIcզUN"ˇ")S*"A$bzH N~ ӱLY*bjl`+Izy= * A bсP"uUجl Ɛo9 F"4EGcJA*eِte,0ʈcW1KH_,OE( ys8~K L֞zW+maΝG>pw|P3onMO$xxs:G=NG&I0ԤDE+:ԸNFPrՙ螸m^F gű*P8(p$VbR=PTjdP#Կ'~YaNF ˄Dm8R) ۜޘ7cFҩF,Ubr[s@Ah"?{uޟ s$Qh7Dˢ 3; ْ3|~/h8`z)VtJi"ѹBQX# ˟q 6ul`dAe8-ǜZG+Wk@R󺛱%HLWΌ>5;wl?l1HH_~ %(Rٻbn#鈪j%JLqłψ~19ÉJ{&! ]'KZD*myR <4j/$TQcm}RZ9$ W@Ǘ}__,&k@5IH쵹{þ#,ݛ dz{xm=[AlOT 6I=&cA͚)D@\S7_ c! 5~9I4I\Iy~ Ql ϊZrPS(rF;5ʌd;4NO#EhLNVjbFezNw%I nI{;7\Ae4y"N@ `Chl`/*ިt* nA$^+MGR()-FO'L<`{f %D%6,TlIAp, $NQjh 6̴y=D&HA"JHEHEpPꨏC6Y&ӏ(oV9@4dڸ  ehHl%s0ZT);E Eh51C! |sSe;w,>&MvΐujM^ U$+,EXv<~AS3]+8NfZ@JD"Ȋ;.icY NEH8YB/2XM`bș] Tc&@ldh$ieP#ÝtRF;|f7JXb*PH80b~u}0{hL xqge@UrD4'T,I{Px(8=i 'hHN bJ'Wj↹cCˈخjX(n_KG4$u\YovA<΢Ĺp4B$)i%Vj^2)_7s6f(A!`$(T#CE1H$T5KL'C$y;)k#H%K&^I!-R@1"bXRVR#ƪy#~C?p&0a RK Bl0N@ FHrpa V!r x bL϶aD t1jCNp@$#hF ov{x+/,g띛iΏ84< (tތޭKSNe*g !Vf8bD^vbbƁ`$JHs rBmqXDLPL30K:΀I@Ck 1 3&s)=]] I<'V@  &9fjof Ҙv5ÀQ8CBƅu\y#/jdV'y|!l2./^?\L2$;bl/'&PBT3 u)~N{id31K-:MKslg8E B6ʵ\ό@ֲ*TR<:>"R{Kz_ F]P$K$jXHhFG&?A3jh#f2.'/I4b.V(H`\T\q` jTq9FoLJNs1a&I2S!K SlfifFZ.)34Y9ڵqIIDK^sgME H M(' x8#e]iQ$5zz[uALX]_}p +Z|שPݳḧ::zsH`0xk_?_}ݯӏ%M].4C,ƸknQ.ˌ2MjTnCK isƵ5h&dXWJ9 145P9g@:-3ƪ-oEGui$w9^\@xjfBQjޭzTޢ;72 LrE/*Z5;//mGOAO;yz6m:6ƻk\|W6ޚ7og'ź2X}u|tO lMfo1 UJPxPfltf!5HUY(919Q֡ xG"$%K%S ?Hj@~l0u}Bu(}us+׷[hQ? {nd}%E-G}>y3y*Ҁjg ίSg=.pOB\pjlyuWZ/O0`crj0Hx S Y>cBG(F] GsbY6u۷3y%\5"}eD*#i`&}q)Bȍ/= U9Ǧҧ>Ya}9&`<\ ʼ‡yR8UYu=7'{~L/.Ͽ]/$ApUg,eEs(urxRY@p8VC ?6 9%I)f Œy2Prp^T{캆#QQgGen{&d!X '͆CC 86 kLy혼[ί*LFe5s͝ ű|y]|c6iyl?>lwƻףP=ټz!лP:}^rd:TIq8ӴK-Fƌ 3!PvJؓ[c6N"vq)jbcm`KP/4ՍJC9//Yμa^nҔ^QY!g]SwRR2543ʓp`)3s'/F﹇EXBb IW^?x5Qe Oü_ɼ2jRP7QKpYAj ^᪢iO6ӵ]/p1>i+^ю'GcQMc.{/5*|=q#ph4Mՠ"CX:I`KfY%8p[Mͩ,\5+"TaK4nCdH-)NPE;iNQ~`m$hXM^_Q] ~f*<nnW4N] kXmy7o#sʹ`9ڇPusyUJC$Qd e Crh;ƣm%녋84 D)دܠ}&$ImKp⁔"yxU2c7Q>~_"%PSW +h[ E _37 k龍 ,<}N>:.ǘ,٢3~˘/[f,wWG+4<{+_aO3ɞQه2~)c胑D!XQP  tzGY\ VuhE&4 n"U^BĖ9:y{5&` 96!jOY?_旨nҬy0*~L,UӃg仫63O%ٙzP9K bG7,g!ܜHP Sra=# ,`suҎ @.Sxy v# .V(p5Ca96JڴuL#h $V)d89Q=.L _ү=#yp75Tx)!6P ΋ Zd0{e*{ny~2I^j֯WfzZ&a~H R=I!b8 9+5k=2 lXŴS#9@!Zj4"]L`x{TU w^L"%N^jQܗm'al/>WxAW連O\Lm@YfYqe0_sFayAx\Q)D1@㇁gu k)Q9p3_ٝM W4oMuLImQ 1<ˌ'jQKr5T-+@D@O EܝꟌ" 8 ҄6\ֻ#")܀:K Nm~|v/Fyz,Lނ~|B#@tӛQy^+7W 'A,=xHw#+rp6' :b~:sm3Թ3 gj!Nu"b{ĺr}uh6Gmf!5~Y@/#6V5]m$jge*}vŸY?'t.XDl7F㣂L<)حeb=zO&$.ZD+2X0yog`.dM-<#9D9F܅l[6Dd:Ϯ&@+h1g5V<|I𻥸-Z#=F"Į2][ <++Q f3r]HXtIF6wM xB 9s{!7~f~pLJׇݵ%C~h7^j-DaQFG"HwY49(/ , ьmNKTĐ2z 87WHaEBrC2H63LAFGJ"آ5鑂~3,`ݾegm\>d۬%W,𻡀r-+˒ K`# "%9y*X`Cڮ~3$`a,p8c]!d; ?KF}Υq1`6HV_I'r<,B^RqQg gUo?+W21cgmBn$#k̫\ۑ=N\Fnڋ!Uqs ZgZϑ^2FRx I2dKW5P̅%؏r|Yh5&.)FU_22IK`厸@,%׉;dr M"̰-\ix}6DMAn 9>'YgwD^| _yɒZl 0kM+PT5'8 `Ef.+I2;{:Y+qTe@zYk |Qó!)*eHA20#f#Yur, wkyu Yᒭ=uVdE5+moɉqKjlHJ6qԲumL1|s>a 4|%,k vm6&t|y t6RVB<8g~QdY}vO '=Hiļkf-ye=d5 !5b^ONU)9Uyn a1G*:L ffFy3[(9WKB+O d28I$3IPxEAxCwuSn)*ExH%׈rNfL&&:ZR!< W,P#atQ+ W$Zūt#j I}Y ¡F(YպH|CK0.cuBrx !3DnH tGvʈ:";"v $H`ԾF_HQ-:^4zHK}(WM2]镨v/ UGopr{/ 6fhum3@,#H\q mbްl&[͸9蠂\ Lzd Qlmā+Qn2ڌn i,4,(h/^`{:ONXNvE:' f0`7YOV ڙ[UɻYe 0UO2$"HS7je(7 C_!>@ \@evAqT↊8L:#uI[Qd)id`U!twGDH#S~$C"F8"дu{\me[#0_%PP,`TC%0"oLޗ"Z^?\ ^ ']8cl;Da1]TUW612A&mB'OP$aKl_!.7&z2;4Ru] O"+:UY(~z fQ ):HHn,`KL)ubAxw$٪a?_ {'i0}kݿX{?vl37>AZ}2KaF"g cw{ô:Ѐ׻YE _HZ'ƣIY/0@B) ~W:1BR/^O1nE"C jǼڭA[O UTҞDhr0ttԗ,f#ˌ\cgG+.\LUc?Gw;ᐼ4)KQFT}H*c'IԏF_,H` O}´V6 KtiTZEn c[LiCMrG*0 fj{d~F@q8`p^ V C˖cXN|9,V^ Rf/bTe%ZW~o)Ho}`1$C Za2.,(*JN]0íU֓8 J}' oq!KT?j0&v VaZAO9*8<67ڬ#bhAW"ES;zPh 'DB e+uiҭt))L4-;ucPQ[hǜ7W;w}d$ +UU[v[`ڔXv3nJ$=ur@IGWQƆC}3ZThDB-4A1dS5h͒ YFtSb8X-A 4bG=vf.|LM*$=ݹ_oqx t"y+T kRen J{=L(R!,UPs"9TQ[g&.sMl4lJ{!+̫pZZICSeyeZ 32,Q㍘etm>*ْ9̦>6i ʫUx6mA&Et*N8Ͽa/ Ϟ`ZiOu?6 );{C/ Ai׏Vw@BH8]~[|jp~9̚ &bƙɿJ Bl(8%$ZI01a $xr|Us?m<,-J-&`n*eʤCFbXd=d)2ab Exl#MC_ J2A֍$r !@LTp8 Yi%<͌aѢ\'TpT\#DɜtԕLUr# ׻#'؁]5d ;eLɐ|8 ~2@T:_U й&rc t8[*RA~pġXMk,N_ WKǸvR2둘f590#]H1I[#|B'``^V2҈ؖQ3"Qj3.sseRXvh3LM '̂SFKU÷a^#Z aZ@$ jnwtUN}"Pk`(f] [|ŝ*!JԍbBv如 Q0W1PyTi(1ÓVAO6AR%i-;>0eqwԧI8ÒNo~%lw|*s^1idY(T֡V!NI%WFqQm qOdWCwL ,H[jYĈ쩜.;>!sm QؼwT+V+}AY@<@ijC|TDeb<e0Dj4H>l)K*2=$s0!!WjU,{Kt I?S)=s0[K3S d`/׻Q;NdHM 6/nlPPPr^?~Ȗ-bA|77N}r|fA곿qRAeQ^ K@J gQpA1`1j<=烵xݹeZv5fBh&MJHU '| BHk$eP1cAiJo&?-).UV%@UwֽQ KgkwʴS>x a2fLAz@oe>+)-c̒n_j6zgOZ]J*ɐݙ-]&ڄdX|Tlj)a~xqcqO7o@&KL~o^ +1>~V{+ϟ]3+}&Acg: t뒌(e{ZH^8YcԼ&ZLKکO.GXzD 4L=eJZ|p `«*} ZV̯D hM%n_8ya'*sѨ2p~=?'Ə<𣐻i[|dH k]zB{_ߣ~eV;z;fTY!y ΊjP9{ʅ{ͷ;Vgvg\=g<(CɤdP7}Se?kQ|Bx{OocŤ!~L7KH0v0[  heb$,,R//MۑFtꥹk\u^enmUڟWqB9F,QΔPd& ıP%g4IlKUTɰV7ێF^p]KjFm?yOT?xs/H'B`}Pk&be P߄>)Q(Cבp2DA94{ͫ8׈xm<ziί|'#вlu];_\g\8nj8J)\=?W|+ūWI9R*KMRϙ$Ɗe^ȓ(IRzMdqeyk zPΟ%"OV~?rC[A(p.WGV=2XBbJCAOHɅܾR wϿwOH3ϖ5\Iނ!"ܢpǰ Zfî -\!#f6x,΢ x 9^y_~xҿRdv0lOcx|H.rP9Bf:F8!E΄ +"@*#ߺwQ797~`QwM r?|yT[>%eF.EtoszFo!?w7־$Ե[Q:"Av) 5d] SZ*ONDA8?wN2LhjZSnY%s#odo1S֗p:Z2al 1~-Dcdxێ[x΁v_8qnc#5kE^5~8FbMPͶTu2(A{>72U =qy#H9I?13<GhCc{{~C6VW(bjVPy7e@_?Ĥ-438E 2,lTxʄh@8 Q2/0u#oM?^*xF>QlxxRj1$I|m7wfi'SpG@Ѱ@ou ڄ. {'K?ttF$NRȧ=SG&+O,DeNiܤbԓ oRcxG<;]Amۈz%g ~esN"(D-*ODG9'*&fah.Rx !&Yfe 1B%Sû Q_~Ngԇx'^{ϟȖ7/L%AT0Yܿ8)ڋ&o+OoS^e_$}7$wWGۆ[mOh[V( S~9E/K'(z>X ك 2dddm_ɕU!᯷G~'&kA_"Ċr~rbR߲wN4˧<3y'loo1F0 WF,Q+9SXdmT v()nOTJ@OېEv5k'IuI[窾: Ac!28I]yqN;WLd(/h1] dnNl;^C 2L ðXrA`Zk͕a׮C2fƦ]ϙ+CY(ܲcAI3A9l CHFwAcZ訣ztZl7z [XXi{Q]vdCC7tUbDTޘO Q? =^f8^K&[u7u.^jѶ71G =hDź(K/6n$qEW3S*NW+{uTz@?NHSwq@1Kb {,͆ǰ,`ݷvœ%RZm4sN\ @~Iq>ؤ>``q,<7fLu ԗ ~\P޺~X+4Y= \yϺ+'o3 jsw:[>5zků%á̓Vwf9#b'tb8vD Y x8đJ"˄der|kX=|_?Q/72mK RD-Dw>L "Y;Sn[; ֫Q6֕@n&:>K včw}(CTe<:Xs )Y2BW6g"rmM`km@ZFf~O C :%ѹ5QIgF${m±BMN7~X~&cL:pȃ/4l i,[}#uMvGy:TL4Ш9p|CRJ1;BPCB: *(G=弥QZ)FE0#J9EJi )VCDqʤxJlQEךOKCh3NGm2}6O QmAehxq~SIOPبOhJ~[up||Vy}GooIFuos{z}Dqv7A9zoG<|tn gZČf}'~9Y LN/<<7Y-7RW[nQ3ױ.l7z j3"!ݕqw|AuzM?cg9xAEɠ'R9ZY\Ò.+zX1|XbD3G0|P9~}= Ci`}jGRW;oˇ~'*CN}|$)Y^Y]fޱj,h?|x`KVsin~롙=cۧ?vܵmB J5]ZFf[ ޺C{c>(ʋK mR|l̮@0hk_lĞ,=ڄB~e>nFq"m >h^ 2|܎{>wZͳsmZ$/o!,ǽ=z~Z;6Si.ի' n`zj"[intnW-{ܳ89k{!)_PI4֑{gjΑۧwxpvt?ڰϽ܈˫?xW@wэ.CŪX?Nj9Ј+ŷCA$ $3ůz7$$k F4n:%Q}[o(&y|,\VҺͤt&.V0="K36g JI=CrnQ(.]WtpaL peu]8z~0JA0,ُox1xn;}؇]&va7o=Q_ճc?ٙG܋ T4Ņ(g[O^ݐ]92U3(sI$mb>jO,/QƅXxa /B YVg?ֆƽՍ mxP*5#5V<9PO+k.?Y7ftF~f O%C/r| S$oO5NSiqZ='=P'$R*? S\=oӞr)P4&Rs.q_loBowqU[~T\HU?F EгH5Q5P2Rӭ)8<_C#[?mÿc#6Ox=DٴbW5B1l`X*:D!Ju ےqwؕUGirSOYԽxBKَXG#dSvtԘ`q~ܗ^;K}?do,µ~}AeD(Vw5/cMD~w_ `n"E8FSҁC *Ѽx2LVLv{RaXC}|g}"S_Y[Vh**%U2߃hp3\\T /~jQGO>iЄk^0vOu \iv'ʥ;wmmw_y |xܗwAϿp+}84C7f_;rbd3O| J|K"jY<޾Pw噤{X%ƠLA:{l<y/ ĈDɠ1h\l]zܟןP=H8ϼϸ[yBVR,X~wLP)KO'PRͪ(,X{µ~|vRez"&q\t'Tc"պ 㐱nocqlP% ='{;զFk^\^_)O[fO! ȓΜ~v[w욪KA@ܮ c8^t..}_}f HOtzȮz^\\zs/^b:ߠ`kЩ)wF/%3zو8o쉫>}|# re \pBI! ըvDP{^8g\X2`Q'.%U5{I -J6NJɠ˯ѠVVLRlw%k7Tkƒ]77P sPV8 ,3 ;X>z %H\54:9.7D0=?&I؊I‡!etǝZAHs}Әbc|r"gf7V'* anz^Gݩx ;jL`;8XԜԚʛ!x|@àZY09oI/uQ/͏ʁQDҋvRҋbzrI 0+%7+C2fnL†w`Tl$[;i5:h)39CT9EsLƑs[=W*ՄՂ -S@q@J:Q͸IXi/,Kc4`l3>l:)(g Cg\;7f(!ڒA"ޅ\bFVG L$̘*SYDPʧMYhv/4Lg(Dqwr1h%zZۭ jV۟vn{P )֝Q󭧇vznP*G 2MKussFePfKnK]B AܚAAND S ZV1 >#o(z' TF蓳H燥 ոVw㿽6~_xxe}% *݇{é1J=r#I ,&=Q^@sJOdM*tjf,kHMFE4s0p@8b(Zek0gԉ}WkU}1UVtbd /z`v@;tZ6+ʣ˄Jj)0x`%V'@PEq]] o_*| L>6=MH+ oЛ`zrvW7kA+B-^^nBjPM h_AO.4h\О[2|~QE)%A;1zf4H)1#cJ9R,?p+ikzL6"2SuWBEk`-lVB GBD^)Մs5wA""\NIP8ʋbZ#VX!JR/,E3;e x|Y]@& $P^7SS4mL7/M@zSBIַFi+KKzvPOQ2LC,R+7ڑ\( 4/8vi1"-RJ:*S&C64k9'sqkcZ=%M6PhJjd1oh? \i( Si*sT52@f@t(Q%y=NC~" '@<;=?kC_!$`4wEgje96G-(J@jrS[FI,@u[L}L⫦YigHq<3 hP3!SZHr}I2ARPmĹ; ޠkf8P`n(pdh&0H,Df8E9[ L\֨30ƕk' Ray{p>jRisHM\`ҿwoiw?}s7V2'QPͻ+`fe(76B6h2hU)լ^֦_@+G؟:)̶bHV.7E񑹼"F!60$jR:ePJTyӑؓm]'Q44H;ꮩ:>S>^V+JLhC!t H–H3Qr̘JoΣFvo'\|-jI6bT,*jOVAck݈g1G66H|Q fE7ʱuKP RK ܅Hfu"@ۣQGEqLbRk0 AF oG=ouNnfGu(FC"2(꺇d۱I-~.gCas4D e; yz퀔u3:fMFGc@uVx>rx+jqAA;T.0v\Plk/rVܳ}fZu< 4NnXtkKh"%=TJ֑?{EJT6h @)E' j]EP^:բ퍱 jؒ d5 <{iFnMݒ+1isr4+oM=ܣ$l2Gʱ*ee^Z-<:}SXӬ;߃q|jyS \<5O(!L񙎦0Օ IAF xHh0A´^'JJ Q964l̹M3$®-OK0)l Rb} HfA C'  leA5!_wa,Q~;P+)NĜ Ām DFqCI>J؝N,CiUU)IaH->naYpȾf w)vr8QhjFR)l!)EJ'b0tK. W+mxuynAH~\8ܚ:HFΓ\3!qLI@s9r633jֻ<,(QG,$Ź-k\+T17Z1jjhj:mUhC4եJ"=X;l!T*g$ 1hnkT}dçpxd&tl]!>WN [ƌRYdΌ5bT!'*3}ME厺h.Zx3`{7 1%?0X'Hփx_ .xOjfECz t"u7wd @StPqf Byh:`Q1^ umk,gI&5rcDZh[EVbc[[4 K8A&dP) t&آ$Sͬ(a XA-{#ܠb%QܡL<%չLV[gĪ^762Œ ;{;ȟL,PW\,9&bep?] Η0gB[{[𖔥 R=Gd^Ps90LͼZc5:6㬮pr5rBdlSX=5tt!z(jEŚc 2 OJD:E#@Z mWkiԆ_6E\dCcY3qS:nܸYQ4fƒ Efx裛;*d~}wmTs ̢/ &4DOtv?7a{x?3yjX0YK-Xm瞉Tie'ĥSh7-Ӵ[_-tG%0ee&ۆ$V>$.237`>9PPF($9&(ռd4e`` (aGN+ΠV&rb&3``6bV&/B=N̬A/`F}= >#ҡ_{w 6-6ۿ {JmTx﹀mZBZnQS45*ɤb[7y!ʚR>D!\tN5WQW,AF1P=\NT:U܋({Aҵ0J/ӅLWx&hRU$q'~omϻs׈P [f@ŠD"%EFXYL 3˓0Ъb^4KĭPĈ*^(^Dž;XÔ#v`=xѱ 5+҇hqAO9is7CJWi+,EW{ck֫,wy"% Z=,RWmhAΆk!(l+JL2O=POfP*Z&fO;S,aXzvg|JƍǨk.-Ņ8&CKG!VdLEE`)efoxFr1m Jl e3kHF~t=̈́htT$kBX7/ƌlu`9c㳻W]٤Di*`+`aIE$0Q\HTeb(+m(r"#Uup[W$QpໃEB4jν|5re"~ frGXuaz|`wO6Ux zP>3@pUVC*9 58J>1#3j+1괷VF;l3bMzy  990TmAʊ[Oj4c@:lodaSmvgFlXXzvi">dskD!=HBX> (.QDڢTͰ*JwM}"Ka!\O}=36HD}0ōBW ;~K9}VV xStA*TB1Q~I-TpW m0G&'VPDe yzr*崙(Hzh6itkLy:n@(g豉u8*p21Xw/&,`a>."1 ʆgĊIl|;+P@C2K84K !xX)U܄wtsZ\lbeҁ"Ch:&)IIPLӍd`\+xH±u6> oXk8M u\ÁE@J C&ޓv?I9 Nqe (^l/ BT- 4ߵwW>A/1'{'O}\>>:%|Q?BFpdō,{NV+L0e04H,'R BCU#^+4A} FGn㝛*K&E'BDW+ΝKKI)F3-;1+Q:$A5^4DQ13``߅Zǂ"ɇLXQ0S13dZ䳗KK- +Xy0Y&x%),d,CfBkg~_)GWLԊ@hhU[0pW 6[".G,SLdI=މmt2`=+{IEA6ıavJcbCbd55P&LoD;.oדwOYY)&n(X :oPag:l_zh}9ghhOy0Jn  1o4 ^LW;':{&;'J\ h^iLa3Kh{O&=JĖpCW:G"ǹ15<}v'6F蔠+;Ǫe/H_Kl\m7&,Jt{xybwLbQ*5RMѢi`l-ZI)'c`'TY aCx$ HAz^sGx} VM(j*J)CE*JQƮ @σ2OgK:ƑqboYKpm,I W$BC/-o+5'NhL5 &ǔ&^yٯ_FcA+* Ks_]oG!RW,$ڽdC+"@ )D?SO6uwNWl/\Qip(KPhCu 8(ŝݰ0Ih)?}?Q>N,&Z]i}%'(ۻWYV&UX􉽐^`g\Hƺ,# c)$A$f)EACB `}ο^"͔ ;ab m~ J^BZA $0^9k!ABI+f+ݤ P4^ Zx@l ,ܻ~ugًhNdٸA_[)%acP^{'{p-l$e:όÝ6~mq{eR ;޳[fY2ͭm~:8MCZp27SA@"nZHb\XBL{%SթR-cOO6֯8bA Ÿ6Ɲ+kqڦGaQ4H38`|tlj7,eB6?A 7:{G>S0/iM*$[NwJ|Ś!F03e!׮ e 'ɕ hV4kllq#ϸW/7:I&q%Lqrd[Yd gUb`gu2`+ĴŁs!z=CE$NΊQƼ֬X&\yj'+٥_*(^j|2#c%oL.҉qv 1MM^ 1ӧYn5޳[_VjL:uʠ/!Y#`$hƕ~m?q5ujTw愑FKT»T5l,b'YbsxXԱ?S;, )|! YQ+,>u#H& `r6,9I&1|bYGsdu e }oM P ~`wCf%As)u󓤔DAݾv٦LR>!g{GKO 3?rH|oT (bjz)A(vg rӞd5Z~V&rdR L٫in+fj@S< X2\L4#M)B)P>scʏSwUfJW^DYvX4i*WF¢q'~;_kK1`76rRgCG;i*@Ha s&- $oؿxoBklVtv=:_J.n`?VZiӬ[-5fEK]>E`5LV;&SL?]K! }5R1,~bk|xG+]|lOL㨹!*&)i  aidurXe @ݠLs/?<) s(ݮ)ꙉTeZsz;D$%iW&GXǻ-%MJLO@5j!iG fyV=jRc|^z&1ORzP?E hꯖ 7I)W!ͽ{'wUk^(2ANCxt{5d(DHk]'=<рbB pڎj#gL]!I{{u|+)vW ~/T$}_7N 3Z9y8k#qw{8v^Ev纝ݻ`bs=3o,`̄axW{(/6~jۃW7 &#ɤUe{^:ڷ̶Mw' Lr_n_i_nޝ<k76JG! /4K_>^+ߌxEoVxeJ)BGW}nv~ƌc)\Ϛ>wUN4LĀz/|Ӹ);%@G{a}k5|вVa$fGS65Q̜Q#M:8 !Lbcm9 X:XjM[t$LG7wg>Z #tWy7ցq5/PȺ3BЈX)'i?}MƝ1Úya5ړSұ!n^LXc+ek'%(!#C˗z.,,`+K'^Ї>848^e ;tv{  2'Y7AYeVy宨зsW6}ɳڱIn2&np}RF'+&"߫dʄ'wF8anV"7ȞwHaD(7QLP~$r -h/Ӕg v.\#^*T)#3WA  \zZ[gn6rG &UC9ƚܙӰ! 0"?&g&t̀i^{'g'rGmpGۋ~2WSInac m!̾_~^|Ljk8'n{T.K[)z))$'|ځr8cSߏЏ~_zR6T*FmlsjK_:d=AFs@emWo_緼 :_g5ckG'BCE(0w3Dwm2/0I%+.sR(#OL!@XFVOuGJ\3nivۉ+(ЙDegח nMp']E"$3i׃q| ?{rsD2d4o'{8Ro*S80E@qOo0j yH ܤm^\yyU.Mo"1ڼU9DE @#V֝ dk=_̃x({vzr=8X,'큸+U-)2'fK'Ξ=WvMNy睇>t Iⓟ[&2 )f>td2"j<m[órloMwIM(%^%jHꋨbr^\En4qrA[*vC)ۉQ8S(?CdJ?$M%߭A`,wj{ɟm5| I."K&NӇsr{svzs_톎3Y|}:r>tl@H)Hoy^" Smp!׿~4}fz꣏>'uw.z622]$Sޞ}O#G|Ǘgu~(0#[`o?۱q?5kOOO !h@,:b $l yLBXfHEɷj&U.ΕT}f'MNIku5t rEZ* M?q Ͼܪ뾳sWgP~k<ҍ fk $ֹ5j]Yz\/3XK<ꘚ49)h[?~*' o=ioC{۽qJZb+ē_oHb /BǶ#?֦o݇qa0tjiw 1Q()3N#Rr}n߿̔ t%KK(P{#Yr!FK]gOo& .TG~  Nd^[ԅvpڼ-qqIy8{EϠoE$#ng%cQ]}.y6pҋܭϡ7x;H[^t'Zӑ]`Mg\14:8"1`SN߹^2*:ug'x'UR*[]FSڱ]̓Ո_WYYDzaŹ@W%7L)[ӭ|k~Put͈JC92-4sO6VּP5Eۮx1ya )UNahs%^"Nl bkE !VHl4X _yZ+Ol˶d x0J&YYŦmtmWK /33_:;Ki?5G͙g: oFo$2 !95=ȢB@|k(}7x|5l",o/ &%W^3xj}(F>&6bփv ^/&J"b֋Kd昁vwv ŋ]&%0VwRCj#( 7 2pzI^}v  P?gժ@_'Xi}TLf, $MgI>/$+EKLXu%b(NrcvU~#k%kP+Rv|?pg8rWNOk&1!NUM╍jhB˅~FI閲x==Ԝ(,zt]t١zǡ?㐃R||{kw}mݺ\T,˚(K]os~4<8vo |i+)BآaMss=;gMGG"*$97@wwlj,ۯۡ_62Y:2;ywq2dYFT2k +g.>_53F'h0U3ZܼgP| ?Aq sB8ïnŭo.$#jO􆸲HAa\*j734gn*vEg-kNS 6̧e]bb]+mόj~9{1zarc dBS>\Ԙ?|}jյ g}⣟6=م o+kU1GRˉƽۜ՞[1/:@RLbzcTu6P2:jvNa dwD$1AnY&dj[Gν e=*}Mm- ѹKBR~5z {\N\cb3V"sUaF2pcQ z/kk?gf~ԭ}'^.U|!(mO5'V 9C-'cڶ_fU!ixCllkLt{fmR@=R߿? ֔)B^'ֿ:OvlGնyA(rOo> tF-$a'k˨lN]gIԧshfG"kMȹt^-;8~S_e,Gc]Wۓ Gs문k?f>(ͩ2g˞m$bvݵg/p1'4hƀk+lke -bYxV֫\vhO1kGW+VM kųKW7͍i$d2[Lm_4mK-iPCb.nB Y@ aR&գ2JP4\: EN1Uxn2!@0sM$S.2*ÒȉIs'$e6s;J\< CBY}ʟZlgwQ>ËR1:#0A_ tkg[@HI~s=W+5ƀvehd_I(c¿ꢺ$0>(Dʕa 8 6g;W<{JtiM@]W9JO%ې@rw9gq5֚<VXQ$(Q)PQ1S;:1pne'Y;2yq],\=3C|dO]]Q,nw*fImzҰ^k Ul/n^5z_()Y#TX|R缵Εi\\L2(JQwwr jS { Ɵ>KןZlVZ2'86 [D޹ɷ9x>PiL"4]Z60pX\F/Ne~NJc7GԳ4CeAv_0prǏ*EXExvifY{v2B0Mg}̢N quD26iro܅׳k8tӐ]Im_](4wKOь^uj}a5˻ȷ Al:k{F{k26kN*N!VfΥĮk|ܫ/Wa'N. 4 5°-+B; X}CC+ uƻ:s3>5YFi1G!c c&7?W˙qM=EUwMEp 03峛g+v>:>a!3Zf@vQ5mUYDRBP:<9v@KdUB9bH g^r%ЋJG9lف>L1PaZݳ:pF5l|{XΕ?~'"=fGTaL;"憖]w8uwfM%N)z&-qhqxle*C]9ٺ{=ZzasA7B64s#4ՠe<93fZWw6S_s\M'B S5~~7<֯V``]Tyo2Ѝ+Nˡ:LfX~PM+Q$&/2N`p/~l(% 6}SDJJ1߾Z+k>K1\.8ӡ1^Hwi :`4``<ъ瞸[Sy.zM_g:5(:@JbNռM!ii^Ns9rS۞me}L+x=ϭK۳bnUy5|G5/^ϸLS"iIy?t| ͓Ĕ ?we,!ƽrfB0yң*"%)sjF1Y{a]¸(onv/W5sov,ӽ=֪HAcg~P #5M3vѶOP*UJʁl/vt^{y/t su˸NcaEpY2"ruWˡ&Z _mf 7VPHq8nŵt[AZ,Ym/zsr:PlO/~]Ímf%xMp twYQ_jin 3wzS:8~\ZӃ2uIg{3~`9 QMu%?.ybO6˞?گf>KF+e"BWb)Gg>C9a&|,kóe\▅ZBa(K d,y\\g bC[ȤtqcAnS<_Q rCY|=(?DC% nUGxWxsahqt,4cu.47OW/6Us- ?Fb043j0b_ Bا+#?0Kģ[w^~QEì!ϓ.9D J(yʓG^M:*,IFO!>!o!C hEʡq .rnoeq"'lyW1S4KA?ZcԳ,hgM76G[A_Di*l: 2cšohV{,ֱ3Ϯݟ_m}<4)ODv2Pga(04bmQW`tLҹ!L:aaPuhf>rw OVojŲMحKzxD2d6%v Hfo,?⚱Us9ifͮwi[G|ו($H}D`6dϒj3^{ukQyr}o`a*R eأkmtî=Yafji-ϙҩ1]a1njO{?D?&aA ^EP徸HEqjZLbu]62kru\1?w֎6wms:g?,xuyBpMi5'Q(|%7,dAuH3;Q j"A8 ɱS-! AQ iRNrbSWG1v5I=!552~qCQ#3#x 5io k 0OoԽ̦_˧k{|׉ʞ3T(%oa W'ZvR;:[G']ψimWu̵ްkFӨuED0JTB-s}if ?o9{ؙNjPvjߏ6(^\qE LAE#ucvnc,9ҸB(Hb(p-꘶\ u Mh (M9GvZwZ7ݼr7Zy'Ȩ+􊺜 Fa<^[,qܩ'd-m&?ex/)hBҟ$#(˨u0Ўx?c҈mۄɑmdGί鶉}Y^cq"] 65UqskƮ_=*^DOjI$/&AO=ݬer.ڱ'֚)'] w( 쑂[ΆewqK0'"fڎ^ٴf˨p<ԡ8(R3^Y\bsԖ_ Ā; RtF*u34􃲂nwJjB-aL!LXf,dթoR/9E9e\jxݙ&*@Qz vT P(MV̦LݍMx#Mud. '@#ُ%ZcoiЎTrja&a91vˑ'xmw@׽̖_f_ͽMj&K(裏ى (ٕKsم3Ls7HŶ`[l8(cz!G@9AlE^Nƈ /QYuK3rVoXm0-AuG 0~ws=67TZ6.b F;\?XDDuX@2uirI,{^f>Yr$ry*k[CAAv.@hj"1=XvI46h^X=azaOdxQ4@oTWRr6_/wNzșY/zqV%?/5'X}SG6ڢ(=PBZ}.!Xe*kKx/8إ]J10|,JU0K@cEj $e恸Gֺ =һ2^Nrgپޅbd8cm2!E,ώ"%:*A OfW_g R6r]\5WuY}9~_>_[&9@7*ntm+Tw9L4|b~rH;Lz]84pz);elG|XR0FZ6V=Ϟ8rcomO|)BZ4hFɔ:[xQI[mU^ *I3 1퉪3ܶG:v}d\ޝݘxK@@ X+h^AQ4*~Ͳ6%v󸡡v.UD  [dP40&A ff~wiu"UvoË˭bde hjDeZ+-g.$ ;?yp?KlHDp@}H;81BL oęxD1B:Ĕ'<# " xBD%/|<0⡁!@PBFh>ʣr:8ɠ*i)R֬: Wl;jhd@1w*oEDjaFtYy1R)+NQigx.qշug?>.AD#s8;m,nӅkWaMq= qD.`ۂN Qr6 U0hD>0&p#\bEāQdB`C4P28Vp,O(f/\YF(T6BE+Ҧd‘p.7%Ҩ̀Y"@qHnXfJL^G>65 ESljRzIEKwX,`[CAVeJN;Ae jM3: oZh|/_]|{ _z1}-apW׀v6w#q+2 AJ} Hf(=!q 1ʘf ?8[HkP!@A Q`}ADyR)#@WQAc(((HPC$: BJ Uɶ\*JҠ_[߆?%OˁF`JDeM=y OF:B#}7=(JQhI tf5Lޓ=M 4 򠩊SX GR$Q!׈ &L1<  b4%1Tlc 5AaJcJL0K(Y< VD.JA'U=fl˹R)C)als^~WuɸA!c-e& v0elɹg*ね;wNzV+W3 A(EQ">G2b^J'lP!ɛTFc 5%P_EHrD:BRQ4xHħ$GI(FJȍ Hr$9a ` [_@pLjǡϑB0ϲ gA}#h$asIB/^ܷB`,A+3 ʨH< (*x!RwPL$[3~(ơ8D④W?1G U$$:$KO4U>TɗrRq%ɚ.R/؁8OBKz>8,a?¨X#vG^BFi MZ.nw<`,V,UNUs͸NZ!xdcc%Uz e2PJ;''S)s@O!eJoň+Ȍ5@\Z "*I¥@)aG13:H2 XF_yQ8{IGBN}}џcOHA1A(y.W7{Jp3W&Zv3KkMH{*D)VU)㑄b T`#kF1&SႜJ*TwՈ?DIXB. i<X*g<?$(ݽ#(F= [@\%os6giM)2[{zZgW\ L W|O`a NmS-eb v¹j+\; N&* e!5 8q}{k3u~"Gmb[ 8nw _ʛ!uߍa@#ݦ!A 2G=S] wmޔ;G8g!<!G *B,'U_ yF]v2~kM5FOa;w'p@ۍ$s6}v8M4%{)>A|jMh݂ M)tS2|zPm^Hj#0Bw<5 %wM醘Ht~"w2ftӗ$yM~ `=B mv쬹; e;] f` "۴#yFtv ec�ώӆ̶(lZSЅNutyڪ `4|ɚ;kLalߜMBߖvw͹` ؘǍ/7K'=.'Xl6`ر.ihfQLnЎaY0xP#@kglzSϟvmy\4= sq`elCYmb5S,`uc3|6rRKݜ["! "(Tk^a(pF c۲;&&-wgD.hcar.#*:~c(#UgQ,FȮ PSmk bdy.cw!ۢH"7UO{ֽ:kΎaA40P+G(+FZE9$GZl$.9bb`ܲ"7jL4bh](Hk; ծ)v̡܋(ΏGk+]tB3&6۽-0'mR+JY_3:Y (CÜncbF"e  pe `)[-&tJ5攍>5_&( Arq4aNB*ʯNS׀⧘&T@s*,ϬƗ%s'b^1($0p]W7jb@)Vb sp&oS^ S㬇uvX2&r=c3q1oJ_(cP=XOMf*$+5n'NǼns!eW86 ~9_lԂn=c7@7k2 f * gU^Yuv ]"T\g!A QNTe * ꦡ0cqIq_a .9_"BfwadG3J 1=+T;a&Wp [*:QN$ںT1i؁E?rY;ǜ ,%!nҝ8beW-,E*V/Tyyq`ݧGƛ2zeH`pVqrhv /ۦ(GObv$1A)ys.PR?'Uv"R #Fl>1iLY A Glౠ`-Ɩ%͈U!4 ařu1 }5X񡳐&>4'.PAݓ ոob?*,78'nVxs1lY# 5q!$3,y੠6|/Ew8euW-c.$Vs%Eع PyLP Le,?_.Ovm!9OMOJ-N ZjF/XlS\Dkżۊ_!!WS`*ʇ2kg?if KZPggb5XQplS \aX5ƞ qP6)ET58搪PclrBAhD.u 6:פx^ba|j,'OT2@ ?YU&N$rd6eKr|T{PTTKeq/c uA%$ 0 !xLI/xLFWz+GEW \5"Uu7fV*{r+)xŷΘ[xT'[П=kes(Ŧ'fݟ P =f FyG4ąYal-[а nPEpU<*I.J=r'9fPL&WIrSfE蜗l츟}!ەʜx o\E8T̍l9| -'8~%Z)8STţ"fŤ6ڰNenS5لC3 jqM]Ҝ̄(]bJ@f*T\]PT~XK@m)$2.fb5XFhlćj ǵIēUpx ,s@/ -VX~J_ ;UQsJ,ΩD#dWiz&v!tL22WU> eE#d2@VcU2^~"fWP՛NfIdxEfŝ L$/'[8Ag }qzEh:5G7$QБdib.E`.BklBc9;d60H|kdQ/T";#.l5YJ08@ϝJ2TuuqrvEwmSAp6\NkTJ`X|n5Rn=?h@Ej?WύɦGp  @ ` QPOzdkRK%/peqLn;$l>9L _i\0/,\׺PĊxVMmbtq6u\eK& og!vQE(e~/Z>8sƺq2 +:= 2"G_׋pPEO9\A]M,8&xVd|}X.X7ܰZUkapsq-BZQY*q.PhZdFJ B`'z\jćʽ6*o{s?kc#<Ä@!S .m&@5 G''%rdhS4:VG G YNvV]Jv0S0Q%cRb4jo2mdǜaX183֯U3,fP8~v0?')BsTd娂[ʺ` Z4( [34. UT g'2[*!*њYU'_\|-ģ͵VuX3*rt1 IljǛAX&LR,I@uW r*4 BWLœH`T,PAupu*/qJ*6 P;'7, +&uO;f`LCj_3|Eg_8zkm ۷e[GH3hwֲ>{`mtq+;B>11BfJ'Z($qY4I)''9߬jdw1 u[ {I}S˜i]E+軗)KcvNf2ްS,8#k@G] K Y]strd+C<`Ɖ ,P73k^c^UnAzƸ~"G5 "+  j6W}[J@DCbvDAhP€D|ѺOv#CUfQ_ว vKWn&?*\k"MA.`%W*touf9e#` Jpf~+VgÓ^&d.K0kMZ ѐ~Gx%Tpr8. :_1y1GÕ|błlaMU}`NP-urB\Űw'Q>8`sߐEYlz@>hIkjZVFH0l[z={~bgs5iTJ2^d (|:yy;jq?-7à yPjLID* #֘uZmq2;B庠0IQ=EwFQKKw.t6L͐j`JOXhV=utXCKPetPӝtĚ9#4Ȳ&L~VL"`c>5( Z njF'1'@.aBPw 9NI ]D@.&D` Rd",Hq$+ǖFyZ:܇\6S?_z GcһbIʠtE҃;3B˾g@UnDP FGW˚O`_ "P"hݸ#mܜV?9FJal 4B9;i6-O 6ĿrK<\Z%oEAoy }zH(j^+.XЦ~ ݰr3^ $ TrcL?w{!.O*m]0WsǾ,!u Kfzs_2 pwVb| 2kl_zShX,u veY*ھf uOWqgFj !G$$[5籶;_L2~O|;?znQD9d5HA xo>q V9Y+ԥ"f(A]|nyZ3`xGF>qُs).$tu=LjD'BmlͲ㽗Q*36SvD-,<Ϲi raE؄9G>'CÄ*<(.=lѿ@ÉAcO<`J Sar)OCvŬnLYK=UgSR$>Xj_<4Iѳ9[ҍo*XI6^q<:<IM,ǒ ނ0)[@V9'(rBIXEU6Z V**(k t?dΊ}ZeE3Ke?vR &SP C<{.,:mv ۺ@&&siiK|w}ܹO]_}b s <.0ݹuʐ3;7}&)'_7އ؆&2Mm mj1?)l$;Wh:(MIܫbΩ A9 tdFe&XևBMzXZSKYtH}u$b.IS?%sUcfޱJՇj*TH$aP+!vrfS1٣(]I`::W5F[/f]hمⰬ\^/2dht%m? H)%GKMۏm=!a^J0Lhͻ Ok984q,}QpeKjU|XX+IȕhFKjwҝPYۡS3 ͪ 9$r -n"h,y= 12mKd1*K7uFV"J*TziBV (I%!FŲYqw:*q|A`漑|R.*9LsJ;Qĥ =[AwP!+T ']gVV)N"IʬdK) NʗTQa{9;E"f$(~EJ ʟ].Sj HA +AƫQ O)6@QKdgj$2,H,"8)uTB)Y7Ilɤ{x$`]0S.MEWoCƻhQ%I$ML%{r,lDE6%}n9L] l-gbak erN%uѶDfl ~mimn_p DTFW:dvKDj_ӦO6'\Cv8$Y)$Dd&sj'`4Z sg[e'M\qNERsiVlYɨ x-:e"n}FL*v(;%92]t!1T<5¢)z_tm`GyɡJvOzDcfh ƅ[/(ioEFc=zSqB:EFY( \ԺF͙Aa4ZJL9>@H> z<U }fZ;iɊ_Q,/7͡OϹ? v. {*HzIҘ{N%FX&W@o86_͟A Zsxoe`2N-dx(hq޹s~:w][޽vǗwd 4cp5F&@dY\'ȧ5r^BpaX qĶRԐ'%c&OK8е* DHq9bADN'Y7`J: 5-7LcwH.@N3VX z@ N~I\W(Ufb´Dg]Աst*2 $,(5J,G٦#e`q5 QSE^] G |Ux/>??nݿჟ&Z5ge3qjBMbBhO7,k+m**5k.\1;;%5*΁aS67{QłSl*+) |P Sp=zT(v'+.͠{jҬ='$ e]A`UJl LKI4]0tt~rкFUv"tA'! Ya/u(C"J2+X5 =p)JفQQ |w ;j( emefm>Kb1O YDwg ABTq,w &·v hiiiH h"EH`3acgָmhHj7!׸!lBoz/&@KTNꇉ(&4l7kvmc1lG-A B?4r,|"aT RGj('Ԅ`LnmVc`?ob3{ss s~ӅIBsyqo}.Lp :K_ גf][M:?S=@=T=IѦK\.x#~o Eox؍_K A$-agt 8\otEs|R-!4 5aZ?W]67(a~w/~`9iJ!]HL=#"݅K<<=;7_|ջݵ sz';-E e6٬LXs*XS *h4MNi=Ư˵My&%Bsm\᡻ѡ]xaNXf2T;GogCS"ІT=.}U[腹}OxnǾၛQ>;_=I,PgaJ  o?ͯh}:FHUzاo~J {G=n;NhĔw8V(h48z+S \r_v]Z9fA \:`r Spmv}˻_}'rwg|DK|?v[}BJ?0WlŃ$i6Z2 -!a%Ndi;!ȩ[$[4(t1iʩ=ڋvq윋5ubj@7b XupmW=%y濝~J;o֎n=;[[ݳLF7>YS(A0"$摠7רfBݍi4t6uPhY@i;ޠ7$/BD!8:u;g]yҜ=Kf֥ӹF^M#HҾXæܵ؟_^\N?o0L":,Gъra#X< ̓gY[^dp흺ky{N`.n;P:WҚ3{Nw&`,ϓP@BH.ba !TSΠI'{[™'GRj8 cɜIffWA.-$5atL]&shKn# BB3[Zq7k@jh]0r"1^qts|rR?섰_曧ҝ5s%4 3Z #<71Ts!/7fƸiЧ>B]M=Som F3s ʹ]afexؘ!$<Pm"J{1AVJZp}\0#;I#;B\vӵ{e8&ߦ h<5M i'3$:};mNLalA $IQhyܩ[8tz+l7rK;2ߑ#oy8T'曾Pvkl//k"ZJ*']wR6bTTiL[a(צNS/c+6Rxt]c(紇ǎNmoiN |۬iǥ\8ldzM[.±gTv0iďgyB܍[6d]"Uq2w/qRl7{&ЎX^0~Rfu7J>sOu^o ݒN1^ɘj:o )Q;J,ۏ5)]C94j"0jhj}aBu4s#b%xgQ*mm23ݴ ٨hu]Y~|xRS* xÑ驰sHh%|GP%ft3_tπqbӧSg2>S5;bY,4pd'07ӰqnƉ]L3ooشTw/:`pۉ[fJ]7EE`I1K2T`%t?R?ө[Jep8NM>A[Җ.= 0uQVf(|l!U6͆ iAhA "8 4'Ri 㘋fA5AsZCYFmL/obF9F( 䢃Oe8:] *bnfp#vEBl_ݽB2}dhSGA =>Ʒyp(d.m>_%V G/zo r˴H4Wֵ6}>U*O{)T8)%,KԦ;vF `b6t"'cb vlU] qTgUqf9 U`${jmF\ j=TضcWb٢KfM=z1A T>\}1y#w;u߼馿xjU?]wEw`Ke!+a.!Rj|"UhCh^{)XL݌C/5"@ѭ#3 ?nS ˯+Tyʚ&)`H)pvFhzIى5LD4.tȼ*E ]8A TA5پ~u@В P茔AR1%eB7DrD/B *GȧGk50G s&eqڂV8njpPb{X\Lte 65!t /q1~o knBxCě%т|YK=9m{-DYav9b"0lc<2P0!41;>lS_ C 44 kǍJ#̰^l> bHvzE_:…*G0cf0@ 'm A~C_p"T0pЙ3DG\P&!Qn3!!t5KQ5N9btfcDO'[RPYxBpm嘥MT<74n$rwbz/|…/40c #Z_N#l´JaN_M[ujP΃s#XSq&+5H\Q z#vV7]ĀH3J0jX~?bX3<.% 9EzÞ:ˮ'I P]EkGnayq09-O fٻRmHI"RY@VRQM0i-_x:iİ1HkFGBh^#IiLc{6m?FAw8]Nl[zJ1RΡm~t5ș %j0h&ʸMD v(r}oCh=v\vM< ӈ M^RS ]-mNX:ɭ4z1n'afASqkkuljeE(xꍏKf"^X=pkgٻ=c8h3*4.ofo\! Ge]0GVW#F5P[JC #vumM|km+0oDtTX#CigLCYd[U07yt9jr n:f j1& DOWRdz{&v!!lܽw~o<|?9 1M:NX*=޼ՐXBi,szNvnő7w8/f E-ZE-_MˬU)-= ¬!jO- z̵ij&X@ xDfWm1y_?Y+l'왮bЍ#g,uX&'֓;laYVRԪYW$f$`r=ڵai0viFh0HжӮ5]Ћ1 u{0Zv0*ytYbe5A6_x/wKf7-A8ts^f;"p3&Cbln.{wt7|}3)wm|@?/M<>6 7Fë+GN-B?Hqmڿ18tǛm)`6L8qQqڡ_s_zumX ?z8``h>SYJBzHtuv~e= w-aGܮ)O9v&jR*Ex~:O}?>bn`yKЌ]7Gncӎ_iT>)9ǙEdQDQZ4TX,6G>fN t+-` X7_75?o}?7y!, q?/~uٿZ^s>Sw/0?m&- ѿG㊏x>ޮ%_ɚT4׶ ?;a;W_WZ7tW`$GS&mV>h*qtd ;9>}qtQaק-zۍJmxMTZsp)&>q?wʷ>6Z?[ub#?z۱=r?]+\,6/$\/1,Uc4ǚw(8L =w\?xƛo0S⎗/ݻ0so\/,[?/|3o?1^~OxO@o8[AN0$>tlOxTӟ, ^wloQfhYR*0Ot oܸ+B~}E(>x}/`YzDnt=Aq} szz ]ϐ tIGz ?|UwVpWT=G*DFitܽCD( kmg'mvdZKߺt6 1| Dв#ۣӜNvozV՛b N b}ڮq?MV zkOѻOUh恻pK5KA#%=hIyKej)߹O~S"C q~9oW#6̝Z ssٽ{|_8@}qv>'kZ7[, MD]M{ox[>{'ۉ1^+c63B[bz/mǒ)'|,Mg?{FL{؟^KN;~ln51M*yI3XQ:w@a#T϶LO*CZؓ'1Ej yfRR=( !`anqc~W ˼\ %[Wi{vwxL˳?3w;ki \zKwƫO}ǛcRfxCݫhBe" +w]xN's~}oЗai_[ff=$PGq"M&"4K7z` fn/?]'e4 {b#p>3 1ƹf x>'o Mh";Wc53TH` g jSi .AG(2|ͧ?=$$*H&s_ڹ﮻nO9j%TJVR5}~h9v^g]`Z"B/X\Ϳ.] [I-.A#~>MzXjGb~v/lr?S7#_D) tj&% +/XYIF~nI5xV$:d7jjC1Ʀu/7>zkv K>McDa\c|ꁓ7B3iP R"v'Fow) e R΢Mrݓ>`dSjb/{M뷿l70Ue;^{.TM_}L|k^MaɊP|a.U|}˷̧>9V^}G=^A|!Kw~h l3@kB4,Y06chfe+⤫??_8w7,L,&͡3ӠCX=AVAkp (ڒ<] n,t> ӕgw|M#?{}KP^3:^ 7^p'Éq|m-A3CEB88Ō1F)!Խ eU;&ͥɲ,ɒ,al&@Bt$& !ѝugu$t@1ec![KKRJ5{{Zks{U*!u֭{= Pv (-˼ % 7Z7}ͩ"~{M pU4ȭ@.)Q2ԓ͛:|Dxw±w #:%Dn9kW+3g?~7z?|vk綣G&%&K!ZR`r)'L*Rd"\=0{%ӤlLqCᆵg?swOR?gx3/01b)eLOy5k#)f/: "`1 Ǩ$O!!؅uConzicWNŏg?m)T5 [ʽz.\y nl 8^:ߺPU EP n2Q 7 ~_O~&Cqn|{xD$ĔD:n'Qn1>0Z_j\)"-o\Cζ/owꫫj?koFՓos}:Ęk7~t7ㆍNoXw?g|!4T*͔b7R;DW2T_`) Bn%A*k0`DglyOybTM]5E I!l:` {Ϝ~:ϟ;uOQ=4! *3#4IZiE=ƑUXV,e!CXYX9eAWCs}&]t耫s9Um}Ӿ95BPKɯHQt~Ho10d DǚQ}ou1ّz*Q'>(60)CCNwQE˾&kŠXfILwM wev\f ;KZtSa랄c&rɨQ>U+%2 1YUh'j-z1e %&cF63EvB (p`sHM4}?5u9:]4o/_g&YN!ԏ +E\o cY0ӈ(N^D1;hev&w#{@M(Qw'cj..bUWa"C;IWΈHnyF"1@-adpDD;;a^xK`uf{L:R7Q5_0̗eI^hAcȶ8 5)/JFe"y C /0kGzTA/+09E?Ƙt_Jy$3A . {AXdR3"y^4~ca=MLAXΆ)whJ+X.2#!Yv4χRI*EDxQR4b(OgZ7XV 1!H x"wwGk୏ѷ>G?4º1du1?[sxj\%|.!,[X^Iw"*ҰS2{NDt_IeT%҉W`z#{e̩+ .$4S6;+l)DSG+ʸP P]W5c^m_,Lτrm !O' ƒtÏ9FQ=PKe|D7@\p_^FpɧoCՄjX^g3|5r`7AE^{(!1zPIT(96}gVsm5'bOgƁk1̌ )eJk|` ## D-\*Nɠ[;/]^lWxs?m_~wV)rLZcŋr7qg|ni-JQtX, ,K^J@hw3<^Ag!DsqKV-$ό[nR~9m;Cҋk_-=~P6>kڞ&ˬS '(aF gP=/z|mҩLa  >0&D'P큙,Hvqe=}\lUM!)lSηCDQ+kδ8+7DAHY({8ZT4jW?)n8a iGj*ɂe#縉HypM%bsc]f mE<|!-N 0'Y5X|W9 _-zybzx=h44>^i$%W?2qx3DYB9kB481l +ܸ\)GhA ErVsj*ljOH[FE}'h#1Ϡ'Z$ pHX}=lDUDa_ؠᅊ˄Un5vy,"Omޕ_- ǻt}eY',gRADY! Չ |W F.̎EU݈A#*|e(7mO'95B٦h0ùf3 e˔ &›ɩ##p(V^*̾يQfzx`UG@݇ri`> `lQ 93/M:*LP|QAf)9Kf ,UbH/m֠YP2wGMD)?(Yq+A2OA(eq*&[~ <` [ {fL$R&wWTm0<4̬CZݕd'#f1K^ &J9E;3yݵ}c^|tߚ WY0k@2pu6%VeApFzءfH:ؓmCct-t0dzh5aٔxpiRt[M`1Ja={aݥry8T5c5'qت&Bc 5ٺ2Qr*|xZɯdήLl[{Y/+% P3'PJl2(#PlHg(3)1W#'G&C(G?=A sHKtҰ?\ՉW#݇|b)S"~:hᕕv_Fj )&} bDvا,D4Q)oӏc!qk빳'pqicdd  #5Iw)&Dcxyݲ}|?;c.Li@KVF>}.m+^qZ:=A cqᨗA1 Q+\cu\dERFq#XQ멖4}h)ˈo5⤂BBfE=};7}olIHK+͘CzrT^IJh`Ȉ%$:+樳eG25)ZD%pH|zhq!WF2|Xt9qϰhoH3ȭ?V9uF,f @#Б Z䖊d(J2IXObL QaMM]TR(T[ĊStEhi,r=+KJcGڝT0ي02hyG塁8h|#oDGܳhveD).(b4T;Ɩ*Z4`@qGՄ@)$)T2+X!e%eԕ&T) jW -s%}Zppy%2PM`@O{b)q˰-0(` !M#O1yG̀E&Jf 08YckҭjYB(bZ(\xG@lخ.bVC5-s5\Ea嗪sе#%_ߜ(B XXPYD͛XTJ)LpLqʹ[xhx<~Y8qbTOd|5w܊_*JWU&]6̲`E,c)3E=l\zrd'cRerP_T[/?&ZG|A!|bm55sj2Å8x2'zaS,ڝWf5A>X2!ּX RKV~jsKJYp aBဂן9)3TM6Vs œr=o >H?褏qrRt};49Ə}`ѹь(밄v52 D3 p*wLV!Y$1E l1&J!}:@6"Ϛ42dtJkKP@X-H(.T4zϛ٥K'Nܵ[;> +U[Uh+ @"kF.5Y!YR5AN)7uHnx$)Ü`߱vb.4p DEVП,"ԣIOǫKKDY/`[ҒR&VWWX~dBCz@k ˵އcxHr@X~4 |Y I+$hAH r}AN&ȂL^1TC5c/u;8 V0W!))n{[x: mBr[ HBgp}pL3J}xnRar=2J/LJtp+w@$qm' خ:0k\<]s*=LK3WV9&fP=ЅZ>~s2[;drPUץ{8CA﫸=1L03egX%aH26F) 1b 6b,W,JOx>D"Chߴ|>/pGnWV&U5B0mwK/=wEhhZՓgxDKx9RA LXDXJaIC) ,CeyaQϊ_|B6Q. EqaS3a.K,{0 (Xn/:TsOLtOΪbӁ>@ X19L3}tMWsh{5A<<{cHdȏ壣J{,}/yAjZb;@cld3F*Ra1uX:FlɌj̺3 ,w9H5#nUNݤHET3e3tEU&{wȷ[R+K7((Wp+lq;4RV)a*5|P+q^l½#t)K2dȒGιѨ^[[ Mw[w/| v=kk\mz}}sZ29KV;5ҕb WˈC0€11D4Ja>(=e`ϕ*:ҭ"fO sH\c(ѸhoLR1٢L:\Ҏ؜`i[9>k=^1ZiPXW׏Y*iu)& U.1)@/VOCYZf8 0سKQQ G!V ScP6 E)֕"^U7e*8_#JD>b %;#b8=ǵK;*3"a^\4[+T[ Ў LO0 !,aZEaH1A`!}VLs#D|9dVM$a3(dYʪ2}xUZw0%Ξn!cu$ӱo,˒Vzz"?eM97cEfe޻A4rܕեsDVʋ9noshk4yh`>bq<6G9J.w>\T8>MLήX aF@8@ŔkL^0, bZy4" zvSG*1F1:ДFMFr@idQ9C1~)YT5_̸r{yB4{댤0=}*u(:0Jbޣ^]Ҥ/mR55 Yx W V&\gdJ4Q,EeH" Шd< 1mȢf>gk ݐvlω] E(mF-VSQEE1crr";A˩2MkDSmP,=յ0SY0"6[-Vj2L)%,8;IDATf]n*gϟB%>](Y sY2R0E,fDh8թ港=':}@ 3.I/$cؘCm6áJE(=̂tw`jH9-ΏRYGMY4I{Q+!n[}2q@A#x IAWq%W\%P6@ȥrXZĥ~Vh1) H\CzA#WzkG vl9t2ÌXW)?;,Rk!wv xN,U(G2]rϋs+"˪.𬐔gQƊ,VX 6\^䀴 PrOWgUgӰ>Xj JEt WCU$,zf:TB)kry+1M|]ˠGm#W$<[/<@BS릝_8#:+J!fVSK5Bs%jTf2o_9I@=yñpO2t:3ۥ_,S7Rv\ ׌5]]r<\DXzD97Y,a )/g͓1[^pbq 2RKLf[3+k{xAgtz4zDcsj"Y a_!#:ӤSuyiO BHQJT)/1c.F9ȨeIh^=P #dR aȆQOwC BA:yY-St^[bqZF,_St##?rꆿvyKI85iCDRlp9. ؟>cѦ }[>F~~OyxcрvAL1ck&UZec J X,P=)uoPK }f _,/<#t0ɣ@Mʂ'QbD DAwHWtŊYj|4-LN|xڈPκ& aysCQ:q:*97s.,aCIXK!9(ڵ9v4R!Lx [Jd ϊZQkE騊dy0c(r}h%Il(# (5`]jڑnDB Awϩ^<*s '}0w쭖,|ϏAqf \0o*oCXk_ߎ,fq7u:xX M8+}H\tђAU!ue),=F ʸދEL]%APUλ~P\ dr j 7:B?, ]{/7pHÁo! @D<)c~Q6rg5&LsLV[MuM{#zkN,E(87D=}嗺“Lck३5Q\M ]yFX={{/i1ْ@8[0q81rh8ȓ0Nd}0xA`2PҟY̡ P5:y:u7Tq8?Ʃk==tY,F/W>*h-\nU!KUabŬ8 1,5Q >z0_JQ#5Y-Lбh$&@r\\t"Cak$j&WQs|qՁqrɠw n@uCg <_RֲZOggOVS1dE^mԵ@;_j$2N!4&s F<{Ks a` nW?+=0xO\X(/큶xD92vR~E!,Bx,ɹȽ\I ?%BpC(, o'? FM-?h#Ծq.=6ƿ fٺqpt9m`m<t@@Y l~bч}٪%mKAdR:)@Saj| ș2"eyiS6zwM!e"\9VKc VBmىAPKq4nxjLܩ:&N``胨fE1ʀ,!-4[dhPs\%_>GX ]y98I\h3jik{@%-5R|pxE4cRwhD?aʃ&.د fXpAg s.e_ٚv?z\YQرo;P0Ժ!/;[}7mVa5ep0lYҵko'pJY (9r Ϛo@T:w2eyLCZI+Z4J׈^8#y)i)=E ~{gQ^iuV&p<0ڟ pFBv^)\ZQߐT&)CF`XYhvD*kP!|au0fZ@RbJpQR*PP$]>]=>T|^ipv++GC:N*=<KJ%Qڰ&{y=L ,vkOA*66 uXчm۵]p rH3̦D[ۡb)=Gע4ԁD3(YLPILx?){ɶye P,*h 8n^Td^Fcċ;,&-A3S U<y~FvtL#E_=}5ЅH43*qpS1R`gg L쿈IwҪ8҈z#592 iT P r $J6~68%*-k^#Z)˲tƄ1S왴X1'%`LcsmJz?YК/<~,v#T) M{z\?sm}EJɪn~ Xs:H.\>I+95T rg\yLРZ*k1K]&ŊO|tXGSyplb;pگ۽ =FV"dz(z@*,^6@a~ hV~Zj7K,t6{fM]]]aÂ~n6ỳҥ}stp^,#VoVԶU;62XqtM'~ӳiw]!gm7Ufd^4jK^aO=l{)Z>m,8h+8bWB0h@%~ @d{ /^uC)g(o"Q dGvh{+Ͼ=Ք{zk|MGXuM[Ӹcuy;Y姗H2tGsPG`Ҽb(l()j&1%?9_vvPS0-Vy^b Zf=m϶4p#HA^]I\YĐ,R] 0/l\qY(JfΪc~{>dVj 9DƀKTS R:TXp,VF]ǎ}6qզ[qMeC|pm3?jn&-|~o܆jy#fu1=õ =W+,X}q.97_P #`V˿S` Yрx~nG,%'$8%}*Md cJ0Q^ x|0Cxa_R8% j,!bEpO[p?f(r,s5g *8h=J~ T1%. ]Kܻ-6468pj 2 KPc,{ַr]0P`2+Jj,W ,8"(ؕEoVuͣDĜϤ{qF4ZrU*3t#dվ(5%3QWQR)w;b6kբvĴΒAvюmEw_ 7h&\I?XDGsMܯyܻykXy\QmKtF;L1D%Q1Gڻ.*~57=݌Qk֕W5\]KT d2`e0SŨɖJK8ÑHEILP ,D3?74vtk+h vk aFCgox+n[fV(TB?^glAPXp|G"Yp [^v#퍧|hmp-.]JPZ `:BXnI ?i`*\DkRkUkɺfj.$XI0_.ư$M}M22ma%aɔFg;Pp*s@Uzí{knQ۰QǮ[9U8ҫ{hc5 n7p;};q6ͳxN}SڇՓY4r?~؇Oy46'~sy-6o_#=ͼ5]_|j}ꭷ]ଆ*JVkZ.fC6ug\f,cGbnrnSH'Oaљ٘:E v]]yM,yjw绗\E?T0n=/=wK nw[e6$ဿJH.EL_b3T{p Ykc9 4# Bmucph;}z~s:UdJd~]l`i!V8Y:șeגaacChlb/lCMag@tlڎ*POEoH˽f0Ft _oЎ[7?cݨ׭W׭Tm*i| x޺.T~7CSxN*Y>1<0{z6`= ajKvIަ_] ] l^{_47]3[J{ˎzTԭۜɗ~u1`jFXf*!O2/ PEQV) R7<(T[iGW7,F&8;R@l1B<\iň\xʙش+.ē~p?ɧ^e<:\aP+Rsj{K4M|zO_+:EUh[{r\hZ8 ;@C.'ʹ%R=GچzN CJeĢRR`016`}k ~N;oPw 3ǀgmKo_=9jwa]"-X!<[e2ZqY Yg"˯Д 9׫# iQi8  G+C⪖.LZXz wS_~ ]e_|lhtD|ոSx [X[#F-T`[Ͻ3ݳ AL)7?[=t )096.*7|rDCcUFLGUHy) `mN!c|15b;鐽zBȑw৶3Ouy rybVz ۟nFCqE$z=\UAU3V吇 zV{vYkYCCU:|EEEPcC'N=͵cv*mRЭ3nܟy+/sdi00|K_pnoetgR=z20vՋLj#G?5r7t8 Tub X2II2<^(n=@Au)[xsGlfǝa}f}J5Zvp N ]M`a޸j6RꀽY;3;v[<9.'޼UG)Fv&5_"n`ASUޙSh+4jQu#^|3[w] 2met{} l;h-->ӽn`ylHw R`R*_l83_EPk{[_ZųLDaޱVUHkz) o ^N c1$.Jò#5kV?eEIJ_3ݪvѹOU{ $3jF0';7TLV: d ^ZJ$ fz(T\x #3F.ܕW=F_a:xC7|DK x20g unKV0חNodG΄q6v\ #NS/8V/[ ^܃"-UIά`cV*pI1r2%-\cgR-yKpn}wWZp!]$cS>i;I$ljG(bC$#uDvNO8đ5W8Vb|ZD0o5z@Wp 7|OeF5nZԶr)v&Z1!; l>~H +US?vBOv֋8Tq6|ۯ=%3\ Ŭale\tkP,2].@ Dޮҝ>J O6Qv6p}hrnZ(8|KWyDSy޸v0դ%X}束}wvB!f]5X!_d:P45ȒWR8nNCO `i66UuZs Dkk|ʙQ$=@z X?X:2MmBNų[TvB0Pv*c=m5 T oSb*\&5W^Ch4):`X= o[u-!5 [coiޠAoQr8l Z5>EyǗ9Йn3GNfФ4:H&O nݨn[Xąؑfk#q1[MsS4#{N!tMY.Vpwh>r~bu=_{lb!g ,; bKg'LeLvX!Y)CY7 XxhՋ0M.6+7 ]{6~YfY0  w&`rP܌}ʟxݳGP&"^اɗ™gw &fEQ$aZϪzgB\}}rbeän7&~́=۴vuzfc]n^ߴ865,Y[Z K/ eljc6Ƶ"^ݥYQmgVm|ɇN7~[l !+)PLi 2#'BNݴ ӯ˕YԸc05/8q^/^;(Y4h,FE(&w!6^hGol/ښ[юW㶺NM P DY1sk&-N.e,l`2J'ceE`pu2sAWZzb4Vm9z;~EV-~a:= ݸV8cD"n6kgkG|nrO_ ?^z2u U<~G "F _@}|No4 Ͼ3֧z8!!ccgO?NluLJA_j:yR4Х|c}h8 {Ǿm铓+kݨf{wMoX!"Whqq푿?};{Wݹ_3^g1Qɏ뵧nCB8X?q 2edPu8%&t[/??~9'Fz4~VڑKl^weҙƮ^i:q*M.oп{c{du~=7y®Ǻ(X;kXvnW?t^}ko`aEե]C-x|R~#{o<isio  `ae:vPY{JnaZsGo>«bDk`f+]u6cvx? ttN8Ra \:whxCƭWk95!=sypveUUL(Ye9csceYv/,aY]]q/b=.#8[8ʶ$Ke%kFϜޯsF{FtWWWS/YQ>⹨jwޥܠnb/_XW!`FH~Æ閈t-ӥ8ӣ~xjCg^4:\|nٛn"D `j𦇃CuYEW9"Ⱦ!* FTK~w]B^ĈH(iUOX~Y\+;9=\q2GfV@hB {Y- 5֬*5| Vg,( IBusթ2Dz x8/ㅣU:Ұ%o2!*`k(0r| [n6jPph:Cb@% 7DJ[ | ]]⶛oi֭W}s*Yk %o仯?}b] V!(rNC nиIڟ<Loxt0ruD"|o2HH^?@bgԝ۰rʽo8}낱>oJk)PH|u>υByrh_ 8*d4[2g<%e0Lo2qbyI1UþO*4-Lxt%4=aQ-*pK`q`H5_ұ%mvdd$H%al\tpX#Sʈx<21ċ,,qonʪ*2љ2k̍6E>DWH&%`ъ'\x"}5a/J@s h㋱iW֨jH +b pV $2\\oDDIb87 \(Jݝ ַ:񐫳o_r9ԇ܂G)3Y:xbۉ* \A@@Qh,$B~4(;>őDmh RSd*)EKŋgu mrr3C.~YXrՅkk :+l`xL]l;ƓD2:1JG_qūsݺu7/}_Ww%QӍp|/4~ƲMp UZVc깁57=:̹q ߿ҷ9t7" 39krd%ҡ1;Qk CÕeAđ·} PT}Lo TTyhЀ~kYV%ewk2L)#fd;ށ6RY+f (NdlgPaIc*ifNwOjq)x `#q ))8)HVrFk$@jcOC"THv4"eYX{|Q2Y׺) ЦgPP2q)%ⸯN,`"٨JE JV*) ՃϳV8/{ǰ[ \ n^S:aaj6Jzu}.>..H5?*Aʢ:dD q/ٟa]3*9%#4CuȜjc ш8'qV%EG`BٖzHRx 7kؽ{>q<ġJ}%J'{=/yZׇG(9 'g\*9Yi(8ʗ^όܽZgkkc+MEQP5? PG/Ũt\^Z}ebٟu+ҥ8\UZaK˷# 4B&sBSGJ\ "ntȌP1YJJ$_ΣQ!Pr QcuZ+>Sa#Tk`=Hu`&:f~gBBTjgQD`3ִ+G܁%qh@#4k/d[RO.ny4/&ϪW ek)(}NJZp$!gmu}#PJnZV|#Ͱ㠞~b&Qv><EQR).U=M17iјSѬ6.1[3u9R(.A0ɝo<ی>s1?y;zBbg3t`96Hienfd? t`bDZôsMEE9~PDz抋Jh!m=~¤H3 uL(QjA\ZUPCJl II1)3Jv "?dYMWo*C.3B&pYS&&k%)t;>g"7RU]PV.0VBˮSUb jhYw/ 5?<]D+z#|+6{8eu뿐_'f Ty:qdi1!݈#`dFIVk""1 QB*ͯKMwkM7o+X2p6cN o^EX~nӻ)q%GrE^oQ"#2݄Ƌ``h8M\+v8?cs9cX*j:{"ue B)|( 8 @EwC]'MI9|sðq.M\[v& x+bA,F#JFRq˩4ȁIqZ4}κ =Lt2I@KIJ]+j !UЀ͍ &MXU>j`6gףaL*}3;738qweN-uM[4̮\5ߴKLDB>\dMvJ炀l!t|{Z@=UOTVem vT7!T -N9['vf֠[ٿB߽bS7~{'7^[Фўh3}K,uax #h1;G<곩V-fZ3ӿNoEklq0܉UȕP{}4y[cQXF 8HPQ(ѯ,dPe2I W)ٲaG)~IՈK<[OJF8fe!DSGC˧w)PU6R7>+`A.WZ@F|r\O]uEF/֑]G,I>hh@\ cTEWX\@F$l' 3mf0zTrdY&mc$\XY9 P.)!Fxh;:6ҵ@)фԆ&X%6gip ;j3rXzlea>L!AZv d!.ڄH]VFPNc27n{Q8==}|jn|D%!&el}c~z{wt ןv- ɾ*# 0 ea047*OШHW $?-'[N, GUYQZ O0" %Hc43 "n VT& ޷ۧB<=?p {fl69T.[k0 x@_.5P]DEVCZCˮw57tHՅJe2_]Xhik/|W^939!8OΊQgx|kG0/vv> Uʵrcãc7c;up.w̎櫛۔i9_H:SA(Е3ExǝD l./a($;ׯBÇcx )BaSI 钷xIr(IBKx4ku0c2IIēODeuP&@6BٌdChD:P),"MeCaWrڶg~0^\Ej_žNl⬝3}qvw^18/Grsgl^ ]+4o>/c2h*Ȣ3%X&j]fl!-*dhOxlm!-&YZܲƾߴ}s~,YPڡ%xŞKe?CȳwQ~admVu C'NQ]00W5>Vo^rc3TՒ:VV)Xslԯ\;N rqk1\zoJN:)6x47vh)VheС< 8cNII zLDW35vֲZJ`42YJOI'l8PۧĖ |zB?bA9=f{Հtr2&Dqw,uU:ҷ,9O^>@vHtjाe}/nϕYΦz`z2 1gywGR2hٯu*#/*׿{âux$HϞE 9k<-P]A=u3D 0Ԩ']KY%! .p@zLM#w:>6…WO055`1={0?Fkxe?^׏ =>L*SU(Tp\#<D1(~}904xg\2w*Ġ(,~у3 ߢ70V$Q!;f؂h1xd _YNO &}5M?.}_?=VWF; ٟ́xG$v$}21BiXJ5U*>씒Q=Gޭ"$gijL$qNJVw|p/:&H% ;J&n]r$cV=]7}s Je9Z-ѧ1p'vl/}gIB t3+_ ?Bp#OÅisϕWW.s]f7z(|E8N[>sqwx !\zIgQb 'eR*kETMꦨ$lHeL]%nxѡ)7Nӟ,-#dzpϬ("&}vk$9C#"[JB|{ S>1#޸Jt{InqmiiOFkx㓟/{9@D9c^+׺m۞`gˇV tu[VTBP5ErCw4LT*R jUU54fyιÜ&OnCRr2[jLС?_0usBpCWo !ڭ:+M$Ic{ G5U?j@HC {JG+S}: 1}"I۫`7d(IJjʆeHWM8ˊ}R^ey#(Lp,tV3VRoxfSpAإҺB =G$ɄBG "% 7 ͐,\J.g L6o{X(Et=p!D&c,\4p9ii#Y/c${WJc$T-(8c?_f1KZd *||!Ռ1Tq0N2GڵL-_eؓiryOjOdH}689YPA׾7pCsT liaJ!eW2p c=o}P`$fu[c~ߖF gemcQ Mc!U%KA3nf_& S|YkEmzq+jRTHlE4s2sC|wQ={6=,h]CZ%G^ &T.R. Wr2|UՔaiQFȼ懯h5~7ZKT(N49:Dg,„FpMxo?U[Q(3'?/1 #7r_}Z bJ\aآAت(0޵J|'^٬rY Smx_awr"g )([}7JRzb d !\ӨTcneǕPi][&BҵZ?q![8GgIGYWoĶjz%$N<ޖ5R L$KL;6T32ƹh"97 @9!ሚPv2,nQd0OIJ5[OCB㎓fuH@̬v$(B\OBӴv>P2W"O{AD_lebYh#ݰ O&" J*JX'cB.H$h\h8 'Wu5ʵv{Z/ ^l˪_܁Z?*Zbju~˯E)& ^?> jLVվ!QpQ +&W{X(;g9YVnOk1DѦ-J** 'HWJ4{BMI>D,r]Yg\eLJHdz@l/"%GAj+i|ag6{HTiigʅ׻\(%,Q]^Wj;MBfw*Ύ\_6e߶m}JYkevIz͵G=uiS1Sjv}RTK%2;ǒrUͷ693qooz'*uKO(o@ԾqGo3 ¹3gY=V0 C n1"Nlk6˞hIlg1I۾hl!hMB-1 fuH] A#< _bITs K~%l ׾#ѾO"ٚ^fJ]@9JBkZ ٘~*{JO(jHIj, {q0C n 2xQ%?D ߠ5RFNmxj!r1WW+q@w, HY5f:r횖.1X%?tqn:tabg^ֹS b/0ܣU#`z̪ƲqP_aa,ͻ&4P@PՏ4F Ooq$ȪB4߹o^V5GJvABc"?$ ?$dm !i7"鹑*5""ˬ^\L|[_~E?+P!{s:: V6~>H=JIkNSYyd V6Ȏ^$HY/9$m&eӭfV-\X8U7hP|Ԛ [ 1xXDӐĖZj/-xCEpZtNEHtA()}Nњd:B&%nbXHR.i+RuňpucƕR.)D3tc( ١˦<;R9Sɿg]5ՌG+S /} l (<Ѽg¿>ؚPb~U$ZE;{vyڌRUDDP{:1NKɎ*C,G^e8PWvdyUByвcJFNjCH a'ڜMiCYHlX"Ht#2ۛ(w\=՞lLHL3SH}HRJQIFi!4H tyB7 ]G55- I>ı9BsnuaPŶDKݜAW*`{(=3Rw<1M1O{Z GBq)柤]3h׫^TX Y2a/*Ԕ% 8`bg\> }c:juIqXck ؛v~KMTQ>gVQ*Sޯq36+VLj[RrN~ ]])`Z[}7/⮹Z9Q! M])(0aƁJ$!4lSr۠B&fh<Yn^$j|yuXb%PDJK-,1#h4>.vWI'!Cuʘk_vf;J-cV%d cO`H{d~Uf~gUgWnqIۼɕDg.:, q4q3rktOV qcX@OPtM޲s]_qy& HIf9Y%PNSlVԣҡn!ܨb[0;dJ`dIY-7orm0PZڹqȈW?rn[vǯ[qfQ rE9JkCg ]U&ֈ|4H(j˕ս5f}+3I "a–#fam}@&tNv Z9Emı@ iJ(@${dtߒlsJB-*-B겠AEtD"6 ɵ26SشG(*b Uf([w>>?~jEI̶=BKկ+ m]d#nyMFR4*xou4ifIݫY$ImH{EVjlZʭ{m<)۽E Z5ҫi?EJk^쁝/IlZ\H50~)DN9ȓ7=7UN,ɻ&_rtY)OUpEt(: s,s3Jb % Si*(k='ZB[Ueȟ?9vH$'$Yk `8`;Z%d3]NRO֪ҧpfvtd~$!xH(U& 4CXVd:bQ Ztu?ciQ)$5Oag%2mW1fV!H$SFbz~amn`M~pm<Gz0<07G%ƢnnTr5{B4H ?2S"̊hvx{Mќd#^}s?RNە\qwCCM/ۖ$JBw`NX5-f!Rg*%ν=~?G,zh`awi?]c8$\"NCoWEǯzo>rjNEՀEÿyXܰjL2K^sDFH*A-u-iIVXZ+P/hz' fI3,ug.3|&-E0ӕF2.*B`FxE BdHBg/xK;Ieeo%K]X4kaRR>'mzB4^aqGH;^-loB kV~ǧDaũ}R>ͳ%Ͻ;u~o?wghBsZ6HP(Dzk}B@ڊ0Uf2P>ăʮL٭)JJ:<**Z))Ŕ~,u !5yd9HH8MS 9,EX8L>m|+pX*yFLs 3=* #D0z! 1&RN1"LRd3I`6B:5{O>'~w~_ScG.Q]sa|՟ N#T77za&EN iְd Js+nMA =݇o%UٚrG=Pyc*oYHV-.l &Č$}ww3Վfȭ4H1YY!{Ow.Bsm8yD]$QRRqJ޲ J'~Vq~vǿL\zdգ_{7rrDlDZRDF~svWy4RO@@q@µ]Db Rj/BٿbAJylc?STDGi!6/HV^4C(:fo} }B5g٧-@ .]VC hZ ?ۗc̩6ԍ ivHPQIj8Jt#ueqCͮe77ZbOn:Ke'{W-j̮Η{o3Mj>St}II`V O"$P~3*%@au7_{K^gK ;߅s䆳4?!Iē+Q}n;g}hFH{"[,tvqIK_YTQ-`Ef{zvw}ϧZ= UF 9W^ך_l(k+BS}^i&PHlSHCviOtnE K;&`tCG(HFZS:(Pћ WJp1ElIl\ʹ9RAJ"3HFΘ#j9 V)ݿǒNfU$=?lMHJ.}zlOOaiWS; B]אPR TРZ^G3gPh2B=s$PFdG27݃O:/o{E#LafTȾhKD4;4"E%0)B/%{ e(Nb~Co)?阾xJ|i\yIP!;' 7$Rŗ$.WpoO,c{8ޛa^xLcEnJ[j3"*%]_N@˝M /]yڅY9}۞ّ}Zjڹ^k՟4xNsJ`YJiv_ C"TFPm/"'J,-!dP.j ~%cSJYDp *j–;GrTtZ+&Ҵi #="bs <dR2y䈹jǦ*6B9+P*B+$*.` %(h)B^w8rX{vOMC H;OtG<]QmQGI8bBJS`zrw]EZyr)w|3ߺO|~|_.N] ll "^7Rk/ȧ*' .ba}>j bKE GN)n1xg )k[{[~SPCZ"Or~9HjQR:q0@DzSuGZGnrm ϾpAt*-bleiƜK9aG,xsZxu٣u7Y$R sPAxu ral;_qHt-\F.#/c^ &*9<؊@~tbI#h$L$DӔJRNl;F5jA uaPMq='Tv%]Q={.^'+q٦5kE\pSCL>4ޔ4EkHYv/sg3X]8M9pPPՏ-NE "r W7&\>{"2qJ8`nx h{ 5 ʏN%S 0"Ø!)DS95Bo.<_y_rNf7]Ln"lѣK`S`BjD`u)kFD ptUERX2cIeA &#-50B1A" z"- >SؚէQbz]iѕ - XMLBi1C<#ca_3 COI/ <#ͯ'Bś*ʻkOH NBsQjB=6"rn0eGλy_-y3{Z!s RdDy˷syIP Lt<%/Ʀ p*'qIMN!" `0׽G>8g|zpMJa a *kn*@kݽ*R bVFƶ=#\R6̞9Kc #M)cTx06G^u9Cb:l<b(%kuvE%](VY9MqRŅ@sy< ne4/D"mRu2R*U˯ 6XZ3OS΀bn|8J2}з>d!g0_lW ^-$0Bd8 H{;/j(ʋ~sYk~(<,{i[?SWC "!W, W y(Ѫ\Mٳ:I>Z Y讳[Eb Vڌ,˞Z.AlUhBwtBH2,*ǒ|{$dCHP'p!P8SLwc1mZpkB(D3HF )&j**AxMrWHOM_}5K 5I|*f`C3\ =NTSPUʁD# מ0O5VXD_ΖG@f[үlA$4%i+7 Fɸg"teڍ`i9~찬0.A^3ёをj%ʃ&@DE2OW1xx1$$|Dj5a3VR{Uwz1w9I]fjb/A/: >9<z N ?̓kz J*!^O-k7 ́S)$ ,OXXW"Mґsqhkn`Nh$^3ȟ7Lg ۭYSeq)d*B#c@A2:z ??la#{.?_p̈;`-R(tH="D(Xq^kL?*I^xB%"\UD٘o+H(e쾇@ZeALH7 fngmʃZ3|Am=j6`Qk \G+jij3Dߗ4jCaGQV(:gvJ.4=! P YUZyˆSHGv$FMJ)xIc=)}PJOpG s*9-qxk`OSeRDEZ'j#E8x\RiX+bS%OOD! (FgE܃hnLr,.ƟGldITe0]#!HC/cNa+q/rh|LR+rQ}PĦJ%fKjiT}/Z:c8\cI6T-Ҷ;iUZ;xL7;A vnԨ 9`U|/'KN3DX]-D <=m@BbXiIh$,ຽaHB(<)InN-y-V||V;ۯ|nXUp#[(0MTli{.B[qYl] n0Z}d lsiDor I2rwۋ].BP7VvNfamBЪ2OZcQkj [E^y>FI!H3`ka@eWPEp߄myIl!"*vPAXkgML`0ÏcdƟ8AD-HJ {J L5#HERɺ$!A&PBBz`-(u JpDオЏG'޶!xMxЕ~DWYe~MkL! 'iż5񋊱uhH)M&Mi*V.3!Jg}+#V .F?%KoJH,2?a{y] |.7_ O9Գ(j0D¾<8MôEٺL[y9L,wZMDs7>J9'gMy8La3. M ܸZz` e֊C{LtҎuj!(S|OnSдv%@ (guăYL`3 Ihc~γ>#j qB@6aZ*Ұns=U Hg笮vLe.im 'c󧮘yٺWW_qy":?1XmbBu .y BJ{~s *~mFBHAٿT7G>GBJ .=kЊrpEb$uBRʇ9vYs&hl<%T9)|ܞ#Ȫr#EҔ.ٲNn *rO嘐{hR,DbF/duހ<ز^{sH0@( PHPE IHH* 6aXX5V[Cjzzxs+Z jMz}}w޳K2͌ŝTyEzgtʒUakbve) kxFWK[ґxGӴ]b:CǮL`)VsRwT+ӫ \EX"V) F3MWҤ\쌻K,OIf>0%lUO7/r\א_|ҙpB)J٤v|wT&y7~3ćgiU%ȟ_^"+>OSut|h=œ!l=ky]Vhkum-?z9k) S L Y3ctƇF/yBSuW&XȔeV5]^\?у$0 ,ѵ[\~ԏw\0u"nLV%a*MH*Qe"f!,8v,i+;t&D&ǩ)Џt?tS} TxdLd6:1Zc;Xvɻg.ϊް1'(M\ ъڐۑ MI⎧73$ϜIJIg4m==҅3;C*d2IDAT0CS&_Ͻwh uSU"P 7|3D~! w,{UK&;_2ѩIJK&](z;'ʩ}޵Y9a҃-7=]'H/f^R,lp ]qp.(DhoMve粹' ٸȶސ:[~Aמ?{dcCHK,1c)kIkW/;`Mn2Y<ۋ^zm3Ϯlm`#Нn[ܴ2qyL'6IYivdI ,xc#yXndKtkܽ{ٍSO^}Bo '8Qf5, n,`X2d8jI* CdAAAX~L gNak\$ĝ٣ҚqfJ,a{[-sW^t1AOW.? CR*҂ֿqW:=:c#ZaKLP?•Go<=Z)!!HA–F!:_ ČބTIEbڼY+zİNb͐N,VG%7ޜܣnN˝xbsUY7QַG#)&_ (+V)]E)fzЇPeU# A_C-c[: .twO]߽[ {Xe ,s d7ߕofa5b:C'm&.tNl+ټμsgv)*(vM#XV}?xUGW/`^V,Dz?0?Λ7pnpmːOL &wXlWqOb@I$q͚ cgUCWS̩wf5x `X6֛Fv, F9ҞՂK6tHZLK%t;EIWS 2[&vq<w\wݝ6e8=__ :2*;%u|nz[һ 2[dH6,r%bVe3,"o,` ί$K ™H v?K^!!uKcGnN 6-\76!Q@ĠVbBt)ӱ1p1s!Z!!c1dב?a ;/YԐIꏖ&%'j8>rgg[ӹzqVGF75*v)W._4`+Tv탢No/Tՙ HaZ{oo=lItص\6E'6bv~Ch1ޞt^kBW2-{9O}v|ϟ;I(7M ec"Xaub{,lmsn푝ؓ?}R/yz *3=mܜuc UTOfbיh&pO^5g:FaL@uHLs ~^j<%NRs25DvGp芴(©;~f6ɨQ ystK'{ά-npeynׁ bR)(S'~Iqf%"~)6mB@EKa?Rg&~r6}@[c ̈́Aʳ)0EgȅE.Exv,aƅK~rbTfkUIo߁3ȳMTa+WRx@DcvU xrguODx՛+8TK$m[Q}2l,d/,~F3/fq'q/Bu(wPRHLfסPe[t&.*a/lS_tG%+ZVތVPd]% z+-g|o~C~rO?y60c"nz!%](+7ǿ oÐ s|PrȥDԁmɠ׈̧vA(R_9ז挳!@SM]X/Ǘf-ta) æ1FaX]ʬ,G_uǶPdqTuVEĸClaD`E؛`l:T;KAk >^A ';o/ZL$F$4u82{ a8` d3ko7_Vژ.dy=l!,O'Zaž>1Llӵr_,/=0&~Lw`zeW_̶,+k0e`b;B:hFdz;I8ѰNk4 6 $k=e^|]de6t~h(ldc,30ƣL ;7LCLz;w~5ݼr@\2VK}QO9ё2b+,^~+(-\OiQCk/M=n3jbi!cݝcTlo ٬dxlB P,E&HnG"Ij嶪JN0vLe3 #.Jj{(\n,A6rkxI]tg&j/e^:O?m'-V}ShJ9VYkGeftOc|]P:dE~ D5S*WZ/aMmOw|b:-rM#+afdisð`㛿`࿾S;icMl> bH.rj~%2h/LCChXJs26&zͪDZ(d6p` j[ƅ]I(gƱCtsB%XZS}'gO|u8ywN~[WĺT)L7%K&Ù yupHo`nJ|,vV_Wr)c;0L 7iS&pb;x'7 L?:]j,cu%dcK; %O4`X]YWF-P H4Kw7 2ZDL{a Ϊ@@1 wxbV͒b>-i;;[n3'?SwB jS0J6]%AMUg\=|BKcUݴ쥓n9ǿ|ݿs=k&˫G$E#_NiË3G|f&;1=C m<{M0ziZ y֦lJ qrjHp;0#ߚUPϪݭ#ܠe=8e([?}G|px$h|CNA+gy|gk|Ih/&wBEÑl(\ Edi<92tvVp I'(b}[NzԄ2%@vP "0q6F{\6{f;ٝ`_а=Kv'r<\>C OSoJԶ5RBGˈNGJFF⢌o+3?K]8UB,{1lĭszaE_Gfݝ.$lfՕ)TSgTV y462YѭEKr璂jJLe'%O,qw~rd`ǩ)ǞlTC6 *㣅8Hj}%wCdٗ 87\e'gBf#6$f0qtFYnˏR37|(:=zGRo}ҚS9Gžȯ$j)!7yY?_.ynrܩKw af? R=Ӧa:`IZ"X}wG6n7%C@;|CjHᜐ$w@*Qt 6L>: kgO#K *qE`>BGh@+fanŬU@@WI^%CQkM'}TrUS[ c!U6 @sN}UIon^ PP5%j|*b%Yɚ[p#nC8U57%lge,M~h?h0rppw/CDȘ3&*o+<_uH4vlɍ13m X{DžykRQ'A^(7lZbX|g4Ʊ\O-ٟ'_es-}F^E!=7~o)FD<@?ӗ`a||{f~\~s'_~]^ EQnupq@ϗZM=pJL׶Ud9+$žj>:ٳ"ԓeŀ XB@ćި:qHd)0P[Y&ae8Y -&"AWovu7m]< zS3Ndp@1j" j|L*EA<-QեdEӅ/EvbŰ.;66V>\^Πl *~vPPe >:26̞hu e(A[@ ˫+ܰ쩦ҝzXu 'jy-_~ Kw-={Ͼ'~g[gNma 2Ἕڙg68r\($: Ʊ:(v8{68^*|Zn %j5lU'K[ۋWB.cy0SœIH9ҳ͜"8<ð'*_Cт]UTPPe#`IrH٬JiL(^3+rpt[69TܠNHMS;QRTv612+.W^uIfjl%fRWQUUi_Ӱ~B۔BG {-If5ד*dڍ⊹L S>!C]*^WSU$Vު`6:6i՘būnkki؆l:B X]҇ |y:@) -oHMH~Do_Zn?[B:^ۆvX܇T@9Wg㣔Uj$YU,0.$dj2K9V~:>r#?6ΰDR1 FIt 4JH9tVmc4T:#"/K^(>p<- ҳ>>ߢ- q2$[E$,O<1hG?U +[ȵNQR(LJX}"$6.Dֈ @uKp4 zcC@nQ=M8 dĴKbhX92V|2I$F*=iAe%(p™qӖPDCJwf01"QNLAh>YuȩNLwʯؔRJkH~RAFDrzSO?rȝ@$ &Gr#b%jNȅ~Pq>7/C֒zEfeʃ(#{SIP("jh|y-ْQP /Du)69}hGWmi`*N_YPV]R-Sib.}G]7Y4)]V 5HE"5*I ^%%8k[O"({pRD4YI )L/sr܅{NAt{OwGWF3¶r`r?\_J^;@*t*JDFɜn*Se:YŜ|Ո@= '[yEۏ1@u{@)22 o>qT#DZ6V~ji8E8LS5S?wd4Oy+ꒄ#YincnD YR)J+SٴKN%4ifاVD&%byLcWz_ 2g.kEv ")kxFj]ZTq*-Tvl#%l(Q`Jr֩ƻgZcEF1ESIf{=r[?7t~|ήK!Z &p5Ȓ=0ܾ i^ß<7ϸ$ɕXqXV5L7/RhAbQ\&BU 1q^Z"*sTn> P('/q =g !CtR84TMbt)jmLcopUFUdSx4 a4VZEjc*W?0:&jJv0b(ۆ֔'C-DAqBd2&>!j]*5Nob.~â4rїr45A{"l*ީ}C\AXbz-aۓN x˞˳';u.lcaáh'㗧 ZO[!(',7:; D djU6'H2,~m(γ3c5ư1zT8oe-IU:BPUL:`OV{W$={fzEiѶ;AQ`Ϳ ?ג"IXX12zJ!Ljɱ)kj؆:߳iO%{c JŪORQ7~`$U9+UDw@S_S ALsi>h4C8SZ9*JDnW3T7~z$>qv<ʧ \;o9uvsX^ݱGC)]g'e,hNJ u u!s3w+/G*v}ˆCP_S }묮>c2cOD'58QQɼ@oQ,VHuHN{TD7ab(64(\ QTN=t'ZMc=hϰtaXH">Ȇ\k۠4 3Nt^'**ɓQ wҘHV' 9.~٧Dͱ8Մ5j[bHԃkǐ,[Տ<;JPVϛG~_MΟ/>\T %XyMTUꠕjoАΖhgmu;%µ]z . ~)Ka~ݲ0Y̸̋B;'o<0_#}HDD͏Ǩ#zɠZob"=eI]F5B,CN6Qͭz{KO90+aĢ'v#MPzM0Y-*|vuqx+8+]Za0aMDxH նJkfodHaW0%uEMo@+umXDZ9bCGjS=xMY&QH[ߝמChf8 !JZs]bgM:aц#C}^a_fn7Po ^*ؾ+|UPU2|s݃O$Bg'3o=Kp&8'6x[wS-h87%CxNTMn-fyS+ic1)E#':}xbxGhtp5PʪAY&6\Scab)ŚpҜ$l)@̨'N)Tehb̒AIj.W~xkQNP_#[$=<['<#94Y.'rF!ca+ ;R^0y>~-1.+PeB|5:;pn#8%ܠ7MqL Up*jYoPC"ASh>~Os5, UrX>V@/,237JKճЅn !;[=} px8D4]xvT&3Bd#{1\yTHG(/UjǁM*0aSl,*{D@D ;+VY l'uy6k2$ <53CyЊ& 1Ŷ v}tXbh<-҇D$8?ˣ֪Z1ܾ yV[Ch^lV$,QGdBe2zU9X{ieD*i7pL["2d؏mCc~kt(#3ve^kmO\4EH0 aR‡2}+S4f{TYp{k=W c6q#qaOWd+:f N&(VҳzLkA DRPNb2AY&0"[GWI\}#lXY`bWqU6DFK݉3wh^wd/Yamk?<ࡍXJPMx`&*U u| 銾90R bLQ|kR"PTU^G N@}@=5ߥIx՗#$>LeS+W2}fHwFs.#y 2*xZxnm5D]O|"+f ;%Lf7/e2|eL M7L{C4ʠR}jD}x"Uh!.yy5uT 1>QUEÖi\oE3poM9i7\iS${^jqVuDmqIUn(7&j.=؀5cE']h(cFyΔ0YƊm=%؜#Q/M|k 5UGE#OTڎ~?_7BX -UUrimpf_G+}> qUrw?0@iq)sr;T\F^3,x3Y'ϽYrc XCcʜc儦Ø:m1+(1F?&#mIצ4'1,]jWc2fg[4"dM HJ_`-ΔWXiٟŋ;3/| 6Rd P6:Eۥ'" aǢǶJ46VIuP]Bb^lB8+1<285hJ^چ#|y+(R5tIENDB`gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_400x200_fill_box_bottomleft_3.png000066400000000000000000001653031420147000300352420ustar00rootroot00000000000000hugo-0.92.2/resources/testdata/goldenPNG  IHDRIw IDATx u`%6 JI")ҒMY%9"˻D^/vVKr/N|lQ):RHŤ$S u`~uսuouC_wuuկ~woj=8 u? 8HT Q絃#>?…fo #Bϙp*9 `yK$`;?s~܅O2SVuƶ*V@~ૻՉOǃ &`?OSu~lLfR;(``AL_(I);H25m4$Mvq7n4G;p@kUI #qMo|P|&دk_0mǚ( 02 hR29b"i,(.Sj41LUgg pDx+B84AB8,O0><:Qq`4_ _i@v.y:_|1.@%{o |v-*aXh $J_fműWji<8LL܃pߩ߂I'WHiۦ3r۴GEeD%ŗ-sYt 's&Z Z`QeQ?H4#hDBDhcI܊d \J` "$jaAl@ 3<wEJJH,z1GJ9TI xIQ^Ȼ8Y:XéG9dFJPQ`eŘh[=_ =D[ Yhn.یh%<(H{-_I,~c i &x b#{<`/4o0Tjʵ+ (Ҝ(TQ2^/^AYϼNh cVd*yHxjPnvlPcitALUQGKZU!v%L lX;G{[>nG !j;G<`2+ UǕEjX[DԸC1u9E_٘hVP2ېTt9.^j) ,QCJ,2v0'he 񂃘sL> YKE"oѳZU*A>$Jkpi]JL.DZ\Ъ(9):X r2$8'F~ԎS30dp1_8` dcc`p.-^d/IkxPж,F?Tqa n($:ho{u^E)Om- #q rϢP^X AM{ v$\I2R+?J97ŤoLȕ"գ0Dzr gYDԊYԄa0 PsR/yҝUPHbJUyNb 0*K$ yKQLxzlGebč`?w10}@x"d&jQwLM#,oU % %gXBqAbP{Rz"ۇ< " :0 DsHdDǡ$P+=; .EPt8U1ԐߢZ FV$!Yăi ˁЏ"D2MYT"#@I/C9ϰ^EE!%-U߉T$FDXԖbRր%K(VyȪ pFIRDVOh*K^4Y1GG+SBs<WӢB.Iu[C8+e*_kX"R 2' k #Ҩ|N&_ F#<ߤo0y˃L(R$C*c"LqG|hK$6ZmKQ#,ظ3O~Xy3щ_ΰ("P\&j>%v]PXÄZ;mxoP:}jc]wl#P"=A€`e~13w?1=8E6 $GWBo[ФH7{`{륄}qY#T $*hũ[IH1jQF/h',yA[&'srT\,䓻2M*hFRߔ1x:7lHɃ 0@`"~D:BjӒȤ?eC*enOq^Fu L 3,҃k"Z8P L5;fC.e=jR/U1Lި46v\YP PawITyi,AH6b󏟄 X5`‡Eڝ(\#י-2X%`"q&8E %[07`LH ڂ4 BA]ciV%$yͪP~v!/W!J5 AL^)] &9ԩP1؀ ɃxZ{Fi}sX%W@DYP\j.TvviiUjPbٳпv Vh>[44󒡮BImLc/ET\,u EЖ>hMY[%åšG,%GSڳW 8[߈M/"`#JG/bSoːlV] N .vGʴ֜u[h"&C Y[ cSƙKhK 5b+ fdEK* +I߭r'`P$<@r}-**VQk >Y6H`1+v'{VV*"J+k)ʯXa[JЪ 4&r!~1 &Ў<Eİ2E ~lFL c#U0So,ǚ@DV`N2H g( ejJU'DPL6^Fhk]RZW|?XCw"{uA S~mda[gjҤA4GTr~`xAwQ^ʑ`Yd'Yd$}^ {$lJiFq \ 2(& "ai`nK!`\^gĊ| RkRXU43 U6T$BGhuUp%k<1HFXWP:\dK#K:Zmc86Q!T*sB%GB&p8P,t0oY#h'w26ZF%9[6YAd4 uDJub{qa6D( 5 x -S~8tA⇲v9Z i :0Mdq< 1A"/v]*Vmy)%&RHebmsd8iG~yy+DHp'(Ƌ\ PY IGϣUto[#, W,3&"|ʅDEW,{֍FzͩǏ{!=wŨ] q ~_iR<`-VXqp51Yb1i`Ə0w |;)@'Ueװ*4Z@E&S`eeȄ<HD.ƹE&͛:Ȏ{Vx,'3Lɴ`-+ߙ߶˟ʅZYT-ɗ8'QT)cџƦu\TCQ9DfBү>x~k 'fݲw]ivnệ(m4bU$IUVʠJ:uĢ7/Jv:CmAܜ _%@k.æ6]Y4hwd 4 2F@j-ޥ7L@. &[RU:f(yi:fx qc\(#ō K t5قE(teݏt2y/tц|F/_sG3=qӵUrr Ւ9A#wA+)<}V67d۲\Yo=yp-]nh{ tY09[5@%2|(yjJQ<҂euҗP/ W'I[$Ebh(Rq[N C\C%,3%{] rR(J(t:1K5&&l] i "7K@ar_tʪ_~+dcYBXz$qV"/VʾR\jػnTgڳG['_8CD/S f' [bh_S1һ;\gf['Of/iM?(Rޚz ](QCFu :Q3AI 1:Lؑb*VW AQ<ԀZBKDA 7[oIYAa φh늡C]{je|H$vIcRqfwlg `%ZV\$VaF{׿.6C[C[`?홃S/uHnPrqXX6AlTsX\γzV~lt;Ǿ필+?oU;ѿ4;"Xi3Q&0Ș{&g~&i㹩̑hjEw u(Ug8}s/뤳΋+.3ҡ[ Dj #1 Ѧh Y^+grNd|N[.$%#י6 crv9᝟%^1qڏ͏ݩڣݢ<+xI%PPV]cj\y|SF ?ܢvGgC)ySNm8>PbI5 QS|P$#m)98p3h2.*ER0$P"u`И༰Mde&󓜄I,&obnpW$.ޅ'V.(v؂MTzDgJ2na99 7sl֚.j]s[y=G.γԿ O#{fA+umԳ`9 a9R뗕%z8g)@,2A氫`@$Yx̾/5`D"L䯢P԰p]4!)Eer6 B9ɚ%wAbO@ƒ7 XF'=S^P$3d/3r0wUUm?4SG?bѢ_(gat #V۷']-(Y>:tk+Ax)EYˎ,je+ZLCdBͰ0]~ X\2(?$Lr@7a ˟ʅyF ba%<,Pܡ .l )_Ű 9昝ʴsV=EH Me)g8uF-Ԗ Pܗӎ-Lx 54D⅑b&F#֏ LBQETâa˪N:š8r[B BX Y;D B&'kZwvrny7.~|(`lN,5J;" TAJn1eR v1cU(W0y(hcWe nԼ-@i,`]ayT˴t\?Unpu@v DVlN 0'>8YKb;YϠ(AQdW-gL&"fn14$iA8ؤ"cyOp \g1 RSRxH{ 6x_<žtHlfq,Tʧ%"Hh @`bX Tpv`[%=HY΢F?.ۃYhYe󺱢gvd[UǬ y:gvN>:y_k%ZT$ taMRw@WKtXdc2Aˮ]hP:&&Gay^}SwDMgON=uE|bc+o4yjnnX{k` dY.&FOLs<49;67+Mdkpϱ&&sݍHP"c7 jeXyefY۵gOO9FD?xD ~[ٴ}uEJ#z=CW7n߹ءv=~ϋϞ_*œII*(~ʹ%IIZjƒgxm˺ Z<l)`uB}k«7}ۚ.\Z ̆z.\1xx߫6'|vѧgUMyj%LB5l_5{G<0u %zw3/?_!ktZV^xXK iCjϊ7,C=#;j766^˃ԋ2Qk41pE_ůj'%2nghW1q=}+{NbSW^۷˥Wìty\P e[kGw\9>y4w{`$ɜ^+];n/ڱCy>3cncQŠ^sx;f}5 ׭JU]._b],BDe{/\Wו[Ɲ 2KxVɪ6+d$23(JDK+O>s%RSgNTM*qQ_k ]7SKA+SӑWMRf}[؆5'L-P<D/!8 Ư,mnUX:.]Wg$Aĕ*9g*> "P]ٮ#jwGvG+]{>w}w$|cqXdד(VPKF(HC%3_ڱUJf㿿u 0cU;wR2v$19h/S3'+@HYS >(1f"HAKW6kآo+o~+ՒŴB!P<;)HZmhⒺ ZqĖh`pE*9Z! (5j`?{?޾z*Rmw̷ݗ}ʉ;s?vXd줓|m(h h5 yt»o};/z)-۹yj|Ĺkv#03֚ P9@{ j](_VeD>?_4 '>%x`).AjP3(zh8z?{\R wz03v.,d5 LEJALHKnyoZ 3FZ9= ucXr6*gE2+e}_gْ[a2Mχ ̭*#lT/.d9"МU7N\0!q/VR}x /2X]w\3uw?Ȭ a }`c(ND KMjkvpYdi5tt⥽ dܨN#&ZsƜ %DKlLϮtӴµa`OJK*~` ̱ {]fY#nK +ϚP}ayι\ŰhD}+/':T8ׄ kX]fL_5[Y$qgR_!%,gĽѪ@@ )~W)e_xHU-rRIiNTv-洀E5f6+OnM֤6FOvqL'x7fūT Ж9=j2S2}5ₛsUH>['a|a &cU"8 N(uzC6_x[vv2v Cl'R«;˶wv.jaĪ ܓYלB"qZW[#! j׬yiڭо a+T0oGr **, L>FNAijh}_麚$epfz/y(gڞe:+smUgpzV8/H)ba} 2"TNjU~} δ5#Fʑ (H砗|v͵C43?ZiV7n]c%Oi# qoz PVt5_}akj`f5303[+{h_<7ʱ9ұ/FGXm47UVJqW?'eI&AXa8V* &:^6^"N~-?UsO|r_Rk߸VLQ`ܻ ʀوQ\{\}v&djkŋO(_G6h I1:2債ա$Oُ?1l;݊\?2r 9޻9}Ɖ.t4VUxmqӈ&@Q<=Z4e>w{v- ^W]Gs!}5<[NEJm(ץ|ʥJ3,INj,)Os|j☜ c>֞:tKzmC8: 5YN(N(37>ʡ*Dsc{`ٲu˗WR:5>O܌O׺qa9ڑWhmYV!gf?B}_+/qx$&rހdV㰩`R#*09yZ0 :Ϣ5$S S;/7X]}ǎUpbtaAOy4< T* vg娔A✪Bt2.Ȳ 񱙹hFЩcU`4l@O&(ԊJVbCdZ'Y;+5Î,aSȰ|77Uatclc`  ~nqy,)>ƅʮcH spbLMON 9"OzN+.tf.b8C'NTp@n3HKb`Hmb."Z5XǷDUEn߮kP ƪ[R]qy2v&1lȵ\'[ħjחJ&ݕzµTL8gEgsm#5q@F3TʁJq\8k| H6e~aN3J!͹V56u @x~Sk6IGAwf{0Nw D)vS&{65P_;lɜxdBff< _B@I{kNYrY9`=C;S:=x$V勄&aSО|+q\ w#'&u?w=Uȫ~*zP>djB6bs@V#j9bX.%7`Y_OEBVV@Zh[vwGa3?"VP!O3BhXڞ@6&c58s=kzՄ>>P\:/U9RNZ5)$_⎎!+]ܺ dc[ m5MzG*3唬i# ' ![|WYJv{hHKКF ^?gN<PY1wyKqkuqS<k5{A=W5}M +~TQP+K(enu} ©#)V`rϼ]%ta}5*9=Yw_&& [Bdu檕yG^]Ld`}uɱkw[.9Cܝ6T{N *ԫ@2Z7 _7\就ߺ~`Q)` ~t I99]r#/ܰf̷MCOZ.=<[L ?R8e^G}КKV_30?iKxY+3;Vl`G͕ v~꘹`5f/%t)7SO58IY~ypY=i SI ܼ*4^w\Z8Z3reGwxj=:1zLȲ?xr~뿻yoToa՝XjcӪ }MŜ MԫJ3eOUeRmb]*kvG~C:[w.vz6Twg;2;e$ֈ%oK~ X~o_WV~v2W1l"{vi|`TBI]vݻfdmCWxr!W펎ݻn]޿|يwx]rU5o\56ozMyhifo~^]azaҪa&Bm|y]7]?}|"1<ݐ:'?u.߼}\kd?uö*/gو/:T=&JC0ש[UƟݿ5ìaO͞۞&Ƭl t`UUl8u[+7Nx?6}Tx%ov͌>jEqAAP>$(ZȋP@(L{aMF]r?˵m "JvNL>6bw뷾-?Ks :))s{†_ܸщنUnޞ'9|X\-Gc6wu|}'Z10$rEA],xۺVO?5ûG'έzǵW/QS+AK7)T*d^Deeais{}NWl_Q#:qʎAROS\s{+O2rѭ#Zs'O i@ms42`~xDT\557=:;uo"ߚ(8ns3͵}hwO Z=y}ն ?|kto>c!kX5%x3lY+|" pqk;^PX-c985so"A$<{O@*k&e2PuԑF^M/OEL)0})JZ&~yv~,>1euJߏ҃/cBMؒSf'Կ^&=5uAM#y |{~湄=Mzɹܴqbf-a9O40"N`Gy-KME$Z~LrAMd_Oӝ"&@}OFif?ǘo+b9*| zyO*@U; b6 sR (CaysGSVA23<~۱z+gi(u{zCEzP!(khFk)]nxѻ:x_rEaWa1UR*jmmT4V&齇ܩ3>kyϮ?<3xc~xa!,oQǗ 6|1+Thȃ]/2wFΧ&OU'l9ˇbE(f+|kfzkrhl;x`MțS5B|WM~QÕuD@okf[:]Mo0.e]*rPhWԣk|] Ry ) f.mBk}BsN9}Pl?,[Ru!,s3 <#{'?&pf(<5R-ҤES@ŗ}Ʃ@E8s:߽ c z{ߡoՉzS~c!X?Z5 ],a[HiɔšZrlק^\U$iMB%yab/&vͱ+˕eU}RUT_SL굃pt$q!.h_*@5z2} #OY)e-BQ u٦?_w~̇7ON M7(<>Z+ufŧh"BęP]TX^q@w󱗎Yx{tSq~ ?a=RV6n6 *jC.jyݚ^+SfǞs#eef4SԟvrNOjMĞ Qeq֩kvby]5N?D OCwfU 3|?P-U)Uvz{ϟ~=~~~*$9$۝ŌE? Hj|~t"|~';~j›}yJk͝:ԑ&~uw}*m%/L_\yO=b!O0箱g?yj%z5F)0$-LE^&pi jfogCN3N/98rߵ&?Чy]x}f޷l[[v_|>x6`TRPab"|}E /d$d6>w?q?q{ۺF/O=GcѠ(tO0:x+y"HYGa\@g)朓;$v۷+/ U hԉS:=ߜ>v/ЬʘƯU9j6uU[Z'^8'&v5K_%^!J\ko\vs♏玀[C믄\1=C IuMFT>8/Upa[j`M/M"|ľ]}?jtp1pu=~bcu}a|el-^lheќ?v}NNO{G79= +s>O~-ܱ_uE[,ɩw}ܷgLzsy&7>J'yz_|f#v_½_~,$hpGz΋.ɋGճV ~3-VJSrG 6dۇ~D WhNL-q_C@@NeqY`o6Z>|`h8Gֱ'ƞ9vr(![ ܺeí{ow9| v<o% C1A6ܴbh8>jaV^蘟:`aXt6ZR* `l7e2rủCEz ,eLˋ5  f2lA۞CWwKG%qsy%5:SR<6!3)]"l #cT!{(F^ _xr./`6}bfO 8۠"l`bڗC{ =hb'fVb= B={žA3)] 2YJh,Gg>^|\^6גv p)2,ED ׳0.~c83( #!>ˢ^&@ c]b9?}SM,CιHݭз9 #h_HxIRctz,y1+b(f`VJJ `RT/CXU!.D>eɸ8(4-)t΀|C`гyFa9"B$N))4XQ'z㻯Ǟo~3SQlLLq+G*s.-0 }L("Ho!_m DayOKe+^d)$({5KEd'%Tg3vE3'B~^i&[”RR{$~T<@Hqc7c'2Ce 2k $ 1m X <5@+̣C z]_d! wDž2dPA!( YX2glN s5(YP\$7^#=-7^>t)27o ,}I2bR'a=y])4i~NBp?cY5Lӫ`# AF ؅GGtv})&Se֍HWQ6V6sr֭TAVQT@dRJ3hwa,%H&d>;Rh6c/KrT4V}D#ܣ*0On e>qȘК4HW<0lciVX5#d4l{CWG]JFo]!VyswOk6{7ݲmWҧ}| 'z`r0 ҩȭ[yZT7 .&52q*x%2FUnO޽N2cKMa)rbfEk &mfBf, cO9:R^6lmJ ?V$~Wܢ*3vKϝpiI1WxтA Zl*`GP"]ѸiQav 2\ɏsaE&AHd,>L2x)Atbo4?Te_q}E 7!B a|̼|W b{ ɠX;O־ZW37 "73 fMB*TvM`V*2%^³ ,(!U%tB,*Tf<&ưV(Mf Wh=v,"DuFG4\Ƨ R:IBAwLSXIa0ID 6֕.(~:3+>F26Bd9;a zG:S0C[ggo֞fݠ:+0, n ͐cQ!1q\;; U$GIez ALAgQBe#]4vLYjh!Lbm"B\-FC-dvѡjuK3l-JNÒ3} A3=NAPR)p+,&m֙F8CYpcz;e5V$hIT=H_(=b)21>ˏdíyS % .֛}Gڟ^B9:6ر'CِL=Ѐ)l"XNC!DQ%8 TVsh C ,VZ,uU9l-jDQ.zhI`ztbFQ +V?fEB)i]DKG荰E%2ehef/#PښFWm,)CCdE4e?S0yx UNOJXp}DD`,6'B%)=_e;\O}+.iОOcG Sk) qfBm7! e,T!Y#ݹ+aBhBQ nbjE0pD7FI'R^Tj-+_ hdOOieͳ.HU !ZC7?Y TB iSA 'PYA5.\WHs4ymKV Ȋs,dY,ʐNrEVPo- SK۔PKvئ/_~kCQD٭;R }Q8|L@2n&sE#0QX3H'6bòt.`/,$+i%[NMQy&b !q{weȂR-`| k\+cwJǕU"tTRXm‡9bJdz4KsdB?GKi0Jd)ĸZ!OCU mΑAv^#_lVlH1gv?;?~)_sv^t>i_5BF̠UL(9^J$.DTǃLǦSr mC*r88ϵ(՜ D#@ UxA) Z>5pz` ,DgߢE- ZVrS+.|-X8BdҰe<8vn!&V>ҝ21WnWYE,q)Gax(ï s[ T镧Z-/+/ knXeWksnv~G=OM$ s+F{'P:ZU:@&o!S.CeeL >ubC^ BªyG~Ǚ\Kaim+&/ :dIh`j,~g n }r!p5+*mBXʮb b.iR@s 3-5}y а*P8cb)saf1 be"HykHZTC^/r>rе)*f[!4F^wwkOώOSgynƆB/"kS ζ)\P\̦) l=m'!/RQ| R fTƭz"NQJGcGA]RzvbVҢҤ c8o`h Xuq: AQPW<1QY̷v2ڹ,{ƝGG :QB$YPRA aC*"pD?m Y)P0,sA61$~!/مٙ?gѢF"בi1/^:#1i1.1O!AlǠPo{ =[#ӼbMA0azz䵆tyDb_aqMb<-mz$IUB,22|-*hCIφJ6[OoAK j+ 0H_h&\/3bbm;c!J (eq2A%aEyص4vIM\(qC^9w$Ɂ hp32h1a(>:յ"^\VS47ÎYWR>Ԧzr2GukXdWFp=Aqg'ϕ_,Tou ̟Hl=ЮP"8ޣ l*'6FP֯q+2u9(WlOrBBmKFń0W p+1r_ڴ2wET6=1L(&v aDKfX%>m/lst扁zM]<\3X3״A 7lOO{~x!l&mߗ%PD.wg]B&OAB2} 9NOkQElýSJ- tvC &qj k})$E)cfM * J+P[f;:@3N ]Lz.fe*%q!Q. 4G$d:FG0O [cy+ڡ,h 0jG2oBQTϱ"iJ4 g}HEjx.M* 0IMqfcoxtA"öClhy^/|o-{fdC i%>ĻG<٦i 6tM}Pג %O+rK"THr'=d>yZQI/5"`1Iq eLDNK`V8GEɃ1 5n$t݊ɐ@U+jǣAx6D1^D%5dMѶ rߔ`69pH@v AK:. &A:zD̘5lܶxTA0$U%`V+՘k&^u|&>E+KQUަ?ٞ=O czCs/52goSa &تDtƇBkKCИTgV-bD٥ľG9cvs>;@v?<0F]\REԡ[?X0Aa8Hh lz#*Fip~m!2Q I$#ѝJpz/9#orQ?V)!AX1>xWh_kt3Owh~O5$J<KW #i݄dz6{$[2_)!h^PnGϝ2CK8YmHٞ{0#P?jO'Qc&ͯa FT^`ѐ嬌9ъ1^l9rXymAQ@ wQ{׾uEk'"0t~f`o~Ddކ\G*~Ne6T0,*rs â0(P-,NocC7]бxI,ز&twr 6~,{*-mKpXX yVŹAY*b%oejʇ6!1S<օi?,?i`0=4:\ `Ad)fkRg(lܽ%Gy.Zgg< BB|׏`l0\ lL $ "JI( t̜vU9sF[,fݻCuu_IDh.xFv~hU +!NJ#_  IU)%)*e 7Q4%DPpϓ\Mpu ׂC3$ߢɩ%WNe6z.Jl XGZe<1~>ۂF^Pmm-o٨h4~8O PGoR. F",ɏQdN(-ƅ ⷼ0%&pGd ղb"'&P0 SS'"ڞ, -9s?aϻ+f~hs0PVo ࡰ&8H8!_vyb,X8ƑX 9 -(KqvᐆB gAb;$֗()tKnTgVJ~%f_J$>2!HMi3AVpJʷd>kf_Xy!'usWNK}/{i}hyW)<<va*=tGH+9 a2Uit|AEY|Dl &b +!(TB.v9Hɠ@Gy">+qHl!!_LSXޚa4YA&ݳW鼶iK;> ;G# /*jnRW-ވ A&c+G6% _}+Nbs^a(( Gl%D))rZ{kɊӉ80Y*SQ=H?Ud1zSѭ7Cg .E]e?LETB(sn$ȇ#PC% b;Ba;BߊHy O!X[&R([>Đ'PR;X&gVBJy3PnK۰Xm=5U{>ߺEn B M5U}*-h!dU4|vhu LPl `/Yx qsf5]pHCNRw;4P b㽟%Y$} ?H%a(Ъ:ۢE*&^jEm }P} ‡xFi!҇A0ab7+$ki!kx@ku@ A+\@&d +yW@'ˉ*T!B;+^ uڞib썕0aP]͛҈S8 O1׾y }N@%H^ Hr7c[B!~GR̗t MߝrbӞ Sf A 0_ww,9}8,Dh^,ĥTIDu@+I¾P p$C2Ntz]apECٌY+.E %2B$Cf="e`=!?P+CLE Jim; 0X0 ly$SM^"*bn.m2V)ٔbظ`QW'rfsw?Y3,{+MQ!f_gaӟrֿ5L-u 5~OCm, P+Urp4J\5:+qs7~;F<@THqzd)![ǎ pW`q4T]8l[a"K)F-v'J($05@[$  aA2 g3ؒ ]I0 e[Kl`1S! 8:tJf' jD2J`(@9d%B1pb  ;.Ejю9BFaA/_#$zB,=(ŊQ~.%ZGf+ݣ& ƠsrK{jI*Vc]jz8 EY am~E=ҔVT>Rsi9sRdqXa1Zp6U2E+_acf+}p)㶉[v4 DD+n"% 1 gpVEl^Aٽ{ #b<?$d ?ٚ{00<ɤ@wo&v*Zg5e)0BT8+T"$|JB$?"&V/9AJzD`1)&qR+ԬY3*CV̴-{.=oFI4Ǡ2 pŬ&:=+n{WK #q(Ip%~E5hǿH9+Ζb?fR~)'!*e#s#%P}M*1]`c|h?^(Z4LҲc= {Q)0%Z&m8x"bEgV%29;pqۨsPkKZA tGhkQ|FZomp9`l@z SeT o$PD ~tٚ_d*DG60'$[dXˈ!DAÛM%p؛v|sOyzXfb=ZyY3)3 3gVda:KԊ(RfW?27nL`[G;qd C(Pй\:5[=}`Ie=V8ŋ)bOƴ* .QnC2C.V[%}ډ1w lӱG'~Ic  &LƋ./x5ϻ妔\ IioDlQppƻ]đ L'|*kk3cLacu=H(F^Gh%KE>dD+儒Kb&nD ÿRē*^pV8 qL8L!,XdJAe f a]9x񇶔zE{vQs >uaAd|A`eBks̪[ŅNpc<'T-JrpVj5l)x2KNq ^2;XvK^ F/#ϤUUmHa(_/X.SZ;LRb% AHD9#"5) bj :=BLf˸^M\")Zע%:-xX`3, {BgkC!d)p*   !p(,cΎ%lCzP(M _. Y#ʁzHg\kw̆^dv;w,*A88)M cjD*󯻆ZƺcH+.RtL) ]<' 7tCoVž\R !P}DbYY|馇/{zĪ>U֜昄{+©0fƘ"7MֈXuLxaޥwb%"B]I 8X3W?35 W|le1VR%KDƯ+B*<G°Q8uNw V@]1_0IZ#Q?ۍ  L t@WFʃzuSC p x q/Xm̷p4! MOX+/lTϹ?âŊߣt4].f{`K:`u@@ꀁf2!_pZXWC Q_C13#wKqyx܍#8n*FJX`/Cw )i=F~GyWmuUWI$n\slҹCJ:4dNO8~Dah S;&,(5fOdqFI2#0a@wWXvʫnXkWyde%RʬNS8)2Vn8zXЩ;X]0rV{7gr_ZyS8ظ+u8+g!*Rwg_B1pg_` #NJjcG]TaURb4=Z6-VNך+6( q]6VWR3J) d*NXJ6bWNݱUVv!&ib`h1 :ub+4 4i3kw\_+X]l%m"f߈axEVBDH$\UEҪ"Ais.7\C F[ M`ɸPRHOhQxk3ZfwzE=x8km;ziĖ͍/Vʾ,|peb Eʩ*E9Ȭu@VR`+'|N ri.ң-|ry.Ye=_J Ī.m?dz MhC/B)Z#L;PQT.aIO+I%S#xE_77E20kHrWݐT>(^q' pCE\yEc0)؝5.3|agDP@&M@CǪh HO g 0КA%]%{Q]Yc$ zDV,p(0͗VRZt5\TɕpN |BqF9ŘpƒQt/NZ4Ui%:зtӦGoogynXfG5נeBm [M 2ygHeJ[ޡDhX[2kzt^ŌD'TSĖ5gՈG腫o&e\5}_Gc\vg֮Pb8C'IIPђH\!B."+gT5-1pGL 5M\TkclQUz%Z8<@GL<^*Ψt|R8% B[aoyk LחS[ &2x-WpW[mWZmJ"ruhM4." S<9! RèeaI64F`9&٦X .71zZeN%QOt2L7mz'֐٨vE-Z W/ΈbD^BKX&67kn;eϿsaOiFxj~IDAT,[*:@/K`I<|C!_) KHiߥC]po}ʕYy:JpO"7ՃPW$rJtjYQ\|"F >ktπajjFB,Op [>]ϵxnpar豢疝܅3.u"Q%VhĈ{'m(DU퀁kP2eHTʓ1T[HpE1!瞆\8zma ܠ* `&+3g]9$̳ o.'PcX tÄu:[!]|pWCdX-! hFf^Gk}@]ppI{ w’Uf!-wubFUTsKcɿzT')HVXG`R` NNPmj8,'eേ+xp귮<7b%^R̟.4M`'_N5R+ή)&ɂQjirS.xWTQ0HJC aq첮eALǮm2Z2 రi,IKC)NBX4 hAp+e-l9\QޱDd BE1B;+˯qq\7QU'=use-2km4L&/]eU|x^ eVOjeA+Ko53I'ʸICՎX lUh -6F j[FqyWx :+r{^M  ̯c찮Z)z'Bϋt^ۻxէ)cAqQo<5%|d`tz7ʸQ"v4h$ m`skA7Mm,aW. xq<2|Wi.zA,+ JUIqX+#:F]f`q-1 XԂp;2w*l8wA?L+R]ٿdG6mW?q-osOw {0fA|OG]hyK4AKwAz.RZ}f@=z hWw ֣ nhizn{򨚜4 fOhd[17)=+}`vCf "\ѱW٤lla,//9ztnnX,^|хFDOK'9!`$%ՅF+>}7='pUBỏO~"vHvYU bgj&LE{vpSch[FǞȽ.¸㿊,5Ny;MKv/H/Jݣ,>R%I(x i04-4m]J~l.@rx lTFKg_\F@P[cϮ0^pi dkjP6"gPz]gYj7rR~WN, 5m$ڂHo|@<`ACEm dTF޲kcT6YVw4VqWj2Ǖ{6㊄^Ҏ!oz 9Dge3̱v.-X/\~xxgAgc6 [{g?+Z<2aC(J_+9] ,<jƝws yk_^REpΫoS>[8I[%~{_lڛ]OWA#"mP4?=Pk8|S׼>2rƞQwE98u[~:0q3u{`h\g lPS=`F 8JDM Zu_f?%,Z/b"6𓆬}0)FuB{b+KrSIjtd Dt ,š 6Zex|u?5aOĘ@##X]Mk[ďnV]5٣4X8#0ozoM^d˴4ի~;Go{>z6EʫmguA*0]e;pAo*]5A"hk2Qe{X~yu{`Wҙ}H87 @k/]i[' pl4Yᚡw npCI2N5TF-=S?hgϾ꺎_7Vӟ'qPJR<cEsrw m#Q4ԁ")tih_svJN.NYzϾ`x%_:#jb4dѦ+&X =&gbIskRVHRt-D۞Yϱ^܌f;_r;5[eJ)Ξʙ; $35Y->Oc+SX1{ K4tJF{vڅڴiu{ի~ud0K|vgw]˜yꁌ /XO+;# 0\LۇE`:[NJCɻC8BaU(ֱup4R*F,o!#:cثWJ">|FO{xTk\D\+ KG<_.SP S""6- Hp^PBÆN D Qd=, |ݟ ͟}T5FKٺ","Jbݣ YשwAe5k`M&#S^~\ ̢^AsX(Wy~1^ a)*rexG>j)cǎBSBUN?ܼ3.>d3YwI2))븤YsQwzz (Kl-.{NstY6Z7 ^?)[EOWP$Le, aFw$_;|˿?q}8oCX"X)dVQXH;rS6ku_ʾ/FeYq眏;ik'ǻj0g=^]gO_zs(so S +[9Bo}v[ afG7CZoq8ne0jw01_91gij}5A3ܞD-Ohu9VV/F0o'Nlݺ5Qi{|9ݵآUE#cdD,?gy pj?QKmv6نh8XX "_o>R. `=cotQKKBf&B,$(V` Ki͒FtR])tsn6BrmA@N$"2jb٨8(r@"C!kgQ<nBd@O]H "L)6!s+2psNܿz{ t]WtIe՛/fp K&>~KRj- g 2$tH "jb_+w*6ZR>\i[~>&XK&更}k֑V~B^\b DFH   9'li? cDOjwJ) G)dƕo;B3P|L$h1 &* WD;~63VaNԼSUĢwxO7rVz' )O-5۫%p#ѾdNp 㘷+F%kA'hben! )ֲ<:F\\xIHąS.U=3.a~,w534s˳&_7yIJ2ߜl, &/8;_=Moەe-8xʥ&mgw *xAsakZlyT83# gX sӍmALg3uޞIa&;ìd5_"1䉾|<ȊeݻgjjZ=0 y-ؾudZ+ bSu)|X']t4Z{gej%_oxu1C##%ٛAT>Ul&3*"SO0Un./1CCzqi'XbĶ0ADoL}oD bou9汷AC_O|t+t2M/ɩoynFo~/, ;UFC{OCg[o'yfiWpѿyyDᡡ??3R;w~r=H7_:xa|?wW׼5z?AU{~w_Z(+-{' qn)]_pK_I8H4ΪoDpʇv1A]sjoI+~F)^NE5MuU2sEeh'ei"L}}bKDzP$gDI0}Ȯ?swa@qS8㭕7>/w.OeEU|T.9X/G͉O5;{rAݝof/WxIRtMrq%37] :qNiS/>tۛ+.|||lxhh~ЭE ʘaԮu'cv*#~ⓟ AP^.x0Ÿ4Y-UAO,ȌW(%X-? u򄒹k)90t(dN$g4 6P*1ZwS>B,E;Jd,6zI8^U!~w"b4˹#A8MOKtJ>'gxs*QG~u-U$4j+mꏰ{#rgERj`͹?1(ţGhf)0zyXb]1?S$<ēO>\,׽uO7af?˿7 nޡ SaGL0x(pjiO (t$U(-rDGLfyIE~uRUY3J&uHz^$&SJy A%!(*٩gfC뼚r]+fU&HɈWM E!䷬숶B Xh(7K=Wcұ qv @ؒy~Ͻ[!Lr:׏EiIpyclhq( X){/YHHc}c@1՜Ou{D@Td\uDÞ^ejt mP?KեC{׮r!(w8f8y/؍6[ cހzJO)1H1+9cz'8E 5Gp<}k9Wl2JByH#K$r2 szC؍7N腲i!fss8y @0x:1 e1 .NYJ 01Sqx'(R+'Gk(Z×rYe@R8o}c} s7Ƅ+ZrXNFQE2?4 8I| ;34žg~^KbX r.Y&@0]嵰ͣ;+愩-]9W'*3ZM|\NVNkv'JhzAo]}{ÏUO@<ǎePZ9@7ҙd 5, ABNҨ^~-O)8RcLو>Ou2j})+bHjvEvXr۩C&BWoZNvUG8eYS8n X 0!~ > gX 8!Sx3+j xo?x[6+[~Oe~j8kzi~UuO~cضU1:=VXk'jg( 2(V<  -|sS ]q" գ)'_YeDrk|UİX&vrY"L IXy=\Ɖ@^xz%Wɖ}/љW^vH-@r6&1 v80-?k/{Gƈjwn l{béÐ_a̋ЉWꊪъ[G{y_X>v]K?\28?ygo4o~LH2l?|+v闎iz۶m۵sg[iy#M*N';wt>d(3wld˙XZ)CXrS`Tcɠ-{c)3JvX1ƙ/8™;~Mэx縢 R`Yԕz4s{Xke} dnIHJSwt[!zZ0_Iʭ.58=gp!Udrl%N rh3T !LD⧴!X@p@RG>kj?MkEz?6Å]#{>ޣ"%e8#,˵E#u[}d¦Ƙ .ޑ'A޾&(4rϝpZMX*D/Zx"FRU@>*8G^K"C$.%b8zώtPMJ|bT>2HNey|_['U|E 1֏,Q=Q{4ۼ9Eˉ Z~DJso>fX~J&z=:8(@hʱK9j/~9%B9z/~«{-{?ẖ^)55w#UN< `#mF mݼt RTW{Lq†9N1RXa)@kҖ5ii=P߼H;NKMo KϰNw^)dKG^XBkv`NOV>v^OpѰϟ4~槀13.UgWڿU]/?tOK^{x`Jِa+ƻTVHt9Nγ޵Rެ9:~}YVY 驆e+( |2)Sp*2Aã@U?J-9'XV$DIxIkfTseT%l 1(ݷrE#;իߝsf'05<:?mϙǚAX_D&3ce6%3͝>˜۹=km Fޞ᭩QR)8yk+G _#"܃:>9޶矸w*+[kvrS'wyBkl@[SZ! wp&3-9;g!Y)|0*b䂢()@*(3.TYgnsB>B:*NOBpŭWd/ɋ+K@BFi"Tq4g.< ,@i ip_KGyTzJqϛSc͚>i%mm9k֍y/D`a^ѼW̷?훷Mn,`20K'+~o:^;F:8^?v:hUdxsO*SMΥvZJHTH|J/IlCr_X"۟|sTyQI~E=|J*L6^y [{Jxw_ځsfz,N|$B|iE>Yq8__={2aUn +&SL@wʃ;sP9c-Peل$M5cF2KDDz߅g}lԗqb]t*|a0s4f Zk@&@qs˟86'OZ㙆>1<+/`VqDkƝB?]ٗ]4 S+MH^ȩ\~{vpbgo8-w?A0*Nt)uA"H-t `+TjfA`{`IȤ ÎT~anfRz tPϤU%[,L?mP|6B(PX>̒OvƜϝ~ۮLuG3?o}e 2`煤QoМ'S8[y7Oe+ʮwȧq}~W4_si~>-=QwF$XbM\s'OX\U ]{WwLܹ%D .QT#Dp?{Sߙ37_BgQXjfZ9=Noe3Xf+,f}YTh>$o%O K2J9sy"8rgʊ\78Ej$|]e,<,ېVv 骓KO7k>cH:|!3~q&b|}d|G)b䢶&V3DQWDPO-A\No[;D)\2nӕu+nޑNpJ(:18G8\A߈8ʈ>}煕Q+vpe}7>Z;YTlUA}ێ%(=aS/cBmI G[yĞJidJa۫{q{*{ʞ܀֎''(̩ѐ%0$-B*UA7ִ?C|ADZkr`\,osac.]24#Ccsڬ:m~V&:]M> qhC|ާH<3PCul GG*/3mDR$B`ŒiuIY$,2Y jqfp8Uyw; -ۋ7Vo*oͶ+\&9~+x]dCW]S/o=ohCeJ]Z)i̬Tc%'p"H9ƁxzBs" ++b"AOCjW/l#wDMu{_o-h[WG/[.l\xnf g g}[{tX58=s9\RDY%)|;* H&˅ HɀQ};cm q/k 7[瞒a=U4M  ^0!]PVP`ϑːN+){f>}d'WRZj[;Y&OD[#E%!*C_1jFj!|Իާ.yE.hx{t$W} maDgς͵/\WnXmL""I%ֆX8hXu< xmWoךNVύO}U;0~Q\,t8ؘgUvӳ hQZqO/#toz*&oڠbAAHC rP'Ȭ@ oh.T=ar,`|MJqt~ [G8\plp*&)<{ovwVȡ%l1AoCEe+)VwxǪ dTR}iv0JT 8c%j{. ʢ,uahxE/Ͼ~dw8vgU-(B|5JHrE)B.쾨xͰ{N 㵷"H`*yk?WeӽӄjGwǂ5sHT1{O= õ63PKnc-?OwEt=\l?'*Gf~g}{ vٗ_xy W#ȭ'離k$Jҷ"U1T\PjBVX@ ,zu,5  x]kvX^Mq*mTpL,UgAP`&sJv*eUA я,^!GZ@sqW @3 >eoM;^5d‘e U. {wcN-j afJc7تGJZ9"j+n=~޶+nߓIjO5n;zճJNF6 /Wqa_.Ye+@=4rzA3NNm'!ޜj<>jvV[qT|%oYD8Bpeg;kh񒚧I߱$sU8'X)2wϮog ~pG4E L`/hX'pmӯ @g$jk?]5ѹ~7(o^ _'xkÿ`ʱx&CĤ"PxyAtƇgYm9e|V1|1LU;p?^TI0k&w_vLJE, >2\lq WeL<'߼/|?:O|cĜxA  D6.σL,֏mֽ#DD|T$F')J:P,I`a8lY-L(, m`<>f"!boj͆wӣ"i'Nv7{Pz.J'ԬC:fQޛNBZ9(bmUJ릝Ϟ[{v#~f-j_oL]%$4üBU!ubXV,fi"@If(a񒡁-p-aMۯ|c 'PFGI1YxPc^,8 ; 'ԦfשCoGִ$ U$lvREj0erSkw3-OD8[8),N)7Bˀeg,׾{h>v}hzn5#X3׀k\NɺfD7`lO\V- &E:`82;IEgH%G4ӷJ_%H Ĭ:|lyg9Gvg@Ub=9珐0! \#/G[%Eɳ@#Y"׌mO^INEvJQQA\#dK˳2|fZ Y/⣤PuuTHB@c TK>R1KlCQ, &7 X䕚!ĐmtT7WTK&Vďy7h~wc#[&`E! *[mE+VQ8.L +6զ ZJ?ϜzLgw'Ep6"Ĉc)G KՋa1M Ҍx*YQݻKr#/ϧ5ZY>l5zƮ}x7]Ev o;hf)e|G!1Cώ3Rp؝J* ra0ϧUYQjuQ˟ԗ6[x4(akIg!+VP~Hdk-\j9zS&lc೼5ˣa{ڝd?\싇2qH1V X`!}}!͉N^gYQҐl=KpvGGkGQt8 & K Rr>:Nps$!!/aI3k[S 峏~k'WVIEꢬhGE_@J*PY 7΅a;lYd[IP؉Qm?gl ԫ,,F4(*EX"󤗧''NePY 47OD۲#ߣsgE&fx8Ωm#Ě;ˊU^4AIG+V,?A~T(2J#4,B%TE@n> 2CH [&; ~<"n\9ThrK-XQf@7j*=$b[ų_FkOcŁHdч{}V @ēx&y4ۣ}o18H{?4t ZVU tҫXqlgۃ蹓${`oGa0|Ekqq)Q5QPt#b(Z)^2,p,"-,'%-ʐ8˻qIvG^^mX,Ve oUO$Q*K- LI]yu1~->JJB [ ǃvݒ|>LD NyXPdq-{ύMA HiVJrP%يBXa9#)3f|+?}';~Rh%%PA%0VXeR-' \`*ʵ mVy:-Bzk E9&!m0#Ke5lb垿(޼*e]xr2DE›pWM Jauc;?6Vk/a MO3$b+;,$1Qko TPPGyg?H{.9݀`mѫXJr[_|չ~nv&O턣yt4sXvnlJ6OV7enKY[2ύ-t9Nuri0M<:{7iI{}@ FnՒFnUg!oa?e׀Qh `t>?,bO,89_?9FS:m(ϊ4 b$!¢H;YɇmUtc/ IO=3XkU-2BB&481`x*,HC̷QG$uBK1I_j0?,V` H\hwb TEApaRd9Uc@)WE ; qlƋן\|%_ojx8 omHx1+!\ߙQByrezP*d|'b>x}A]P;(-C23HLړ$Q !dpbH60*Uw-$*/X+F\Tb'mDN:^*grUA^VPڳt2eneD.B~~ti7Xs~rtmB°s-xKKE(I+Sݺ`ZARj?kGO#9Os>^ɘԳy,m7?Cqƿ^.k)L}a1 g ijR56y x -Aоy0 1[|bK_ 9nuvXdΎdUĥe-v/No?}Gi̴,Рz']iK7h+?$$d#8TJ3 3!8([r#yKB2YIJHD Xrȅvyl+Yo\2OW0b@T63L9!Qa7aS-J;mqry>ch-G3i}HB,B^H؊E#p[{B`*ykQ]}gt.r/|M_kFWKxj+ɐ8lkwW?{'ǒJCY` Ff笼8PՁjk_sړSthyij?5);)J:$)%%*}Tת:dq;MK$~ȰjzlBU:[fd1/m\o^_?E5[" yD)o"sby&"e,e[󭗎.ɭ<^z;F ٘[X=E(5shKk [$gvFwcCfiNSU h4x˱:'If_r_d)]Gy TYĦ]ZiAKDcU<ؔ/su%ȼ(s?ON>JDpi%uUI(K'_<1:uxrB> Y U\PqQy;Y `jx ts!xRmnj>O2&fȣe`ϢlA~vWүzϰG,6WkoVwю*kȣ g$B{'r}3ߍ1d2jљda8J~r:8s?*<^-BJY'{GO$3D5ey$K4$+6+cuR E)1'Q/8w+XENa.exEldc`D{%; 2[)=ƵB6᳤Fz/-xt/?g&5KŞ0^Y"Rڦf6jn%x7qg(g u>U02CKy)ޖe]3?s kk[, x֩0|צk[LXV3YC3,DOՃ߹c7AN"A|c퐅Au'd.ngG<{><; ޵ sW_m]{'jx[S;jb hkCizC#X:cDky *S[{ڢdy^ڎ^4{}18;sTpݻn o$Nf6]hFl %rQf}XI Cj|=( ٜr`e"F5QE0s}@yd؉2u!Zi+`(ڙhei؅%`8¢5 T*l^MiުVYus߼tjӰd%`M38 ax-o- ;c Q KLέo]뿹;xNt0#y^u;3ЍP k'#β!z]O =^R-|