diff --git a/.babelrc b/.babelrc
index cf97ee5ce..43a5682a6 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,10 +1,9 @@
{
"presets": [
[
- "@babel/preset-env",
+ "env",
{
- "useBuiltIns": "entry",
- "targets": "> 2%"
+ "forceAllTransforms": true
}
]
]
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index cdfdd3780..000000000
--- a/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-yarn.lock binary
diff --git a/.gitignore b/.gitignore
index 8e067e264..810939e66 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,8 +3,4 @@ _site
.jekyll-metadata
/node_modules
/vendor
-.idea/
-
-# Generated by 'yarn dev'
-/_includes/2017/critical/critical-home.js
-/_includes/2017/critical/critical-sheet.js
+.idea/
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
index 4f49fe278..ae863e143 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,6 +1,5 @@
{
"semi": false,
"singleQuote": true,
- "jsxSingleQuote": true,
- "trailingComma": "none"
+ "jsxSingleQuote": true
}
diff --git a/.travis.yml b/.travis.yml
index f5002202e..3f83d39f1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,25 +1,10 @@
language: ruby
-rvm: [2.7.1]
-
-before_install:
- - nvm install 12
- - nvm use 12
- - node --version
- - ruby --version
-
-install:
- - yarn --frozen-lockfile
- - bundle --jobs=3 --retry=3 --deployment --path=${BUNDLE_PATH:-vendor/bundle}
-
+rvm:
+- 2.5
script:
- - yarn build
- - yarn test
- - if ! make test; then make test-warning; exit 16; fi
-
-cache:
- bundler: true
- yarn: true
-
+- make -B _site
+- if ! make test; then make test-warning; exit 16; fi
+cache: bundler
notifications:
slack:
if: branch = master OR branch =~ ^.*slack.*$
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f5268af92..8fc6a1912 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,7 +1,6 @@
# Developer notes
-## Gitpod
-
+## Gitpod
This repository supports contribution using [gitpod](https://gitpod.io) which is online IDE using [Theia](https://github.com/eclipse-theia/theia).
To open-up the environment simple natigate on https://gitpod.io/#https://github.com/rstacruz/cheatsheets
@@ -10,14 +9,14 @@ Or using a button:
[](https://gitpod.io/#https://github.com/rstacruz/cheatsheets)
### Preview built website
-
To preview the website you need to first build it then you can navigate to file that you are trying to contribute and preview directly.
+
## Starting a local instance
-This starts Jekyll and Parcel. This requires recent versions of [Node.js], [Yarn], [Ruby] and [Bundler] installed.
+This starts Jekyll and Webpack. This requires recent versions of [Node.js], [Yarn], [Ruby] and [Bundler] installed.
```bash
yarn install
@@ -57,11 +56,9 @@ See for a reference on styling.
## JavaScript
-When updating JavaScript, be sure Parcel is running (`yarn dev` takes care of this).
+When updating JavaScript, be sure webpack is running (`yarn run dev` takes care of this).
-This auto-updates `/assets/packed/` and `_includes/2017/critical/` with sources in `_parcel/`.
-
-Before committing, run `yarn parcel:build` first.
+This auto-updates `/assets/packed/` with sources in `_js/`.
## JavaScript tests
@@ -78,16 +75,16 @@ Each sheet supports these metadata:
```yml
---
title: React.js
-layout: 2017/sheet # 'default' | '2017/sheet'
+layout: 2017/sheet # 'default' | '2017/sheet'
# Optional:
category: React
-updated: 2017-08-30 # To show in the updated list
-ads: false # Add this to disable ads
-weight: -5 # lower number = higher in related posts list
-deprecated: true # Don't show in related posts
-deprecated_by: /enzyme # Point to latest version
-prism_languages: [vim] # Extra syntax highlighting
+updated: 2017-08-30 # To show in the updated list
+ads: false # Add this to disable ads
+weight: -5 # lower number = higher in related posts list
+deprecated: true # Don't show in related posts
+deprecated_by: /enzyme # Point to latest version
+prism_languages: [vim] # Extra syntax highlighting
intro: |
This is some *Markdown* at the beginning of the article.
tags:
@@ -96,10 +93,9 @@ tags:
# Special pages:
# (don't set these for cheatsheets)
-type: home # home | article | error
-og_type: website # opengraph type
+type: home # home | article | error
+og_type: website # opengraph type
---
-
```
## Prism languages
@@ -119,7 +115,6 @@ title: ES2015
category: Hidden
redirect_to: /es6
---
-
```
## Localizations
@@ -175,3 +170,26 @@ building web user interfaces...
### intro only
If you left out `description` or `keywords`, a default description will be added.
+
+## Critical path CSS
+
+The critical path CSS is stored in:
+
+- `_includes/2017/critical/home.html`
+- `_includes/2017/critical/sheet.html`
+
+You'll need to update these every now and then when you change something in the CSS. Use this to update these snippets:
+
+```
+yarn run critical
+```
+
+You can temporarily disable critical path optimizations by loading it with `?nocrit=1`, eg, `https://devhints.io/?nocrit=1`.
+
+## Critical path JS
+
+There's JavaScript that's included inline in every page. It's entrypoint is:
+
+- `_js/critical.js`
+
+This is automatically compiled into the partial `_includes/2017/critical/critical.js`. Keep this bundle as small as possible.
diff --git a/Dockerfile b/Dockerfile
index 817e26443..997ad584f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
-FROM ruby:2.7.1
-RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
+FROM ruby:2.5.1
+RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -qq --no-install-recommends \
diff --git a/Makefile b/Makefile
index f63846fed..e2ad817c4 100644
--- a/Makefile
+++ b/Makefile
@@ -9,14 +9,43 @@ help:
@echo
# Builds intermediate files. Needs a _site built first though
-update: _site
+update: _site critical
# Builds _site
_site:
- yarn build
+ bundle exec jekyll build --incremental
-dev:
- yarn dev
+critical: _site ## Builds critical path CSS/JS
+ node _support/critical.js
+
+# Ensure that bins are available.
+ensure-bin:
+ @if [ ! -d $(npmbin) ]; then \
+ echo "---"; \
+ echo "Error: $(npmbin) not found, you may need to run '[docker-compose run --rm web] yarn install'."; \
+ echo "---"; \
+ exit 1; \
+ fi
+ @if ! which jekyll &>/dev/null; then \
+ echo "---"; \
+ echo "Warning: Jekyll not found, you may need to run '[docker-compose run --rm web] bundle install'."; \
+ echo "---"; \
+ fi
+
+dev: ensure-bin ## Starts development server
+ $(npmbin)/concurrently -k -p command -c "blue,green" \
+ "make dev-webpack" \
+ "make dev-jekyll"
+
+dev-webpack: ensure-bin
+ $(npmbin)/webpack --watch --colors -p
+
+dev-jekyll: ensure-bin
+ if [ -f _site ]; then \
+ bundle exec jekyll serve --safe --trace --drafts --watch --incremental --host $(HOST) --port $(PORT); \
+ else \
+ bundle exec jekyll serve --safe --trace --drafts --watch --host $(HOST) --port $(PORT); \
+ fi
test: _site ## Runs rudimentary tests
@test -f _site/vim.html
diff --git a/_config.yml b/_config.yml
index 499ea866f..f931eb28a 100644
--- a/_config.yml
+++ b/_config.yml
@@ -9,23 +9,21 @@ plugins:
- jekyll-github-metadata
exclude:
- - .babelrc
- - .cache
- - CNAME
+ - Makefile
+ - README.md
- CONTRIBUTING.md
- - docker_compose.yml
- - Dockerfile
- Gemfile
- Gemfile.lock
- - Makefile
- - node_modules
- - package.json
- - package-lock.json
- - README.md
+ - CNAME
- vendor
- - webpack.config.js
- - yarn-error.log
+ - package.json
+ - .babelrc
- yarn.lock
+ - package-lock.json
+ - webpack.config.js
+ - node_modules
+ - Dockerfile
+ - docker_compose.yml
# Markdown
diff --git a/_includes/2017/critical/critical-home.css b/_includes/2017/critical/critical-home.css
deleted file mode 100644
index 5b114b574..000000000
--- a/_includes/2017/critical/critical-home.css
+++ /dev/null
@@ -1,3 +0,0 @@
-*,:after,:before{box-sizing:border-box}:after,:before{text-decoration:inherit;vertical-align:inherit}html{cursor:default;line-height:1.5;-moz-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;word-break:break-word}body{margin:0}h1{font-size:2em;margin:.67em 0}dl dl,dl ol,dl ul,ol dl,ol ol,ol ul,ul dl,ul ol,ul ul{margin:0}hr{height:0;overflow:visible}main{display:block}nav ol,nav ul{list-style:none;padding:0}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}audio,canvas,iframe,img,svg,video{vertical-align:middle}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}iframe,img{border-style:none}svg:not([fill]){fill:currentColor}svg:not(:root){overflow:hidden}table{border-collapse:collapse}button,input,select{margin:0}button{overflow:visible;text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}fieldset{border:1px solid #a0a0a0;padding:.35em .75em .625em}input{overflow:visible}legend{color:inherit;display:table;max-width:100%;white-space:normal}progress{display:inline-block;vertical-align:baseline}select{text-transform:none}textarea{margin:0;overflow:auto;resize:vertical}[type=checkbox],[type=radio]{padding:0}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-moz-focus-inner{border-style:none;padding:0}:-moz-focusring{outline:1px dotted ButtonText}:-moz-ui-invalid{box-shadow:none}details,dialog{display:block}dialog{background-color:#fff;border:solid;color:#000;height:-moz-fit-content;height:-webkit-fit-content;height:fit-content;left:0;margin:auto;padding:1em;position:absolute;right:0;width:-moz-fit-content;width:-webkit-fit-content;width:fit-content}dialog:not([open]){display:none}summary{display:list-item}canvas{display:inline-block}template{display:none}[tabindex],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}[hidden]{display:none}[aria-busy=true]{cursor:progress}[aria-controls]{cursor:pointer}[aria-disabled=true],[disabled]{cursor:not-allowed}[aria-hidden=false][hidden]{display:initial}[aria-hidden=false][hidden]:not(:focus){clip:rect(0,0,0,0);position:absolute}@charset "UTF-8";
-/*! ionicons-inline v0.0.10 | MIT | https://github.com/rstacruz/ionicons-inline */
-/*! ionicons-inline v0.0.10 | MIT | https://github.com/rstacruz/ionicons-inline */body,html{background:#f1f3f5;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:14px;line-height:1.6;color:#345;overflow-x:hidden}body{font-size:13px;padding:0;margin:0}@media (min-width:480px) and (max-width:768px){body{font-size:calc(13px + 1*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){body{font-size:calc(14px + 0*(100vw - 768px)/512)}}@media (min-width:1280px){body{font-size:14px}}code,pre{font-family:cousine,SFMono-Regular,Consolas,Menlo,Liberation Mono,Ubuntu Mono,Courier,monospace;letter-spacing:-.03em}pre{font-size:.96em}:not(pre):not(code){-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a{color:#26648e}a:visited{color:#15234d}a:hover{color:#3ac1cb}[aria-hidden]:not(.line-highlight){display:none!important}@media (max-width:580px){.hint--bottom:after,.hint--bottom:before{display:none}}html.WithJs .post-content{opacity:0}html.WithJs .intro-content,html.WithJs .pages-list,html.WithJs .post-content.-wrapified{opacity:.4}html.WithJs.LoadDone .intro-content,html.WithJs.LoadDone .pages-list,html.WithJs.LoadDone .post-content.-wrapified{opacity:1;transition:opacity .1s linear .1s}.attribute-peg{display:inline-block;height:12px;width:20px;text-align:center}.attribute-peg>span{display:inline-block;width:8px;height:8px;background:#77dab2;border-radius:50%}.announcements-item{position:relative;box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3),0 8px 12px rgba(58,193,203,.1);border-radius:1px;background:#fff;padding:16px 48px 16px 16px;animation:announcements-item-flyin .5s ease-out;transition:opacity .5s linear,transform .5s ease-out}.announcements-item.-hide{display:none}.announcements-item>.title{font-size:14.95px;font-weight:400;color:#745fb5;margin:0;padding:0}@media (min-width:480px) and (max-width:768px){.announcements-item>.title{font-size:calc(14.95px + 1.29*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.announcements-item>.title{font-size:calc(16.24px + 0.14*(100vw - 768px)/512)}}@media (min-width:1280px){.announcements-item>.title{font-size:16.38px}}.announcements-item>.body>p{margin:0;padding:0}.announcements-item>.body>p+p{margin-top:1em}.announcements-item>.close{position:absolute;right:0;top:0;width:40px;height:40px;line-height:40px;text-align:center;border:0;margin:0;padding:0;cursor:pointer;background:transparent}.announcements-item>.close:focus,.announcements-item>.close:hover{color:#745fb5}.announcements-item>.close:before{content:"×";font-size:14px}@keyframes announcements-item-flyin{0%{transform:translate3d(0,32px,0);opacity:0}to{transform:translateZ(0);opacity:1}}.announcements-list{position:fixed;left:0;bottom:0;max-width:420px;padding:0;z-index:10}@media (min-width:481px){.announcements-list{padding:16px}}@media (min-width:769px){.announcements-list{padding:32px}}.back-button{text-decoration:none;width:48px;height:48px;line-height:46px;text-align:center;display:inline-block;border-radius:50%;transition:all .1s linear}@media (max-width:480px){.back-button{width:32px;height:32px;line-height:30px}}.back-button,.back-button:visited{color:#678}.back-button:focus,.back-button:hover{color:#fff;background:#745fb5;opacity:1}.back-button:before{content:"";display:inline-block;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23345' d='M427 234.625H167.296l119.702-119.702L256 85 85 256l171 171 29.922-29.924-118.626-119.7H427v-42.75z'/%3E%3C/svg%3E") 50%/24px 24px no-repeat;height:24px;width:24px;vertical-align:middle}.back-button:focus:before,.back-button:hover:before{display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23FFF' d='M427 234.625H167.296l119.702-119.702L256 85 85 256l171 171 29.922-29.924-118.626-119.7H427v-42.75z'/%3E%3C/svg%3E") 50%/24px 24px no-repeat;height:24px;width:24px}@media (max-width:480px){.back-button:before{font-size:16px}}.body-area{max-width:1232px;margin:0 auto;padding:16px}@media (max-width:480px){.body-area{padding:16px}}.body-area.-slim{max-width:740px}.codefund-sponsor{min-height:114px}.codefund-sponsor .cf-wrapper{margin-left:auto;margin-right:auto}.page-actions{margin:0;padding:0;height:32px}.page-actions>.link.link>a{display:inline-block;height:32px;line-height:32px;vertical-align:top;width:auto}.page-actions>li{margin:0;padding:0;list-style-type:none}.page-actions>li>a,.page-actions>li>a:visited{color:#678;text-decoration:none}.page-actions>li>a:focus,.page-actions>li>a:focus>.text,.page-actions>li>a:hover,.page-actions>li>a:hover>.text{color:#745fb5}.page-actions>li>a>.text{font-size:11.3043478261px;display:none}@media (min-width:480px) and (max-width:768px){.page-actions>li>a>.text{font-size:calc(11.30435px + 0.76462*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.page-actions>li>a>.text{font-size:calc(12.06897px + -0.10315*(100vw - 768px)/512)}}@media (min-width:1280px){.page-actions>li>a>.text{font-size:11.9658119658px}}.page-actions>li>a>.text.-visible{display:inline}.page-actions+.page-actions{margin-left:8px}.page-actions>.facebook>a:before,.page-actions>.github>a:before,.page-actions>.twitter>a:before{content:"";vertical-align:middle}.page-actions>.facebook>a:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23345' d='M426.8 64H85.2C73.5 64 64 73.5 64 85.2v341.6c0 11.7 9.5 21.2 21.2 21.2H256V296h-45.9v-56H256v-41.4c0-49.6 34.4-76.6 78.7-76.6 21.2 0 44 1.6 49.3 2.3v51.8h-35.3c-24.1 0-28.7 11.4-28.7 28.2V240h57.4l-7.5 56H320v152h106.8c11.7 0 21.2-9.5 21.2-21.2V85.2c0-11.7-9.5-21.2-21.2-21.2z'/%3E%3C/svg%3E") 50%/16px 16px no-repeat}.page-actions>.facebook>a:before,.page-actions>.twitter>a:before{display:inline-block;vertical-align:middle;height:16px;width:16px}.page-actions>.twitter>a:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23345' d='M492 109.5c-17.4 7.7-36 12.9-55.6 15.3 20-12 35.4-31 42.6-53.6-18.7 11.1-39.4 19.2-61.5 23.5C399.8 75.8 374.6 64 346.8 64c-53.5 0-96.8 43.4-96.8 96.9 0 7.6.8 15 2.5 22.1-80.5-4-151.9-42.6-199.6-101.3-8.3 14.3-13.1 31-13.1 48.7 0 33.6 17.2 63.3 43.2 80.7-16-.4-31-4.8-44-12.1v1.2c0 47 33.4 86.1 77.7 95-8.1 2.2-16.7 3.4-25.5 3.4-6.2 0-12.3-.6-18.2-1.8 12.3 38.5 48.1 66.5 90.5 67.3-33.1 26-74.9 41.5-120.3 41.5-7.8 0-15.5-.5-23.1-1.4C62.8 432 113.7 448 168.3 448 346.6 448 444 300.3 444 172.2c0-4.2-.1-8.4-.3-12.5C462.6 146 479 129 492 109.5z'/%3E%3C/svg%3E") 50%/16px 16px no-repeat}.page-actions>.github>a:before{display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23345' d='M256 32C132.3 32 32 134.9 32 261.7c0 101.5 64.2 187.5 153.2 217.9 1.4.3 2.6.4 3.8.4 8.3 0 11.5-6.1 11.5-11.4 0-5.5-.2-19.9-.3-39.1-8.4 1.9-15.9 2.7-22.6 2.7-43.1 0-52.9-33.5-52.9-33.5-10.2-26.5-24.9-33.6-24.9-33.6-19.5-13.7-.1-14.1 1.4-14.1h.1c22.5 2 34.3 23.8 34.3 23.8 11.2 19.6 26.2 25.1 39.6 25.1 10.5 0 20-3.4 25.6-6 2-14.8 7.8-24.9 14.2-30.7-49.7-5.8-102-25.5-102-113.5 0-25.1 8.7-45.6 23-61.6-2.3-5.8-10-29.2 2.2-60.8 0 0 1.6-.5 5-.5 8.1 0 26.4 3.1 56.6 24.1 17.9-5.1 37-7.6 56.1-7.7 19 .1 38.2 2.6 56.1 7.7 30.2-21 48.5-24.1 56.6-24.1 3.4 0 5 .5 5 .5 12.2 31.6 4.5 55 2.2 60.8 14.3 16.1 23 36.6 23 61.6 0 88.2-52.4 107.6-102.3 113.3 8 7.1 15.2 21.1 15.2 42.5 0 30.7-.3 55.5-.3 63 0 5.4 3.1 11.5 11.4 11.5 1.2 0 2.6-.1 4-.4C415.9 449.2 480 363.1 480 261.7 480 134.9 379.7 32 256 32z'/%3E%3C/svg%3E") 50%/16px 16px no-repeat;height:16px;width:16px}.page-actions>.github>a:hover:before{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23FFF' d='M256 32C132.3 32 32 134.9 32 261.7c0 101.5 64.2 187.5 153.2 217.9 1.4.3 2.6.4 3.8.4 8.3 0 11.5-6.1 11.5-11.4 0-5.5-.2-19.9-.3-39.1-8.4 1.9-15.9 2.7-22.6 2.7-43.1 0-52.9-33.5-52.9-33.5-10.2-26.5-24.9-33.6-24.9-33.6-19.5-13.7-.1-14.1 1.4-14.1h.1c22.5 2 34.3 23.8 34.3 23.8 11.2 19.6 26.2 25.1 39.6 25.1 10.5 0 20-3.4 25.6-6 2-14.8 7.8-24.9 14.2-30.7-49.7-5.8-102-25.5-102-113.5 0-25.1 8.7-45.6 23-61.6-2.3-5.8-10-29.2 2.2-60.8 0 0 1.6-.5 5-.5 8.1 0 26.4 3.1 56.6 24.1 17.9-5.1 37-7.6 56.1-7.7 19 .1 38.2 2.6 56.1 7.7 30.2-21 48.5-24.1 56.6-24.1 3.4 0 5 .5 5 .5 12.2 31.6 4.5 55 2.2 60.8 14.3 16.1 23 36.6 23 61.6 0 88.2-52.4 107.6-102.3 113.3 8 7.1 15.2 21.1 15.2 42.5 0 30.7-.3 55.5-.3 63 0 5.4 3.1 11.5 11.4 11.5 1.2 0 2.6-.1 4-.4C415.9 449.2 480 363.1 480 261.7 480 134.9 379.7 32 256 32z'/%3E%3C/svg%3E")}.page-actions>.facebook>a:before,.page-actions>.twitter>a:before{width:32px;height:32px}.page-actions>.github>a:before{position:relative;top:-2px}.page-actions>.link.-button>a{box-shadow:inset 0 0 0 1px rgba(102,119,136,.2);border-radius:2px;padding:0 16px;margin:0 8px;transition:all .1s linear}.page-actions>.link.-button>a>.text{margin-left:4px;position:relative;top:-1px}.page-actions>.link.-button>a:focus,.page-actions>.link.-button>a:hover{background:linear-gradient(5deg,#745fb5,#9066b8);box-shadow:0 1px 1px rgba(102,119,136,.55)}.page-actions>.link.-button>a:focus,.page-actions>.link.-button>a:focus>.text,.page-actions>.link.-button>a:hover,.page-actions>.link.-button>a:hover>.text{color:#fff}@media (max-width:768px){.page-actions>.link{margin-left:16px}}.page-actions>.link:first-child>a{margin-left:0}.page-actions>.link:last-child>a{margin-right:0}.pages-list{display:flex;flex-wrap:wrap}.pages-list>.item{flex:0 0 100%}.pages-list>.item.article{flex:0 0 50%}@media (min-width:581px){.pages-list>.item.top-sheet{flex:0 0 25%}}.pages-list>.article{text-decoration:none;display:block;white-space:nowrap;padding:4px 0}.pages-list>.article,.pages-list>.article:visited{color:#92a0ad}.pages-list>.article>.info>.slug{color:#111}.pages-list>.article:visited>.info>.slug{color:#345}.pages-list>.article>.info>.title:before{content:"";margin:0 4px}.pages-list>.article>.info>.title{opacity:0}@media (max-width:768px){.pages-list>.article>.info>.title{display:none}}.pages-list>.article:focus,.pages-list>.article:hover{color:#678}.pages-list>.article:focus>.info>.title,.pages-list>.article:hover>.info>.title{opacity:1;color:#745fb5}.pages-list>.category{font-size:14.95px;border-bottom:1px solid rgba(102,119,136,.2);margin:16px 0;padding:0 0 16px;font-weight:400;color:#745fb5}@media (min-width:480px) and (max-width:768px){.pages-list>.category{font-size:calc(14.95px + 1.29*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.pages-list>.category{font-size:calc(16.24px + 0.14*(100vw - 768px)/512)}}@media (min-width:1280px){.pages-list>.category{font-size:16.38px}}.search-box{background:#fff;box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3);display:flex;height:64px;align-items:center;cursor:text}.search-box>input{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:17.1925px;height:64px;background:transparent;border:0;flex:1 1 auto;padding:16px 16px 16px 0;font-weight:700;color:#111;min-width:48px}@media (min-width:480px) and (max-width:768px){.search-box>input{font-size:calc(17.1925px + 1.6459*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.search-box>input{font-size:calc(18.8384px + 0.3262*(100vw - 768px)/512)}}@media (min-width:1280px){.search-box>input{font-size:19.1646px}}.search-box>input::placeholder{font-weight:400;color:#678}.search-box>input:focus{outline:0}.search-box>.prefix{font-size:13px;display:block;color:rgba(102,119,136,.5);font-weight:400;user-select:none;line-height:1.5em;padding:2px 8px;border-radius:3px;background:rgba(241,243,245,.5);margin:0 0 0 16px;box-shadow:0 1px 1px rgba(102,119,136,.25)}@media (min-width:480px) and (max-width:768px){.search-box>.prefix{font-size:calc(13px + 1*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.search-box>.prefix{font-size:calc(14px + 0*(100vw - 768px)/512)}}@media (min-width:1280px){.search-box>.prefix{font-size:14px}}.search-box>.sep{color:rgba(102,119,136,.5);font-size:17.1925px;margin:0 8px}@media (min-width:480px) and (max-width:768px){.search-box>.sep{font-size:calc(17.1925px + 1.6459*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.search-box>.sep{font-size:calc(18.8384px + 0.3262*(100vw - 768px)/512)}}@media (min-width:1280px){.search-box>.sep{font-size:19.1646px}}@media (max-width:768px){.search-box>.prefix,.search-box>.sep{display:none}.search-box>input{padding-left:16px}}.search-box:before{content:"";display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23111' d='M337.51 305.372h-17.502l-6.57-5.486c20.79-25.232 33.92-57.054 33.92-93.257C347.36 127.63 283.897 64 205.136 64 127.452 64 64 127.632 64 206.63s63.452 142.627 142.225 142.627c35.01 0 67.83-13.167 92.99-34.008l6.562 5.486v17.55L415.18 448 448 415.086 337.51 305.372zm-131.285 0c-54.702 0-98.463-43.887-98.463-98.743 0-54.86 43.76-98.743 98.463-98.743 54.7 0 98.462 43.884 98.462 98.742 0 54.855-43.762 98.742-98.462 98.742z'/%3E%3C/svg%3E") 50%/32px 32px no-repeat;height:32px;width:32px;background-position:50%;flex:0 0 64px;width:64px;order:2}.search-box.-small{height:48px}.search-box.-small>input{height:48px;padding:8px 8px 8px 0}.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:14.95px}@media (min-width:480px) and (max-width:768px){.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:calc(14.95px + 1.29*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:calc(16.24px + 0.14*(100vw - 768px)/512)}}@media (min-width:1280px){.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:16.38px}}.search-box.-small:before{flex:0 0 48px;width:48px;line-height:48px;background-size:24px 24px;background-position:50%}.site-header{margin:32px 0}.site-header>p{margin:0;padding:0;text-align:center;color:#678}.site-header>p>a{text-decoration:none}.site-header>h1{font-size:39.767297213px;line-height:1.2;padding:0;color:#111;font-weight:200;text-align:center;margin:0 0 16px}@media (min-width:480px) and (max-width:768px){.site-header>h1{font-size:calc(39.7673px + 6.13051*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.site-header>h1{font-size:calc(45.89781px + 3.26254*(100vw - 768px)/512)}}@media (min-width:1280px){.site-header>h1{font-size:49.1603458612px}}.site-header>.action,.site-header>.search{margin-top:32px}.site-header>.adbox{margin:16px auto}@media (max-width:480px){.site-header>.adbox{margin-left:-16px;margin-right:-16px}}.top-nav,.top-nav>.container{height:64px;line-height:64px;text-align:center;position:relative}@media (max-width:480px){.top-nav>.container{height:32px;line-height:32px;margin-top:8px}.top-nav{height:48px;padding:8px 0;border-bottom:1px solid rgba(102,119,136,.2);margin-bottom:8px}}.top-nav>.container{padding-left:16px;padding-right:16px;max-width:1232px;margin:0 auto}@media (max-width:480px){.top-nav>.container{padding-left:16px;padding-right:16px}}.top-nav>.container{display:flex;align-items:center;position:relative}.top-nav>.container>.left{flex:0 0 auto;line-height:32px}.top-nav>.container>.brand{flex:1 1 auto}.top-nav>.container>.actions{flex:0 0 auto;display:flex}.top-nav>.container>.brand{font-size:11.3043478261px;display:inline-block;font-weight:700;text-transform:uppercase;letter-spacing:.05em;text-decoration:none}@media (min-width:480px) and (max-width:768px){.top-nav>.container>.brand{font-size:calc(11.30435px + 0.76462*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.top-nav>.container>.brand{font-size:calc(12.06897px + -0.10315*(100vw - 768px)/512)}}@media (min-width:1280px){.top-nav>.container>.brand{font-size:11.9658119658px}}.top-nav>.container>.brand,.top-nav>.container>.brand:visited{color:#345}.top-nav>.container>.brand:hover{color:#745fb5}@media (max-width:480px){.top-nav>.container>.brand{display:none}.top-nav>.container>.actions{margin-left:auto}}@media (min-width:481px){.top-nav>.container>.actions{position:absolute;right:16px;top:16px}}@media (min-width:481px) and (max-width:480px){.top-nav>.container>.actions{right:16px}}@media (min-width:481px){.top-nav>.container>.left{position:absolute;left:16px;top:16px}}@media (min-width:481px) and (max-width:480px){.top-nav>.container>.left{left:16px}}@media (min-width:1232px){.top-nav>.container>.left>.home{position:relative;left:-16px}}.top-sheet.top-sheet{padding:4px;text-decoration:none}.top-sheet.top-sheet>.info{display:block;background:#745fb5;color:#fff;text-align:left;padding:16px;width:auto;border-radius:3px;box-shadow:0 1px 1px rgba(102,119,136,.55);text-shadow:0 1px 1px rgba(51,68,85,.3);white-space:nowrap}.top-sheet.top-sheet:focus>.info,.top-sheet.top-sheet:hover>.info{box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3)}.top-sheet.top-sheet:nth-of-type(3n+1)>.info{background:linear-gradient(15deg,#745fb5,#9a6dbb)}.top-sheet.top-sheet:nth-of-type(3n+1):focus>.info,.top-sheet.top-sheet:nth-of-type(3n+1):hover>.info{background:#5f4aa1}.top-sheet.top-sheet:nth-of-type(3n+2)>.info{background:linear-gradient(15deg,#678,#6f8793)}.top-sheet.top-sheet:nth-of-type(3n+2):focus>.info,.top-sheet.top-sheet:nth-of-type(3n+2):hover>.info{background:#556371}.top-sheet.top-sheet:nth-of-type(3n+3)>.info{background:linear-gradient(15deg,#14af83,#15b89a)}.top-sheet.top-sheet:nth-of-type(3n+3):focus>.info,.top-sheet.top-sheet:nth-of-type(3n+3):hover>.info{background:#108b68}.top-sheet.top-sheet>.info>.title{display:none}
\ No newline at end of file
diff --git a/_includes/2017/critical/critical-sheet.css b/_includes/2017/critical/critical-sheet.css
deleted file mode 100644
index ccef97024..000000000
--- a/_includes/2017/critical/critical-sheet.css
+++ /dev/null
@@ -1,3 +0,0 @@
-*,:after,:before{box-sizing:border-box}:after,:before{text-decoration:inherit;vertical-align:inherit}html{cursor:default;line-height:1.5;-moz-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;word-break:break-word}body{margin:0}h1{font-size:2em;margin:.67em 0}dl dl,dl ol,dl ul,ol dl,ol ol,ol ul,ul dl,ul ol,ul ul{margin:0}hr{height:0;overflow:visible}main{display:block}nav ol,nav ul{list-style:none;padding:0}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}audio,canvas,iframe,img,svg,video{vertical-align:middle}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}iframe,img{border-style:none}svg:not([fill]){fill:currentColor}svg:not(:root){overflow:hidden}table{border-collapse:collapse}button,input,select{margin:0}button{overflow:visible;text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}fieldset{border:1px solid #a0a0a0;padding:.35em .75em .625em}input{overflow:visible}legend{color:inherit;display:table;max-width:100%;white-space:normal}progress{display:inline-block;vertical-align:baseline}select{text-transform:none}textarea{margin:0;overflow:auto;resize:vertical}[type=checkbox],[type=radio]{padding:0}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-moz-focus-inner{border-style:none;padding:0}:-moz-focusring{outline:1px dotted ButtonText}:-moz-ui-invalid{box-shadow:none}details,dialog{display:block}dialog{background-color:#fff;border:solid;color:#000;height:-moz-fit-content;height:-webkit-fit-content;height:fit-content;left:0;margin:auto;padding:1em;position:absolute;right:0;width:-moz-fit-content;width:-webkit-fit-content;width:fit-content}dialog:not([open]){display:none}summary{display:list-item}canvas{display:inline-block}template{display:none}[tabindex],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}[hidden]{display:none}[aria-busy=true]{cursor:progress}[aria-controls]{cursor:pointer}[aria-disabled=true],[disabled]{cursor:not-allowed}[aria-hidden=false][hidden]{display:initial}[aria-hidden=false][hidden]:not(:focus){clip:rect(0,0,0,0);position:absolute}@charset "UTF-8";
-/*! ionicons-inline v0.0.10 | MIT | https://github.com/rstacruz/ionicons-inline */
-/*! ionicons-inline v0.0.10 | MIT | https://github.com/rstacruz/ionicons-inline */body,html{background:#f1f3f5;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:14px;line-height:1.6;color:#345;overflow-x:hidden}body{font-size:13px;padding:0;margin:0}@media (min-width:480px) and (max-width:768px){body{font-size:calc(13px + 1*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){body{font-size:calc(14px + 0*(100vw - 768px)/512)}}@media (min-width:1280px){body{font-size:14px}}code,pre{font-family:cousine,SFMono-Regular,Consolas,Menlo,Liberation Mono,Ubuntu Mono,Courier,monospace;letter-spacing:-.03em}pre{font-size:.96em}:not(pre):not(code){-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a{color:#26648e}a:visited{color:#15234d}a:hover{color:#3ac1cb}[aria-hidden]:not(.line-highlight){display:none!important}@media (max-width:580px){.hint--bottom:after,.hint--bottom:before{display:none}}html.WithJs .post-content{opacity:0}html.WithJs .intro-content,html.WithJs .pages-list,html.WithJs .post-content.-wrapified{opacity:.4}html.WithJs.LoadDone .intro-content,html.WithJs.LoadDone .pages-list,html.WithJs.LoadDone .post-content.-wrapified{opacity:1;transition:opacity .1s linear .1s}.attribute-peg{display:inline-block;height:12px;width:20px;text-align:center}.attribute-peg>span{display:inline-block;width:8px;height:8px;background:#77dab2;border-radius:50%}.announcements-item{position:relative;box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3),0 8px 12px rgba(58,193,203,.1);border-radius:1px;background:#fff;padding:16px 48px 16px 16px;animation:announcements-item-flyin .5s ease-out;transition:opacity .5s linear,transform .5s ease-out}.announcements-item.-hide{display:none}.announcements-item>.title{font-size:14.95px;font-weight:400;color:#745fb5;margin:0;padding:0}@media (min-width:480px) and (max-width:768px){.announcements-item>.title{font-size:calc(14.95px + 1.29*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.announcements-item>.title{font-size:calc(16.24px + 0.14*(100vw - 768px)/512)}}@media (min-width:1280px){.announcements-item>.title{font-size:16.38px}}.announcements-item>.body>p{margin:0;padding:0}.announcements-item>.body>p+p{margin-top:1em}.announcements-item>.close{position:absolute;right:0;top:0;width:40px;height:40px;line-height:40px;text-align:center;border:0;margin:0;padding:0;cursor:pointer;background:transparent}.announcements-item>.close:focus,.announcements-item>.close:hover{color:#745fb5}.announcements-item>.close:before{content:"×";font-size:14px}@keyframes announcements-item-flyin{0%{transform:translate3d(0,32px,0);opacity:0}to{transform:translateZ(0);opacity:1}}.announcements-list{position:fixed;left:0;bottom:0;max-width:420px;padding:0;z-index:10}@media (min-width:481px){.announcements-list{padding:16px}}@media (min-width:769px){.announcements-list{padding:32px}}.pages-list{display:flex;flex-wrap:wrap}.pages-list>.item{flex:0 0 100%}.pages-list>.item.article{flex:0 0 50%}@media (min-width:581px){.pages-list>.item.top-sheet{flex:0 0 25%}}.pages-list>.article{text-decoration:none;display:block;white-space:nowrap;padding:4px 0}.pages-list>.article,.pages-list>.article:visited{color:#92a0ad}.pages-list>.article>.info>.slug{color:#111}.pages-list>.article:visited>.info>.slug{color:#345}.pages-list>.article>.info>.title:before{content:"";margin:0 4px}.pages-list>.article>.info>.title{opacity:0}@media (max-width:768px){.pages-list>.article>.info>.title{display:none}}.pages-list>.article:focus,.pages-list>.article:hover{color:#678}.pages-list>.article:focus>.info>.title,.pages-list>.article:hover>.info>.title{opacity:1;color:#745fb5}.pages-list>.category{font-size:14.95px;border-bottom:1px solid rgba(102,119,136,.2);margin:16px 0;padding:0 0 16px;font-weight:400;color:#745fb5}@media (min-width:480px) and (max-width:768px){.pages-list>.category{font-size:calc(14.95px + 1.29*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.pages-list>.category{font-size:calc(16.24px + 0.14*(100vw - 768px)/512)}}@media (min-width:1280px){.pages-list>.category{font-size:16.38px}}.search-box{background:#fff;box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3);display:flex;height:64px;align-items:center;cursor:text}.search-box>input{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:17.1925px;height:64px;background:transparent;border:0;flex:1 1 auto;padding:16px 16px 16px 0;font-weight:700;color:#111;min-width:48px}@media (min-width:480px) and (max-width:768px){.search-box>input{font-size:calc(17.1925px + 1.6459*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.search-box>input{font-size:calc(18.8384px + 0.3262*(100vw - 768px)/512)}}@media (min-width:1280px){.search-box>input{font-size:19.1646px}}.search-box>input::placeholder{font-weight:400;color:#678}.search-box>input:focus{outline:0}.search-box>.prefix{font-size:13px;display:block;color:rgba(102,119,136,.5);font-weight:400;user-select:none;line-height:1.5em;padding:2px 8px;border-radius:3px;background:rgba(241,243,245,.5);margin:0 0 0 16px;box-shadow:0 1px 1px rgba(102,119,136,.25)}@media (min-width:480px) and (max-width:768px){.search-box>.prefix{font-size:calc(13px + 1*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.search-box>.prefix{font-size:calc(14px + 0*(100vw - 768px)/512)}}@media (min-width:1280px){.search-box>.prefix{font-size:14px}}.search-box>.sep{color:rgba(102,119,136,.5);font-size:17.1925px;margin:0 8px}@media (min-width:480px) and (max-width:768px){.search-box>.sep{font-size:calc(17.1925px + 1.6459*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.search-box>.sep{font-size:calc(18.8384px + 0.3262*(100vw - 768px)/512)}}@media (min-width:1280px){.search-box>.sep{font-size:19.1646px}}@media (max-width:768px){.search-box>.prefix,.search-box>.sep{display:none}.search-box>input{padding-left:16px}}.search-box:before{content:"";display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23111' d='M337.51 305.372h-17.502l-6.57-5.486c20.79-25.232 33.92-57.054 33.92-93.257C347.36 127.63 283.897 64 205.136 64 127.452 64 64 127.632 64 206.63s63.452 142.627 142.225 142.627c35.01 0 67.83-13.167 92.99-34.008l6.562 5.486v17.55L415.18 448 448 415.086 337.51 305.372zm-131.285 0c-54.702 0-98.463-43.887-98.463-98.743 0-54.86 43.76-98.743 98.463-98.743 54.7 0 98.462 43.884 98.462 98.742 0 54.855-43.762 98.742-98.462 98.742z'/%3E%3C/svg%3E") 50%/32px 32px no-repeat;height:32px;width:32px;background-position:50%;flex:0 0 64px;width:64px;order:2}.search-box.-small{height:48px}.search-box.-small>input{height:48px;padding:8px 8px 8px 0}.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:14.95px}@media (min-width:480px) and (max-width:768px){.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:calc(14.95px + 1.29*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:calc(16.24px + 0.14*(100vw - 768px)/512)}}@media (min-width:1280px){.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:16.38px}}.search-box.-small:before{flex:0 0 48px;width:48px;line-height:48px;background-size:24px 24px;background-position:50%}.site-header{margin:32px 0}.site-header>p{margin:0;padding:0;text-align:center;color:#678}.site-header>p>a{text-decoration:none}.site-header>h1{font-size:39.767297213px;line-height:1.2;padding:0;color:#111;font-weight:200;text-align:center;margin:0 0 16px}@media (min-width:480px) and (max-width:768px){.site-header>h1{font-size:calc(39.7673px + 6.13051*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.site-header>h1{font-size:calc(45.89781px + 3.26254*(100vw - 768px)/512)}}@media (min-width:1280px){.site-header>h1{font-size:49.1603458612px}}.site-header>.action,.site-header>.search{margin-top:32px}.site-header>.adbox{margin:16px auto}@media (max-width:480px){.site-header>.adbox{margin-left:-16px;margin-right:-16px}}.top-sheet.top-sheet{padding:4px;text-decoration:none}.top-sheet.top-sheet>.info{display:block;background:#745fb5;color:#fff;text-align:left;padding:16px;width:auto;border-radius:3px;box-shadow:0 1px 1px rgba(102,119,136,.55);text-shadow:0 1px 1px rgba(51,68,85,.3);white-space:nowrap}.top-sheet.top-sheet:focus>.info,.top-sheet.top-sheet:hover>.info{box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3)}.top-sheet.top-sheet:nth-of-type(3n+1)>.info{background:linear-gradient(15deg,#745fb5,#9a6dbb)}.top-sheet.top-sheet:nth-of-type(3n+1):focus>.info,.top-sheet.top-sheet:nth-of-type(3n+1):hover>.info{background:#5f4aa1}.top-sheet.top-sheet:nth-of-type(3n+2)>.info{background:linear-gradient(15deg,#678,#6f8793)}.top-sheet.top-sheet:nth-of-type(3n+2):focus>.info,.top-sheet.top-sheet:nth-of-type(3n+2):hover>.info{background:#556371}.top-sheet.top-sheet:nth-of-type(3n+3)>.info{background:linear-gradient(15deg,#14af83,#15b89a)}.top-sheet.top-sheet:nth-of-type(3n+3):focus>.info,.top-sheet.top-sheet:nth-of-type(3n+3):hover>.info{background:#108b68}.top-sheet.top-sheet>.info>.title{display:none}.MarkdownBody.MarkdownBody a+em{opacity:.5}.MarkdownBody code{color:#678;font-size:.96em}.MarkdownBody code,.MarkdownBody pre{font-family:cousine,SFMono-Regular,Consolas,Menlo,Liberation Mono,Ubuntu Mono,Courier,monospace}.MarkdownBody pre.-box-chars{line-height:1.32}.MarkdownBody pre.-figlet{line-height:1;font-size:11px}.MarkdownBody pre{box-shadow:none;border-left:0;overflow:hidden;overflow-x:auto;background:#fff;font-size:.96em;line-height:1.5}.MarkdownBody pre.-wrap{white-space:pre-wrap}.MarkdownBody pre>code{color:#111;max-height:auto;padding:0;background:transparent;overflow:visible;font-size:1em}.MarkdownBody .line-highlight{transform:translate3d(0,2px,0);background:linear-gradient(90deg,rgba(20,175,131,.05) 25%,transparent)}.MarkdownBody .line-highlight[data-end]{margin-top:0}.MarkdownBody .line-highlight:after,.MarkdownBody .line-highlight:before{display:none}.MarkdownBody p.-crosslink,.MarkdownBody p.-setup,.MarkdownBody pre.-setup,.MarkdownBody ul.-setup{background:#f8f9fa}.token.keyword,.token.tag{color:#26648e}.token.tag{color:#1d406e}.token.attr-value,.token.boolean,.token.number,.token.regex,.token.string,.token.value{color:#14af83}.token.attr-name,.token.function{color:#2e90ae}.token.comment,.token.operator,.token.punctuation{color:#aaa}.MarkdownBody h2{padding:0;position:relative;font-size:30.0697899531px;line-height:1.2;font-weight:200;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;margin:0 0 24px}@media (max-width:768px){.MarkdownBody h2{margin-bottom:8px;margin-top:32px}}@media (max-width:480px){.MarkdownBody h2{margin-bottom:8px;margin-top:32px}}@media (min-width:480px) and (max-width:768px){.MarkdownBody h2{font-size:calc(30.06979px + 4.03976*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.MarkdownBody h2{font-size:calc(34.10955px + 1.80275*(100vw - 768px)/512)}}@media (min-width:1280px){.MarkdownBody h2{font-size:35.9122988248px}}.MarkdownBody h2:target{color:#745fb5}.MarkdownBody h3{padding:0;margin:0 0 16px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:17.1925px;font-weight:400;color:#745fb5}@media (min-width:480px) and (max-width:768px){.MarkdownBody h3{font-size:calc(17.1925px + 1.6459*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.MarkdownBody h3{font-size:calc(18.8384px + 0.3262*(100vw - 768px)/512)}}@media (min-width:1280px){.MarkdownBody h3{font-size:19.1646px}}.MarkdownBody a,.MarkdownBody a:visited{color:#26648e;text-decoration:none}.MarkdownBody a:hover{text-decoration:underline}.MarkdownBody em{font-style:normal;color:#678}.MarkdownBody iframe{border:0;margin:0;width:100%}.local-anchor{margin-left:-.9em;margin-right:.1em;padding:0 .1em}.MarkdownBody .local-anchor,.MarkdownBody .local-anchor:visited{color:#678;text-decoration:inherit;opacity:.5}.MarkdownBody .local-anchor:target,.MarkdownBody :target>.local-anchor{color:#745fb5;opacity:1}.MarkdownBody .local-anchor:focus,.MarkdownBody .local-anchor:hover{color:#fff;background:#745fb5;opacity:1;text-decoration:inherit}.MarkdownBody.MarkdownBody img{max-width:100%}.MarkdownBody.MarkdownBody p.-crosslink>a{display:block;text-decoration:none;color:#745fb5;border-bottom:0;box-shadow:none;margin:-16px;padding:16px}.MarkdownBody.MarkdownBody p.-crosslink>a:visited{color:#745fb5}.MarkdownBody.MarkdownBody p.-crosslink>a:before{content:"";display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23FFF' d='M85 277.375h259.704L225.002 397.077 256 427l171-171L256 85l-29.922 29.924 118.626 119.7H85v42.75z'/%3E%3C/svg%3E") 50%/16px 16px no-repeat;height:16px;width:16px;margin-right:16px;width:32px;height:32px;line-height:32px;border-radius:50%}.MarkdownBody.MarkdownBody p.-crosslink>a:before,.MarkdownBody.MarkdownBody p.-crosslink>a:visited:before{background-color:#745fb5;color:#fff}.MarkdownBody.MarkdownBody p.-crosslink>a:focus,.MarkdownBody.MarkdownBody p.-crosslink>a:hover{color:#673d85}.MarkdownBody.MarkdownBody p.-crosslink>a:focus:before,.MarkdownBody.MarkdownBody p.-crosslink>a:hover:before{background-color:#673d85}.MarkdownBody table{width:100%}.MarkdownBody table tr+tr{border-top:1px solid rgba(102,119,136,.05)}.MarkdownBody table tbody+tbody{border-top:1px solid rgba(102,119,136,.2)}.MarkdownBody table td,.MarkdownBody table th{padding:8px 16px;vertical-align:top;text-align:left}.MarkdownBody table tr td:last-child,.MarkdownBody table tr th:last-child{text-align:right}.MarkdownBody table td:first-child{white-space:nowrap}.MarkdownBody table td>code{font-size:.96em}.MarkdownBody table td:first-child>code{color:#35a}.MarkdownBody table a,.MarkdownBody table a:visited{color:#35a;text-decoration:none}.MarkdownBody table td:first-child>code~em{font-size:11.3043478261px;font-style:normal;color:#678}@media (min-width:480px) and (max-width:768px){.MarkdownBody table td:first-child>code~em{font-size:calc(11.30435px + 0.76462*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.MarkdownBody table td:first-child>code~em{font-size:calc(12.06897px + -0.10315*(100vw - 768px)/512)}}@media (min-width:1280px){.MarkdownBody table td:first-child>code~em{font-size:11.9658119658px}}.MarkdownBody table thead{display:none}.MarkdownBody table thead th{font-weight:400;color:#745fb5}.MarkdownBody table.-shortcuts-right td:last-child>code,.MarkdownBody table.-shortcuts td:first-child>code{font-size:1rem;padding:5px 6px 5px 8px;background:#f8f9fa;border-radius:3px;margin-right:2px;letter-spacing:.1em;color:#345}.MarkdownBody table.-left-align tr td,.MarkdownBody table.-left-align tr td:last-child,.MarkdownBody table.-left-align tr th{text-align:left}.MarkdownBody table.-headers thead{display:table-header-group;border-bottom:1px solid rgba(102,119,136,.2)}.MarkdownBody table.-key-values tbody tr td+td code{display:block}.MarkdownBody table.-css-breakdown tr td,.MarkdownBody table.-css-breakdown tr td:last-child,.MarkdownBody table.-css-breakdown tr th{text-align:left}.MarkdownBody table.-css-breakdown tr td{font-size:14.95px;white-space:nowrap}@media (min-width:480px) and (max-width:768px){.MarkdownBody table.-css-breakdown tr td{font-size:calc(14.95px + 1.29*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.MarkdownBody table.-css-breakdown tr td{font-size:calc(16.24px + 0.14*(100vw - 768px)/512)}}@media (min-width:1280px){.MarkdownBody table.-css-breakdown tr td{font-size:16.38px}}.MarkdownBody table.-css-breakdown tr td:not(:last-child){padding-right:4px}.MarkdownBody table.-css-breakdown tr td:not(:first-child){padding-left:4px}.MarkdownBody table.-css-breakdown tr:last-child{background:#f8f9fa}.MarkdownBody table.-css-breakdown tr:last-child td{font-size:11.3043478261px;color:#678;white-space:auto}@media (min-width:480px) and (max-width:768px){.MarkdownBody table.-css-breakdown tr:last-child td{font-size:calc(11.30435px + 0.76462*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.MarkdownBody table.-css-breakdown tr:last-child td{font-size:calc(12.06897px + -0.10315*(100vw - 768px)/512)}}@media (min-width:1280px){.MarkdownBody table.-css-breakdown tr:last-child td{font-size:11.9658119658px}}.MarkdownBody table.-bold-first tr>td:first-child{font-weight:700}.MarkdownBody table.-no-wrap td,.MarkdownBody table.-no-wrap th{white-space:nowrap}.MarkdownBody table.-mute-em td em,.MarkdownBody table.-mute-em th em{opacity:.5}.MarkdownBody table.-mute-em td em>code,.MarkdownBody table.-mute-em th em>code{margin-right:.5em}.MarkdownBody ul.-six-column{display:flex;flex-wrap:wrap}.MarkdownBody ul.-six-column>li{flex:0 0 16.6666666667%}@media (max-width:480px){.MarkdownBody ul.-six-column>li{flex:0 0 50%}}@media (max-width:768px){.MarkdownBody ul.-six-column>li{flex:0 0 25%}}.MarkdownBody ul.-four-column{display:flex;flex-wrap:wrap}.MarkdownBody ul.-four-column>li{flex:0 0 25%}@media (max-width:480px){.MarkdownBody ul.-four-column>li{flex:0 0 50%}}@media (max-width:768px){.MarkdownBody ul.-four-column>li{flex:0 0 33.3333333333%}}.back-button{text-decoration:none;width:48px;height:48px;line-height:46px;text-align:center;display:inline-block;border-radius:50%;transition:all .1s linear}@media (max-width:480px){.back-button{width:32px;height:32px;line-height:30px}}.back-button,.back-button:visited{color:#678}.back-button:focus,.back-button:hover{color:#fff;background:#745fb5;opacity:1}.back-button:before{content:"";display:inline-block;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23345' d='M427 234.625H167.296l119.702-119.702L256 85 85 256l171 171 29.922-29.924-118.626-119.7H427v-42.75z'/%3E%3C/svg%3E") 50%/24px 24px no-repeat;height:24px;width:24px;vertical-align:middle}.back-button:focus:before,.back-button:hover:before{display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23FFF' d='M427 234.625H167.296l119.702-119.702L256 85 85 256l171 171 29.922-29.924-118.626-119.7H427v-42.75z'/%3E%3C/svg%3E") 50%/24px 24px no-repeat;height:24px;width:24px}@media (max-width:480px){.back-button:before{font-size:16px}}.body-area{max-width:1232px;margin:0 auto;padding:16px}@media (max-width:480px){.body-area{padding:16px}}.body-area.-slim{max-width:740px}.codefund-sponsor{min-height:114px}.codefund-sponsor .cf-wrapper{margin-left:auto;margin-right:auto}.h3-section>.body>pre{margin:0;padding:16px}@media (max-width:768px){.h3-section>.body{overflow-x:auto}}.h3-section>.body{background:#fff;box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3)}@media (max-width:480px){.h3-section>.body{margin:0 -16px;box-shadow:0 1px 1px rgba(102,119,136,.55)}}@media (min-width:481px){.h3-section>.body{border-radius:2px}.h3-section>.body>:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.h3-section>.body>:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}}.h3-section>h3{margin-top:8px;margin-bottom:16px;white-space:nowrap;overflow:hidden}@media (max-width:768px){.h3-section>h3{margin-top:0}}.h3-section>h3:after{margin-left:24px;content:"";display:inline-block;vertical-align:middle;width:100%;height:1px;background:linear-gradient(90deg,rgba(116,95,181,.2),transparent 80%)}.h3-section>.body>ul{margin:0;padding:0;list-style-type:none}.h3-section>.body>ul>li{padding:8px 8px 8px 36px;position:relative}.h3-section>.body>ul>li>p{margin:0;padding:0}.h3-section>.body>ul>li:before{content:"";position:absolute;display:inline-block;width:4px;height:4px;background:#678;border-radius:50%;left:16px;top:18px}.h3-section>.body>ul>li+li{border-top:1px solid rgba(102,119,136,.05)}.h3-section>.body>p{padding:16px;margin:0}.h3-section>.body>h4{font-size:11.3043478261px;margin:0;padding:4px 16px;font-weight:400;background:#f8f9fa;color:#678}@media (min-width:480px) and (max-width:768px){.h3-section>.body>h4{font-size:calc(11.30435px + 0.76462*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.h3-section>.body>h4{font-size:calc(12.06897px + -0.10315*(100vw - 768px)/512)}}@media (min-width:1280px){.h3-section>.body>h4{font-size:11.9658119658px}}.h3-section>.body>h4+*{border-top:1px solid rgba(102,119,136,.05)}.h3-section>.body>iframe~p,.h3-section>.body>pre~p,.h3-section>.body>table~p,.h3-section>.body>ul~p{background:#f8f9fa;color:#678}.h3-section>.body>iframe~p a,.h3-section>.body>iframe~p a:visited,.h3-section>.body>pre~p a,.h3-section>.body>pre~p a:visited,.h3-section>.body>table~p a,.h3-section>.body>table~p a:visited,.h3-section>.body>ul~p a,.h3-section>.body>ul~p a:visited{color:#345;text-decoration:none;border-bottom:1px solid rgba(102,119,136,.05)}.h3-section>.body>iframe~p a:hover,.h3-section>.body>pre~p a:hover,.h3-section>.body>table~p a:hover,.h3-section>.body>ul~p a:hover{color:#26648e}.h3-section>.body>:not(:first-child){border-top:1px solid rgba(102,119,136,.05)}.h3-section>.body>p+p,.h3-section>.body>p+p:not(:first-child){margin-top:-1.5em;border-top:0}@media (min-width:481px){.h3-section.-prime>.body{border-radius:2px;box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3),0 8px 12px rgba(58,193,203,.1)}}ul.-also-see.-also-see.-also-see{display:flex;flex-wrap:wrap;background:#f8f9fa}ul.-also-see.-also-see.-also-see>li{flex:1 0 20%;padding:24px;border-top:1px solid rgba(102,119,136,.2)}ul.-also-see.-also-see.-also-see>li+li{border-left:1px solid rgba(102,119,136,.2)}ul.-also-see.-also-see.-also-see,ul.-also-see.-also-see.-also-see>li{list-style-type:none}ul.-also-see.-also-see.-also-see>li:before{display:none}ul.-also-see.-also-see.-also-see>li>a{font-size:14.95px;display:block}@media (min-width:480px) and (max-width:768px){ul.-also-see.-also-see.-also-see>li>a{font-size:calc(14.95px + 1.29*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){ul.-also-see.-also-see.-also-see>li>a{font-size:calc(16.24px + 0.14*(100vw - 768px)/512)}}@media (min-width:1280px){ul.-also-see.-also-see.-also-see>li>a{font-size:16.38px}}ul.-also-see.-also-see.-also-see>li>em{font-size:11.3043478261px;display:block}@media (min-width:480px) and (max-width:768px){ul.-also-see.-also-see.-also-see>li>em{font-size:calc(11.30435px + 0.76462*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){ul.-also-see.-also-see.-also-see>li>em{font-size:calc(12.06897px + -0.10315*(100vw - 768px)/512)}}@media (min-width:1280px){ul.-also-see.-also-see.-also-see>li>em{font-size:11.9658119658px}}.h3-section-list{margin:0 -16px}@media (max-width:1264px){.h3-section-list{margin-left:-8px;margin-right:-8px}}.h3-section-list:after{content:"";display:table;clear:both;zoom:1}.h3-section-list>.h3-section{padding:16px;float:left;width:100%}@media (max-width:1264px){.h3-section-list>.h3-section{padding:8px}}@media (min-width:769px){.h3-section-list>.h3-section{padding-top:0}}@media (min-width:769px){.h3-section-list.-two-column>.h3-section,.h3-section-list>.h3-section{width:50%}}.h3-section-list.-one-column>.h3-section{width:100%}.h3-section-list.-one-column>.h3-section+.h3-section{margin-top:16px}@media (min-width:769px){.h3-section-list.-three-column>.h3-section{width:50%}}@media (min-width:961px){.h3-section-list.-three-column>.h3-section{width:33.33%}}@media (min-width:769px){.h3-section-list.-left-reference>.h3-section{width:50%}}@media (min-width:961px){.h3-section-list.-left-reference>.h3-section{width:66.67%}.h3-section-list.-left-reference>.h3-section:first-child{width:33.33%}}.main-heading{padding:0;margin:64px 0 24px;position:relative}@media (max-width:768px){.main-heading{margin-bottom:8px;margin-top:32px}}@media (max-width:480px){.main-heading{margin-bottom:8px;margin-top:32px}}.main-heading{margin-top:0;margin-bottom:0}.main-heading>h1{font-size:39.767297213px;line-height:1.2;font-weight:200;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;margin:0}@media (min-width:480px) and (max-width:768px){.main-heading>h1{font-size:calc(39.7673px + 6.13051*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.main-heading>h1{font-size:calc(45.89781px + 3.26254*(100vw - 768px)/512)}}@media (min-width:1280px){.main-heading>h1{font-size:49.1603458612px}}.main-heading>h1>em{font-style:normal;color:#9eaab6}.main-heading.-center>h1{text-align:center}.main-heading.-center>.adbox{margin-top:16px;text-align:center}.main-heading.-center>.adbox>.ad{display:inline-block}.main-heading.-center>.adbox>.ad.-carbon,.PreviewMode .main-heading{margin-top:16px}.page-actions{margin:0;padding:0;height:32px}.page-actions>.link.link>a{display:inline-block;height:32px;line-height:32px;vertical-align:top;width:auto}.page-actions>li{margin:0;padding:0;list-style-type:none}.page-actions>li>a,.page-actions>li>a:visited{color:#678;text-decoration:none}.page-actions>li>a:focus,.page-actions>li>a:focus>.text,.page-actions>li>a:hover,.page-actions>li>a:hover>.text{color:#745fb5}.page-actions>li>a>.text{font-size:11.3043478261px;display:none}@media (min-width:480px) and (max-width:768px){.page-actions>li>a>.text{font-size:calc(11.30435px + 0.76462*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.page-actions>li>a>.text{font-size:calc(12.06897px + -0.10315*(100vw - 768px)/512)}}@media (min-width:1280px){.page-actions>li>a>.text{font-size:11.9658119658px}}.page-actions>li>a>.text.-visible{display:inline}.page-actions+.page-actions{margin-left:8px}.page-actions>.facebook>a:before,.page-actions>.github>a:before,.page-actions>.twitter>a:before{content:"";vertical-align:middle}.page-actions>.facebook>a:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23345' d='M426.8 64H85.2C73.5 64 64 73.5 64 85.2v341.6c0 11.7 9.5 21.2 21.2 21.2H256V296h-45.9v-56H256v-41.4c0-49.6 34.4-76.6 78.7-76.6 21.2 0 44 1.6 49.3 2.3v51.8h-35.3c-24.1 0-28.7 11.4-28.7 28.2V240h57.4l-7.5 56H320v152h106.8c11.7 0 21.2-9.5 21.2-21.2V85.2c0-11.7-9.5-21.2-21.2-21.2z'/%3E%3C/svg%3E") 50%/16px 16px no-repeat}.page-actions>.facebook>a:before,.page-actions>.twitter>a:before{display:inline-block;vertical-align:middle;height:16px;width:16px}.page-actions>.twitter>a:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23345' d='M492 109.5c-17.4 7.7-36 12.9-55.6 15.3 20-12 35.4-31 42.6-53.6-18.7 11.1-39.4 19.2-61.5 23.5C399.8 75.8 374.6 64 346.8 64c-53.5 0-96.8 43.4-96.8 96.9 0 7.6.8 15 2.5 22.1-80.5-4-151.9-42.6-199.6-101.3-8.3 14.3-13.1 31-13.1 48.7 0 33.6 17.2 63.3 43.2 80.7-16-.4-31-4.8-44-12.1v1.2c0 47 33.4 86.1 77.7 95-8.1 2.2-16.7 3.4-25.5 3.4-6.2 0-12.3-.6-18.2-1.8 12.3 38.5 48.1 66.5 90.5 67.3-33.1 26-74.9 41.5-120.3 41.5-7.8 0-15.5-.5-23.1-1.4C62.8 432 113.7 448 168.3 448 346.6 448 444 300.3 444 172.2c0-4.2-.1-8.4-.3-12.5C462.6 146 479 129 492 109.5z'/%3E%3C/svg%3E") 50%/16px 16px no-repeat}.page-actions>.github>a:before{display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23345' d='M256 32C132.3 32 32 134.9 32 261.7c0 101.5 64.2 187.5 153.2 217.9 1.4.3 2.6.4 3.8.4 8.3 0 11.5-6.1 11.5-11.4 0-5.5-.2-19.9-.3-39.1-8.4 1.9-15.9 2.7-22.6 2.7-43.1 0-52.9-33.5-52.9-33.5-10.2-26.5-24.9-33.6-24.9-33.6-19.5-13.7-.1-14.1 1.4-14.1h.1c22.5 2 34.3 23.8 34.3 23.8 11.2 19.6 26.2 25.1 39.6 25.1 10.5 0 20-3.4 25.6-6 2-14.8 7.8-24.9 14.2-30.7-49.7-5.8-102-25.5-102-113.5 0-25.1 8.7-45.6 23-61.6-2.3-5.8-10-29.2 2.2-60.8 0 0 1.6-.5 5-.5 8.1 0 26.4 3.1 56.6 24.1 17.9-5.1 37-7.6 56.1-7.7 19 .1 38.2 2.6 56.1 7.7 30.2-21 48.5-24.1 56.6-24.1 3.4 0 5 .5 5 .5 12.2 31.6 4.5 55 2.2 60.8 14.3 16.1 23 36.6 23 61.6 0 88.2-52.4 107.6-102.3 113.3 8 7.1 15.2 21.1 15.2 42.5 0 30.7-.3 55.5-.3 63 0 5.4 3.1 11.5 11.4 11.5 1.2 0 2.6-.1 4-.4C415.9 449.2 480 363.1 480 261.7 480 134.9 379.7 32 256 32z'/%3E%3C/svg%3E") 50%/16px 16px no-repeat;height:16px;width:16px}.page-actions>.github>a:hover:before{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cpath fill='%23FFF' d='M256 32C132.3 32 32 134.9 32 261.7c0 101.5 64.2 187.5 153.2 217.9 1.4.3 2.6.4 3.8.4 8.3 0 11.5-6.1 11.5-11.4 0-5.5-.2-19.9-.3-39.1-8.4 1.9-15.9 2.7-22.6 2.7-43.1 0-52.9-33.5-52.9-33.5-10.2-26.5-24.9-33.6-24.9-33.6-19.5-13.7-.1-14.1 1.4-14.1h.1c22.5 2 34.3 23.8 34.3 23.8 11.2 19.6 26.2 25.1 39.6 25.1 10.5 0 20-3.4 25.6-6 2-14.8 7.8-24.9 14.2-30.7-49.7-5.8-102-25.5-102-113.5 0-25.1 8.7-45.6 23-61.6-2.3-5.8-10-29.2 2.2-60.8 0 0 1.6-.5 5-.5 8.1 0 26.4 3.1 56.6 24.1 17.9-5.1 37-7.6 56.1-7.7 19 .1 38.2 2.6 56.1 7.7 30.2-21 48.5-24.1 56.6-24.1 3.4 0 5 .5 5 .5 12.2 31.6 4.5 55 2.2 60.8 14.3 16.1 23 36.6 23 61.6 0 88.2-52.4 107.6-102.3 113.3 8 7.1 15.2 21.1 15.2 42.5 0 30.7-.3 55.5-.3 63 0 5.4 3.1 11.5 11.4 11.5 1.2 0 2.6-.1 4-.4C415.9 449.2 480 363.1 480 261.7 480 134.9 379.7 32 256 32z'/%3E%3C/svg%3E")}.page-actions>.facebook>a:before,.page-actions>.twitter>a:before{width:32px;height:32px}.page-actions>.github>a:before{position:relative;top:-2px}.page-actions>.link.-button>a{box-shadow:inset 0 0 0 1px rgba(102,119,136,.2);border-radius:2px;padding:0 16px;margin:0 8px;transition:all .1s linear}.page-actions>.link.-button>a>.text{margin-left:4px;position:relative;top:-1px}.page-actions>.link.-button>a:focus,.page-actions>.link.-button>a:hover{background:linear-gradient(5deg,#745fb5,#9066b8);box-shadow:0 1px 1px rgba(102,119,136,.55)}.page-actions>.link.-button>a:focus,.page-actions>.link.-button>a:focus>.text,.page-actions>.link.-button>a:hover,.page-actions>.link.-button>a:hover>.text{color:#fff}@media (max-width:768px){.page-actions>.link{margin-left:16px}}.page-actions>.link:first-child>a{margin-left:0}.page-actions>.link:last-child>a{margin-right:0}.top-nav,.top-nav>.container{height:64px;line-height:64px;text-align:center;position:relative}@media (max-width:480px){.top-nav>.container{height:32px;line-height:32px;margin-top:8px}.top-nav{height:48px;padding:8px 0;border-bottom:1px solid rgba(102,119,136,.2);margin-bottom:8px}}.top-nav>.container{padding-left:16px;padding-right:16px;max-width:1232px;margin:0 auto}@media (max-width:480px){.top-nav>.container{padding-left:16px;padding-right:16px}}.top-nav>.container{display:flex;align-items:center;position:relative}.top-nav>.container>.left{flex:0 0 auto;line-height:32px}.top-nav>.container>.brand{flex:1 1 auto}.top-nav>.container>.actions{flex:0 0 auto;display:flex}.top-nav>.container>.brand{font-size:11.3043478261px;display:inline-block;font-weight:700;text-transform:uppercase;letter-spacing:.05em;text-decoration:none}@media (min-width:480px) and (max-width:768px){.top-nav>.container>.brand{font-size:calc(11.30435px + 0.76462*(100vw - 480px)/288)}}@media (min-width:768px) and (max-width:1280px){.top-nav>.container>.brand{font-size:calc(12.06897px + -0.10315*(100vw - 768px)/512)}}@media (min-width:1280px){.top-nav>.container>.brand{font-size:11.9658119658px}}.top-nav>.container>.brand,.top-nav>.container>.brand:visited{color:#345}.top-nav>.container>.brand:hover{color:#745fb5}@media (max-width:480px){.top-nav>.container>.brand{display:none}.top-nav>.container>.actions{margin-left:auto}}@media (min-width:481px){.top-nav>.container>.actions{position:absolute;right:16px;top:16px}}@media (min-width:481px) and (max-width:480px){.top-nav>.container>.actions{right:16px}}@media (min-width:481px){.top-nav>.container>.left{position:absolute;left:16px;top:16px}}@media (min-width:481px) and (max-width:480px){.top-nav>.container>.left{left:16px}}@media (min-width:1232px){.top-nav>.container>.left>.home{position:relative;left:-16px}}
\ No newline at end of file
diff --git a/_includes/2017/critical/critical.js b/_includes/2017/critical/critical.js
index 3d02adbea..9a95fcaa0 100644
--- a/_includes/2017/critical/critical.js
+++ b/_includes/2017/critical/critical.js
@@ -1,15 +1 @@
-parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;ct.length)&&(e=t.length);for(var r=0,n=new Array(e);rr.length)&&(t=r.length);for(var n=0,e=new Array(t);nspan{display:inline-block;width:8px;height:8px;background:#77dab2;border-radius:50%}.announcements-item{position:relative;padding:16px;box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3),0 8px 12px rgba(58,193,203,.1);border-radius:1px;background:#fff;padding-right:48px;animation:announcements-item-flyin .5s ease-out}.announcements-item.-hide{display:none}.announcements-item>.title{font-size:15px;font-weight:400;color:#745fb5;margin:0;padding:0}@media (min-width:480px) and (max-width:768px){.announcements-item>.title{font-size:calc(15px + 1 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.announcements-item>.title{font-size:calc(16px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.announcements-item>.title{font-size:16px}}.announcements-item>.body>p{margin:0;padding:0}.announcements-item>.body>p+p{margin-top:1em}.announcements-item>.close{position:absolute;right:0;top:0;width:40px;height:40px;line-height:40px;text-align:center;border:0;margin:0;padding:0}.announcements-item>.close::before{content:"\00D7";font-size:14px}@keyframes announcements-item-flyin{0%{transform:translate3d(0,32px,0);opacity:0}100%{transform:translate3d(0,0,0);opacity:1}}.announcements-list{position:fixed;left:0;bottom:0;max-width:420px;padding:0;z-index:10}@media (min-width:481px){.announcements-list{padding:16px}}@media (min-width:769px){.announcements-list{padding:32px}}.back-button{text-decoration:none;width:48px;height:48px;line-height:46px;text-align:center;display:inline-block;border-radius:50%}@media (max-width:480px){.back-button{width:32px;height:32px;line-height:30px}}.back-button,.back-button:visited{color:#678}.back-button::before{content:'';display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%3E%3Cpath%20fill%3D%22rgb(51%2C68%2C85)%22%20d%3D%22M427%20234.625H167.296l119.702-119.702L256%2085%2085%20256l171%20171%2029.922-29.924-118.626-119.7H427v-42.75z%22%2F%3E%3C%2Fsvg%3E") center center/24px 24px no-repeat;height:24px;width:24px;vertical-align:middle}@media (max-width:480px){.back-button::before{font-size:16px}}.body-area{max-width:1232px;margin:0 auto;padding:16px}@media (max-width:480px){.body-area{padding:16px}}.body-area.-slim{max-width:740px}.codefund-sponsor{min-height:114px}.page-actions{margin:0;padding:0}.page-actions{height:32px}.page-actions>.link.link>a{display:inline-block;height:32px;line-height:32px;vertical-align:top;width:auto}.page-actions>li{margin:0;padding:0;list-style-type:none}.page-actions>li>a,.page-actions>li>a:visited{color:#678;text-decoration:none}.page-actions>li>a>.text{font-size:11px;display:none}@media (min-width:480px) and (max-width:768px){.page-actions>li>a>.text{font-size:calc(11px + 1 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.page-actions>li>a>.text{font-size:calc(12px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.page-actions>li>a>.text{font-size:12px}}.page-actions>.facebook>a::before,.page-actions>.twitter>a::before{content:'';vertical-align:middle}.page-actions>.facebook>a::before{display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20512%20512%22%3E%3Cpath%20fill%3D%22rgb(51%2C68%2C85)%22%20d%3D%22M426.8%2064H85.2C73.5%2064%2064%2073.5%2064%2085.2v341.6c0%2011.7%209.5%2021.2%2021.2%2021.2H256V296h-45.9v-56H256v-41.4c0-49.6%2034.4-76.6%2078.7-76.6%2021.2%200%2044%201.6%2049.3%202.3v51.8h-35.3c-24.1%200-28.7%2011.4-28.7%2028.2V240h57.4l-7.5%2056H320v152h106.8c11.7%200%2021.2-9.5%2021.2-21.2V85.2c0-11.7-9.5-21.2-21.2-21.2z%22%2F%3E%3C%2Fsvg%3E") center center/16px 16px no-repeat;height:16px;width:16px}.page-actions>.twitter>a::before{display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%3E%3Cpath%20fill%3D%22rgb(51%2C68%2C85)%22%20d%3D%22M492%20109.5c-17.4%207.7-36%2012.9-55.6%2015.3%2020-12%2035.4-31%2042.6-53.6-18.7%2011.1-39.4%2019.2-61.5%2023.5C399.8%2075.8%20374.6%2064%20346.8%2064c-53.5%200-96.8%2043.4-96.8%2096.9%200%207.6.8%2015%202.5%2022.1-80.5-4-151.9-42.6-199.6-101.3-8.3%2014.3-13.1%2031-13.1%2048.7%200%2033.6%2017.2%2063.3%2043.2%2080.7-16-.4-31-4.8-44-12.1v1.2c0%2047%2033.4%2086.1%2077.7%2095-8.1%202.2-16.7%203.4-25.5%203.4-6.2%200-12.3-.6-18.2-1.8%2012.3%2038.5%2048.1%2066.5%2090.5%2067.3-33.1%2026-74.9%2041.5-120.3%2041.5-7.8%200-15.5-.5-23.1-1.4C62.8%20432%20113.7%20448%20168.3%20448%20346.6%20448%20444%20300.3%20444%20172.2c0-4.2-.1-8.4-.3-12.5C462.6%20146%20479%20129%20492%20109.5z%22%2F%3E%3C%2Fsvg%3E") center center/16px 16px no-repeat;height:16px;width:16px}.page-actions>.facebook>a::before,.page-actions>.twitter>a::before{width:32px;height:32px}@media (max-width:768px){.page-actions>.link{margin-left:16px}}.page-actions>.link:first-child>a{margin-left:0}.page-actions>.link:last-child>a{margin-right:0}.pages-list{display:flex;flex-wrap:wrap}.pages-list>.item{flex:0 0 100%}@media (min-width:581px){.pages-list>.item.top-sheet{flex:0 0 25%}}.search-box{background:#fff;box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3);display:flex;height:64px;align-items:center}.search-box>input{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif;font-size:17px;padding:16px;height:64px;background:0 0;border:0;flex:1 1 auto;padding-left:0;font-weight:700;color:#111;min-width:48px}@media (min-width:480px) and (max-width:768px){.search-box>input{font-size:calc(17px + 2 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.search-box>input{font-size:calc(19px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.search-box>input{font-size:19px}}.search-box>input::placeholder{font-weight:400;color:#678}.search-box>input:focus{outline:0}.search-box>.prefix{font-size:13px;display:block;color:rgba(102,119,136,.5);font-weight:400;line-height:1.5em;padding:2px 8px;border-radius:3px;background:rgba(241,243,245,.5);margin:0 0 0 16px;box-shadow:0 1px 1px rgba(102,119,136,.25)}@media (min-width:480px) and (max-width:768px){.search-box>.prefix{font-size:calc(13px + 1 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.search-box>.prefix{font-size:calc(14px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.search-box>.prefix{font-size:14px}}.search-box>.sep{color:rgba(102,119,136,.5);font-size:17px;margin:0 8px}@media (min-width:480px) and (max-width:768px){.search-box>.sep{font-size:calc(17px + 2 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.search-box>.sep{font-size:calc(19px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.search-box>.sep{font-size:19px}}@media (max-width:768px){.search-box>.prefix,.search-box>.sep{display:none}.search-box>input{padding-left:16px}}.search-box::before{content:'';display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%3E%3Cpath%20fill%3D%22rgb(17%2C17%2C17)%22%20d%3D%22M337.51%20305.372h-17.502l-6.57-5.486c20.79-25.232%2033.92-57.054%2033.92-93.257C347.36%20127.63%20283.897%2064%20205.136%2064%20127.452%2064%2064%20127.632%2064%20206.63s63.452%20142.627%20142.225%20142.627c35.01%200%2067.83-13.167%2092.99-34.008l6.562%205.486v17.55L415.18%20448%20448%20415.086%20337.51%20305.372zm-131.285%200c-54.702%200-98.463-43.887-98.463-98.743%200-54.86%2043.76-98.743%2098.463-98.743%2054.7%200%2098.462%2043.884%2098.462%2098.742%200%2054.855-43.762%2098.742-98.462%2098.742z%22%2F%3E%3C%2Fsvg%3E") center center/32px 32px no-repeat;height:32px;width:32px;background-position:center center;flex:0 0 64px;width:64px;order:2}.search-box.-small{height:48px}.search-box.-small>input{padding:8px;height:48px;padding-left:0}.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:15px}@media (min-width:480px) and (max-width:768px){.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:calc(15px + 1 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:calc(16px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.search-box.-small>.prefix,.search-box.-small>.sep,.search-box.-small>input{font-size:16px}}.search-box.-small::before{flex:0 0 48px;width:48px;line-height:48px;background-size:24px 24px;background-position:center center}.site-header{margin:32px 0}.site-header>p{margin:0;padding:0;text-align:center;color:#678}.site-header>p>a{text-decoration:none}.site-header>h1{font-size:40px;line-height:1.2;margin:0;padding:0;color:#111;font-weight:200;text-align:center;margin-bottom:16px}@media (min-width:480px) and (max-width:768px){.site-header>h1{font-size:calc(40px + 6 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.site-header>h1{font-size:calc(46px + 3 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.site-header>h1{font-size:49px}}.site-header>.search{margin-top:32px}.site-header>.adbox{margin:16px auto}@media (max-width:480px){.site-header>.adbox{margin-left:-16px;margin-right:-16px}}.top-nav,.top-nav>.container{height:64px;line-height:64px;text-align:center;position:relative}@media (max-width:480px){.top-nav>.container{height:32px;line-height:32px;margin-top:8px}.top-nav{height:48px;padding:8px 0;border-bottom:solid 1px rgba(102,119,136,.2);margin-bottom:8px}}.top-nav>.container{padding-left:16px;padding-right:16px;max-width:1232px;margin:0 auto}@media (max-width:480px){.top-nav>.container{padding-left:16px}}@media (max-width:480px){.top-nav>.container{padding-right:16px}}.top-nav>.container{display:flex;align-items:center;position:relative}.top-nav>.container>.left{flex:0 0 auto;line-height:32px}.top-nav>.container>.brand{flex:1 1 auto}.top-nav>.container>.actions{flex:0 0 auto;display:flex}.top-nav>.container>.brand{font-size:11px;display:inline-block;font-weight:700;text-transform:uppercase;letter-spacing:.05em;text-decoration:none}@media (min-width:480px) and (max-width:768px){.top-nav>.container>.brand{font-size:calc(11px + 1 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.top-nav>.container>.brand{font-size:calc(12px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.top-nav>.container>.brand{font-size:12px}}.top-nav>.container>.brand,.top-nav>.container>.brand:visited{color:#345}@media (max-width:480px){.top-nav>.container>.brand{display:none}.top-nav>.container>.actions{margin-left:auto}}@media (min-width:481px){.top-nav>.container>.actions{position:absolute;right:16px;top:16px}}@media (min-width:481px) and (max-width:480px){.top-nav>.container>.actions{right:16px}}@media (min-width:481px){.top-nav>.container>.left{position:absolute;left:16px;top:16px}}@media (min-width:481px) and (max-width:480px){.top-nav>.container>.left{left:16px}}@media (min-width:1232px){.top-nav>.container>.left>.home{position:relative;left:-16px}}.top-sheet.top-sheet{padding:4px;text-decoration:none}.top-sheet.top-sheet>.info{display:block;background:#745fb5;color:#fff;text-align:left;padding:16px;width:auto;border-radius:3px;box-shadow:0 1px 1px rgba(102,119,136,.55);text-shadow:0 1px 1px rgba(51,68,85,.3);white-space:nowrap}.top-sheet.top-sheet:nth-of-type(3n+1)>.info{background:linear-gradient(15deg,#745fb5,#9a6dbb)}.top-sheet.top-sheet:nth-of-type(3n+2)>.info{background:linear-gradient(15deg,#678,#6f8793)}.top-sheet.top-sheet:nth-of-type(3n+3)>.info{background:linear-gradient(15deg,#14af83,#15b89a)}.top-sheet.top-sheet>.info>.title{display:none}
\ No newline at end of file
diff --git a/_includes/2017/critical/sheet.css b/_includes/2017/critical/sheet.css
new file mode 100644
index 000000000..74b1d18a6
--- /dev/null
+++ b/_includes/2017/critical/sheet.css
@@ -0,0 +1 @@
+*,::after,::before{background-repeat:no-repeat;box-sizing:inherit}::after,::before{text-decoration:inherit;vertical-align:inherit}html{box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}aside,header,nav{display:block}body{margin:0}h1{font-size:2em;margin:.67em 0}main{display:block}nav ul{list-style:none}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}code{font-family:monospace,monospace;font-size:1em}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}a{-ms-touch-action:manipulation;touch-action:manipulation}body,html{background:#f1f3f5;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif;font-size:14px;line-height:1.6;color:#345;overflow-x:hidden}body{font-size:13px;padding:0;margin:0}@media (min-width:480px) and (max-width:768px){body{font-size:calc(13px + 1 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){body{font-size:calc(14px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){body{font-size:14px}}code,pre{font-family:cousine,SFMono-Regular,Consolas,Menlo,"Liberation Mono","Ubuntu Mono",Courier,monospace;letter-spacing:-.03em}pre{font-size:.96em}:not(pre):not(code){-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a{color:#26648e}a:visited{color:#15234d}@media (max-width:580px){.hint--bottom::after,.hint--bottom::before{display:none}}html.WithJs .post-content{opacity:0}html.WithJs .intro-content,html.WithJs .pages-list,html.WithJs .post-content.-wrapified{opacity:.4}html.WithJs.LoadDone .intro-content,html.WithJs.LoadDone .pages-list,html.WithJs.LoadDone .post-content.-wrapified{opacity:1}.MarkdownBody code{color:#678;font-size:.96em}.MarkdownBody code,.MarkdownBody pre{font-family:cousine,SFMono-Regular,Consolas,Menlo,"Liberation Mono","Ubuntu Mono",Courier,monospace}.MarkdownBody pre{box-shadow:none;border-left:0;overflow:hidden;overflow-x:auto;background:#fff;font-size:.96em;line-height:1.5}.MarkdownBody pre>code{color:#111;max-height:auto;padding:0;background:0 0;overflow:visible;font-size:1em}.MarkdownBody pre.-setup{background:#f8f9fa}.MarkdownBody h2{margin:0;padding:0;margin-bottom:24px;margin-top:64px;position:relative;font-size:30px;line-height:1.2;font-weight:200;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif;margin-top:0}@media (max-width:768px){.MarkdownBody h2{margin-bottom:8px;margin-top:32px}}@media (max-width:480px){.MarkdownBody h2{margin-bottom:8px;margin-top:32px}}@media (min-width:480px) and (max-width:768px){.MarkdownBody h2{font-size:calc(30px + 4 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.MarkdownBody h2{font-size:calc(34px + 2 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.MarkdownBody h2{font-size:36px}}.MarkdownBody h3{margin:0;padding:0;margin-bottom:16px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif;font-size:17px;font-weight:400;color:#745fb5}@media (min-width:480px) and (max-width:768px){.MarkdownBody h3{font-size:calc(17px + 2 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.MarkdownBody h3{font-size:calc(19px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.MarkdownBody h3{font-size:19px}}.MarkdownBody a,.MarkdownBody a:visited{color:#26648e;text-decoration:none}.MarkdownBody table th{padding:8px 16px;vertical-align:top;text-align:left}.MarkdownBody table tr th:last-child{text-align:right}.MarkdownBody table thead{display:none}.MarkdownBody table thead th{font-weight:400;color:#745fb5}.MarkdownBody ul.-six-column{display:flex;flex-wrap:wrap}.MarkdownBody ul.-six-column>li{flex:0 0 16.6666666667%}@media (max-width:480px){.MarkdownBody ul.-six-column>li{flex:0 0 50%}}@media (max-width:768px){.MarkdownBody ul.-six-column>li{flex:0 0 25%}}.MarkdownBody ul.-four-column{display:flex;flex-wrap:wrap}.MarkdownBody ul.-four-column>li{flex:0 0 25%}@media (max-width:480px){.MarkdownBody ul.-four-column>li{flex:0 0 50%}}@media (max-width:768px){.MarkdownBody ul.-four-column>li{flex:0 0 33.3333333333%}}.back-button{text-decoration:none;width:48px;height:48px;line-height:46px;text-align:center;display:inline-block;border-radius:50%}@media (max-width:480px){.back-button{width:32px;height:32px;line-height:30px}}.back-button,.back-button:visited{color:#678}.back-button::before{content:'';display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%3E%3Cpath%20fill%3D%22rgb(51%2C68%2C85)%22%20d%3D%22M427%20234.625H167.296l119.702-119.702L256%2085%2085%20256l171%20171%2029.922-29.924-118.626-119.7H427v-42.75z%22%2F%3E%3C%2Fsvg%3E") center center/24px 24px no-repeat;height:24px;width:24px;vertical-align:middle}@media (max-width:480px){.back-button::before{font-size:16px}}.body-area{max-width:1232px;margin:0 auto;padding:16px}@media (max-width:480px){.body-area{padding:16px}}.codefund-sponsor{min-height:114px}.comments-section{display:flex}@media (max-width:768px){.comments-section>.comments{flex:1 0 100%;width:100%}}@media (min-width:769px){.comments-section>.comments{flex:0 1 66%;min-width:300px}}.h2-section:first-child:not(.-no-hide)>h2{display:none}.h3-section>.body>pre{margin:0;padding:16px}@media (max-width:768px){.h3-section>.body{overflow-x:auto}}.h3-section>.body{background:#fff;box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3)}@media (max-width:480px){.h3-section>.body{margin:0 -16px;box-shadow:0 1px 1px rgba(102,119,136,.55)}}@media (min-width:481px){.h3-section>.body{border-radius:2px}.h3-section>.body>:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.h3-section>.body>:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}}.h3-section>h3{margin-top:8px;margin-bottom:16px;white-space:nowrap;overflow:hidden}@media (max-width:768px){.h3-section>h3{margin-top:0}}.h3-section>h3::after{margin-left:24px;content:'';display:inline-block;vertical-align:middle;width:100%;height:1px;background:linear-gradient(to right,rgba(116,95,181,.2),transparent 80%)}.h3-section>.body>ul{margin:0;padding:0;list-style-type:none}.h3-section>.body>ul>li{padding:8px;padding-left:36px;position:relative}.h3-section>.body>ul>li>p{margin:0;padding:0}.h3-section>.body>ul>li::before{content:'';position:absolute;display:inline-block;width:4px;height:4px;background:#678;border-radius:50%;left:16px;top:18px}.h3-section>.body>ul>li+li{border-top:solid 1px rgba(102,119,136,.05)}.h3-section>.body>p{padding:16px;margin:0}.h3-section>.body>h4{font-size:11px;margin:0;padding:4px 16px;font-weight:400;background:#f8f9fa;color:#678}@media (min-width:480px) and (max-width:768px){.h3-section>.body>h4{font-size:calc(11px + 1 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.h3-section>.body>h4{font-size:calc(12px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.h3-section>.body>h4{font-size:12px}}.h3-section>.body>h4+*{border-top:solid 1px rgba(102,119,136,.05)}.h3-section>.body>iframe~p,.h3-section>.body>pre~p,.h3-section>.body>table~p,.h3-section>.body>ul~p{background:#f8f9fa;color:#678}.h3-section>.body>iframe~p a,.h3-section>.body>iframe~p a:visited,.h3-section>.body>pre~p a,.h3-section>.body>pre~p a:visited,.h3-section>.body>table~p a,.h3-section>.body>table~p a:visited,.h3-section>.body>ul~p a,.h3-section>.body>ul~p a:visited{color:#345;text-decoration:none;border-bottom:solid 1px rgba(102,119,136,.05)}.h3-section>.body>iframe~p a:hover,.h3-section>.body>pre~p a:hover,.h3-section>.body>table~p a:hover,.h3-section>.body>ul~p a:hover{color:#26648e}.h3-section>.body>:not(:first-child){border-top:solid 1px rgba(102,119,136,.05)}.h3-section>.body>p+p,.h3-section>.body>p+p:not(:first-child){margin-top:-1.5em;border-top:0}@media (min-width:481px){.h3-section.-prime>.body{border-radius:2px;box-shadow:0 6px 8px rgba(102,119,136,.03),0 1px 2px rgba(102,119,136,.3),0 8px 12px rgba(58,193,203,.1)}}.h3-section-list{margin-left:-16px;margin-right:-16px;margin-top:0;margin-bottom:0}@media (max-width:1264px){.h3-section-list{margin-left:-8px}}@media (max-width:1264px){.h3-section-list{margin-right:-8px}}.h3-section-list::after{content:'';display:table;clear:both;zoom:1}.h3-section-list>.h3-section{padding:16px;float:left;width:100%}@media (max-width:1264px){.h3-section-list>.h3-section{padding:8px}}@media (min-width:769px){.h3-section-list>.h3-section{padding-top:0}}@media (min-width:769px){.h3-section-list.-two-column>.h3-section,.h3-section-list>.h3-section{width:50%}}.h3-section-list.-one-column>.h3-section{width:100%}.h3-section-list.-one-column>.h3-section+.h3-section{margin-top:16px}@media (min-width:769px){.h3-section-list.-three-column>.h3-section{width:50%}}@media (min-width:961px){.h3-section-list.-three-column>.h3-section{width:33.33%}}@media (min-width:769px){.h3-section-list.-left-reference>.h3-section{width:50%}}@media (min-width:961px){.h3-section-list.-left-reference>.h3-section{width:66.67%}.h3-section-list.-left-reference>.h3-section:first-child{width:33.33%}}.main-heading{margin:0;padding:0;margin-bottom:24px;margin-top:64px;position:relative}@media (max-width:768px){.main-heading{margin-bottom:8px;margin-top:32px}}@media (max-width:480px){.main-heading{margin-bottom:8px;margin-top:32px}}.main-heading{margin-top:0;margin-bottom:0}.main-heading>h1{font-size:40px;line-height:1.2;font-weight:200;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif;margin:0}@media (min-width:480px) and (max-width:768px){.main-heading>h1{font-size:calc(40px + 6 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.main-heading>h1{font-size:calc(46px + 3 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.main-heading>h1{font-size:49px}}.main-heading>h1>em{font-style:normal;color:#9eaab6}.main-heading.-center>h1{text-align:center}.main-heading.-center>.adbox{margin-top:16px;text-align:center}.main-heading.-center>.adbox>.ad{display:inline-block}.page-actions{margin:0;padding:0}.page-actions{height:32px}.page-actions>.link.link>a{display:inline-block;height:32px;line-height:32px;vertical-align:top;width:auto}.page-actions>li{margin:0;padding:0;list-style-type:none}.page-actions>li>a,.page-actions>li>a:visited{color:#678;text-decoration:none}.page-actions>li>a>.text{font-size:11px;display:none}@media (min-width:480px) and (max-width:768px){.page-actions>li>a>.text{font-size:calc(11px + 1 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.page-actions>li>a>.text{font-size:calc(12px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.page-actions>li>a>.text{font-size:12px}}.page-actions>li>a>.text.-visible{display:inline}.page-actions+.page-actions{margin-left:8px}.page-actions>.facebook>a::before,.page-actions>.github>a::before,.page-actions>.twitter>a::before{content:'';vertical-align:middle}.page-actions>.facebook>a::before{display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20512%20512%22%3E%3Cpath%20fill%3D%22rgb(51%2C68%2C85)%22%20d%3D%22M426.8%2064H85.2C73.5%2064%2064%2073.5%2064%2085.2v341.6c0%2011.7%209.5%2021.2%2021.2%2021.2H256V296h-45.9v-56H256v-41.4c0-49.6%2034.4-76.6%2078.7-76.6%2021.2%200%2044%201.6%2049.3%202.3v51.8h-35.3c-24.1%200-28.7%2011.4-28.7%2028.2V240h57.4l-7.5%2056H320v152h106.8c11.7%200%2021.2-9.5%2021.2-21.2V85.2c0-11.7-9.5-21.2-21.2-21.2z%22%2F%3E%3C%2Fsvg%3E") center center/16px 16px no-repeat;height:16px;width:16px}.page-actions>.twitter>a::before{display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%3E%3Cpath%20fill%3D%22rgb(51%2C68%2C85)%22%20d%3D%22M492%20109.5c-17.4%207.7-36%2012.9-55.6%2015.3%2020-12%2035.4-31%2042.6-53.6-18.7%2011.1-39.4%2019.2-61.5%2023.5C399.8%2075.8%20374.6%2064%20346.8%2064c-53.5%200-96.8%2043.4-96.8%2096.9%200%207.6.8%2015%202.5%2022.1-80.5-4-151.9-42.6-199.6-101.3-8.3%2014.3-13.1%2031-13.1%2048.7%200%2033.6%2017.2%2063.3%2043.2%2080.7-16-.4-31-4.8-44-12.1v1.2c0%2047%2033.4%2086.1%2077.7%2095-8.1%202.2-16.7%203.4-25.5%203.4-6.2%200-12.3-.6-18.2-1.8%2012.3%2038.5%2048.1%2066.5%2090.5%2067.3-33.1%2026-74.9%2041.5-120.3%2041.5-7.8%200-15.5-.5-23.1-1.4C62.8%20432%20113.7%20448%20168.3%20448%20346.6%20448%20444%20300.3%20444%20172.2c0-4.2-.1-8.4-.3-12.5C462.6%20146%20479%20129%20492%20109.5z%22%2F%3E%3C%2Fsvg%3E") center center/16px 16px no-repeat;height:16px;width:16px}.page-actions>.github>a::before{display:inline-block;vertical-align:middle;background:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%3E%3Cpath%20fill%3D%22rgb(51%2C68%2C85)%22%20d%3D%22M256%2032C132.3%2032%2032%20134.9%2032%20261.7c0%20101.5%2064.2%20187.5%20153.2%20217.9%201.4.3%202.6.4%203.8.4%208.3%200%2011.5-6.1%2011.5-11.4%200-5.5-.2-19.9-.3-39.1-8.4%201.9-15.9%202.7-22.6%202.7-43.1%200-52.9-33.5-52.9-33.5-10.2-26.5-24.9-33.6-24.9-33.6-19.5-13.7-.1-14.1%201.4-14.1h.1c22.5%202%2034.3%2023.8%2034.3%2023.8%2011.2%2019.6%2026.2%2025.1%2039.6%2025.1%2010.5%200%2020-3.4%2025.6-6%202-14.8%207.8-24.9%2014.2-30.7-49.7-5.8-102-25.5-102-113.5%200-25.1%208.7-45.6%2023-61.6-2.3-5.8-10-29.2%202.2-60.8%200%200%201.6-.5%205-.5%208.1%200%2026.4%203.1%2056.6%2024.1%2017.9-5.1%2037-7.6%2056.1-7.7%2019%20.1%2038.2%202.6%2056.1%207.7%2030.2-21%2048.5-24.1%2056.6-24.1%203.4%200%205%20.5%205%20.5%2012.2%2031.6%204.5%2055%202.2%2060.8%2014.3%2016.1%2023%2036.6%2023%2061.6%200%2088.2-52.4%20107.6-102.3%20113.3%208%207.1%2015.2%2021.1%2015.2%2042.5%200%2030.7-.3%2055.5-.3%2063%200%205.4%203.1%2011.5%2011.4%2011.5%201.2%200%202.6-.1%204-.4C415.9%20449.2%20480%20363.1%20480%20261.7%20480%20134.9%20379.7%2032%20256%2032z%22%2F%3E%3C%2Fsvg%3E") center center/16px 16px no-repeat;height:16px;width:16px}.page-actions>.facebook>a::before,.page-actions>.twitter>a::before{width:32px;height:32px}.page-actions>.github>a::before{position:relative;top:-2px}.page-actions>.link.-button>a{box-shadow:inset 0 0 0 1px rgba(102,119,136,.2);border-radius:2px;padding:0 16px;margin:0 8px}.page-actions>.link.-button>a>.text{margin-left:4px;position:relative;top:-1px}@media (max-width:768px){.page-actions>.link{margin-left:16px}}.page-actions>.link:first-child>a{margin-left:0}.page-actions>.link:last-child>a{margin-right:0}.top-nav,.top-nav>.container{height:64px;line-height:64px;text-align:center;position:relative}@media (max-width:480px){.top-nav>.container{height:32px;line-height:32px;margin-top:8px}.top-nav{height:48px;padding:8px 0;border-bottom:solid 1px rgba(102,119,136,.2);margin-bottom:8px}}.top-nav>.container{padding-left:16px;padding-right:16px;max-width:1232px;margin:0 auto}@media (max-width:480px){.top-nav>.container{padding-left:16px}}@media (max-width:480px){.top-nav>.container{padding-right:16px}}.top-nav>.container{display:flex;align-items:center;position:relative}.top-nav>.container>.left{flex:0 0 auto;line-height:32px}.top-nav>.container>.brand{flex:1 1 auto}.top-nav>.container>.actions{flex:0 0 auto;display:flex}.top-nav>.container>.brand{font-size:11px;display:inline-block;font-weight:700;text-transform:uppercase;letter-spacing:.05em;text-decoration:none}@media (min-width:480px) and (max-width:768px){.top-nav>.container>.brand{font-size:calc(11px + 1 * ((100vw - 480px)/ 288))}}@media (min-width:768px) and (max-width:1280px){.top-nav>.container>.brand{font-size:calc(12px + 0 * ((100vw - 768px)/ 512))}}@media (min-width:1280px){.top-nav>.container>.brand{font-size:12px}}.top-nav>.container>.brand,.top-nav>.container>.brand:visited{color:#345}@media (max-width:480px){.top-nav>.container>.brand{display:none}.top-nav>.container>.actions{margin-left:auto}}@media (min-width:481px){.top-nav>.container>.actions{position:absolute;right:16px;top:16px}}@media (min-width:481px) and (max-width:480px){.top-nav>.container>.actions{right:16px}}@media (min-width:481px){.top-nav>.container>.left{position:absolute;left:16px;top:16px}}@media (min-width:481px) and (max-width:480px){.top-nav>.container>.left{left:16px}}@media (min-width:1232px){.top-nav>.container>.left>.home{position:relative;left:-16px}}
\ No newline at end of file
diff --git a/_includes/2017/foot.html b/_includes/2017/foot.html
index 038762af7..947185b6c 100644
--- a/_includes/2017/foot.html
+++ b/_includes/2017/foot.html
@@ -1,3 +1,5 @@
+
+
{% for lang in page.prism_languages %}{% endfor %}
diff --git a/_includes/2017/head.html b/_includes/2017/head.html
index a5b05d464..12ee9ce3d 100644
--- a/_includes/2017/head.html
+++ b/_includes/2017/head.html
@@ -3,11 +3,11 @@
{% if include.critical == 'home'
-%}{%
+%}{%
endif
%}{%
if include.critical == 'sheet'
-%}{%
+%}{%
endif %}
diff --git a/_js/app.js b/_js/app.js
new file mode 100644
index 000000000..1099f465c
--- /dev/null
+++ b/_js/app.js
@@ -0,0 +1,7 @@
+// 3rd party libs
+window.Prism = require('prismjs')
+
+// All the others
+function requireAll (r) { r.keys().forEach(r) }
+requireAll(require.context('./initializers/', true, /\.js$/))
+requireAll(require.context('./behaviors/', true, /\.js$/))
diff --git a/_parcel/behaviors/anchors.js b/_js/behaviors/anchors.js
similarity index 93%
rename from _parcel/behaviors/anchors.js
rename to _js/behaviors/anchors.js
index efe8f7ca4..025b5b14e 100644
--- a/_parcel/behaviors/anchors.js
+++ b/_js/behaviors/anchors.js
@@ -9,7 +9,7 @@ const DEFAULTS = {
// text of anchor
text: '#',
// append before or after innerText?
- shouldAppend: false
+ shouldAppend: false,
}
/*
@@ -19,9 +19,7 @@ const DEFAULTS = {
onmount('[data-js-anchors]', function () {
const data = JSON.parse(this.getAttribute('data-js-anchors') || '{}')
const rules = Array.isArray(data)
- ? data.length
- ? data
- : [DEFAULTS]
+ ? (data.length ? data : [DEFAULTS])
: [Object.assign({}, DEFAULTS, data)]
for (const { rule, className, text, shouldAppend } of rules) {
diff --git a/_parcel/behaviors/dismiss.js b/_js/behaviors/dismiss.js
similarity index 94%
rename from _parcel/behaviors/dismiss.js
rename to _js/behaviors/dismiss.js
index 8dba8cd44..676db0f11 100644
--- a/_parcel/behaviors/dismiss.js
+++ b/_js/behaviors/dismiss.js
@@ -14,7 +14,7 @@ onmount('[data-js-dismiss]', function () {
const dismissable = getData(parent, 'js-dismissable')
const id = (dismissable && dismissable.id) || ''
- on(this, 'click', (e) => {
+ on(this, 'click', e => {
Dismiss.setDismissed(id)
e.preventDefault()
if (parent) remove(parent)
diff --git a/_parcel/behaviors/dismissable.js b/_js/behaviors/dismissable.js
similarity index 100%
rename from _parcel/behaviors/dismissable.js
rename to _js/behaviors/dismissable.js
diff --git a/_parcel/behaviors/disqus.js b/_js/behaviors/disqus.js
similarity index 100%
rename from _parcel/behaviors/disqus.js
rename to _js/behaviors/disqus.js
diff --git a/_parcel/behaviors/h3-section-list.js b/_js/behaviors/h3-section-list.js
similarity index 87%
rename from _parcel/behaviors/h3-section-list.js
rename to _js/behaviors/h3-section-list.js
index 9a6bd5598..45ba06d16 100644
--- a/_parcel/behaviors/h3-section-list.js
+++ b/_js/behaviors/h3-section-list.js
@@ -1,6 +1,6 @@
/* eslint-disable no-new */
-import Isotope from 'isotope-layout'
+import Isotope from 'isotope-layout/dist/isotope.pkgd.js'
import onmount from 'onmount'
import on from 'dom101/on'
import qsa from 'dom101/query-selector-all'
@@ -17,7 +17,7 @@ onmount('[data-js-h3-section-list]', function () {
const images = qsa('img', this)
- images.forEach((image) => {
+ images.forEach(image => {
on(image, 'load', () => {
iso.layout()
})
diff --git a/_parcel/behaviors/main-body.js b/_js/behaviors/main-body.js
similarity index 100%
rename from _parcel/behaviors/main-body.js
rename to _js/behaviors/main-body.js
diff --git a/_parcel/behaviors/no-preview.js b/_js/behaviors/no-preview.js
similarity index 100%
rename from _parcel/behaviors/no-preview.js
rename to _js/behaviors/no-preview.js
diff --git a/_parcel/behaviors/search-form.js b/_js/behaviors/search-form.js
similarity index 91%
rename from _parcel/behaviors/search-form.js
rename to _js/behaviors/search-form.js
index 2cf243516..c0091bf24 100644
--- a/_parcel/behaviors/search-form.js
+++ b/_js/behaviors/search-form.js
@@ -6,7 +6,7 @@ import on from 'dom101/on'
*/
onmount('[data-js-search-form]', function () {
- on(this, 'submit', (e) => {
+ on(this, 'submit', e => {
e.preventDefault()
const link = document.querySelector('a[data-search-index]:visible')
diff --git a/_parcel/behaviors/search-input.js b/_js/behaviors/search-input.js
similarity index 88%
rename from _parcel/behaviors/search-input.js
rename to _js/behaviors/search-input.js
index ae17e0ac7..0162a2903 100644
--- a/_parcel/behaviors/search-input.js
+++ b/_js/behaviors/search-input.js
@@ -17,8 +17,6 @@ onmount('[data-js-search-input]', function () {
const query = (qs(window.location.search) || {}).q
if (query && query.length) {
this.value = query
- setTimeout(() => {
- Search.show(query)
- })
+ setTimeout(() => { Search.show(query) })
}
})
diff --git a/_parcel/behaviors/searchable-header.js b/_js/behaviors/searchable-header.js
similarity index 70%
rename from _parcel/behaviors/searchable-header.js
rename to _js/behaviors/searchable-header.js
index b569921dc..a9947944b 100644
--- a/_parcel/behaviors/searchable-header.js
+++ b/_js/behaviors/searchable-header.js
@@ -10,12 +10,11 @@ import './searchable-item'
*/
onmount('[data-js-searchable-header]', function () {
- const els = nextUntil(this, '[data-js-searchable-header]').filter((el) =>
- matches(el, '[data-search-index]')
- )
+ const els = nextUntil(this, '[data-js-searchable-header]')
+ .filter(el => matches(el, '[data-search-index]'))
const keywords = els
- .map((n) => n.getAttribute('data-search-index'))
+ .map(n => n.getAttribute('data-search-index'))
.join(' ')
.split(' ')
diff --git a/_parcel/behaviors/searchable-item.js b/_js/behaviors/searchable-item.js
similarity index 100%
rename from _parcel/behaviors/searchable-item.js
rename to _js/behaviors/searchable-item.js
diff --git a/_parcel/critical.js b/_js/critical.js
similarity index 96%
rename from _parcel/critical.js
rename to _js/critical.js
index b92f80be7..d949e5e85 100644
--- a/_parcel/critical.js
+++ b/_js/critical.js
@@ -20,7 +20,7 @@ on(window, 'load', done)
setTimeout(done, 5000)
let isDone
-function done() {
+function done () {
if (isDone) return
addClass(document.documentElement, 'LoadDone')
isDone = true
diff --git a/_js/helpers/__tests__/qs.test.js b/_js/helpers/__tests__/qs.test.js
new file mode 100644
index 000000000..e71495c32
--- /dev/null
+++ b/_js/helpers/__tests__/qs.test.js
@@ -0,0 +1,21 @@
+/* eslint-env jest */
+import qs from '../qs'
+
+describe('qs()', () => {
+ test('basic', run({
+ input: '?preview=1',
+ output: { preview: '1' }
+ }))
+
+ test('two fragments', run({
+ input: '?a=1&b=2',
+ output: { a: '1', b: '2' }
+ }))
+
+ function run ({ input, output }) {
+ return function () {
+ const result = qs(input)
+ expect(result).toEqual(output)
+ }
+ }
+})
diff --git a/_parcel/helpers/data.js b/_js/helpers/data.js
similarity index 74%
rename from _parcel/helpers/data.js
rename to _js/helpers/data.js
index fddc4073a..2e74e4285 100644
--- a/_parcel/helpers/data.js
+++ b/_js/helpers/data.js
@@ -2,7 +2,7 @@
* Stores and retrieves data from an element. Works like jQuery.data().
*/
-export function data(el, key, val) {
+export function data (el, key, val) {
if (typeof val !== 'undefined') {
return getData(el, key)
} else {
@@ -10,11 +10,11 @@ export function data(el, key, val) {
}
}
-export function getData(el, key) {
+export function getData (el, key) {
const str = el.getAttribute('data-' + key)
return JSON.parse(str || '{}')
}
-export function setData(el, key, val) {
+export function setData (el, key, val) {
el.setAttribute('data-' + key, JSON.stringify(val))
}
diff --git a/_parcel/helpers/dismiss.js b/_js/helpers/dismiss.js
similarity index 87%
rename from _parcel/helpers/dismiss.js
rename to _js/helpers/dismiss.js
index 2d8b1a207..b629d2b71 100644
--- a/_parcel/helpers/dismiss.js
+++ b/_js/helpers/dismiss.js
@@ -7,7 +7,7 @@ import * as Store from './store'
* setDismissed('2017-09-02-happy-birthday')
*/
-export function setDismissed(id) {
+export function setDismissed (id) {
Store.update('dismissed', function (data) {
data[id] = true
return data
@@ -22,7 +22,7 @@ export function setDismissed(id) {
* isDismissed('2017-09-02-happy-birthday') => true
*/
-export function isDismissed(id) {
+export function isDismissed (id) {
const data = Store.fetch('dismissed')
return data && data[id]
}
diff --git a/_parcel/helpers/dom.js b/_js/helpers/dom.js
similarity index 55%
rename from _parcel/helpers/dom.js
rename to _js/helpers/dom.js
index 723c41fc5..bf94941cb 100644
--- a/_parcel/helpers/dom.js
+++ b/_js/helpers/dom.js
@@ -4,35 +4,33 @@ import matches from 'dom101/matches'
* Just like jQuery.append
*/
-export function appendMany(el, children) {
- children.forEach((child) => {
- el.appendChild(child)
- })
+export function appendMany (el, children) {
+ children.forEach(child => { el.appendChild(child) })
}
/*
* Just like jQuery.nextUntil
*/
-export function nextUntil(el, selector) {
+export function nextUntil (el, selector) {
const nextEl = el.nextSibling
return nextUntilTick(nextEl, selector, [])
}
-function nextUntilTick(el, selector, acc) {
+function nextUntilTick (el, selector, acc) {
if (!el) return acc
const isMatch = matches(el, selector)
if (isMatch) return acc
- return nextUntilTick(el.nextSibling, selector, [...acc, el])
+ return nextUntilTick(el.nextSibling, selector, [ ...acc, el ])
}
/*
* Just like jQuery.before
*/
-export function before(reference, newNode) {
+export function before (reference, newNode) {
reference.parentNode.insertBefore(newNode, reference)
}
@@ -40,8 +38,9 @@ export function before(reference, newNode) {
* Like jQuery.children('selector')
*/
-export function findChildren(el, selector) {
- return [].slice.call(el.children).filter((child) => matches(child, selector))
+export function findChildren (el, selector) {
+ return [].slice.call(el.children)
+ .filter(child => matches(child, selector))
}
/**
@@ -53,9 +52,9 @@ export function findChildren(el, selector) {
* createDiv({ class: 'foo' })
*/
-export function createDiv(props) {
+export function createDiv (props) {
const d = document.createElement('div')
- Object.keys(props).forEach((key) => {
+ Object.keys(props).forEach(key => {
d.setAttribute(key, props[key])
})
return d
diff --git a/_parcel/helpers/inject_disqus.js b/_js/helpers/inject_disqus.js
similarity index 81%
rename from _parcel/helpers/inject_disqus.js
rename to _js/helpers/inject_disqus.js
index 5fd742504..886b15faa 100644
--- a/_parcel/helpers/inject_disqus.js
+++ b/_js/helpers/inject_disqus.js
@@ -5,12 +5,12 @@
* inject('devhints.disqus.com')
*/
-export default function inject(host) {
+export default function inject (host) {
injectEmbed(host)
injectCount(host)
}
-export function injectEmbed(host) {
+export function injectEmbed (host) {
const d = document
const s = d.createElement('script')
s.src = `https://${host}/embed.js`
@@ -18,7 +18,7 @@ export function injectEmbed(host) {
;(d.head || d.body).appendChild(s)
}
-export function injectCount(host) {
+export function injectCount (host) {
const d = document
const s = d.createElement('script')
s.src = `https://${host}/count.js`
diff --git a/_parcel/helpers/noop.js b/_js/helpers/noop.js
similarity index 100%
rename from _parcel/helpers/noop.js
rename to _js/helpers/noop.js
diff --git a/_parcel/helpers/permutate.js b/_js/helpers/permutate.js
similarity index 79%
rename from _parcel/helpers/permutate.js
rename to _js/helpers/permutate.js
index 2bbb4e9ca..99918d7a6 100644
--- a/_parcel/helpers/permutate.js
+++ b/_js/helpers/permutate.js
@@ -7,7 +7,7 @@
* })
*/
-export default function permutate(data) {
+export default function permutate (data) {
let words = []
if (data.slug) {
words = words.concat(permutateString(data.slug))
@@ -26,11 +26,11 @@ export default function permutate(data) {
* => ['h', 'hi', 'j', 'jo', 'joe']
*/
-export function permutateString(str) {
+export function permutateString (str) {
let words = []
let inputs = splitwords(str)
- inputs.forEach((word) => {
+ inputs.forEach(word => {
words = words.concat(permutateWord(word))
})
@@ -45,7 +45,7 @@ export function permutateString(str) {
* => ['h', 'he', 'hel', 'hell', 'hello']
*/
-export function permutateWord(str) {
+export function permutateWord (str) {
let words = []
const len = str.length
for (var i = 1; i <= len; ++i) {
@@ -62,11 +62,10 @@ export function permutateWord(str) {
* => ['hello', 'world']
*/
-export function splitwords(str) {
- const words = str
- .toLowerCase()
+export function splitwords (str) {
+ const words = str.toLowerCase()
.split(/[ /\-_]/)
- .filter((k) => k && k.length !== 0)
+ .filter(k => k && k.length !== 0)
return words
}
diff --git a/_parcel/helpers/preview.js b/_js/helpers/preview.js
similarity index 79%
rename from _parcel/helpers/preview.js
rename to _js/helpers/preview.js
index 1c1a49eff..670c09c68 100644
--- a/_parcel/helpers/preview.js
+++ b/_js/helpers/preview.js
@@ -2,6 +2,6 @@
* Checks if we're in preview mode (?preview=1).
*/
-export function isPreview() {
+export function isPreview () {
return window.location.search.indexOf('preview=1') !== -1
}
diff --git a/_parcel/helpers/qs.js b/_js/helpers/qs.js
similarity index 67%
rename from _parcel/helpers/qs.js
rename to _js/helpers/qs.js
index e2a2fdc8a..c87edee8a 100644
--- a/_parcel/helpers/qs.js
+++ b/_js/helpers/qs.js
@@ -2,16 +2,16 @@
* Helper: minimal qs implementation
*/
-export default function qs(search) {
+export default function qs (search) {
search = search.substr(1)
- const parts = search.split('&').map((p) => p.split('='))
+ const parts = search.split('&').map(p => p.split('='))
return parts.reduce((result, part) => {
result[part[0]] = qsdecode(part[1])
return result
}, {})
}
-export function qsdecode(string) {
+export function qsdecode (string) {
if (!string) string = ''
string = string.replace(/\+/g, ' ')
return string
diff --git a/_parcel/helpers/search.js b/_js/helpers/search.js
similarity index 66%
rename from _parcel/helpers/search.js
rename to _js/helpers/search.js
index db6548664..914b6ef94 100644
--- a/_parcel/helpers/search.js
+++ b/_js/helpers/search.js
@@ -8,8 +8,8 @@ import qsa from 'dom101/query-selector-all'
* Search.showAll()
*/
-export function showAll() {
- qsa('[data-search-index]').forEach((el) => {
+export function showAll () {
+ qsa('[data-search-index]').forEach(el => {
el.removeAttribute('aria-hidden')
})
}
@@ -21,20 +21,20 @@ export function showAll() {
* Search.show('hello')
*/
-export function show(val) {
+export function show (val) {
const keywords = splitwords(val)
if (!keywords.length) return showAll()
const selectors = keywords
- .map((k) => `[data-search-index~=${JSON.stringify(k)}]`)
+ .map(k => `[data-search-index~=${JSON.stringify(k)}]`)
.join('')
- qsa('[data-search-index]').forEach((el) => {
+ qsa('[data-search-index]').forEach(el => {
el.setAttribute('aria-hidden', true)
})
- qsa(selectors).forEach((el) => {
+ qsa(selectors).forEach(el => {
el.removeAttribute('aria-hidden')
})
}
diff --git a/_parcel/helpers/store.js b/_js/helpers/store.js
similarity index 89%
rename from _parcel/helpers/store.js
rename to _js/helpers/store.js
index a2f4ad652..8da6af718 100644
--- a/_parcel/helpers/store.js
+++ b/_js/helpers/store.js
@@ -9,7 +9,7 @@
* })
*/
-export function update(key, fn) {
+export function update (key, fn) {
if (!window.localStorage) return
let data = JSON.parse(window.localStorage[key] || '{}')
data = fn(data)
@@ -23,7 +23,7 @@ export function update(key, fn) {
* const data = fetch('dismissed')
*/
-export function fetch(key) {
+export function fetch (key) {
if (!window.localStorage) return
return JSON.parse(window.localStorage[key] || '{}')
}
diff --git a/_parcel/initializers/onmount.js b/_js/initializers/onmount.js
similarity index 73%
rename from _parcel/initializers/onmount.js
rename to _js/initializers/onmount.js
index 26958618a..f015e59eb 100644
--- a/_parcel/initializers/onmount.js
+++ b/_js/initializers/onmount.js
@@ -6,7 +6,5 @@ import onmount from 'onmount'
*/
ready(() => {
- setTimeout(() => {
- onmount()
- })
+ setTimeout(() => { onmount() })
})
diff --git a/_parcel/wrapify/__tests__/__snapshots__/index.test.js.snap b/_js/wrapify/__tests__/__snapshots__/index.test.js.snap
similarity index 100%
rename from _parcel/wrapify/__tests__/__snapshots__/index.test.js.snap
rename to _js/wrapify/__tests__/__snapshots__/index.test.js.snap
diff --git a/_js/wrapify/__tests__/index.test.js b/_js/wrapify/__tests__/index.test.js
new file mode 100644
index 000000000..1b51f359d
--- /dev/null
+++ b/_js/wrapify/__tests__/index.test.js
@@ -0,0 +1,63 @@
+/* eslint-env jest */
+import wrapify from '../index'
+import $ from 'jquery'
+
+it('simple usage', run(`
+
+
simple usage
+
+ install
+
(install)
+
+
usage
+
(usage)
+
+`, $div => {
+ expect($div.find('.h2-section .h3-section-list .h3-section').length).toEqual(2)
+}))
+
+it('h3 with class', run(`
+
+`, $div => {
+ expect($div.find('div.h3-section.-hello').length).toEqual(1)
+ expect($div.find('div.h3-section-list.-hello').length).toEqual(1)
+}))
+
+it('multiple h2s', run(`
+
+
multiple h2
+
+ install
+
(install)
+
+
usage
+
(usage)
+
+
getting started
+
+ first
+
(first)
+
+
second
+
(second)
+
+`))
+
+function run (input, fn) {
+ return function () {
+ const $div = $(input)
+ wrapify($div[0])
+ expect($div[0]).toMatchSnapshot()
+ if (fn) fn($div)
+ }
+}
+
+it('h2 + pre', run(`
+
+`))
diff --git a/_parcel/wrapify/index.js b/_js/wrapify/index.js
similarity index 77%
rename from _parcel/wrapify/index.js
rename to _js/wrapify/index.js
index 0af5fbaf1..e2b93f589 100644
--- a/_parcel/wrapify/index.js
+++ b/_js/wrapify/index.js
@@ -1,12 +1,6 @@
import matches from 'dom101/matches'
import addClass from 'dom101/add-class'
-import {
- appendMany,
- nextUntil,
- before,
- findChildren,
- createDiv
-} from '../helpers/dom'
+import { appendMany, nextUntil, before, findChildren, createDiv } from '../helpers/dom'
/**
* Wraps h2 sections into h2-section.
@@ -15,16 +9,14 @@ import {
* @private
*/
-export default function wrapify(root) {
+export default function wrapify (root) {
// These are your H2 sections. Returns a list of .h2-section nodes.
const sections = wrapifyH2(root)
// For each h2 section, wrap the H3's in them
- sections.forEach((section) => {
+ sections.forEach(section => {
const bodies = findChildren(section, '[data-js-h3-section-list]')
- bodies.forEach((body) => {
- wrapifyH3(body)
- })
+ bodies.forEach(body => { wrapifyH3(body) })
})
}
@@ -41,15 +33,14 @@ export default function wrapify(root) {
* @private
*/
-function wrapifyH2(root) {
+function wrapifyH2 (root) {
return groupify(root, {
tag: 'h2',
wrapperFn: () => createDiv({ class: 'h2-section' }),
- bodyFn: () =>
- createDiv({
- class: 'body h3-section-list',
- 'data-js-h3-section-list': ''
- })
+ bodyFn: () => createDiv({
+ class: 'body h3-section-list',
+ 'data-js-h3-section-list': ''
+ })
})
}
@@ -66,7 +57,7 @@ function wrapifyH2(root) {
* @private
*/
-function wrapifyH3(root) {
+function wrapifyH3 (root) {
return groupify(root, {
tag: 'h3',
wrapperFn: () => createDiv({ class: 'h3-section' }),
@@ -80,27 +71,27 @@ function wrapifyH3(root) {
* @private
*/
-export function groupify(el, { tag, wrapperFn, bodyFn }) {
+export function groupify (el, { tag, wrapperFn, bodyFn }) {
const first = el.children[0]
let result = []
// Handle the markup before the first h2
if (first && !matches(first, tag)) {
const sibs = nextUntil(first, tag)
- result.push(wrap(first, null, [first, ...sibs]))
+ result.push(wrap(first, null, [ first, ...sibs ]))
}
// Find all h3's inside it
const children = findChildren(el, tag)
- children.forEach((child) => {
+ children.forEach(child => {
const sibs = nextUntil(child, tag)
result.push(wrap(child, child, sibs))
})
return result
- function wrap(pivot, first, sibs) {
+ function wrap (pivot, first, sibs) {
const wrap = wrapperFn()
const pivotClass = pivot.className
diff --git a/_parcel/_base.scss b/_parcel/_base.scss
deleted file mode 100644
index daebb4d5d..000000000
--- a/_parcel/_base.scss
+++ /dev/null
@@ -1,32 +0,0 @@
-// Vendor and variables
-@import 'sanitize.css/sanitize.css';
-@import '../_sass/2017/variables.scss';
-@import '../node_modules/modularscale-sass/stylesheets/_modularscale.scss';
-@import '../_sass/vendor/ionicons-inline/ionicons.scss';
-
-// Utilities
-@import '../_sass/2017/utils/carbon-style.scss';
-@import '../_sass/2017/utils/_font-size.scss';
-@import '../_sass/2017/utils/gutter.scss';
-@import '../_sass/2017/utils/heading-style.scss';
-@import '../_sass/2017/utils/section-gutter.scss';
-@import '../_sass/2017/utils/section-with-container.scss';
-
-// Base
-@import 'sanitize.css/sanitize.css';
-@import '../_sass/2017/base/base.scss';
-@import '../_sass/2017/base/fade.scss';
-
-// Components
-@import '../_sass/2017/components/attribute-peg.scss';
-@import '../_sass/2017/components/announcements-item.scss';
-@import '../_sass/2017/components/announcements-list.scss';
-@import '../_sass/2017/components/back-button.scss';
-@import '../_sass/2017/components/body-area.scss';
-@import '../_sass/2017/components/codefund-sponsor.scss';
-@import '../_sass/2017/components/page-actions.scss';
-@import '../_sass/2017/components/pages-list.scss';
-@import '../_sass/2017/components/search-box.scss';
-@import '../_sass/2017/components/site-header.scss';
-@import '../_sass/2017/components/top-nav.scss';
-@import '../_sass/2017/components/top-sheet.scss';
diff --git a/_parcel/_utils.scss b/_parcel/_utils.scss
deleted file mode 100644
index c19fd887b..000000000
--- a/_parcel/_utils.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-// Vendor
-@import '../_sass/2017/variables.scss';
-@import '../node_modules/modularscale-sass/stylesheets/_modularscale.scss';
-@import '../_sass/vendor/ionicons-inline/ionicons.scss';
-
-// Utilities
-@import '../_sass/2017/utils/carbon-style.scss';
-@import '../_sass/2017/utils/_font-size.scss';
-@import '../_sass/2017/utils/gutter.scss';
-@import '../_sass/2017/utils/heading-style.scss';
-@import '../_sass/2017/utils/section-gutter.scss';
-@import '../_sass/2017/utils/section-with-container.scss';
diff --git a/_parcel/app.js b/_parcel/app.js
deleted file mode 100644
index 24a50911c..000000000
--- a/_parcel/app.js
+++ /dev/null
@@ -1,30 +0,0 @@
-// Prismjs
-import 'prismjs'
-import 'prismjs/plugins/line-highlight/prism-line-highlight.min.js'
-import 'prismjs/components/prism-jsx.min.js'
-import 'prismjs/components/prism-bash.min.js'
-import 'prismjs/components/prism-scss.min.js'
-import 'prismjs/components/prism-css.min.js'
-import 'prismjs/components/prism-elixir.min.js'
-import 'prismjs/components/prism-ruby.min.js'
-
-// Initializers
-import './initializers/prism'
-import './initializers/onmount'
-
-// Behaviors
-import './behaviors/anchors'
-import './behaviors/dismissable'
-import './behaviors/dismiss'
-import './behaviors/disqus'
-import './behaviors/h3-section-list'
-import './behaviors/main-body'
-import './behaviors/no-preview'
-import './behaviors/searchable-header'
-import './behaviors/searchable-item'
-import './behaviors/search-form'
-import './behaviors/search-input'
-
-// CSS
-import 'prismjs/plugins/line-highlight/prism-line-highlight.css'
-import 'hint.css/hint.min.css'
diff --git a/_parcel/critical-home.scss b/_parcel/critical-home.scss
deleted file mode 100644
index c97e2bb79..000000000
--- a/_parcel/critical-home.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-@import './_utils.scss';
-@import './_base.scss';
-
-// Components
-@import '../_sass/2017/components/attribute-peg.scss';
-@import '../_sass/2017/components/announcements-item.scss';
-@import '../_sass/2017/components/announcements-list.scss';
-@import '../_sass/2017/components/back-button.scss';
-@import '../_sass/2017/components/body-area.scss';
-@import '../_sass/2017/components/codefund-sponsor.scss';
-@import '../_sass/2017/components/page-actions.scss';
-@import '../_sass/2017/components/pages-list.scss';
-@import '../_sass/2017/components/search-box.scss';
-@import '../_sass/2017/components/site-header.scss';
-@import '../_sass/2017/components/top-nav.scss';
-@import '../_sass/2017/components/top-sheet.scss';
diff --git a/_parcel/critical-sheet.scss b/_parcel/critical-sheet.scss
deleted file mode 100644
index d8fab1425..000000000
--- a/_parcel/critical-sheet.scss
+++ /dev/null
@@ -1,21 +0,0 @@
-@import './_utils.scss';
-@import './_base.scss';
-
-// Markdown
-@import '../_sass/2017/markdown/a-em.scss';
-@import '../_sass/2017/markdown/code.scss';
-@import '../_sass/2017/markdown/headings.scss';
-@import '../_sass/2017/markdown/local-anchor.scss';
-@import '../_sass/2017/markdown/p.scss';
-@import '../_sass/2017/markdown/table.scss';
-@import '../_sass/2017/markdown/ul.scss';
-
-// Components
-@import '../_sass/2017/components/back-button.scss';
-@import '../_sass/2017/components/body-area.scss';
-@import '../_sass/2017/components/codefund-sponsor.scss';
-@import '../_sass/2017/components/h3-section.scss';
-@import '../_sass/2017/components/h3-section-list.scss';
-@import '../_sass/2017/components/main-heading.scss';
-@import '../_sass/2017/components/page-actions.scss';
-@import '../_sass/2017/components/top-nav.scss';
diff --git a/_parcel/initializers/prism.js b/_parcel/initializers/prism.js
deleted file mode 100644
index b32e140f8..000000000
--- a/_parcel/initializers/prism.js
+++ /dev/null
@@ -1 +0,0 @@
-window.Prism = require('prismjs')
diff --git a/_parcel/wrapify/__tests__/index.test.js b/_parcel/wrapify/__tests__/index.test.js
deleted file mode 100644
index 019161994..000000000
--- a/_parcel/wrapify/__tests__/index.test.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/* eslint-env jest */
-import wrapify from '../index'
-
-it(
- 'simple usage',
- run(
- `
-
-
simple usage
-
- install
-
(install)
-
-
usage
-
(usage)
-
-`,
- (root) => {
- expect(
- root.querySelectorAll('.h2-section .h3-section-list .h3-section').length
- ).toEqual(2)
- }
- )
-)
-
-it(
- 'h3 with class',
- run(
- `
-
-`,
- (root) => {
- expect(root.querySelectorAll('div.h3-section.-hello').length).toEqual(1)
- expect(
- root.querySelectorAll('div.h3-section-list.-hello').length
- ).toEqual(1)
- }
- )
-)
-
-it(
- 'multiple h2s',
- run(`
-
-
multiple h2
-
- install
-
(install)
-
-
usage
-
(usage)
-
-
getting started
-
- first
-
(first)
-
-
second
-
(second)
-
-`)
-)
-
-function run(input, fn) {
- return function () {
- const div = document.createElement('div')
- div.innerHTML = input
-
- const root = div.children[0]
- wrapify(root)
- expect(root).toMatchSnapshot()
-
- if (fn) fn(root)
- }
-}
-
-it(
- 'h2 + pre',
- run(`
-
-`)
-)
diff --git a/_sass/2017/components/announcements-item.scss b/_sass/2017/components/announcements-item.scss
index f1a74dd9e..108eb0730 100644
--- a/_sass/2017/components/announcements-item.scss
+++ b/_sass/2017/components/announcements-item.scss
@@ -43,7 +43,6 @@
margin: 0;
padding: 0;
cursor: pointer;
- background: transparent;
&:hover,
&:focus {
diff --git a/_sass/2017/style.scss b/_sass/2017/style.scss
index c69fcde89..fe6454134 100644
--- a/_sass/2017/style.scss
+++ b/_sass/2017/style.scss
@@ -1,6 +1,4 @@
-// Generated by parcel
-@import '../../assets/packed/app.css';
-
+@import '../vendor/sanitize.css/sanitize';
@import './variables';
@import '../vendor/modularscale/modularscale';
@import '../vendor/ionicons-inline/ionicons';
diff --git a/_sass/vendor/modularscale/_modularscale.scss b/_sass/vendor/modularscale/_modularscale.scss
index cfa03c10d..3c21f42cc 100644
--- a/_sass/vendor/modularscale/_modularscale.scss
+++ b/_sass/vendor/modularscale/_modularscale.scss
@@ -80,14 +80,14 @@ $modularscale : () !default;// Parse settings starting with defaults.
// This does not support non-integer exponents,
// Check and return an error if a non-integer exponent is passed.
@if (floor($e) != $e) {
- // @error '
-// ======================================================================
-// Non-integer values are not supported in modularscale by default.
+ @error '
+======================================================================
+Non-integer values are not supported in modularscale by default.
-// Try using mathsass in your project to add non-integer scale support.
-// https://github.com/terkel/mathsass
-// ======================================================================
-// '
+Try using mathsass in your project to add non-integer scale support.
+https://github.com/terkel/mathsass
+======================================================================
+'
}
// Seed the return.
diff --git a/_support/critical.js b/_support/critical.js
new file mode 100644
index 000000000..345b80ffe
--- /dev/null
+++ b/_support/critical.js
@@ -0,0 +1,45 @@
+const critical = require('critical')
+
+console.warn('Generating critical path styles into _includes/2017/critical/...')
+
+const OPTIONS = {
+ base: '_site',
+ width: 1400,
+ height: 900,
+ minify: true,
+ extract: true,
+ ignore: [
+ '@font-face'
+ ],
+ include: [
+ // fade-in magic (base/fade)
+ /html\.WithJs/
+ ]
+}
+
+critical.generate({
+ ...OPTIONS,
+ src: 'index.html',
+ dest: '../_includes/2017/critical/home.css',
+ include: [
+ ...OPTIONS.include,
+
+ // searchbox with placeholder
+ /\.search-box/
+ ]
+})
+
+critical.generate({
+ ...OPTIONS,
+ src: 'react.html',
+ dest: '../_includes/2017/critical/sheet.css',
+ include: [
+ ...OPTIONS.include,
+
+ // sections (and h3 section list), just to be sure
+ /\.h3-section/,
+
+ // eg, -six-column in devhints.io/layout-thrashing
+ /-column/
+ ]
+})
diff --git a/_support/webpack.config.js b/_support/webpack.config.js
new file mode 100644
index 000000000..c11d8376f
--- /dev/null
+++ b/_support/webpack.config.js
@@ -0,0 +1,73 @@
+const join = require('path').resolve
+const webpack = require('webpack')
+
+module.exports = {
+ context: join(__dirname, '..'),
+ entry: {
+ app: './_js/app.js',
+ vendor: [
+ // Large 3rd-party libs
+ 'prismjs',
+
+ // Prism plugins
+ 'prismjs/plugins/line-highlight/prism-line-highlight.min.js',
+ 'prismjs/components/prism-jsx.min.js',
+ 'prismjs/components/prism-bash.min.js',
+ 'prismjs/components/prism-scss.min.js',
+ 'prismjs/components/prism-css.min.js',
+ 'prismjs/components/prism-elixir.min.js',
+ 'prismjs/components/prism-ruby.min.js',
+
+ // CSS
+ 'prismjs/plugins/line-highlight/prism-line-highlight.css',
+ 'hint.css/hint.min.css'
+ ]
+ },
+ output: {
+ path: join(__dirname, '..', 'assets', 'packed'),
+ filename: '[name].js',
+ devtoolModuleFilenameTemplate: 'webpack:///[absolute-resource-path]'
+ },
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ exclude: /node_modules/,
+ use: [
+ { loader: 'babel-loader' }
+ ]
+ },
+ {
+ test: /\.css$/,
+ use: [
+ { loader: 'style-loader' },
+ { loader: 'css-loader' }
+ ]
+ }
+ ]
+ },
+ resolve: {
+ alias: {
+ // Never bundle jQuery
+ 'jquery': join(__dirname, '..', '_js/helpers/noop.js')
+ }
+ },
+ stats: 'minimal',
+ plugins: [
+ // Optimize module ID's for vendor chunks
+ new webpack.HashedModuleIdsPlugin({
+ hashFunction: 'sha256',
+ hashDigest: 'base64',
+ hashDigestLength: 20
+ }),
+
+ // Optimize vendor
+ new webpack.optimize.CommonsChunkPlugin('vendor'),
+
+ // Don't include debug symbols ever
+ new webpack.EnvironmentPlugin({
+ NODE_ENV: 'production'
+ })
+ ],
+ devtool: 'source-map'
+}
diff --git a/_support/webpack.critical.js b/_support/webpack.critical.js
new file mode 100644
index 000000000..e32faf61b
--- /dev/null
+++ b/_support/webpack.critical.js
@@ -0,0 +1,28 @@
+const join = require('path').resolve
+const webpack = require('webpack')
+
+module.exports = {
+ context: join(__dirname, '..'),
+ entry: './_js/critical.js',
+ output: {
+ path: join(__dirname, '..', '_includes', '2017', 'critical'),
+ filename: 'critical.js'
+ },
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ exclude: /node_modules/,
+ use: [
+ { loader: 'babel-loader' }
+ ]
+ }
+ ]
+ },
+ stats: 'minimal',
+ plugins: [
+ new webpack.EnvironmentPlugin({
+ NODE_ENV: 'production'
+ })
+ ]
+}
diff --git a/assets/packed/app.css b/assets/packed/app.css
deleted file mode 100644
index 815dbef27..000000000
--- a/assets/packed/app.css
+++ /dev/null
@@ -1,3 +0,0 @@
-pre[data-line]{position:relative;padding:1em 0 1em 3em}.line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(90deg,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}.line-highlight:before,.line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f5f2f0;font:700 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}.line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}.line-numbers .line-highlight:after,.line-numbers .line-highlight:before{content:none}/*! Hint.css - v2.6.0 - 2019-04-27
-* http://kushagragour.in/lab/hint/
-* Copyright (c) 2019 Kushagra Gour */[class*=hint--]{position:relative;display:inline-block}[class*=hint--]:after,[class*=hint--]:before{position:absolute;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);transform:translateZ(0);visibility:hidden;opacity:0;z-index:1000000;pointer-events:none;-webkit-transition:.3s ease;-moz-transition:.3s ease;transition:.3s ease;-webkit-transition-delay:0s;-moz-transition-delay:0s;transition-delay:0s}[class*=hint--]:hover:after,[class*=hint--]:hover:before{visibility:visible;opacity:1;-webkit-transition-delay:.1s;-moz-transition-delay:.1s;transition-delay:.1s}[class*=hint--]:before{content:"";position:absolute;background:0 0;border:6px solid transparent;z-index:1000001}[class*=hint--]:after{background:#383838;color:#fff;padding:8px 10px;font-size:12px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;line-height:12px;white-space:nowrap;text-shadow:0 -1px 0 #000;box-shadow:4px 4px 8px rgba(0,0,0,.3)}[class*=hint--][aria-label]:after{content:attr(aria-label)}[class*=hint--][data-hint]:after{content:attr(data-hint)}[aria-label=""]:after,[aria-label=""]:before,[data-hint=""]:after,[data-hint=""]:before{display:none!important}.hint--top-left:before,.hint--top-right:before,.hint--top:before{border-top-color:#383838}.hint--bottom-left:before,.hint--bottom-right:before,.hint--bottom:before{border-bottom-color:#383838}.hint--top:after,.hint--top:before{bottom:100%;left:50%}.hint--top:before{margin-bottom:-11px;left:calc(50% - 6px)}.hint--top:after{-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);transform:translateX(-50%)}.hint--top:hover:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--top:hover:after{-webkit-transform:translateX(-50%) translateY(-8px);-moz-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}.hint--bottom:after,.hint--bottom:before{top:100%;left:50%}.hint--bottom:before{margin-top:-11px;left:calc(50% - 6px)}.hint--bottom:after{-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);transform:translateX(-50%)}.hint--bottom:hover:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--bottom:hover:after{-webkit-transform:translateX(-50%) translateY(8px);-moz-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}.hint--right:before{border-right-color:#383838;margin-left:-11px;margin-bottom:-6px}.hint--right:after{margin-bottom:-14px}.hint--right:after,.hint--right:before{left:100%;bottom:50%}.hint--right:hover:after,.hint--right:hover:before{-webkit-transform:translateX(8px);-moz-transform:translateX(8px);transform:translateX(8px)}.hint--left:before{border-left-color:#383838;margin-right:-11px;margin-bottom:-6px}.hint--left:after{margin-bottom:-14px}.hint--left:after,.hint--left:before{right:100%;bottom:50%}.hint--left:hover:after,.hint--left:hover:before{-webkit-transform:translateX(-8px);-moz-transform:translateX(-8px);transform:translateX(-8px)}.hint--top-left:after,.hint--top-left:before{bottom:100%;left:50%}.hint--top-left:before{margin-bottom:-11px;left:calc(50% - 6px)}.hint--top-left:after{-webkit-transform:translateX(-100%);-moz-transform:translateX(-100%);transform:translateX(-100%);margin-left:12px}.hint--top-left:hover:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--top-left:hover:after{-webkit-transform:translateX(-100%) translateY(-8px);-moz-transform:translateX(-100%) translateY(-8px);transform:translateX(-100%) translateY(-8px)}.hint--top-right:after,.hint--top-right:before{bottom:100%;left:50%}.hint--top-right:before{margin-bottom:-11px;left:calc(50% - 6px)}.hint--top-right:after{-webkit-transform:translateX(0);-moz-transform:translateX(0);transform:translateX(0);margin-left:-12px}.hint--top-right:hover:after,.hint--top-right:hover:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--bottom-left:after,.hint--bottom-left:before{top:100%;left:50%}.hint--bottom-left:before{margin-top:-11px;left:calc(50% - 6px)}.hint--bottom-left:after{-webkit-transform:translateX(-100%);-moz-transform:translateX(-100%);transform:translateX(-100%);margin-left:12px}.hint--bottom-left:hover:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--bottom-left:hover:after{-webkit-transform:translateX(-100%) translateY(8px);-moz-transform:translateX(-100%) translateY(8px);transform:translateX(-100%) translateY(8px)}.hint--bottom-right:after,.hint--bottom-right:before{top:100%;left:50%}.hint--bottom-right:before{margin-top:-11px;left:calc(50% - 6px)}.hint--bottom-right:after{-webkit-transform:translateX(0);-moz-transform:translateX(0);transform:translateX(0);margin-left:-12px}.hint--bottom-right:hover:after,.hint--bottom-right:hover:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--large:after,.hint--medium:after,.hint--small:after{white-space:normal;line-height:1.4em;word-wrap:break-word}.hint--small:after{width:80px}.hint--medium:after{width:150px}.hint--large:after{width:300px}.hint--error:after{background-color:#b34e4d;text-shadow:0 -1px 0 #592726}.hint--error.hint--top-left:before,.hint--error.hint--top-right:before,.hint--error.hint--top:before{border-top-color:#b34e4d}.hint--error.hint--bottom-left:before,.hint--error.hint--bottom-right:before,.hint--error.hint--bottom:before{border-bottom-color:#b34e4d}.hint--error.hint--left:before{border-left-color:#b34e4d}.hint--error.hint--right:before{border-right-color:#b34e4d}.hint--warning:after{background-color:#c09854;text-shadow:0 -1px 0 #6c5328}.hint--warning.hint--top-left:before,.hint--warning.hint--top-right:before,.hint--warning.hint--top:before{border-top-color:#c09854}.hint--warning.hint--bottom-left:before,.hint--warning.hint--bottom-right:before,.hint--warning.hint--bottom:before{border-bottom-color:#c09854}.hint--warning.hint--left:before{border-left-color:#c09854}.hint--warning.hint--right:before{border-right-color:#c09854}.hint--info:after{background-color:#3986ac;text-shadow:0 -1px 0 #1a3c4d}.hint--info.hint--top-left:before,.hint--info.hint--top-right:before,.hint--info.hint--top:before{border-top-color:#3986ac}.hint--info.hint--bottom-left:before,.hint--info.hint--bottom-right:before,.hint--info.hint--bottom:before{border-bottom-color:#3986ac}.hint--info.hint--left:before{border-left-color:#3986ac}.hint--info.hint--right:before{border-right-color:#3986ac}.hint--success:after{background-color:#458746;text-shadow:0 -1px 0 #1a321a}.hint--success.hint--top-left:before,.hint--success.hint--top-right:before,.hint--success.hint--top:before{border-top-color:#458746}.hint--success.hint--bottom-left:before,.hint--success.hint--bottom-right:before,.hint--success.hint--bottom:before{border-bottom-color:#458746}.hint--success.hint--left:before{border-left-color:#458746}.hint--success.hint--right:before{border-right-color:#458746}.hint--always:after,.hint--always:before{opacity:1;visibility:visible}.hint--always.hint--top:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--always.hint--top:after{-webkit-transform:translateX(-50%) translateY(-8px);-moz-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}.hint--always.hint--top-left:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--always.hint--top-left:after{-webkit-transform:translateX(-100%) translateY(-8px);-moz-transform:translateX(-100%) translateY(-8px);transform:translateX(-100%) translateY(-8px)}.hint--always.hint--top-right:after,.hint--always.hint--top-right:before{-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}.hint--always.hint--bottom:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--always.hint--bottom:after{-webkit-transform:translateX(-50%) translateY(8px);-moz-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}.hint--always.hint--bottom-left:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--always.hint--bottom-left:after{-webkit-transform:translateX(-100%) translateY(8px);-moz-transform:translateX(-100%) translateY(8px);transform:translateX(-100%) translateY(8px)}.hint--always.hint--bottom-right:after,.hint--always.hint--bottom-right:before{-webkit-transform:translateY(8px);-moz-transform:translateY(8px);transform:translateY(8px)}.hint--always.hint--left:after,.hint--always.hint--left:before{-webkit-transform:translateX(-8px);-moz-transform:translateX(-8px);transform:translateX(-8px)}.hint--always.hint--right:after,.hint--always.hint--right:before{-webkit-transform:translateX(8px);-moz-transform:translateX(8px);transform:translateX(8px)}.hint--rounded:after{border-radius:4px}.hint--no-animate:after,.hint--no-animate:before{-webkit-transition-duration:0s;-moz-transition-duration:0s;transition-duration:0s}.hint--bounce:after,.hint--bounce:before{-webkit-transition:opacity .3s ease,visibility .3s ease,-webkit-transform .3s cubic-bezier(.71,1.7,.77,1.24);-moz-transition:opacity .3s ease,visibility .3s ease,-moz-transform .3s cubic-bezier(.71,1.7,.77,1.24);transition:opacity .3s ease,visibility .3s ease,transform .3s cubic-bezier(.71,1.7,.77,1.24)}.hint--no-shadow:after,.hint--no-shadow:before{text-shadow:none;box-shadow:none}
\ No newline at end of file
diff --git a/assets/packed/app.js b/assets/packed/app.js
index 4958bc441..738692192 100644
--- a/assets/packed/app.js
+++ b/assets/packed/app.js
@@ -1,127 +1,42 @@
-parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;ct.length)return;if(!(A instanceof r)){var S=1;if(y&&x!=n.tail.prev){h.lastIndex=w;var $=h.exec(t);if(!$)break;var _=$.index+(v&&$[1]?$[1].length:0),j=$.index+$[0].length,E=w;for(E+=x.value.length;_>=E;)x=x.next,E+=x.value.length;if(E-=x.value.length,w=E,x.value instanceof r)continue;for(var C=x;C!==n.tail&&(E1&&e(t,n,s,x.prev,w,!0,d+","+f),c)break}else if(c)break}}}}}(e,u,t,u.head,0),function(e){var t=[],n=e.head.next;for(;n!==e.tail;)t.push(n.value),n=n.next;return t}(u)},hooks:{all:{},add:function(e,t){var n=a.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=a.hooks.all[e];if(n&&n.length)for(var r,s=0;r=n[s++];)r(t)}},Token:r};function r(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!r}function s(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function i(e,t,n){var a=t.next,r={value:n,prev:t,next:a};return t.next=r,a.prev=r,e.length++,r}function l(e,t,n){for(var a=t.next,r=0;r"+s.content+""+s.tag+">"},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",function(t){var n=JSON.parse(t.data),r=n.language,s=n.code,i=n.immediateClose;e.postMessage(a.highlight(s,a.languages[r],r)),i&&e.close()},!1),a):a;var o=a.util.currentScript();function u(){a.manual||a.highlightAll()}if(o&&(a.filename=o.src,o.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var c=document.readyState;"loading"===c||"interactive"===c&&o&&o.defer?document.addEventListener("DOMContentLoaded",u):window.requestAnimationFrame?window.requestAnimationFrame(u):window.setTimeout(u,16)}return a}(t);"undefined"!=typeof module&&module.exports&&(module.exports=n),void 0!==e&&(e.Prism=n),n.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:(?!)*\]\s*)?>/i,greedy:!0},cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/?[\da-z]{1,8};/i},n.languages.markup.tag.inside["attr-value"].inside.entity=n.languages.markup.entity,n.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),Object.defineProperty(n.languages.markup.tag,"addInlined",{value:function(e,t){var a={};a["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:n.languages[t]},a.cdata=/^$/i;var r={"included-cdata":{pattern://i,inside:a}};r["language-"+t]={pattern:/[\s\S]+/,inside:n.languages[t]};var s={};s[e]={pattern:RegExp(/(<__[\s\S]*?>)(?:\s*|[\s\S])*?(?=<\/__>)/.source.replace(/__/g,function(){return e}),"i"),lookbehind:!0,greedy:!0,inside:r},n.languages.insertBefore("markup","cdata",s)}}),n.languages.xml=n.languages.extend("markup",{}),n.languages.html=n.languages.markup,n.languages.mathml=n.languages.markup,n.languages.svg=n.languages.markup,function(e){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,lookbehind:!0,alias:"selector"}}},url:{pattern:RegExp("url\\((?:"+t.source+"|[^\n\r()]*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+t.source+")*?(?=\\s*\\{)"),string:{pattern:t,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),e.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:n.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:e.languages.css}},alias:"language-css"}},n.tag))}(n),n.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},n.languages.javascript=n.languages.extend("clike",{"class-name":[n.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/--|\+\+|\*\*=?|=>|&&|\|\||[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?[.?]?|[~:]/}),n.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,n.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*[\s\S]*?\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:n.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:n.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:n.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:n.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),n.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:n.languages.javascript}},string:/[\s\S]+/}}}),n.languages.markup&&n.languages.markup.tag.addInlined("script","javascript"),n.languages.js=n.languages.javascript,"undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector&&(self.Prism.fileHighlight=function(e){e=e||document;var t={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"};Array.prototype.slice.call(e.querySelectorAll("pre[data-src]")).forEach(function(e){if(!e.hasAttribute("data-src-loaded")){for(var a,r=e.getAttribute("data-src"),s=e,i=/\blang(?:uage)?-([\w-]+)\b/i;s&&!i.test(s.className);)s=s.parentNode;if(s&&(a=(e.className.match(i)||[,""])[1]),!a){var l=(r.match(/\.(\w+)$/)||[,""])[1];a=t[l]||l}var o=document.createElement("code");o.className="language-"+a,e.textContent="",o.textContent="Loading…",e.appendChild(o);var u=new XMLHttpRequest;u.open("GET",r,!0),u.onreadystatechange=function(){4==u.readyState&&(u.status<400&&u.responseText?(o.textContent=u.responseText,n.highlightElement(o),e.setAttribute("data-src-loaded","")):u.status>=400?o.textContent="✖ Error "+u.status+" while fetching file: "+u.statusText:o.textContent="✖ Error: File does not exist or is empty")},u.send(null)}})},document.addEventListener("DOMContentLoaded",function(){self.Prism.fileHighlight()}));
-},{}],"FNB3":[function(require,module,exports) {
-!function(){if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var e,t=function(){if(void 0===e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding=0,t.style.border=0,t.innerHTML="
",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e},n=0;Prism.hooks.add("before-sanity-check",function(e){var t=e.element.parentNode,n=t&&t.getAttribute("data-line");if(t&&n&&/pre/i.test(t.nodeName)){var r=0;i(".line-highlight",t).forEach(function(e){r+=e.textContent.length,e.parentNode.removeChild(e)}),r&&/^( \n)+$/.test(e.code.slice(-r))&&(e.code=e.code.slice(0,-r))}}),Prism.hooks.add("complete",function e(t){var i=t.element.parentNode,o=i&&i.getAttribute("data-line");if(i&&o&&/pre/i.test(i.nodeName)){clearTimeout(n);var s=Prism.plugins.lineNumbers,u=t.plugins&&t.plugins.lineNumbers;r(i,"line-numbers")&&s&&!u?Prism.hooks.add("line-numbers",e):(a(i,o)(),n=setTimeout(l,1))}}),window.addEventListener("hashchange",l),window.addEventListener("resize",function(){var e=[];i("pre[data-line]").forEach(function(t){e.push(a(t))}),e.forEach(o)})}function i(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function r(e,t){return t=" "+t+" ",-1<(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)}function o(e){e()}function a(e,n,i){var a=(n="string"==typeof n?n:e.getAttribute("data-line")).replace(/\s+/g,"").split(","),l=+e.getAttribute("data-line-offset")||0,s=(t()?parseInt:parseFloat)(getComputedStyle(e).lineHeight),u=r(e,"line-numbers"),d=u?e:e.querySelector("code")||e,c=[];return a.forEach(function(t){var n=t.split("-"),r=+n[0],o=+n[1]||r,a=e.querySelector('.line-highlight[data-range="'+t+'"]')||document.createElement("div");if(c.push(function(){a.setAttribute("aria-hidden","true"),a.setAttribute("data-range",t),a.className=(i||"")+" line-highlight"}),u&&Prism.plugins.lineNumbers){var f=Prism.plugins.lineNumbers.getLine(e,r),h=Prism.plugins.lineNumbers.getLine(e,o);if(f){var p=f.offsetTop+"px";c.push(function(){a.style.top=p})}if(h){var m=h.offsetTop-f.offsetTop+h.offsetHeight+"px";c.push(function(){a.style.height=m})}}else c.push(function(){a.setAttribute("data-start",r),r=]+|\{(?:\{(?:\{[^}]*\}|[^{}])*\}|[^{}])+\}))?|\{\s*\.{3}\s*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\s*\}))*\s*\/?)?>/i,t.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/i,t.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">]+)/i,t.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,t.languages.insertBefore("inside","attr-name",{spread:{pattern:/\{\s*\.{3}\s*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\s*\}/,inside:{punctuation:/\.{3}|[{}.]/,"attr-value":/\w+/}}},t.languages.jsx.tag),t.languages.insertBefore("inside","attr-value",{script:{pattern:/=(?:\{(?:\{(?:\{[^}]*\}|[^}])*\}|[^}])+\})/i,inside:{"script-punctuation":{pattern:/^=(?={)/,alias:"punctuation"},rest:t.languages.jsx},alias:"language-javascript"}},t.languages.jsx.tag);var e=function(t){return t?"string"==typeof t?t:"string"==typeof t.content?t.content:t.content.map(e).join(""):""},a=function(n){for(var s=[],g=0;g"===i.content[i.content.length-1].content||s.push({tagName:e(i.content[0].content[1]),openedBraces:0}):0>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)\w+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b\w+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+?)\s*(?:\r?\n|\r)[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:n},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s*(?:\r?\n|\r)[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\](?:\\\\)*)(["'])(?:\\[\s\S]|\$\([^)]+\)|`[^`]+`|(?!\2)[^\\])*\2/,lookbehind:!0,greedy:!0,inside:n}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:n.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|aptitude|apt-cache|apt-get|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:if|then|else|elif|fi|for|while|in|case|esac|function|select|do|done|until)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|break|cd|continue|eval|exec|exit|export|getopts|hash|pwd|readonly|return|shift|test|times|trap|umask|unset|alias|bind|builtin|caller|command|declare|echo|enable|help|let|local|logout|mapfile|printf|read|readarray|source|type|typeset|ulimit|unalias|set|shopt)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:true|false)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|==?|!=?|=~|<<[<-]?|[&\d]?>>|\d?[<>]&?|&[>&]?|\|[&|]?|<=?|>=?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}};for(var a=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],r=n.variable[1].inside,s=0;s=?|and|or|not)(?=\s)/,lookbehind:!0}}),Prism.languages.scss.atrule.inside.rest=Prism.languages.scss;
-},{}],"eQGU":[function(require,module,exports) {
-!function(s){var e=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,lookbehind:!0,alias:"selector"}}},url:{pattern:RegExp("url\\((?:"+e.source+"|[^\n\r()]*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+e.source+")*?(?=\\s*\\{)"),string:{pattern:e,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),s.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:t.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:s.languages.css}},alias:"language-css"}},t.tag))}(Prism);
-},{}],"i6Tx":[function(require,module,exports) {
-Prism.languages.elixir={comment:/#.*/m,regex:{pattern:/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,greedy:!0},string:[{pattern:/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,greedy:!0,inside:{}},{pattern:/("""|''')[\s\S]*?\1/,greedy:!0,inside:{}},{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{}}],atom:{pattern:/(^|[^:]):\w+/,lookbehind:!0,alias:"symbol"},"attr-name":/\w+\??:(?!:)/,capture:{pattern:/(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/,lookbehind:!0,alias:"function"},argument:{pattern:/(^|[^&])&\d+/,lookbehind:!0,alias:"variable"},attribute:{pattern:/@\w+/,alias:"variable"},number:/\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i,keyword:/\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct)?|do|else|end|fn|for|if|import|not|or|require|rescue|try|unless|use|when)\b/,boolean:/\b(?:true|false|nil)\b/,operator:[/\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/,{pattern:/([^<])<(?!<)/,lookbehind:!0},{pattern:/([^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,%\[\]{}()]/},Prism.languages.elixir.string.forEach(function(e){e.inside={interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:Prism.languages.elixir}}}});
-},{}],"aTnL":[function(require,module,exports) {
-!function(e){e.languages.ruby=e.languages.extend("clike",{comment:[/#.*/,{pattern:/^=begin\s[\s\S]*?^=end/m,greedy:!0}],"class-name":{pattern:/(\b(?:class)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|protected|private|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/});var n={pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"tag"},rest:e.languages.ruby}};delete e.languages.ruby.function,e.languages.insertBefore("ruby","keyword",{regex:[{pattern:/%r([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[gim]{0,3}/,greedy:!0,inside:{interpolation:n}},{pattern:/%r\((?:[^()\\]|\\[\s\S])*\)[gim]{0,3}/,greedy:!0,inside:{interpolation:n}},{pattern:/%r\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}[gim]{0,3}/,greedy:!0,inside:{interpolation:n}},{pattern:/%r\[(?:[^\[\]\\]|\\[\s\S])*\][gim]{0,3}/,greedy:!0,inside:{interpolation:n}},{pattern:/%r<(?:[^<>\\]|\\[\s\S])*>[gim]{0,3}/,greedy:!0,inside:{interpolation:n}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[gim]{0,3}(?=\s*(?:$|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:{pattern:/(^|[^:]):[a-zA-Z_]\w*(?:[?!]|\b)/,lookbehind:!0},"method-definition":{pattern:/(\bdef\s+)[\w.]+/,lookbehind:!0,inside:{function:/\w+$/,rest:e.languages.ruby}}}),e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|Fixnum|Float|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/,constant:/\b[A-Z]\w*(?:[?!]|\b)/}),e.languages.ruby.string=[{pattern:/%[qQiIwWxs]?([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0,inside:{interpolation:n}},{pattern:/%[qQiIwWxs]?\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0,inside:{interpolation:n}},{pattern:/%[qQiIwWxs]?\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}/,greedy:!0,inside:{interpolation:n}},{pattern:/%[qQiIwWxs]?\[(?:[^\[\]\\]|\\[\s\S])*\]/,greedy:!0,inside:{interpolation:n}},{pattern:/%[qQiIwWxs]?<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0,inside:{interpolation:n}},{pattern:/("|')(?:#\{[^}]+\}|\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{interpolation:n}}],e.languages.rb=e.languages.ruby}(Prism);
-},{}],"Pzu0":[function(require,module,exports) {
-window.Prism=require("prismjs");
-},{"prismjs":"hKAx"}],"a8gM":[function(require,module,exports) {
-function e(e){if(t())return e();document.addEventListener?document.addEventListener("DOMContentLoaded",e):document.attachEvent("onreadystatechange",function(){t()&&e()})}function t(){return"complete"===document.readyState||"interactive"===document.readyState}module.exports=e;
-},{}],"yMxf":[function(require,module,exports) {
-var define;
-var t;!function(e,o){"function"==typeof t&&t.amd?t(o):"object"==typeof exports?module.exports=o():window.jQuery?window.jQuery.onmount=o():e.onmount=o()}(this,function(t){var e,o,n,i,r=0,s=0;function c(t,e,n,i){if("object"==typeof n&&(i=n,n=void 0),0===arguments.length||"function"==typeof(f=t)&&f.fn&&f.noConflict||"object"==typeof(s=t)&&s.target)c.poll();else if(1===arguments.length)c.poll(t);else{var r=new u(t,e,n,i);o.push(r),r.register()}var s,f;return this}function u(t,e,o,n){this.id="b"+r++,this.init=e,this.exit=o,this.selector=c.selectify(t),this.loaded=[],this.key="__onmount:"+r,this.detectMutate=n&&n.detectMutate}function f(t,e){var o=t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector;if(c.$)return c.$(t).is(e);if(o)return o.call(t,e);if(t.parentNode){for(var n=t.parentNode.querySelectorAll(e),i=n.length;i--;0)if(n[i]===t)return!0;return!1}}function l(t,e){var o,n=t.length;if(n===+n)for(o=0;o-1:t.indexOf(e)>-1}(o,t))return this.doExit(t,e)}else if(!function(t){for(;t;){if(t===document.documentElement)return!0;t=t.parentElement}}(t))return this.doExit(t,e)},u.prototype.doExit=function(t,e){void 0===e&&(e=this.loaded.indexOf(t)),this.loaded[e]=void 0,this.exit&&!1!==this.exit.call(t,t[this.key])&&(c.debug&&i("exit",this.selector,t),delete t[this.key])};var d={enter:"background-color:#dfd;font-weight:bold;color:#141",exit:"background-color:#fdd;font-weight:bold;color:#411"};return i=~navigator.userAgent.indexOf("Mozilla")?function(t,e,o){console.log("%c %s ",d[t],e,o)}:function(t,e,o){console.log("(onmount)",t,e)},c.reset(),c});
-},{}],"ijeW":[function(require,module,exports) {
-"use strict";var e=t(require("dom101/ready")),u=t(require("onmount"));function t(e){return e&&e.__esModule?e:{default:e}}(0,e.default)(function(){setTimeout(function(){(0,u.default)()})});
-},{"dom101/ready":"a8gM","onmount":"yMxf"}],"koK4":[function(require,module,exports) {
-function i(i,e){i.firstChild?i.insertBefore(e,i.firstChild):i.appendChild(e)}module.exports=i;
-},{}],"knoa":[function(require,module,exports) {
-"use strict";var t=r(require("onmount")),e=r(require("dom101/prepend"));function r(t){return t&&t.__esModule?t:{default:t}}function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=a(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,u=!0,l=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return u=t.done,t},e:function(t){l=!0,i=t},f:function(){try{u||null==r.return||r.return()}finally{if(l)throw i}}}}function a(t,e){if(t){if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(t,e):void 0}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r1&&o+t>this.cols?0:o;var e=i.size.outerWidth&&i.size.outerHeight;return this.horizontalColIndex=e?o+t:this.horizontalColIndex,{col:o,y:this._getColGroupY(o,t)}},e._manageStamp=function(t){var o=i(t),e=this._getElementOffset(t),h=this._getOption("originLeft")?e.left:e.right,n=h+o.outerWidth,s=Math.floor(h/this.columnWidth);s=Math.max(0,s);var r=Math.floor(n/this.columnWidth);r-=n%this.columnWidth?0:1,r=Math.min(this.cols-1,r);for(var a=(this._getOption("originTop")?e.top:e.bottom)+o.outerHeight,u=s;u<=r;u++)this.colYs[u]=Math.max(a,this.colYs[u])},e._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var t={height:this.maxY};return this._getOption("fitWidth")&&(t.width=this._getContainerFitWidth()),t},e._getContainerFitWidth=function(){for(var t=0,i=this.cols;--i&&0===this.colYs[i];)t++;return(this.cols-t)*this.columnWidth-this.gutter},e.needsResizeLayout=function(){var t=this.containerWidth;return this.getContainerWidth(),t!=this.containerWidth},o});
-},{"outlayer":"k1dT","get-size":"SpQD"}],"U5Zw":[function(require,module,exports) {
-var define;
-var t;!function(o,e){"function"==typeof t&&t.amd?t(["../layout-mode","masonry-layout/masonry"],e):"object"==typeof module&&module.exports?module.exports=e(require("../layout-mode"),require("masonry-layout")):e(o.Isotope.LayoutMode,o.Masonry)}(window,function(t,o){"use strict";var e=t.create("masonry"),i=e.prototype,s={_getElementOffset:!0,layout:!0,_getMeasurement:!0};for(var r in o.prototype)s[r]||(i[r]=o.prototype[r]);var n=i.measureColumns;i.measureColumns=function(){this.items=this.isotope.filteredItems,n.call(this)};var u=i._getOption;return i._getOption=function(t){return"fitWidth"==t?void 0!==this.options.isFitWidth?this.options.isFitWidth:this.options.fitWidth:u.apply(this.isotope,arguments)},e});
-},{"../layout-mode":"Nkzt","masonry-layout":"l7pb"}],"SiBL":[function(require,module,exports) {
-var define;
-var t;!function(e,i){"function"==typeof t&&t.amd?t(["../layout-mode"],i):"object"==typeof exports?module.exports=i(require("../layout-mode")):i(e.Isotope.LayoutMode)}(window,function(t){"use strict";var e=t.create("fitRows"),i=e.prototype;return i._resetLayout=function(){this.x=0,this.y=0,this.maxY=0,this._getMeasurement("gutter","outerWidth")},i._getItemLayoutPosition=function(t){t.getSize();var e=t.size.outerWidth+this.gutter,i=this.isotope.size.innerWidth+this.gutter;0!==this.x&&e+this.x>i&&(this.x=0,this.y=this.maxY);var o={x:this.x,y:this.y};return this.maxY=Math.max(this.maxY,this.y+t.size.outerHeight),this.x+=e,o},i._getContainerSize=function(){return{height:this.maxY}},e});
-},{"../layout-mode":"Nkzt"}],"rlDn":[function(require,module,exports) {
-var define;
-var t;!function(e,o){"function"==typeof t&&t.amd?t(["../layout-mode"],o):"object"==typeof module&&module.exports?module.exports=o(require("../layout-mode")):o(e.Isotope.LayoutMode)}(window,function(t){"use strict";var e=t.create("vertical",{horizontalAlignment:0}),o=e.prototype;return o._resetLayout=function(){this.y=0},o._getItemLayoutPosition=function(t){t.getSize();var e=(this.isotope.size.innerWidth-t.size.outerWidth)*this.options.horizontalAlignment,o=this.y;return this.y+=t.size.outerHeight,{x:e,y:o}},o._getContainerSize=function(){return{height:this.y}},e});
-},{"../layout-mode":"Nkzt"}],"bsRB":[function(require,module,exports) {
-var define;
-var t;!function(e,i){"function"==typeof t&&t.amd?t(["outlayer/outlayer","get-size/get-size","desandro-matches-selector/matches-selector","fizzy-ui-utils/utils","./item","./layout-mode","./layout-modes/masonry","./layout-modes/fit-rows","./layout-modes/vertical"],function(t,r,o,s,n,a){return i(e,t,r,o,s,n,a)}):"object"==typeof module&&module.exports?module.exports=i(e,require("outlayer"),require("get-size"),require("desandro-matches-selector"),require("fizzy-ui-utils"),require("./item"),require("./layout-mode"),require("./layout-modes/masonry"),require("./layout-modes/fit-rows"),require("./layout-modes/vertical")):e.Isotope=i(e,e.Outlayer,e.getSize,e.matchesSelector,e.fizzyUIUtils,e.Isotope.Item,e.Isotope.LayoutMode)}(window,function(t,e,i,r,o,s,n){"use strict";var a=t.jQuery,u=String.prototype.trim?function(t){return t.trim()}:function(t){return t.replace(/^\s+|\s+$/g,"")},h=e.create("isotope",{layoutMode:"masonry",isJQueryFiltering:!0,sortAscending:!0});h.Item=s,h.LayoutMode=n;var l=h.prototype;l._create=function(){for(var t in this.itemGUID=0,this._sorters={},this._getSorters(),e.prototype._create.call(this),this.modes={},this.filteredItems=this.items,this.sortHistory=["original-order"],n.modes)this._initLayoutMode(t)},l.reloadItems=function(){this.itemGUID=0,e.prototype.reloadItems.call(this)},l._itemize=function(){for(var t=e.prototype._itemize.apply(this,arguments),i=0;ia||na?1:-1)*h}}return 0}}(this.sortHistory,this.options.sortAscending);this.filteredItems.sort(e)}},l._getIsSameSortBy=function(t){for(var e=0;et.length)&&(e=t.length);for(var r=0,n=new Array(e);r1&&i+t>this.cols?0:i;var n=e.size.outerWidth&&e.size.outerHeight;return this.horizontalColIndex=n?i+t:this.horizontalColIndex,{col:i,y:this._getColGroupY(i,t)}},n._manageStamp=function(t){var i=e(t),n=this._getElementOffset(t),o=this._getOption("originLeft"),r=o?n.left:n.right,s=r+i.outerWidth,a=Math.floor(r/this.columnWidth);a=Math.max(0,a);var u=Math.floor(s/this.columnWidth);u-=s%this.columnWidth?0:1,u=Math.min(this.cols-1,u);for(var h=this._getOption("originTop"),c=(h?n.top:n.bottom)+i.outerHeight,f=a;f<=u;f++)this.colYs[f]=Math.max(c,this.colYs[f])},n._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var t={height:this.maxY};return this._getOption("fitWidth")&&(t.width=this._getContainerFitWidth()),t},n._getContainerFitWidth=function(){for(var t=0,e=this.cols;--e&&0===this.colYs[e];)t++;return(this.cols-t)*this.columnWidth-this.gutter},n.needsResizeLayout=function(){var t=this.containerWidth;return this.getContainerWidth(),t!=this.containerWidth},i}),/*!
+ * Masonry layout mode
+ * sub-classes Masonry
+ * http://masonry.desandro.com
+ */
+function(t,i){n=[g,y],l=i,_="function"==typeof l?l.apply(e,n):l}(window,function(t,e){"use strict";var i=t.create("masonry"),n=i.prototype,o={_getElementOffset:!0,layout:!0,_getMeasurement:!0};for(var r in e.prototype)o[r]||(n[r]=e.prototype[r]);var s=n.measureColumns;n.measureColumns=function(){this.items=this.isotope.filteredItems,s.call(this)};var a=n._getOption;return n._getOption=function(t){return"fitWidth"==t?void 0!==this.options.isFitWidth?this.options.isFitWidth:this.options.fitWidth:a.apply(this.isotope,arguments)},i}),function(t,i){n=[g],l=i,b="function"==typeof l?l.apply(e,n):l}(window,function(t){"use strict";var e=t.create("fitRows"),i=e.prototype;return i._resetLayout=function(){this.x=0,this.y=0,this.maxY=0,this._getMeasurement("gutter","outerWidth")},i._getItemLayoutPosition=function(t){t.getSize();var e=t.size.outerWidth+this.gutter,i=this.isotope.size.innerWidth+this.gutter;0!==this.x&&e+this.x>i&&(this.x=0,this.y=this.maxY);var n={x:this.x,y:this.y};return this.maxY=Math.max(this.maxY,this.y+t.size.outerHeight),this.x+=e,n},i._getContainerSize=function(){return{height:this.maxY}},e}),function(t,i){n=[g],l=i,E="function"==typeof l?l.apply(e,n):l}(window,function(t){"use strict";var e=t.create("vertical",{horizontalAlignment:0}),i=e.prototype;return i._resetLayout=function(){this.y=0},i._getItemLayoutPosition=function(t){t.getSize();var e=(this.isotope.size.innerWidth-t.size.outerWidth)*this.options.horizontalAlignment,i=this.y;return this.y+=t.size.outerHeight,{x:e,y:i}},i._getContainerSize=function(){return{height:this.y}},e}),/*!
+ * Isotope v3.0.4
+ *
+ * Licensed GPLv3 for open source use
+ * or Isotope Commercial License for commercial use
+ *
+ * http://isotope.metafizzy.co
+ * Copyright 2017 Metafizzy
+ */
+function(i,r){n=[m,u,h,d,v,g,_,b,E],void 0!==(o=function(t,e,n,o,s,a){return r(i,t,e,n,o,s,a)}.apply(e,n))&&(t.exports=o)}(window,function(t,e,i,n,o,r,s){function a(t,e){return function(i,n){for(var o=0;oa||sa?1:-1)*h}}return 0}}var u=t.jQuery,h=String.prototype.trim?function(t){return t.trim()}:function(t){return t.replace(/^\s+|\s+$/g,"")},c=e.create("isotope",{layoutMode:"masonry",isJQueryFiltering:!0,sortAscending:!0});c.Item=r,c.LayoutMode=s;var f=c.prototype;f._create=function(){this.itemGUID=0,this._sorters={},this._getSorters(),e.prototype._create.call(this),this.modes={},this.filteredItems=this.items,this.sortHistory=["original-order"];for(var t in s.modes)this._initLayoutMode(t)},f.reloadItems=function(){this.itemGUID=0,e.prototype.reloadItems.call(this)},f._itemize=function(){for(var t=e.prototype._itemize.apply(this,arguments),i=0;i-1:t.indexOf(i)>-1}function a(t,e){p[t]||(p[t]=[]),p[t].push(e),d.push(e)}function u(t,i){var n=t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector;if(e.$)return e.$(t).is(i);if(n)return n.call(t,i);if(t.parentNode){for(var o=t.parentNode.querySelectorAll(i),r=o.length;r--;0)if(o[r]===t)return!0;return!1}}function h(t,e){var i,n=t.length;if(n===+n)for(i=0;i {\n * data.lol = true\n * return data\n * })\n */\n\nfunction update(key, fn) {\n if (!window.localStorage) return;\n var data = JSON.parse(window.localStorage[key] || '{}');\n data = fn(data);\n window.localStorage[key] = JSON.stringify(data);\n}\n\n/**\n * Fetches a local storage key.\n *\n * @example\n * const data = fetch('dismissed')\n */\n\nfunction fetch(key) {\n if (!window.localStorage) return;\n return JSON.parse(window.localStorage[key] || '{}');\n}\n\n/***/ }),\n\n/***/ \"2QOxTCxkuzN0PP2kJ2jn\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.setDismissed = setDismissed;\nexports.isDismissed = isDismissed;\n\nvar _store = __webpack_require__(\"/k7tj9kxRFhFtZjlt346\");\n\nvar Store = _interopRequireWildcard(_store);\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }\n\n/**\n * Dismisses an announcement.\n *\n * @example\n * setDismissed('2017-09-02-happy-birthday')\n */\n\nfunction setDismissed(id) {\n Store.update('dismissed', function (data) {\n data[id] = true;\n return data;\n });\n}\n\n/**\n * Checks if an announcement has been dismissed before.\n *\n * @example\n * setDismissed('2017-09-02-happy-birthday')\n * isDismissed('2017-09-02-happy-birthday') => true\n */\n\nfunction isDismissed(id) {\n var data = Store.fetch('dismissed');\n return data && data[id];\n}\n\n/***/ }),\n\n/***/ \"2tov+8o2NrZdw/Lg8JZA\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar map = {\n\t\"./onmount.js\": \"6hLKOGpXaWUwTDQA5TL2\"\n};\nfunction webpackContext(req) {\n\treturn __webpack_require__(webpackContextResolve(req));\n};\nfunction webpackContextResolve(req) {\n\tvar id = map[req];\n\tif(!(id + 1)) // check for number or string\n\t\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n\treturn id;\n};\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"2tov+8o2NrZdw/Lg8JZA\";\n\n/***/ }),\n\n/***/ \"6hLKOGpXaWUwTDQA5TL2\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _ready = __webpack_require__(\"tqbVxj9+xGAhlFrQpyTS\");\n\nvar _ready2 = _interopRequireDefault(_ready);\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Behavior: Wrapping\n */\n\n(0, _ready2.default)(function () {\n setTimeout(function () {\n (0, _onmount2.default)();\n });\n});\n\n/***/ }),\n\n/***/ \"BF4TFfJ+K+wsuHfLZ/S3\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.isPreview = isPreview;\n/**\n * Checks if we're in preview mode (?preview=1).\n */\n\nfunction isPreview() {\n return window.location.search.indexOf('preview=1') !== -1;\n}\n\n/***/ }),\n\n/***/ \"BuWMdGeXUEK0GmkN01pU\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nvar _inject_disqus = __webpack_require__(\"cYqQDyTPtD7lV79ovj4Y\");\n\nvar _inject_disqus2 = _interopRequireDefault(_inject_disqus);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Delay disqus by some time. It's at the bottom of the page, there's no need\n * for it to load fast. This will give more time to load more critical assets.\n */\n\nvar DISQUS_DELAY = 100;\n\n/**\n * Injects Disqus onto the page.\n */\n\n(0, _onmount2.default)('[data-js-disqus]', function () {\n var data = JSON.parse(this.getAttribute('data-js-disqus'));\n var $parent = this.parentNode;\n $parent.setAttribute('hidden', true);\n\n window.disqus_config = function () {\n this.page.url = data.url;\n this.page.identifier = data.identifier;\n };\n\n // Disqus takes a while to load, don't do it so eagerly.\n window.addEventListener('load', function () {\n setTimeout(function () {\n (0, _inject_disqus2.default)(data.host);\n $parent.removeAttribute('hidden');\n }, DISQUS_DELAY);\n });\n});\n\n/***/ }),\n\n/***/ \"C2mk7N9JzKWlcOYJrkfi\":\n/***/ (function(module, exports) {\n\n/**\n * matches : matches(el, selector)\n * Checks if a given element `el` matches `selector`.\n * Compare with [$.fn.is](http://api.jquery.com/is/).\n *\n * var matches = require('dom101/matches');\n *\n * matches(button, ':focus');\n */\n\nfunction matches (el, selector) {\n var _matches = el.matches ||\n el.matchesSelector ||\n el.msMatchesSelector ||\n el.mozMatchesSelector ||\n el.webkitMatchesSelector ||\n el.oMatchesSelector\n\n if (_matches) {\n return _matches.call(el, selector)\n } else if (el.parentNode) {\n // IE8 and below\n var nodes = el.parentNode.querySelectorAll(selector)\n for (var i = nodes.length; i--; 0) {\n if (nodes[i] === el) return true\n }\n return false\n }\n}\n\nmodule.exports = matches\n\n\n/***/ }),\n\n/***/ \"CjZN/azBHJxH2NsOjfdD\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.data = data;\nexports.getData = getData;\nexports.setData = setData;\n/**\n * Stores and retrieves data from an element. Works like jQuery.data().\n */\n\nfunction data(el, key, val) {\n if (typeof val !== 'undefined') {\n return getData(el, key);\n } else {\n return setData(el, key, val);\n }\n}\n\nfunction getData(el, key) {\n var str = el.getAttribute('data-' + key);\n return JSON.parse(str || '{}');\n}\n\nfunction setData(el, key, val) {\n el.setAttribute('data-' + key, JSON.stringify(val));\n}\n\n/***/ }),\n\n/***/ \"D3SYMdNAenu80VOO7/Dv\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nvar _on = __webpack_require__(\"MKJaVdnD9jF7rk6rW6AJ\");\n\nvar _on2 = _interopRequireDefault(_on);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Submitting the search form\n */\n\n(0, _onmount2.default)('[data-js-search-form]', function () {\n (0, _on2.default)(this, 'submit', function (e) {\n e.preventDefault();\n\n var link = document.querySelector('a[data-search-index]:visible');\n var href = link && link.getAttribute('href');\n\n if (href) window.location = href;\n });\n});\n\n/***/ }),\n\n/***/ \"DfTyEU8lscjHXmCMlptO\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.showAll = showAll;\nexports.show = show;\n\nvar _permutate = __webpack_require__(\"GOdGag34TlRuHa2OZoh9\");\n\nvar _querySelectorAll = __webpack_require__(\"EvxNxLK9yKFmn1U14Kvw\");\n\nvar _querySelectorAll2 = _interopRequireDefault(_querySelectorAll);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Show everything.\n *\n * @example\n * Search.showAll()\n */\n\nfunction showAll() {\n (0, _querySelectorAll2.default)('[data-search-index]').forEach(function (el) {\n el.removeAttribute('aria-hidden');\n });\n}\n\n/**\n * Search for a given keyword.\n *\n * @example\n * Search.show('hello')\n */\n\nfunction show(val) {\n var keywords = (0, _permutate.splitwords)(val);\n\n if (!keywords.length) return showAll();\n\n var selectors = keywords.map(function (k) {\n return '[data-search-index~=' + JSON.stringify(k) + ']';\n }).join('');\n\n (0, _querySelectorAll2.default)('[data-search-index]').forEach(function (el) {\n el.setAttribute('aria-hidden', true);\n });\n\n (0, _querySelectorAll2.default)(selectors).forEach(function (el) {\n el.removeAttribute('aria-hidden');\n });\n}\n\n/***/ }),\n\n/***/ \"E+dCGfS1pT5WowYv7jpv\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _isotopePkgd = __webpack_require__(\"GbzL7C/QFmiBZDICkla+\");\n\nvar _isotopePkgd2 = _interopRequireDefault(_isotopePkgd);\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nvar _on = __webpack_require__(\"MKJaVdnD9jF7rk6rW6AJ\");\n\nvar _on2 = _interopRequireDefault(_on);\n\nvar _querySelectorAll = __webpack_require__(\"EvxNxLK9yKFmn1U14Kvw\");\n\nvar _querySelectorAll2 = _interopRequireDefault(_querySelectorAll);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/*\n * Behavior: Isotope\n */\n\n/* eslint-disable no-new */\n\n(0, _onmount2.default)('[data-js-h3-section-list]', function () {\n var iso = new _isotopePkgd2.default(this, {\n itemSelector: '.h3-section',\n transitionDuration: 0\n });\n\n var images = (0, _querySelectorAll2.default)('img', this);\n\n images.forEach(function (image) {\n (0, _on2.default)(image, 'load', function () {\n iso.layout();\n });\n });\n\n // Insurance against weirdness on pages like devhints.io/vim, where the\n // critical path CSS may look different from the final CSS (because of the\n // tables).\n (0, _on2.default)(window, 'load', function () {\n iso.layout();\n });\n});\n\n/***/ }),\n\n/***/ \"EvxNxLK9yKFmn1U14Kvw\":\n/***/ (function(module, exports) {\n\n/**\n * querySelectorAll : querySelectorAll(query, [element])\n * Convenience function to access `document.querySelectorAll`. Unlike the\n * default version, this always returns an array.\n *\n * If a 2nd parameter `element` is given, it only searches for descendants of\n * that element.\n *\n * var each = require('dom101/each');\n * var qsa = require('dom101/query-selector-all');\n *\n * qsa('.button').each(el => {\n * addClass('el', 'selected');\n * };\n */\n\nfunction querySelectorAll (query, context) {\n return Array.prototype.slice.call(\n (context || document).querySelectorAll(query)\n )\n}\n\nmodule.exports = querySelectorAll\n\n\n/***/ }),\n\n/***/ \"GOdGag34TlRuHa2OZoh9\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = permutate;\nexports.permutateString = permutateString;\nexports.permutateWord = permutateWord;\nexports.splitwords = splitwords;\n/**\n * Permutates a searcheable item.\n *\n * permutate({\n * slug: 'hello-world',\n * category: 'greetings'\n * })\n */\n\nfunction permutate(data) {\n var words = [];\n if (data.slug) {\n words = words.concat(permutateString(data.slug));\n }\n if (data.category) {\n words = words.concat(permutateString(data.category));\n }\n return words;\n}\n\n/**\n * Permutates strings.\n *\n * @example\n * permutateString('hi joe')\n * => ['h', 'hi', 'j', 'jo', 'joe']\n */\n\nfunction permutateString(str) {\n var words = [];\n var inputs = splitwords(str);\n\n inputs.forEach(function (word) {\n words = words.concat(permutateWord(word));\n });\n\n return words;\n}\n\n/**\n * Permutates a word.\n *\n * @example\n * permutateWord('hello')\n * => ['h', 'he', 'hel', 'hell', 'hello']\n */\n\nfunction permutateWord(str) {\n var words = [];\n var len = str.length;\n for (var i = 1; i <= len; ++i) {\n words.push(str.substr(0, i));\n }\n return words;\n}\n\n/**\n * Helper for splitting to words.\n *\n * @example\n * splitWords('Hello, world!')\n * => ['hello', 'world']\n */\n\nfunction splitwords(str) {\n var words = str.toLowerCase().split(/[ /\\-_]/).filter(function (k) {\n return k && k.length !== 0;\n });\n\n return words;\n}\n\n/***/ }),\n\n/***/ \"GbzL7C/QFmiBZDICkla+\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var __WEBPACK_LOCAL_MODULE_1__, __WEBPACK_LOCAL_MODULE_1__factory, __WEBPACK_LOCAL_MODULE_1__module;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_LOCAL_MODULE_2__;var __WEBPACK_LOCAL_MODULE_3__, __WEBPACK_LOCAL_MODULE_3__factory, __WEBPACK_LOCAL_MODULE_3__module;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_LOCAL_MODULE_4__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_LOCAL_MODULE_5__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_LOCAL_MODULE_6__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_LOCAL_MODULE_7__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_LOCAL_MODULE_8__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_LOCAL_MODULE_9__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_LOCAL_MODULE_10__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_LOCAL_MODULE_11__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_LOCAL_MODULE_12__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!\n * Isotope PACKAGED v3.0.4\n *\n * Licensed GPLv3 for open source use\n * or Isotope Commercial License for commercial use\n *\n * http://isotope.metafizzy.co\n * Copyright 2017 Metafizzy\n */\n\n/**\n * Bridget makes jQuery widgets\n * v2.0.1\n * MIT license\n */\n\n/* jshint browser: true, strict: true, undef: true, unused: true */\n\n( function( window, factory ) {\n // universal module definition\n /*jshint strict: false */ /* globals define, module, require */\n if ( true ) {\n // AMD\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(\"g2okcHDGBNRpe9zqR9sR\") ], __WEBPACK_AMD_DEFINE_RESULT__ = function( jQuery ) {\n return factory( window, jQuery );\n }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n window,\n require('jquery')\n );\n } else {\n // browser global\n window.jQueryBridget = factory(\n window,\n window.jQuery\n );\n }\n\n}( window, function factory( window, jQuery ) {\n'use strict';\n\n// ----- utils ----- //\n\nvar arraySlice = Array.prototype.slice;\n\n// helper function for logging errors\n// $.error breaks jQuery chaining\nvar console = window.console;\nvar logError = typeof console == 'undefined' ? function() {} :\n function( message ) {\n console.error( message );\n };\n\n// ----- jQueryBridget ----- //\n\nfunction jQueryBridget( namespace, PluginClass, $ ) {\n $ = $ || jQuery || window.jQuery;\n if ( !$ ) {\n return;\n }\n\n // add option method -> $().plugin('option', {...})\n if ( !PluginClass.prototype.option ) {\n // option setter\n PluginClass.prototype.option = function( opts ) {\n // bail out if not an object\n if ( !$.isPlainObject( opts ) ){\n return;\n }\n this.options = $.extend( true, this.options, opts );\n };\n }\n\n // make jQuery plugin\n $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {\n if ( typeof arg0 == 'string' ) {\n // method call $().plugin( 'methodName', { options } )\n // shift arguments by 1\n var args = arraySlice.call( arguments, 1 );\n return methodCall( this, arg0, args );\n }\n // just $().plugin({ options })\n plainCall( this, arg0 );\n return this;\n };\n\n // $().plugin('methodName')\n function methodCall( $elems, methodName, args ) {\n var returnValue;\n var pluginMethodStr = '$().' + namespace + '(\"' + methodName + '\")';\n\n $elems.each( function( i, elem ) {\n // get instance\n var instance = $.data( elem, namespace );\n if ( !instance ) {\n logError( namespace + ' not initialized. Cannot call methods, i.e. ' +\n pluginMethodStr );\n return;\n }\n\n var method = instance[ methodName ];\n if ( !method || methodName.charAt(0) == '_' ) {\n logError( pluginMethodStr + ' is not a valid method' );\n return;\n }\n\n // apply method, get return value\n var value = method.apply( instance, args );\n // set return value if value is returned, use only first value\n returnValue = returnValue === undefined ? value : returnValue;\n });\n\n return returnValue !== undefined ? returnValue : $elems;\n }\n\n function plainCall( $elems, options ) {\n $elems.each( function( i, elem ) {\n var instance = $.data( elem, namespace );\n if ( instance ) {\n // set options & init\n instance.option( options );\n instance._init();\n } else {\n // initialize new instance\n instance = new PluginClass( elem, options );\n $.data( elem, namespace, instance );\n }\n });\n }\n\n updateJQuery( $ );\n\n}\n\n// ----- updateJQuery ----- //\n\n// set $.bridget for v1 backwards compatibility\nfunction updateJQuery( $ ) {\n if ( !$ || ( $ && $.bridget ) ) {\n return;\n }\n $.bridget = jQueryBridget;\n}\n\nupdateJQuery( jQuery || window.jQuery );\n\n// ----- ----- //\n\nreturn jQueryBridget;\n\n}));\n\n/**\n * EvEmitter v1.0.3\n * Lil' event emitter\n * MIT License\n */\n\n/* jshint unused: true, undef: true, strict: true */\n\n( function( global, factory ) {\n // universal module definition\n /* jshint strict: false */ /* globals define, module, window */\n if ( true ) {\n // AMD - RequireJS\n !(__WEBPACK_LOCAL_MODULE_1__factory = (factory), (__WEBPACK_LOCAL_MODULE_1__module = { id: \"ev-emitter/ev-emitter\", exports: {}, loaded: false }), __WEBPACK_LOCAL_MODULE_1__ = (typeof __WEBPACK_LOCAL_MODULE_1__factory === 'function' ? (__WEBPACK_LOCAL_MODULE_1__factory.call(__WEBPACK_LOCAL_MODULE_1__module.exports, __webpack_require__, __WEBPACK_LOCAL_MODULE_1__module.exports, __WEBPACK_LOCAL_MODULE_1__module)) : __WEBPACK_LOCAL_MODULE_1__factory), (__WEBPACK_LOCAL_MODULE_1__module.loaded = true), __WEBPACK_LOCAL_MODULE_1__ === undefined && (__WEBPACK_LOCAL_MODULE_1__ = __WEBPACK_LOCAL_MODULE_1__module.exports));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS - Browserify, Webpack\n module.exports = factory();\n } else {\n // Browser globals\n global.EvEmitter = factory();\n }\n\n}( typeof window != 'undefined' ? window : this, function() {\n\n\n\nfunction EvEmitter() {}\n\nvar proto = EvEmitter.prototype;\n\nproto.on = function( eventName, listener ) {\n if ( !eventName || !listener ) {\n return;\n }\n // set events hash\n var events = this._events = this._events || {};\n // set listeners array\n var listeners = events[ eventName ] = events[ eventName ] || [];\n // only add once\n if ( listeners.indexOf( listener ) == -1 ) {\n listeners.push( listener );\n }\n\n return this;\n};\n\nproto.once = function( eventName, listener ) {\n if ( !eventName || !listener ) {\n return;\n }\n // add event\n this.on( eventName, listener );\n // set once flag\n // set onceEvents hash\n var onceEvents = this._onceEvents = this._onceEvents || {};\n // set onceListeners object\n var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};\n // set flag\n onceListeners[ listener ] = true;\n\n return this;\n};\n\nproto.off = function( eventName, listener ) {\n var listeners = this._events && this._events[ eventName ];\n if ( !listeners || !listeners.length ) {\n return;\n }\n var index = listeners.indexOf( listener );\n if ( index != -1 ) {\n listeners.splice( index, 1 );\n }\n\n return this;\n};\n\nproto.emitEvent = function( eventName, args ) {\n var listeners = this._events && this._events[ eventName ];\n if ( !listeners || !listeners.length ) {\n return;\n }\n var i = 0;\n var listener = listeners[i];\n args = args || [];\n // once stuff\n var onceListeners = this._onceEvents && this._onceEvents[ eventName ];\n\n while ( listener ) {\n var isOnce = onceListeners && onceListeners[ listener ];\n if ( isOnce ) {\n // remove listener\n // remove before trigger to prevent recursion\n this.off( eventName, listener );\n // unset once flag\n delete onceListeners[ listener ];\n }\n // trigger listener\n listener.apply( this, args );\n // get next listener\n i += isOnce ? 0 : 1;\n listener = listeners[i];\n }\n\n return this;\n};\n\nreturn EvEmitter;\n\n}));\n\n/*!\n * getSize v2.0.2\n * measure size of elements\n * MIT license\n */\n\n/*jshint browser: true, strict: true, undef: true, unused: true */\n/*global define: false, module: false, console: false */\n\n( function( window, factory ) {\n 'use strict';\n\n if ( true ) {\n // AMD\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_LOCAL_MODULE_2__ = (function() {\n return factory();\n }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory();\n } else {\n // browser global\n window.getSize = factory();\n }\n\n})( window, function factory() {\n'use strict';\n\n// -------------------------- helpers -------------------------- //\n\n// get a number from a string, not a percentage\nfunction getStyleSize( value ) {\n var num = parseFloat( value );\n // not a percent like '100%', and a number\n var isValid = value.indexOf('%') == -1 && !isNaN( num );\n return isValid && num;\n}\n\nfunction noop() {}\n\nvar logError = typeof console == 'undefined' ? noop :\n function( message ) {\n console.error( message );\n };\n\n// -------------------------- measurements -------------------------- //\n\nvar measurements = [\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'paddingBottom',\n 'marginLeft',\n 'marginRight',\n 'marginTop',\n 'marginBottom',\n 'borderLeftWidth',\n 'borderRightWidth',\n 'borderTopWidth',\n 'borderBottomWidth'\n];\n\nvar measurementsLength = measurements.length;\n\nfunction getZeroSize() {\n var size = {\n width: 0,\n height: 0,\n innerWidth: 0,\n innerHeight: 0,\n outerWidth: 0,\n outerHeight: 0\n };\n for ( var i=0; i < measurementsLength; i++ ) {\n var measurement = measurements[i];\n size[ measurement ] = 0;\n }\n return size;\n}\n\n// -------------------------- getStyle -------------------------- //\n\n/**\n * getStyle, get style of element, check for Firefox bug\n * https://bugzilla.mozilla.org/show_bug.cgi?id=548397\n */\nfunction getStyle( elem ) {\n var style = getComputedStyle( elem );\n if ( !style ) {\n logError( 'Style returned ' + style +\n '. Are you running this code in a hidden iframe on Firefox? ' +\n 'See http://bit.ly/getsizebug1' );\n }\n return style;\n}\n\n// -------------------------- setup -------------------------- //\n\nvar isSetup = false;\n\nvar isBoxSizeOuter;\n\n/**\n * setup\n * check isBoxSizerOuter\n * do on first getSize() rather than on page load for Firefox bug\n */\nfunction setup() {\n // setup once\n if ( isSetup ) {\n return;\n }\n isSetup = true;\n\n // -------------------------- box sizing -------------------------- //\n\n /**\n * WebKit measures the outer-width on style.width on border-box elems\n * IE & Firefox<29 measures the inner-width\n */\n var div = document.createElement('div');\n div.style.width = '200px';\n div.style.padding = '1px 2px 3px 4px';\n div.style.borderStyle = 'solid';\n div.style.borderWidth = '1px 2px 3px 4px';\n div.style.boxSizing = 'border-box';\n\n var body = document.body || document.documentElement;\n body.appendChild( div );\n var style = getStyle( div );\n\n getSize.isBoxSizeOuter = isBoxSizeOuter = getStyleSize( style.width ) == 200;\n body.removeChild( div );\n\n}\n\n// -------------------------- getSize -------------------------- //\n\nfunction getSize( elem ) {\n setup();\n\n // use querySeletor if elem is string\n if ( typeof elem == 'string' ) {\n elem = document.querySelector( elem );\n }\n\n // do not proceed on non-objects\n if ( !elem || typeof elem != 'object' || !elem.nodeType ) {\n return;\n }\n\n var style = getStyle( elem );\n\n // if hidden, everything is 0\n if ( style.display == 'none' ) {\n return getZeroSize();\n }\n\n var size = {};\n size.width = elem.offsetWidth;\n size.height = elem.offsetHeight;\n\n var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';\n\n // get all measurements\n for ( var i=0; i < measurementsLength; i++ ) {\n var measurement = measurements[i];\n var value = style[ measurement ];\n var num = parseFloat( value );\n // any 'auto', 'medium' value will be 0\n size[ measurement ] = !isNaN( num ) ? num : 0;\n }\n\n var paddingWidth = size.paddingLeft + size.paddingRight;\n var paddingHeight = size.paddingTop + size.paddingBottom;\n var marginWidth = size.marginLeft + size.marginRight;\n var marginHeight = size.marginTop + size.marginBottom;\n var borderWidth = size.borderLeftWidth + size.borderRightWidth;\n var borderHeight = size.borderTopWidth + size.borderBottomWidth;\n\n var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;\n\n // overwrite width and height if we can get it from style\n var styleWidth = getStyleSize( style.width );\n if ( styleWidth !== false ) {\n size.width = styleWidth +\n // add padding and border unless it's already including it\n ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );\n }\n\n var styleHeight = getStyleSize( style.height );\n if ( styleHeight !== false ) {\n size.height = styleHeight +\n // add padding and border unless it's already including it\n ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );\n }\n\n size.innerWidth = size.width - ( paddingWidth + borderWidth );\n size.innerHeight = size.height - ( paddingHeight + borderHeight );\n\n size.outerWidth = size.width + marginWidth;\n size.outerHeight = size.height + marginHeight;\n\n return size;\n}\n\nreturn getSize;\n\n});\n\n/**\n * matchesSelector v2.0.2\n * matchesSelector( element, '.selector' )\n * MIT license\n */\n\n/*jshint browser: true, strict: true, undef: true, unused: true */\n\n( function( window, factory ) {\n /*global define: false, module: false */\n 'use strict';\n // universal module definition\n if ( true ) {\n // AMD\n !(__WEBPACK_LOCAL_MODULE_3__factory = (factory), (__WEBPACK_LOCAL_MODULE_3__module = { id: \"desandro-matches-selector/matches-selector\", exports: {}, loaded: false }), __WEBPACK_LOCAL_MODULE_3__ = (typeof __WEBPACK_LOCAL_MODULE_3__factory === 'function' ? (__WEBPACK_LOCAL_MODULE_3__factory.call(__WEBPACK_LOCAL_MODULE_3__module.exports, __webpack_require__, __WEBPACK_LOCAL_MODULE_3__module.exports, __WEBPACK_LOCAL_MODULE_3__module)) : __WEBPACK_LOCAL_MODULE_3__factory), (__WEBPACK_LOCAL_MODULE_3__module.loaded = true), __WEBPACK_LOCAL_MODULE_3__ === undefined && (__WEBPACK_LOCAL_MODULE_3__ = __WEBPACK_LOCAL_MODULE_3__module.exports));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory();\n } else {\n // browser global\n window.matchesSelector = factory();\n }\n\n}( window, function factory() {\n 'use strict';\n\n var matchesMethod = ( function() {\n var ElemProto = window.Element.prototype;\n // check for the standard method name first\n if ( ElemProto.matches ) {\n return 'matches';\n }\n // check un-prefixed\n if ( ElemProto.matchesSelector ) {\n return 'matchesSelector';\n }\n // check vendor prefixes\n var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];\n\n for ( var i=0; i < prefixes.length; i++ ) {\n var prefix = prefixes[i];\n var method = prefix + 'MatchesSelector';\n if ( ElemProto[ method ] ) {\n return method;\n }\n }\n })();\n\n return function matchesSelector( elem, selector ) {\n return elem[ matchesMethod ]( selector );\n };\n\n}));\n\n/**\n * Fizzy UI utils v2.0.5\n * MIT license\n */\n\n/*jshint browser: true, undef: true, unused: true, strict: true */\n\n( function( window, factory ) {\n // universal module definition\n /*jshint strict: false */ /*globals define, module, require */\n\n if ( true ) {\n // AMD\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n __WEBPACK_LOCAL_MODULE_3__\n ], __WEBPACK_LOCAL_MODULE_4__ = (function( matchesSelector ) {\n return factory( window, matchesSelector );\n }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n window,\n require('desandro-matches-selector')\n );\n } else {\n // browser global\n window.fizzyUIUtils = factory(\n window,\n window.matchesSelector\n );\n }\n\n}( window, function factory( window, matchesSelector ) {\n\n\n\nvar utils = {};\n\n// ----- extend ----- //\n\n// extends objects\nutils.extend = function( a, b ) {\n for ( var prop in b ) {\n a[ prop ] = b[ prop ];\n }\n return a;\n};\n\n// ----- modulo ----- //\n\nutils.modulo = function( num, div ) {\n return ( ( num % div ) + div ) % div;\n};\n\n// ----- makeArray ----- //\n\n// turn element or nodeList into an array\nutils.makeArray = function( obj ) {\n var ary = [];\n if ( Array.isArray( obj ) ) {\n // use object if already an array\n ary = obj;\n } else if ( obj && typeof obj == 'object' &&\n typeof obj.length == 'number' ) {\n // convert nodeList to array\n for ( var i=0; i < obj.length; i++ ) {\n ary.push( obj[i] );\n }\n } else {\n // array of single index\n ary.push( obj );\n }\n return ary;\n};\n\n// ----- removeFrom ----- //\n\nutils.removeFrom = function( ary, obj ) {\n var index = ary.indexOf( obj );\n if ( index != -1 ) {\n ary.splice( index, 1 );\n }\n};\n\n// ----- getParent ----- //\n\nutils.getParent = function( elem, selector ) {\n while ( elem.parentNode && elem != document.body ) {\n elem = elem.parentNode;\n if ( matchesSelector( elem, selector ) ) {\n return elem;\n }\n }\n};\n\n// ----- getQueryElement ----- //\n\n// use element as selector string\nutils.getQueryElement = function( elem ) {\n if ( typeof elem == 'string' ) {\n return document.querySelector( elem );\n }\n return elem;\n};\n\n// ----- handleEvent ----- //\n\n// enable .ontype to trigger from .addEventListener( elem, 'type' )\nutils.handleEvent = function( event ) {\n var method = 'on' + event.type;\n if ( this[ method ] ) {\n this[ method ]( event );\n }\n};\n\n// ----- filterFindElements ----- //\n\nutils.filterFindElements = function( elems, selector ) {\n // make array of elems\n elems = utils.makeArray( elems );\n var ffElems = [];\n\n elems.forEach( function( elem ) {\n // check that elem is an actual element\n if ( !( elem instanceof HTMLElement ) ) {\n return;\n }\n // add elem if no selector\n if ( !selector ) {\n ffElems.push( elem );\n return;\n }\n // filter & find items if we have a selector\n // filter\n if ( matchesSelector( elem, selector ) ) {\n ffElems.push( elem );\n }\n // find children\n var childElems = elem.querySelectorAll( selector );\n // concat childElems to filterFound array\n for ( var i=0; i < childElems.length; i++ ) {\n ffElems.push( childElems[i] );\n }\n });\n\n return ffElems;\n};\n\n// ----- debounceMethod ----- //\n\nutils.debounceMethod = function( _class, methodName, threshold ) {\n // original method\n var method = _class.prototype[ methodName ];\n var timeoutName = methodName + 'Timeout';\n\n _class.prototype[ methodName ] = function() {\n var timeout = this[ timeoutName ];\n if ( timeout ) {\n clearTimeout( timeout );\n }\n var args = arguments;\n\n var _this = this;\n this[ timeoutName ] = setTimeout( function() {\n method.apply( _this, args );\n delete _this[ timeoutName ];\n }, threshold || 100 );\n };\n};\n\n// ----- docReady ----- //\n\nutils.docReady = function( callback ) {\n var readyState = document.readyState;\n if ( readyState == 'complete' || readyState == 'interactive' ) {\n // do async to allow for other scripts to run. metafizzy/flickity#441\n setTimeout( callback );\n } else {\n document.addEventListener( 'DOMContentLoaded', callback );\n }\n};\n\n// ----- htmlInit ----- //\n\n// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/\nutils.toDashed = function( str ) {\n return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {\n return $1 + '-' + $2;\n }).toLowerCase();\n};\n\nvar console = window.console;\n/**\n * allow user to initialize classes via [data-namespace] or .js-namespace class\n * htmlInit( Widget, 'widgetName' )\n * options are parsed from data-namespace-options\n */\nutils.htmlInit = function( WidgetClass, namespace ) {\n utils.docReady( function() {\n var dashedNamespace = utils.toDashed( namespace );\n var dataAttr = 'data-' + dashedNamespace;\n var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );\n var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );\n var elems = utils.makeArray( dataAttrElems )\n .concat( utils.makeArray( jsDashElems ) );\n var dataOptionsAttr = dataAttr + '-options';\n var jQuery = window.jQuery;\n\n elems.forEach( function( elem ) {\n var attr = elem.getAttribute( dataAttr ) ||\n elem.getAttribute( dataOptionsAttr );\n var options;\n try {\n options = attr && JSON.parse( attr );\n } catch ( error ) {\n // log error, do not initialize\n if ( console ) {\n console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +\n ': ' + error );\n }\n return;\n }\n // initialize\n var instance = new WidgetClass( elem, options );\n // make available via $().data('namespace')\n if ( jQuery ) {\n jQuery.data( elem, namespace, instance );\n }\n });\n\n });\n};\n\n// ----- ----- //\n\nreturn utils;\n\n}));\n\n/**\n * Outlayer Item\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /* globals define, module, require */\n if ( true ) {\n // AMD - RequireJS\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n __WEBPACK_LOCAL_MODULE_1__,\n __WEBPACK_LOCAL_MODULE_2__\n ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_LOCAL_MODULE_5__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS - Browserify, Webpack\n module.exports = factory(\n require('ev-emitter'),\n require('get-size')\n );\n } else {\n // browser global\n window.Outlayer = {};\n window.Outlayer.Item = factory(\n window.EvEmitter,\n window.getSize\n );\n }\n\n}( window, function factory( EvEmitter, getSize ) {\n'use strict';\n\n// ----- helpers ----- //\n\nfunction isEmptyObj( obj ) {\n for ( var prop in obj ) {\n return false;\n }\n prop = null;\n return true;\n}\n\n// -------------------------- CSS3 support -------------------------- //\n\n\nvar docElemStyle = document.documentElement.style;\n\nvar transitionProperty = typeof docElemStyle.transition == 'string' ?\n 'transition' : 'WebkitTransition';\nvar transformProperty = typeof docElemStyle.transform == 'string' ?\n 'transform' : 'WebkitTransform';\n\nvar transitionEndEvent = {\n WebkitTransition: 'webkitTransitionEnd',\n transition: 'transitionend'\n}[ transitionProperty ];\n\n// cache all vendor properties that could have vendor prefix\nvar vendorProperties = {\n transform: transformProperty,\n transition: transitionProperty,\n transitionDuration: transitionProperty + 'Duration',\n transitionProperty: transitionProperty + 'Property',\n transitionDelay: transitionProperty + 'Delay'\n};\n\n// -------------------------- Item -------------------------- //\n\nfunction Item( element, layout ) {\n if ( !element ) {\n return;\n }\n\n this.element = element;\n // parent layout class, i.e. Masonry, Isotope, or Packery\n this.layout = layout;\n this.position = {\n x: 0,\n y: 0\n };\n\n this._create();\n}\n\n// inherit EvEmitter\nvar proto = Item.prototype = Object.create( EvEmitter.prototype );\nproto.constructor = Item;\n\nproto._create = function() {\n // transition objects\n this._transn = {\n ingProperties: {},\n clean: {},\n onEnd: {}\n };\n\n this.css({\n position: 'absolute'\n });\n};\n\n// trigger specified handler for event type\nproto.handleEvent = function( event ) {\n var method = 'on' + event.type;\n if ( this[ method ] ) {\n this[ method ]( event );\n }\n};\n\nproto.getSize = function() {\n this.size = getSize( this.element );\n};\n\n/**\n * apply CSS styles to element\n * @param {Object} style\n */\nproto.css = function( style ) {\n var elemStyle = this.element.style;\n\n for ( var prop in style ) {\n // use vendor property if available\n var supportedProp = vendorProperties[ prop ] || prop;\n elemStyle[ supportedProp ] = style[ prop ];\n }\n};\n\n // measure position, and sets it\nproto.getPosition = function() {\n var style = getComputedStyle( this.element );\n var isOriginLeft = this.layout._getOption('originLeft');\n var isOriginTop = this.layout._getOption('originTop');\n var xValue = style[ isOriginLeft ? 'left' : 'right' ];\n var yValue = style[ isOriginTop ? 'top' : 'bottom' ];\n // convert percent to pixels\n var layoutSize = this.layout.size;\n var x = xValue.indexOf('%') != -1 ?\n ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 );\n var y = yValue.indexOf('%') != -1 ?\n ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 );\n\n // clean up 'auto' or other non-integer values\n x = isNaN( x ) ? 0 : x;\n y = isNaN( y ) ? 0 : y;\n // remove padding from measurement\n x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;\n y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;\n\n this.position.x = x;\n this.position.y = y;\n};\n\n// set settled position, apply padding\nproto.layoutPosition = function() {\n var layoutSize = this.layout.size;\n var style = {};\n var isOriginLeft = this.layout._getOption('originLeft');\n var isOriginTop = this.layout._getOption('originTop');\n\n // x\n var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';\n var xProperty = isOriginLeft ? 'left' : 'right';\n var xResetProperty = isOriginLeft ? 'right' : 'left';\n\n var x = this.position.x + layoutSize[ xPadding ];\n // set in percentage or pixels\n style[ xProperty ] = this.getXValue( x );\n // reset other property\n style[ xResetProperty ] = '';\n\n // y\n var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';\n var yProperty = isOriginTop ? 'top' : 'bottom';\n var yResetProperty = isOriginTop ? 'bottom' : 'top';\n\n var y = this.position.y + layoutSize[ yPadding ];\n // set in percentage or pixels\n style[ yProperty ] = this.getYValue( y );\n // reset other property\n style[ yResetProperty ] = '';\n\n this.css( style );\n this.emitEvent( 'layout', [ this ] );\n};\n\nproto.getXValue = function( x ) {\n var isHorizontal = this.layout._getOption('horizontal');\n return this.layout.options.percentPosition && !isHorizontal ?\n ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';\n};\n\nproto.getYValue = function( y ) {\n var isHorizontal = this.layout._getOption('horizontal');\n return this.layout.options.percentPosition && isHorizontal ?\n ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';\n};\n\nproto._transitionTo = function( x, y ) {\n this.getPosition();\n // get current x & y from top/left\n var curX = this.position.x;\n var curY = this.position.y;\n\n var compareX = parseInt( x, 10 );\n var compareY = parseInt( y, 10 );\n var didNotMove = compareX === this.position.x && compareY === this.position.y;\n\n // save end position\n this.setPosition( x, y );\n\n // if did not move and not transitioning, just go to layout\n if ( didNotMove && !this.isTransitioning ) {\n this.layoutPosition();\n return;\n }\n\n var transX = x - curX;\n var transY = y - curY;\n var transitionStyle = {};\n transitionStyle.transform = this.getTranslate( transX, transY );\n\n this.transition({\n to: transitionStyle,\n onTransitionEnd: {\n transform: this.layoutPosition\n },\n isCleaning: true\n });\n};\n\nproto.getTranslate = function( x, y ) {\n // flip cooridinates if origin on right or bottom\n var isOriginLeft = this.layout._getOption('originLeft');\n var isOriginTop = this.layout._getOption('originTop');\n x = isOriginLeft ? x : -x;\n y = isOriginTop ? y : -y;\n return 'translate3d(' + x + 'px, ' + y + 'px, 0)';\n};\n\n// non transition + transform support\nproto.goTo = function( x, y ) {\n this.setPosition( x, y );\n this.layoutPosition();\n};\n\nproto.moveTo = proto._transitionTo;\n\nproto.setPosition = function( x, y ) {\n this.position.x = parseInt( x, 10 );\n this.position.y = parseInt( y, 10 );\n};\n\n// ----- transition ----- //\n\n/**\n * @param {Object} style - CSS\n * @param {Function} onTransitionEnd\n */\n\n// non transition, just trigger callback\nproto._nonTransition = function( args ) {\n this.css( args.to );\n if ( args.isCleaning ) {\n this._removeStyles( args.to );\n }\n for ( var prop in args.onTransitionEnd ) {\n args.onTransitionEnd[ prop ].call( this );\n }\n};\n\n/**\n * proper transition\n * @param {Object} args - arguments\n * @param {Object} to - style to transition to\n * @param {Object} from - style to start transition from\n * @param {Boolean} isCleaning - removes transition styles after transition\n * @param {Function} onTransitionEnd - callback\n */\nproto.transition = function( args ) {\n // redirect to nonTransition if no transition duration\n if ( !parseFloat( this.layout.options.transitionDuration ) ) {\n this._nonTransition( args );\n return;\n }\n\n var _transition = this._transn;\n // keep track of onTransitionEnd callback by css property\n for ( var prop in args.onTransitionEnd ) {\n _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];\n }\n // keep track of properties that are transitioning\n for ( prop in args.to ) {\n _transition.ingProperties[ prop ] = true;\n // keep track of properties to clean up when transition is done\n if ( args.isCleaning ) {\n _transition.clean[ prop ] = true;\n }\n }\n\n // set from styles\n if ( args.from ) {\n this.css( args.from );\n // force redraw. http://blog.alexmaccaw.com/css-transitions\n var h = this.element.offsetHeight;\n // hack for JSHint to hush about unused var\n h = null;\n }\n // enable transition\n this.enableTransition( args.to );\n // set styles that are transitioning\n this.css( args.to );\n\n this.isTransitioning = true;\n\n};\n\n// dash before all cap letters, including first for\n// WebkitTransform => -webkit-transform\nfunction toDashedAll( str ) {\n return str.replace( /([A-Z])/g, function( $1 ) {\n return '-' + $1.toLowerCase();\n });\n}\n\nvar transitionProps = 'opacity,' + toDashedAll( transformProperty );\n\nproto.enableTransition = function(/* style */) {\n // HACK changing transitionProperty during a transition\n // will cause transition to jump\n if ( this.isTransitioning ) {\n return;\n }\n\n // make `transition: foo, bar, baz` from style object\n // HACK un-comment this when enableTransition can work\n // while a transition is happening\n // var transitionValues = [];\n // for ( var prop in style ) {\n // // dash-ify camelCased properties like WebkitTransition\n // prop = vendorProperties[ prop ] || prop;\n // transitionValues.push( toDashedAll( prop ) );\n // }\n // munge number to millisecond, to match stagger\n var duration = this.layout.options.transitionDuration;\n duration = typeof duration == 'number' ? duration + 'ms' : duration;\n // enable transition styles\n this.css({\n transitionProperty: transitionProps,\n transitionDuration: duration,\n transitionDelay: this.staggerDelay || 0\n });\n // listen for transition end event\n this.element.addEventListener( transitionEndEvent, this, false );\n};\n\n// ----- events ----- //\n\nproto.onwebkitTransitionEnd = function( event ) {\n this.ontransitionend( event );\n};\n\nproto.onotransitionend = function( event ) {\n this.ontransitionend( event );\n};\n\n// properties that I munge to make my life easier\nvar dashedVendorProperties = {\n '-webkit-transform': 'transform'\n};\n\nproto.ontransitionend = function( event ) {\n // disregard bubbled events from children\n if ( event.target !== this.element ) {\n return;\n }\n var _transition = this._transn;\n // get property name of transitioned property, convert to prefix-free\n var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;\n\n // remove property that has completed transitioning\n delete _transition.ingProperties[ propertyName ];\n // check if any properties are still transitioning\n if ( isEmptyObj( _transition.ingProperties ) ) {\n // all properties have completed transitioning\n this.disableTransition();\n }\n // clean style\n if ( propertyName in _transition.clean ) {\n // clean up style\n this.element.style[ event.propertyName ] = '';\n delete _transition.clean[ propertyName ];\n }\n // trigger onTransitionEnd callback\n if ( propertyName in _transition.onEnd ) {\n var onTransitionEnd = _transition.onEnd[ propertyName ];\n onTransitionEnd.call( this );\n delete _transition.onEnd[ propertyName ];\n }\n\n this.emitEvent( 'transitionEnd', [ this ] );\n};\n\nproto.disableTransition = function() {\n this.removeTransitionStyles();\n this.element.removeEventListener( transitionEndEvent, this, false );\n this.isTransitioning = false;\n};\n\n/**\n * removes style property from element\n * @param {Object} style\n**/\nproto._removeStyles = function( style ) {\n // clean up transition styles\n var cleanStyle = {};\n for ( var prop in style ) {\n cleanStyle[ prop ] = '';\n }\n this.css( cleanStyle );\n};\n\nvar cleanTransitionStyle = {\n transitionProperty: '',\n transitionDuration: '',\n transitionDelay: ''\n};\n\nproto.removeTransitionStyles = function() {\n // remove transition\n this.css( cleanTransitionStyle );\n};\n\n// ----- stagger ----- //\n\nproto.stagger = function( delay ) {\n delay = isNaN( delay ) ? 0 : delay;\n this.staggerDelay = delay + 'ms';\n};\n\n// ----- show/hide/remove ----- //\n\n// remove element from DOM\nproto.removeElem = function() {\n this.element.parentNode.removeChild( this.element );\n // remove display: none\n this.css({ display: '' });\n this.emitEvent( 'remove', [ this ] );\n};\n\nproto.remove = function() {\n // just remove element if no transition support or no transition\n if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {\n this.removeElem();\n return;\n }\n\n // start transition\n this.once( 'transitionEnd', function() {\n this.removeElem();\n });\n this.hide();\n};\n\nproto.reveal = function() {\n delete this.isHidden;\n // remove display: none\n this.css({ display: '' });\n\n var options = this.layout.options;\n\n var onTransitionEnd = {};\n var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');\n onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;\n\n this.transition({\n from: options.hiddenStyle,\n to: options.visibleStyle,\n isCleaning: true,\n onTransitionEnd: onTransitionEnd\n });\n};\n\nproto.onRevealTransitionEnd = function() {\n // check if still visible\n // during transition, item may have been hidden\n if ( !this.isHidden ) {\n this.emitEvent('reveal');\n }\n};\n\n/**\n * get style property use for hide/reveal transition end\n * @param {String} styleProperty - hiddenStyle/visibleStyle\n * @returns {String}\n */\nproto.getHideRevealTransitionEndProperty = function( styleProperty ) {\n var optionStyle = this.layout.options[ styleProperty ];\n // use opacity\n if ( optionStyle.opacity ) {\n return 'opacity';\n }\n // get first property\n for ( var prop in optionStyle ) {\n return prop;\n }\n};\n\nproto.hide = function() {\n // set flag\n this.isHidden = true;\n // remove display: none\n this.css({ display: '' });\n\n var options = this.layout.options;\n\n var onTransitionEnd = {};\n var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');\n onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;\n\n this.transition({\n from: options.visibleStyle,\n to: options.hiddenStyle,\n // keep hidden stuff hidden\n isCleaning: true,\n onTransitionEnd: onTransitionEnd\n });\n};\n\nproto.onHideTransitionEnd = function() {\n // check if still hidden\n // during transition, item may have been un-hidden\n if ( this.isHidden ) {\n this.css({ display: 'none' });\n this.emitEvent('hide');\n }\n};\n\nproto.destroy = function() {\n this.css({\n position: '',\n left: '',\n right: '',\n top: '',\n bottom: '',\n transition: '',\n transform: ''\n });\n};\n\nreturn Item;\n\n}));\n\n/*!\n * Outlayer v2.1.0\n * the brains and guts of a layout library\n * MIT license\n */\n\n( function( window, factory ) {\n 'use strict';\n // universal module definition\n /* jshint strict: false */ /* globals define, module, require */\n if ( true ) {\n // AMD - RequireJS\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n __WEBPACK_LOCAL_MODULE_1__,\n __WEBPACK_LOCAL_MODULE_2__,\n __WEBPACK_LOCAL_MODULE_4__,\n __WEBPACK_LOCAL_MODULE_5__\n ], __WEBPACK_LOCAL_MODULE_6__ = (function( EvEmitter, getSize, utils, Item ) {\n return factory( window, EvEmitter, getSize, utils, Item);\n }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS - Browserify, Webpack\n module.exports = factory(\n window,\n require('ev-emitter'),\n require('get-size'),\n require('fizzy-ui-utils'),\n require('./item')\n );\n } else {\n // browser global\n window.Outlayer = factory(\n window,\n window.EvEmitter,\n window.getSize,\n window.fizzyUIUtils,\n window.Outlayer.Item\n );\n }\n\n}( window, function factory( window, EvEmitter, getSize, utils, Item ) {\n'use strict';\n\n// ----- vars ----- //\n\nvar console = window.console;\nvar jQuery = window.jQuery;\nvar noop = function() {};\n\n// -------------------------- Outlayer -------------------------- //\n\n// globally unique identifiers\nvar GUID = 0;\n// internal store of all Outlayer intances\nvar instances = {};\n\n\n/**\n * @param {Element, String} element\n * @param {Object} options\n * @constructor\n */\nfunction Outlayer( element, options ) {\n var queryElement = utils.getQueryElement( element );\n if ( !queryElement ) {\n if ( console ) {\n console.error( 'Bad element for ' + this.constructor.namespace +\n ': ' + ( queryElement || element ) );\n }\n return;\n }\n this.element = queryElement;\n // add jQuery\n if ( jQuery ) {\n this.$element = jQuery( this.element );\n }\n\n // options\n this.options = utils.extend( {}, this.constructor.defaults );\n this.option( options );\n\n // add id for Outlayer.getFromElement\n var id = ++GUID;\n this.element.outlayerGUID = id; // expando\n instances[ id ] = this; // associate via id\n\n // kick it off\n this._create();\n\n var isInitLayout = this._getOption('initLayout');\n if ( isInitLayout ) {\n this.layout();\n }\n}\n\n// settings are for internal use only\nOutlayer.namespace = 'outlayer';\nOutlayer.Item = Item;\n\n// default options\nOutlayer.defaults = {\n containerStyle: {\n position: 'relative'\n },\n initLayout: true,\n originLeft: true,\n originTop: true,\n resize: true,\n resizeContainer: true,\n // item options\n transitionDuration: '0.4s',\n hiddenStyle: {\n opacity: 0,\n transform: 'scale(0.001)'\n },\n visibleStyle: {\n opacity: 1,\n transform: 'scale(1)'\n }\n};\n\nvar proto = Outlayer.prototype;\n// inherit EvEmitter\nutils.extend( proto, EvEmitter.prototype );\n\n/**\n * set options\n * @param {Object} opts\n */\nproto.option = function( opts ) {\n utils.extend( this.options, opts );\n};\n\n/**\n * get backwards compatible option value, check old name\n */\nproto._getOption = function( option ) {\n var oldOption = this.constructor.compatOptions[ option ];\n return oldOption && this.options[ oldOption ] !== undefined ?\n this.options[ oldOption ] : this.options[ option ];\n};\n\nOutlayer.compatOptions = {\n // currentName: oldName\n initLayout: 'isInitLayout',\n horizontal: 'isHorizontal',\n layoutInstant: 'isLayoutInstant',\n originLeft: 'isOriginLeft',\n originTop: 'isOriginTop',\n resize: 'isResizeBound',\n resizeContainer: 'isResizingContainer'\n};\n\nproto._create = function() {\n // get items from children\n this.reloadItems();\n // elements that affect layout, but are not laid out\n this.stamps = [];\n this.stamp( this.options.stamp );\n // set container style\n utils.extend( this.element.style, this.options.containerStyle );\n\n // bind resize method\n var canBindResize = this._getOption('resize');\n if ( canBindResize ) {\n this.bindResize();\n }\n};\n\n// goes through all children again and gets bricks in proper order\nproto.reloadItems = function() {\n // collection of item elements\n this.items = this._itemize( this.element.children );\n};\n\n\n/**\n * turn elements into Outlayer.Items to be used in layout\n * @param {Array or NodeList or HTMLElement} elems\n * @returns {Array} items - collection of new Outlayer Items\n */\nproto._itemize = function( elems ) {\n\n var itemElems = this._filterFindItemElements( elems );\n var Item = this.constructor.Item;\n\n // create new Outlayer Items for collection\n var items = [];\n for ( var i=0; i < itemElems.length; i++ ) {\n var elem = itemElems[i];\n var item = new Item( elem, this );\n items.push( item );\n }\n\n return items;\n};\n\n/**\n * get item elements to be used in layout\n * @param {Array or NodeList or HTMLElement} elems\n * @returns {Array} items - item elements\n */\nproto._filterFindItemElements = function( elems ) {\n return utils.filterFindElements( elems, this.options.itemSelector );\n};\n\n/**\n * getter method for getting item elements\n * @returns {Array} elems - collection of item elements\n */\nproto.getItemElements = function() {\n return this.items.map( function( item ) {\n return item.element;\n });\n};\n\n// ----- init & layout ----- //\n\n/**\n * lays out all items\n */\nproto.layout = function() {\n this._resetLayout();\n this._manageStamps();\n\n // don't animate first layout\n var layoutInstant = this._getOption('layoutInstant');\n var isInstant = layoutInstant !== undefined ?\n layoutInstant : !this._isLayoutInited;\n this.layoutItems( this.items, isInstant );\n\n // flag for initalized\n this._isLayoutInited = true;\n};\n\n// _init is alias for layout\nproto._init = proto.layout;\n\n/**\n * logic before any new layout\n */\nproto._resetLayout = function() {\n this.getSize();\n};\n\n\nproto.getSize = function() {\n this.size = getSize( this.element );\n};\n\n/**\n * get measurement from option, for columnWidth, rowHeight, gutter\n * if option is String -> get element from selector string, & get size of element\n * if option is Element -> get size of element\n * else use option as a number\n *\n * @param {String} measurement\n * @param {String} size - width or height\n * @private\n */\nproto._getMeasurement = function( measurement, size ) {\n var option = this.options[ measurement ];\n var elem;\n if ( !option ) {\n // default to 0\n this[ measurement ] = 0;\n } else {\n // use option as an element\n if ( typeof option == 'string' ) {\n elem = this.element.querySelector( option );\n } else if ( option instanceof HTMLElement ) {\n elem = option;\n }\n // use size of element, if element\n this[ measurement ] = elem ? getSize( elem )[ size ] : option;\n }\n};\n\n/**\n * layout a collection of item elements\n * @api public\n */\nproto.layoutItems = function( items, isInstant ) {\n items = this._getItemsForLayout( items );\n\n this._layoutItems( items, isInstant );\n\n this._postLayout();\n};\n\n/**\n * get the items to be laid out\n * you may want to skip over some items\n * @param {Array} items\n * @returns {Array} items\n */\nproto._getItemsForLayout = function( items ) {\n return items.filter( function( item ) {\n return !item.isIgnored;\n });\n};\n\n/**\n * layout items\n * @param {Array} items\n * @param {Boolean} isInstant\n */\nproto._layoutItems = function( items, isInstant ) {\n this._emitCompleteOnItems( 'layout', items );\n\n if ( !items || !items.length ) {\n // no items, emit event with empty array\n return;\n }\n\n var queue = [];\n\n items.forEach( function( item ) {\n // get x/y object from method\n var position = this._getItemLayoutPosition( item );\n // enqueue\n position.item = item;\n position.isInstant = isInstant || item.isLayoutInstant;\n queue.push( position );\n }, this );\n\n this._processLayoutQueue( queue );\n};\n\n/**\n * get item layout position\n * @param {Outlayer.Item} item\n * @returns {Object} x and y position\n */\nproto._getItemLayoutPosition = function( /* item */ ) {\n return {\n x: 0,\n y: 0\n };\n};\n\n/**\n * iterate over array and position each item\n * Reason being - separating this logic prevents 'layout invalidation'\n * thx @paul_irish\n * @param {Array} queue\n */\nproto._processLayoutQueue = function( queue ) {\n this.updateStagger();\n queue.forEach( function( obj, i ) {\n this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );\n }, this );\n};\n\n// set stagger from option in milliseconds number\nproto.updateStagger = function() {\n var stagger = this.options.stagger;\n if ( stagger === null || stagger === undefined ) {\n this.stagger = 0;\n return;\n }\n this.stagger = getMilliseconds( stagger );\n return this.stagger;\n};\n\n/**\n * Sets position of item in DOM\n * @param {Outlayer.Item} item\n * @param {Number} x - horizontal position\n * @param {Number} y - vertical position\n * @param {Boolean} isInstant - disables transitions\n */\nproto._positionItem = function( item, x, y, isInstant, i ) {\n if ( isInstant ) {\n // if not transition, just set CSS\n item.goTo( x, y );\n } else {\n item.stagger( i * this.stagger );\n item.moveTo( x, y );\n }\n};\n\n/**\n * Any logic you want to do after each layout,\n * i.e. size the container\n */\nproto._postLayout = function() {\n this.resizeContainer();\n};\n\nproto.resizeContainer = function() {\n var isResizingContainer = this._getOption('resizeContainer');\n if ( !isResizingContainer ) {\n return;\n }\n var size = this._getContainerSize();\n if ( size ) {\n this._setContainerMeasure( size.width, true );\n this._setContainerMeasure( size.height, false );\n }\n};\n\n/**\n * Sets width or height of container if returned\n * @returns {Object} size\n * @param {Number} width\n * @param {Number} height\n */\nproto._getContainerSize = noop;\n\n/**\n * @param {Number} measure - size of width or height\n * @param {Boolean} isWidth\n */\nproto._setContainerMeasure = function( measure, isWidth ) {\n if ( measure === undefined ) {\n return;\n }\n\n var elemSize = this.size;\n // add padding and border width if border box\n if ( elemSize.isBorderBox ) {\n measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +\n elemSize.borderLeftWidth + elemSize.borderRightWidth :\n elemSize.paddingBottom + elemSize.paddingTop +\n elemSize.borderTopWidth + elemSize.borderBottomWidth;\n }\n\n measure = Math.max( measure, 0 );\n this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';\n};\n\n/**\n * emit eventComplete on a collection of items events\n * @param {String} eventName\n * @param {Array} items - Outlayer.Items\n */\nproto._emitCompleteOnItems = function( eventName, items ) {\n var _this = this;\n function onComplete() {\n _this.dispatchEvent( eventName + 'Complete', null, [ items ] );\n }\n\n var count = items.length;\n if ( !items || !count ) {\n onComplete();\n return;\n }\n\n var doneCount = 0;\n function tick() {\n doneCount++;\n if ( doneCount == count ) {\n onComplete();\n }\n }\n\n // bind callback\n items.forEach( function( item ) {\n item.once( eventName, tick );\n });\n};\n\n/**\n * emits events via EvEmitter and jQuery events\n * @param {String} type - name of event\n * @param {Event} event - original event\n * @param {Array} args - extra arguments\n */\nproto.dispatchEvent = function( type, event, args ) {\n // add original event to arguments\n var emitArgs = event ? [ event ].concat( args ) : args;\n this.emitEvent( type, emitArgs );\n\n if ( jQuery ) {\n // set this.$element\n this.$element = this.$element || jQuery( this.element );\n if ( event ) {\n // create jQuery event\n var $event = jQuery.Event( event );\n $event.type = type;\n this.$element.trigger( $event, args );\n } else {\n // just trigger with type if no event available\n this.$element.trigger( type, args );\n }\n }\n};\n\n// -------------------------- ignore & stamps -------------------------- //\n\n\n/**\n * keep item in collection, but do not lay it out\n * ignored items do not get skipped in layout\n * @param {Element} elem\n */\nproto.ignore = function( elem ) {\n var item = this.getItem( elem );\n if ( item ) {\n item.isIgnored = true;\n }\n};\n\n/**\n * return item to layout collection\n * @param {Element} elem\n */\nproto.unignore = function( elem ) {\n var item = this.getItem( elem );\n if ( item ) {\n delete item.isIgnored;\n }\n};\n\n/**\n * adds elements to stamps\n * @param {NodeList, Array, Element, or String} elems\n */\nproto.stamp = function( elems ) {\n elems = this._find( elems );\n if ( !elems ) {\n return;\n }\n\n this.stamps = this.stamps.concat( elems );\n // ignore\n elems.forEach( this.ignore, this );\n};\n\n/**\n * removes elements to stamps\n * @param {NodeList, Array, or Element} elems\n */\nproto.unstamp = function( elems ) {\n elems = this._find( elems );\n if ( !elems ){\n return;\n }\n\n elems.forEach( function( elem ) {\n // filter out removed stamp elements\n utils.removeFrom( this.stamps, elem );\n this.unignore( elem );\n }, this );\n};\n\n/**\n * finds child elements\n * @param {NodeList, Array, Element, or String} elems\n * @returns {Array} elems\n */\nproto._find = function( elems ) {\n if ( !elems ) {\n return;\n }\n // if string, use argument as selector string\n if ( typeof elems == 'string' ) {\n elems = this.element.querySelectorAll( elems );\n }\n elems = utils.makeArray( elems );\n return elems;\n};\n\nproto._manageStamps = function() {\n if ( !this.stamps || !this.stamps.length ) {\n return;\n }\n\n this._getBoundingRect();\n\n this.stamps.forEach( this._manageStamp, this );\n};\n\n// update boundingLeft / Top\nproto._getBoundingRect = function() {\n // get bounding rect for container element\n var boundingRect = this.element.getBoundingClientRect();\n var size = this.size;\n this._boundingRect = {\n left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,\n top: boundingRect.top + size.paddingTop + size.borderTopWidth,\n right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),\n bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )\n };\n};\n\n/**\n * @param {Element} stamp\n**/\nproto._manageStamp = noop;\n\n/**\n * get x/y position of element relative to container element\n * @param {Element} elem\n * @returns {Object} offset - has left, top, right, bottom\n */\nproto._getElementOffset = function( elem ) {\n var boundingRect = elem.getBoundingClientRect();\n var thisRect = this._boundingRect;\n var size = getSize( elem );\n var offset = {\n left: boundingRect.left - thisRect.left - size.marginLeft,\n top: boundingRect.top - thisRect.top - size.marginTop,\n right: thisRect.right - boundingRect.right - size.marginRight,\n bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom\n };\n return offset;\n};\n\n// -------------------------- resize -------------------------- //\n\n// enable event handlers for listeners\n// i.e. resize -> onresize\nproto.handleEvent = utils.handleEvent;\n\n/**\n * Bind layout to window resizing\n */\nproto.bindResize = function() {\n window.addEventListener( 'resize', this );\n this.isResizeBound = true;\n};\n\n/**\n * Unbind layout to window resizing\n */\nproto.unbindResize = function() {\n window.removeEventListener( 'resize', this );\n this.isResizeBound = false;\n};\n\nproto.onresize = function() {\n this.resize();\n};\n\nutils.debounceMethod( Outlayer, 'onresize', 100 );\n\nproto.resize = function() {\n // don't trigger if size did not change\n // or if resize was unbound. See #9\n if ( !this.isResizeBound || !this.needsResizeLayout() ) {\n return;\n }\n\n this.layout();\n};\n\n/**\n * check if layout is needed post layout\n * @returns Boolean\n */\nproto.needsResizeLayout = function() {\n var size = getSize( this.element );\n // check that this.size and size are there\n // IE8 triggers resize on body size change, so they might not be\n var hasSizes = this.size && size;\n return hasSizes && size.innerWidth !== this.size.innerWidth;\n};\n\n// -------------------------- methods -------------------------- //\n\n/**\n * add items to Outlayer instance\n * @param {Array or NodeList or Element} elems\n * @returns {Array} items - Outlayer.Items\n**/\nproto.addItems = function( elems ) {\n var items = this._itemize( elems );\n // add items to collection\n if ( items.length ) {\n this.items = this.items.concat( items );\n }\n return items;\n};\n\n/**\n * Layout newly-appended item elements\n * @param {Array or NodeList or Element} elems\n */\nproto.appended = function( elems ) {\n var items = this.addItems( elems );\n if ( !items.length ) {\n return;\n }\n // layout and reveal just the new items\n this.layoutItems( items, true );\n this.reveal( items );\n};\n\n/**\n * Layout prepended elements\n * @param {Array or NodeList or Element} elems\n */\nproto.prepended = function( elems ) {\n var items = this._itemize( elems );\n if ( !items.length ) {\n return;\n }\n // add items to beginning of collection\n var previousItems = this.items.slice(0);\n this.items = items.concat( previousItems );\n // start new layout\n this._resetLayout();\n this._manageStamps();\n // layout new stuff without transition\n this.layoutItems( items, true );\n this.reveal( items );\n // layout previous items\n this.layoutItems( previousItems );\n};\n\n/**\n * reveal a collection of items\n * @param {Array of Outlayer.Items} items\n */\nproto.reveal = function( items ) {\n this._emitCompleteOnItems( 'reveal', items );\n if ( !items || !items.length ) {\n return;\n }\n var stagger = this.updateStagger();\n items.forEach( function( item, i ) {\n item.stagger( i * stagger );\n item.reveal();\n });\n};\n\n/**\n * hide a collection of items\n * @param {Array of Outlayer.Items} items\n */\nproto.hide = function( items ) {\n this._emitCompleteOnItems( 'hide', items );\n if ( !items || !items.length ) {\n return;\n }\n var stagger = this.updateStagger();\n items.forEach( function( item, i ) {\n item.stagger( i * stagger );\n item.hide();\n });\n};\n\n/**\n * reveal item elements\n * @param {Array}, {Element}, {NodeList} items\n */\nproto.revealItemElements = function( elems ) {\n var items = this.getItems( elems );\n this.reveal( items );\n};\n\n/**\n * hide item elements\n * @param {Array}, {Element}, {NodeList} items\n */\nproto.hideItemElements = function( elems ) {\n var items = this.getItems( elems );\n this.hide( items );\n};\n\n/**\n * get Outlayer.Item, given an Element\n * @param {Element} elem\n * @param {Function} callback\n * @returns {Outlayer.Item} item\n */\nproto.getItem = function( elem ) {\n // loop through items to get the one that matches\n for ( var i=0; i < this.items.length; i++ ) {\n var item = this.items[i];\n if ( item.element == elem ) {\n // return item\n return item;\n }\n }\n};\n\n/**\n * get collection of Outlayer.Items, given Elements\n * @param {Array} elems\n * @returns {Array} items - Outlayer.Items\n */\nproto.getItems = function( elems ) {\n elems = utils.makeArray( elems );\n var items = [];\n elems.forEach( function( elem ) {\n var item = this.getItem( elem );\n if ( item ) {\n items.push( item );\n }\n }, this );\n\n return items;\n};\n\n/**\n * remove element(s) from instance and DOM\n * @param {Array or NodeList or Element} elems\n */\nproto.remove = function( elems ) {\n var removeItems = this.getItems( elems );\n\n this._emitCompleteOnItems( 'remove', removeItems );\n\n // bail if no items to remove\n if ( !removeItems || !removeItems.length ) {\n return;\n }\n\n removeItems.forEach( function( item ) {\n item.remove();\n // remove item from collection\n utils.removeFrom( this.items, item );\n }, this );\n};\n\n// ----- destroy ----- //\n\n// remove and disable Outlayer instance\nproto.destroy = function() {\n // clean up dynamic styles\n var style = this.element.style;\n style.height = '';\n style.position = '';\n style.width = '';\n // destroy items\n this.items.forEach( function( item ) {\n item.destroy();\n });\n\n this.unbindResize();\n\n var id = this.element.outlayerGUID;\n delete instances[ id ]; // remove reference to instance by id\n delete this.element.outlayerGUID;\n // remove data for jQuery\n if ( jQuery ) {\n jQuery.removeData( this.element, this.constructor.namespace );\n }\n\n};\n\n// -------------------------- data -------------------------- //\n\n/**\n * get Outlayer instance from element\n * @param {Element} elem\n * @returns {Outlayer}\n */\nOutlayer.data = function( elem ) {\n elem = utils.getQueryElement( elem );\n var id = elem && elem.outlayerGUID;\n return id && instances[ id ];\n};\n\n\n// -------------------------- create Outlayer class -------------------------- //\n\n/**\n * create a layout class\n * @param {String} namespace\n */\nOutlayer.create = function( namespace, options ) {\n // sub-class Outlayer\n var Layout = subclass( Outlayer );\n // apply new options and compatOptions\n Layout.defaults = utils.extend( {}, Outlayer.defaults );\n utils.extend( Layout.defaults, options );\n Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions );\n\n Layout.namespace = namespace;\n\n Layout.data = Outlayer.data;\n\n // sub-class Item\n Layout.Item = subclass( Item );\n\n // -------------------------- declarative -------------------------- //\n\n utils.htmlInit( Layout, namespace );\n\n // -------------------------- jQuery bridge -------------------------- //\n\n // make into jQuery plugin\n if ( jQuery && jQuery.bridget ) {\n jQuery.bridget( namespace, Layout );\n }\n\n return Layout;\n};\n\nfunction subclass( Parent ) {\n function SubClass() {\n Parent.apply( this, arguments );\n }\n\n SubClass.prototype = Object.create( Parent.prototype );\n SubClass.prototype.constructor = SubClass;\n\n return SubClass;\n}\n\n// ----- helpers ----- //\n\n// how many milliseconds are in each unit\nvar msUnits = {\n ms: 1,\n s: 1000\n};\n\n// munge time-like parameter into millisecond number\n// '0.4s' -> 40\nfunction getMilliseconds( time ) {\n if ( typeof time == 'number' ) {\n return time;\n }\n var matches = time.match( /(^\\d*\\.?\\d*)(\\w*)/ );\n var num = matches && matches[1];\n var unit = matches && matches[2];\n if ( !num.length ) {\n return 0;\n }\n num = parseFloat( num );\n var mult = msUnits[ unit ] || 1;\n return num * mult;\n}\n\n// ----- fin ----- //\n\n// back in global\nOutlayer.Item = Item;\n\nreturn Outlayer;\n\n}));\n\n/**\n * Isotope Item\n**/\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( true ) {\n // AMD\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n __WEBPACK_LOCAL_MODULE_6__\n ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_LOCAL_MODULE_7__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('outlayer')\n );\n } else {\n // browser global\n window.Isotope = window.Isotope || {};\n window.Isotope.Item = factory(\n window.Outlayer\n );\n }\n\n}( window, function factory( Outlayer ) {\n'use strict';\n\n// -------------------------- Item -------------------------- //\n\n// sub-class Outlayer Item\nfunction Item() {\n Outlayer.Item.apply( this, arguments );\n}\n\nvar proto = Item.prototype = Object.create( Outlayer.Item.prototype );\n\nvar _create = proto._create;\nproto._create = function() {\n // assign id, used for original-order sorting\n this.id = this.layout.itemGUID++;\n _create.call( this );\n this.sortData = {};\n};\n\nproto.updateSortData = function() {\n if ( this.isIgnored ) {\n return;\n }\n // default sorters\n this.sortData.id = this.id;\n // for backward compatibility\n this.sortData['original-order'] = this.id;\n this.sortData.random = Math.random();\n // go thru getSortData obj and apply the sorters\n var getSortData = this.layout.options.getSortData;\n var sorters = this.layout._sorters;\n for ( var key in getSortData ) {\n var sorter = sorters[ key ];\n this.sortData[ key ] = sorter( this.element, this );\n }\n};\n\nvar _destroy = proto.destroy;\nproto.destroy = function() {\n // call super\n _destroy.apply( this, arguments );\n // reset display, #741\n this.css({\n display: ''\n });\n};\n\nreturn Item;\n\n}));\n\n/**\n * Isotope LayoutMode\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( true ) {\n // AMD\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n __WEBPACK_LOCAL_MODULE_2__,\n __WEBPACK_LOCAL_MODULE_6__\n ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_LOCAL_MODULE_8__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('get-size'),\n require('outlayer')\n );\n } else {\n // browser global\n window.Isotope = window.Isotope || {};\n window.Isotope.LayoutMode = factory(\n window.getSize,\n window.Outlayer\n );\n }\n\n}( window, function factory( getSize, Outlayer ) {\n 'use strict';\n\n // layout mode class\n function LayoutMode( isotope ) {\n this.isotope = isotope;\n // link properties\n if ( isotope ) {\n this.options = isotope.options[ this.namespace ];\n this.element = isotope.element;\n this.items = isotope.filteredItems;\n this.size = isotope.size;\n }\n }\n\n var proto = LayoutMode.prototype;\n\n /**\n * some methods should just defer to default Outlayer method\n * and reference the Isotope instance as `this`\n **/\n var facadeMethods = [\n '_resetLayout',\n '_getItemLayoutPosition',\n '_manageStamp',\n '_getContainerSize',\n '_getElementOffset',\n 'needsResizeLayout',\n '_getOption'\n ];\n\n facadeMethods.forEach( function( methodName ) {\n proto[ methodName ] = function() {\n return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );\n };\n });\n\n // ----- ----- //\n\n // for horizontal layout modes, check vertical size\n proto.needsVerticalResizeLayout = function() {\n // don't trigger if size did not change\n var size = getSize( this.isotope.element );\n // check that this.size and size are there\n // IE8 triggers resize on body size change, so they might not be\n var hasSizes = this.isotope.size && size;\n return hasSizes && size.innerHeight != this.isotope.size.innerHeight;\n };\n\n // ----- measurements ----- //\n\n proto._getMeasurement = function() {\n this.isotope._getMeasurement.apply( this, arguments );\n };\n\n proto.getColumnWidth = function() {\n this.getSegmentSize( 'column', 'Width' );\n };\n\n proto.getRowHeight = function() {\n this.getSegmentSize( 'row', 'Height' );\n };\n\n /**\n * get columnWidth or rowHeight\n * segment: 'column' or 'row'\n * size 'Width' or 'Height'\n **/\n proto.getSegmentSize = function( segment, size ) {\n var segmentName = segment + size;\n var outerSize = 'outer' + size;\n // columnWidth / outerWidth // rowHeight / outerHeight\n this._getMeasurement( segmentName, outerSize );\n // got rowHeight or columnWidth, we can chill\n if ( this[ segmentName ] ) {\n return;\n }\n // fall back to item of first element\n var firstItemSize = this.getFirstItemSize();\n this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||\n // or size of container\n this.isotope.size[ 'inner' + size ];\n };\n\n proto.getFirstItemSize = function() {\n var firstItem = this.isotope.filteredItems[0];\n return firstItem && firstItem.element && getSize( firstItem.element );\n };\n\n // ----- methods that should reference isotope ----- //\n\n proto.layout = function() {\n this.isotope.layout.apply( this.isotope, arguments );\n };\n\n proto.getSize = function() {\n this.isotope.getSize();\n this.size = this.isotope.size;\n };\n\n // -------------------------- create -------------------------- //\n\n LayoutMode.modes = {};\n\n LayoutMode.create = function( namespace, options ) {\n\n function Mode() {\n LayoutMode.apply( this, arguments );\n }\n\n Mode.prototype = Object.create( proto );\n Mode.prototype.constructor = Mode;\n\n // default options\n if ( options ) {\n Mode.options = options;\n }\n\n Mode.prototype.namespace = namespace;\n // register in Isotope\n LayoutMode.modes[ namespace ] = Mode;\n\n return Mode;\n };\n\n return LayoutMode;\n\n}));\n\n/*!\n * Masonry v4.2.0\n * Cascading grid layout library\n * http://masonry.desandro.com\n * MIT License\n * by David DeSandro\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( true ) {\n // AMD\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n __WEBPACK_LOCAL_MODULE_6__,\n __WEBPACK_LOCAL_MODULE_2__\n ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_LOCAL_MODULE_9__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('outlayer'),\n require('get-size')\n );\n } else {\n // browser global\n window.Masonry = factory(\n window.Outlayer,\n window.getSize\n );\n }\n\n}( window, function factory( Outlayer, getSize ) {\n\n\n\n// -------------------------- masonryDefinition -------------------------- //\n\n // create an Outlayer layout class\n var Masonry = Outlayer.create('masonry');\n // isFitWidth -> fitWidth\n Masonry.compatOptions.fitWidth = 'isFitWidth';\n\n var proto = Masonry.prototype;\n\n proto._resetLayout = function() {\n this.getSize();\n this._getMeasurement( 'columnWidth', 'outerWidth' );\n this._getMeasurement( 'gutter', 'outerWidth' );\n this.measureColumns();\n\n // reset column Y\n this.colYs = [];\n for ( var i=0; i < this.cols; i++ ) {\n this.colYs.push( 0 );\n }\n\n this.maxY = 0;\n this.horizontalColIndex = 0;\n };\n\n proto.measureColumns = function() {\n this.getContainerWidth();\n // if columnWidth is 0, default to outerWidth of first item\n if ( !this.columnWidth ) {\n var firstItem = this.items[0];\n var firstItemElem = firstItem && firstItem.element;\n // columnWidth fall back to item of first element\n this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||\n // if first elem has no width, default to size of container\n this.containerWidth;\n }\n\n var columnWidth = this.columnWidth += this.gutter;\n\n // calculate columns\n var containerWidth = this.containerWidth + this.gutter;\n var cols = containerWidth / columnWidth;\n // fix rounding errors, typically with gutters\n var excess = columnWidth - containerWidth % columnWidth;\n // if overshoot is less than a pixel, round up, otherwise floor it\n var mathMethod = excess && excess < 1 ? 'round' : 'floor';\n cols = Math[ mathMethod ]( cols );\n this.cols = Math.max( cols, 1 );\n };\n\n proto.getContainerWidth = function() {\n // container is parent if fit width\n var isFitWidth = this._getOption('fitWidth');\n var container = isFitWidth ? this.element.parentNode : this.element;\n // check that this.size and size are there\n // IE8 triggers resize on body size change, so they might not be\n var size = getSize( container );\n this.containerWidth = size && size.innerWidth;\n };\n\n proto._getItemLayoutPosition = function( item ) {\n item.getSize();\n // how many columns does this brick span\n var remainder = item.size.outerWidth % this.columnWidth;\n var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';\n // round if off by 1 pixel, otherwise use ceil\n var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );\n colSpan = Math.min( colSpan, this.cols );\n // use horizontal or top column position\n var colPosMethod = this.options.horizontalOrder ?\n '_getHorizontalColPosition' : '_getTopColPosition';\n var colPosition = this[ colPosMethod ]( colSpan, item );\n // position the brick\n var position = {\n x: this.columnWidth * colPosition.col,\n y: colPosition.y\n };\n // apply setHeight to necessary columns\n var setHeight = colPosition.y + item.size.outerHeight;\n var setMax = colSpan + colPosition.col;\n for ( var i = colPosition.col; i < setMax; i++ ) {\n this.colYs[i] = setHeight;\n }\n\n return position;\n };\n\n proto._getTopColPosition = function( colSpan ) {\n var colGroup = this._getTopColGroup( colSpan );\n // get the minimum Y value from the columns\n var minimumY = Math.min.apply( Math, colGroup );\n\n return {\n col: colGroup.indexOf( minimumY ),\n y: minimumY,\n };\n };\n\n /**\n * @param {Number} colSpan - number of columns the element spans\n * @returns {Array} colGroup\n */\n proto._getTopColGroup = function( colSpan ) {\n if ( colSpan < 2 ) {\n // if brick spans only one column, use all the column Ys\n return this.colYs;\n }\n\n var colGroup = [];\n // how many different places could this brick fit horizontally\n var groupCount = this.cols + 1 - colSpan;\n // for each group potential horizontal position\n for ( var i = 0; i < groupCount; i++ ) {\n colGroup[i] = this._getColGroupY( i, colSpan );\n }\n return colGroup;\n };\n\n proto._getColGroupY = function( col, colSpan ) {\n if ( colSpan < 2 ) {\n return this.colYs[ col ];\n }\n // make an array of colY values for that one group\n var groupColYs = this.colYs.slice( col, col + colSpan );\n // and get the max value of the array\n return Math.max.apply( Math, groupColYs );\n };\n\n // get column position based on horizontal index. #873\n proto._getHorizontalColPosition = function( colSpan, item ) {\n var col = this.horizontalColIndex % this.cols;\n var isOver = colSpan > 1 && col + colSpan > this.cols;\n // shift to next row if item can't fit on current row\n col = isOver ? 0 : col;\n // don't let zero-size items take up space\n var hasSize = item.size.outerWidth && item.size.outerHeight;\n this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;\n\n return {\n col: col,\n y: this._getColGroupY( col, colSpan ),\n };\n };\n\n proto._manageStamp = function( stamp ) {\n var stampSize = getSize( stamp );\n var offset = this._getElementOffset( stamp );\n // get the columns that this stamp affects\n var isOriginLeft = this._getOption('originLeft');\n var firstX = isOriginLeft ? offset.left : offset.right;\n var lastX = firstX + stampSize.outerWidth;\n var firstCol = Math.floor( firstX / this.columnWidth );\n firstCol = Math.max( 0, firstCol );\n var lastCol = Math.floor( lastX / this.columnWidth );\n // lastCol should not go over if multiple of columnWidth #425\n lastCol -= lastX % this.columnWidth ? 0 : 1;\n lastCol = Math.min( this.cols - 1, lastCol );\n // set colYs to bottom of the stamp\n\n var isOriginTop = this._getOption('originTop');\n var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +\n stampSize.outerHeight;\n for ( var i = firstCol; i <= lastCol; i++ ) {\n this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );\n }\n };\n\n proto._getContainerSize = function() {\n this.maxY = Math.max.apply( Math, this.colYs );\n var size = {\n height: this.maxY\n };\n\n if ( this._getOption('fitWidth') ) {\n size.width = this._getContainerFitWidth();\n }\n\n return size;\n };\n\n proto._getContainerFitWidth = function() {\n var unusedCols = 0;\n // count unused columns\n var i = this.cols;\n while ( --i ) {\n if ( this.colYs[i] !== 0 ) {\n break;\n }\n unusedCols++;\n }\n // fit container to columns that have been used\n return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;\n };\n\n proto.needsResizeLayout = function() {\n var previousWidth = this.containerWidth;\n this.getContainerWidth();\n return previousWidth != this.containerWidth;\n };\n\n return Masonry;\n\n}));\n\n/*!\n * Masonry layout mode\n * sub-classes Masonry\n * http://masonry.desandro.com\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( true ) {\n // AMD\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n __WEBPACK_LOCAL_MODULE_8__,\n __WEBPACK_LOCAL_MODULE_9__\n ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_LOCAL_MODULE_10__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('../layout-mode'),\n require('masonry-layout')\n );\n } else {\n // browser global\n factory(\n window.Isotope.LayoutMode,\n window.Masonry\n );\n }\n\n}( window, function factory( LayoutMode, Masonry ) {\n'use strict';\n\n// -------------------------- masonryDefinition -------------------------- //\n\n // create an Outlayer layout class\n var MasonryMode = LayoutMode.create('masonry');\n\n var proto = MasonryMode.prototype;\n\n var keepModeMethods = {\n _getElementOffset: true,\n layout: true,\n _getMeasurement: true\n };\n\n // inherit Masonry prototype\n for ( var method in Masonry.prototype ) {\n // do not inherit mode methods\n if ( !keepModeMethods[ method ] ) {\n proto[ method ] = Masonry.prototype[ method ];\n }\n }\n\n var measureColumns = proto.measureColumns;\n proto.measureColumns = function() {\n // set items, used if measuring first item\n this.items = this.isotope.filteredItems;\n measureColumns.call( this );\n };\n\n // point to mode options for fitWidth\n var _getOption = proto._getOption;\n proto._getOption = function( option ) {\n if ( option == 'fitWidth' ) {\n return this.options.isFitWidth !== undefined ?\n this.options.isFitWidth : this.options.fitWidth;\n }\n return _getOption.apply( this.isotope, arguments );\n };\n\n return MasonryMode;\n\n}));\n\n/**\n * fitRows layout mode\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( true ) {\n // AMD\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n __WEBPACK_LOCAL_MODULE_8__\n ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_LOCAL_MODULE_11__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__));\n } else if ( typeof exports == 'object' ) {\n // CommonJS\n module.exports = factory(\n require('../layout-mode')\n );\n } else {\n // browser global\n factory(\n window.Isotope.LayoutMode\n );\n }\n\n}( window, function factory( LayoutMode ) {\n'use strict';\n\nvar FitRows = LayoutMode.create('fitRows');\n\nvar proto = FitRows.prototype;\n\nproto._resetLayout = function() {\n this.x = 0;\n this.y = 0;\n this.maxY = 0;\n this._getMeasurement( 'gutter', 'outerWidth' );\n};\n\nproto._getItemLayoutPosition = function( item ) {\n item.getSize();\n\n var itemWidth = item.size.outerWidth + this.gutter;\n // if this element cannot fit in the current row\n var containerWidth = this.isotope.size.innerWidth + this.gutter;\n if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {\n this.x = 0;\n this.y = this.maxY;\n }\n\n var position = {\n x: this.x,\n y: this.y\n };\n\n this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );\n this.x += itemWidth;\n\n return position;\n};\n\nproto._getContainerSize = function() {\n return { height: this.maxY };\n};\n\nreturn FitRows;\n\n}));\n\n/**\n * vertical layout mode\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( true ) {\n // AMD\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n __WEBPACK_LOCAL_MODULE_8__\n ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_LOCAL_MODULE_12__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('../layout-mode')\n );\n } else {\n // browser global\n factory(\n window.Isotope.LayoutMode\n );\n }\n\n}( window, function factory( LayoutMode ) {\n'use strict';\n\nvar Vertical = LayoutMode.create( 'vertical', {\n horizontalAlignment: 0\n});\n\nvar proto = Vertical.prototype;\n\nproto._resetLayout = function() {\n this.y = 0;\n};\n\nproto._getItemLayoutPosition = function( item ) {\n item.getSize();\n var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *\n this.options.horizontalAlignment;\n var y = this.y;\n this.y += item.size.outerHeight;\n return { x: x, y: y };\n};\n\nproto._getContainerSize = function() {\n return { height: this.y };\n};\n\nreturn Vertical;\n\n}));\n\n/*!\n * Isotope v3.0.4\n *\n * Licensed GPLv3 for open source use\n * or Isotope Commercial License for commercial use\n *\n * http://isotope.metafizzy.co\n * Copyright 2017 Metafizzy\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( true ) {\n // AMD\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n __WEBPACK_LOCAL_MODULE_6__,\n __WEBPACK_LOCAL_MODULE_2__,\n __WEBPACK_LOCAL_MODULE_3__,\n __WEBPACK_LOCAL_MODULE_4__,\n __WEBPACK_LOCAL_MODULE_7__,\n __WEBPACK_LOCAL_MODULE_8__,\n // include default layout modes\n __WEBPACK_LOCAL_MODULE_10__,\n __WEBPACK_LOCAL_MODULE_11__,\n __WEBPACK_LOCAL_MODULE_12__\n ], __WEBPACK_AMD_DEFINE_RESULT__ = function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {\n return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );\n }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n window,\n require('outlayer'),\n require('get-size'),\n require('desandro-matches-selector'),\n require('fizzy-ui-utils'),\n require('isotope/js/item'),\n require('isotope/js/layout-mode'),\n // include default layout modes\n require('isotope/js/layout-modes/masonry'),\n require('isotope/js/layout-modes/fit-rows'),\n require('isotope/js/layout-modes/vertical')\n );\n } else {\n // browser global\n window.Isotope = factory(\n window,\n window.Outlayer,\n window.getSize,\n window.matchesSelector,\n window.fizzyUIUtils,\n window.Isotope.Item,\n window.Isotope.LayoutMode\n );\n }\n\n}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,\n Item, LayoutMode ) {\n\n\n\n// -------------------------- vars -------------------------- //\n\nvar jQuery = window.jQuery;\n\n// -------------------------- helpers -------------------------- //\n\nvar trim = String.prototype.trim ?\n function( str ) {\n return str.trim();\n } :\n function( str ) {\n return str.replace( /^\\s+|\\s+$/g, '' );\n };\n\n// -------------------------- isotopeDefinition -------------------------- //\n\n // create an Outlayer layout class\n var Isotope = Outlayer.create( 'isotope', {\n layoutMode: 'masonry',\n isJQueryFiltering: true,\n sortAscending: true\n });\n\n Isotope.Item = Item;\n Isotope.LayoutMode = LayoutMode;\n\n var proto = Isotope.prototype;\n\n proto._create = function() {\n this.itemGUID = 0;\n // functions that sort items\n this._sorters = {};\n this._getSorters();\n // call super\n Outlayer.prototype._create.call( this );\n\n // create layout modes\n this.modes = {};\n // start filteredItems with all items\n this.filteredItems = this.items;\n // keep of track of sortBys\n this.sortHistory = [ 'original-order' ];\n // create from registered layout modes\n for ( var name in LayoutMode.modes ) {\n this._initLayoutMode( name );\n }\n };\n\n proto.reloadItems = function() {\n // reset item ID counter\n this.itemGUID = 0;\n // call super\n Outlayer.prototype.reloadItems.call( this );\n };\n\n proto._itemize = function() {\n var items = Outlayer.prototype._itemize.apply( this, arguments );\n // assign ID for original-order\n for ( var i=0; i < items.length; i++ ) {\n var item = items[i];\n item.id = this.itemGUID++;\n }\n this._updateItemsSortData( items );\n return items;\n };\n\n\n // -------------------------- layout -------------------------- //\n\n proto._initLayoutMode = function( name ) {\n var Mode = LayoutMode.modes[ name ];\n // set mode options\n // HACK extend initial options, back-fill in default options\n var initialOpts = this.options[ name ] || {};\n this.options[ name ] = Mode.options ?\n utils.extend( Mode.options, initialOpts ) : initialOpts;\n // init layout mode instance\n this.modes[ name ] = new Mode( this );\n };\n\n\n proto.layout = function() {\n // if first time doing layout, do all magic\n if ( !this._isLayoutInited && this._getOption('initLayout') ) {\n this.arrange();\n return;\n }\n this._layout();\n };\n\n // private method to be used in layout() & magic()\n proto._layout = function() {\n // don't animate first layout\n var isInstant = this._getIsInstant();\n // layout flow\n this._resetLayout();\n this._manageStamps();\n this.layoutItems( this.filteredItems, isInstant );\n\n // flag for initalized\n this._isLayoutInited = true;\n };\n\n // filter + sort + layout\n proto.arrange = function( opts ) {\n // set any options pass\n this.option( opts );\n this._getIsInstant();\n // filter, sort, and layout\n\n // filter\n var filtered = this._filter( this.items );\n this.filteredItems = filtered.matches;\n\n this._bindArrangeComplete();\n\n if ( this._isInstant ) {\n this._noTransition( this._hideReveal, [ filtered ] );\n } else {\n this._hideReveal( filtered );\n }\n\n this._sort();\n this._layout();\n };\n // alias to _init for main plugin method\n proto._init = proto.arrange;\n\n proto._hideReveal = function( filtered ) {\n this.reveal( filtered.needReveal );\n this.hide( filtered.needHide );\n };\n\n // HACK\n // Don't animate/transition first layout\n // Or don't animate/transition other layouts\n proto._getIsInstant = function() {\n var isLayoutInstant = this._getOption('layoutInstant');\n var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :\n !this._isLayoutInited;\n this._isInstant = isInstant;\n return isInstant;\n };\n\n // listen for layoutComplete, hideComplete and revealComplete\n // to trigger arrangeComplete\n proto._bindArrangeComplete = function() {\n // listen for 3 events to trigger arrangeComplete\n var isLayoutComplete, isHideComplete, isRevealComplete;\n var _this = this;\n function arrangeParallelCallback() {\n if ( isLayoutComplete && isHideComplete && isRevealComplete ) {\n _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );\n }\n }\n this.once( 'layoutComplete', function() {\n isLayoutComplete = true;\n arrangeParallelCallback();\n });\n this.once( 'hideComplete', function() {\n isHideComplete = true;\n arrangeParallelCallback();\n });\n this.once( 'revealComplete', function() {\n isRevealComplete = true;\n arrangeParallelCallback();\n });\n };\n\n // -------------------------- filter -------------------------- //\n\n proto._filter = function( items ) {\n var filter = this.options.filter;\n filter = filter || '*';\n var matches = [];\n var hiddenMatched = [];\n var visibleUnmatched = [];\n\n var test = this._getFilterTest( filter );\n\n // test each item\n for ( var i=0; i < items.length; i++ ) {\n var item = items[i];\n if ( item.isIgnored ) {\n continue;\n }\n // add item to either matched or unmatched group\n var isMatched = test( item );\n // item.isFilterMatched = isMatched;\n // add to matches if its a match\n if ( isMatched ) {\n matches.push( item );\n }\n // add to additional group if item needs to be hidden or revealed\n if ( isMatched && item.isHidden ) {\n hiddenMatched.push( item );\n } else if ( !isMatched && !item.isHidden ) {\n visibleUnmatched.push( item );\n }\n }\n\n // return collections of items to be manipulated\n return {\n matches: matches,\n needReveal: hiddenMatched,\n needHide: visibleUnmatched\n };\n };\n\n // get a jQuery, function, or a matchesSelector test given the filter\n proto._getFilterTest = function( filter ) {\n if ( jQuery && this.options.isJQueryFiltering ) {\n // use jQuery\n return function( item ) {\n return jQuery( item.element ).is( filter );\n };\n }\n if ( typeof filter == 'function' ) {\n // use filter as function\n return function( item ) {\n return filter( item.element );\n };\n }\n // default, use filter as selector string\n return function( item ) {\n return matchesSelector( item.element, filter );\n };\n };\n\n // -------------------------- sorting -------------------------- //\n\n /**\n * @params {Array} elems\n * @public\n */\n proto.updateSortData = function( elems ) {\n // get items\n var items;\n if ( elems ) {\n elems = utils.makeArray( elems );\n items = this.getItems( elems );\n } else {\n // update all items if no elems provided\n items = this.items;\n }\n\n this._getSorters();\n this._updateItemsSortData( items );\n };\n\n proto._getSorters = function() {\n var getSortData = this.options.getSortData;\n for ( var key in getSortData ) {\n var sorter = getSortData[ key ];\n this._sorters[ key ] = mungeSorter( sorter );\n }\n };\n\n /**\n * @params {Array} items - of Isotope.Items\n * @private\n */\n proto._updateItemsSortData = function( items ) {\n // do not update if no items\n var len = items && items.length;\n\n for ( var i=0; len && i < len; i++ ) {\n var item = items[i];\n item.updateSortData();\n }\n };\n\n // ----- munge sorter ----- //\n\n // encapsulate this, as we just need mungeSorter\n // other functions in here are just for munging\n var mungeSorter = ( function() {\n // add a magic layer to sorters for convienent shorthands\n // `.foo-bar` will use the text of .foo-bar querySelector\n // `[foo-bar]` will use attribute\n // you can also add parser\n // `.foo-bar parseInt` will parse that as a number\n function mungeSorter( sorter ) {\n // if not a string, return function or whatever it is\n if ( typeof sorter != 'string' ) {\n return sorter;\n }\n // parse the sorter string\n var args = trim( sorter ).split(' ');\n var query = args[0];\n // check if query looks like [an-attribute]\n var attrMatch = query.match( /^\\[(.+)\\]$/ );\n var attr = attrMatch && attrMatch[1];\n var getValue = getValueGetter( attr, query );\n // use second argument as a parser\n var parser = Isotope.sortDataParsers[ args[1] ];\n // parse the value, if there was a parser\n sorter = parser ? function( elem ) {\n return elem && parser( getValue( elem ) );\n } :\n // otherwise just return value\n function( elem ) {\n return elem && getValue( elem );\n };\n\n return sorter;\n }\n\n // get an attribute getter, or get text of the querySelector\n function getValueGetter( attr, query ) {\n // if query looks like [foo-bar], get attribute\n if ( attr ) {\n return function getAttribute( elem ) {\n return elem.getAttribute( attr );\n };\n }\n\n // otherwise, assume its a querySelector, and get its text\n return function getChildText( elem ) {\n var child = elem.querySelector( query );\n return child && child.textContent;\n };\n }\n\n return mungeSorter;\n })();\n\n // parsers used in getSortData shortcut strings\n Isotope.sortDataParsers = {\n 'parseInt': function( val ) {\n return parseInt( val, 10 );\n },\n 'parseFloat': function( val ) {\n return parseFloat( val );\n }\n };\n\n // ----- sort method ----- //\n\n // sort filteredItem order\n proto._sort = function() {\n if ( !this.options.sortBy ) {\n return;\n }\n // keep track of sortBy History\n var sortBys = utils.makeArray( this.options.sortBy );\n if ( !this._getIsSameSortBy( sortBys ) ) {\n // concat all sortBy and sortHistory, add to front, oldest goes in last\n this.sortHistory = sortBys.concat( this.sortHistory );\n }\n // sort magic\n var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending );\n this.filteredItems.sort( itemSorter );\n };\n\n // check if sortBys is same as start of sortHistory\n proto._getIsSameSortBy = function( sortBys ) {\n for ( var i=0; i < sortBys.length; i++ ) {\n if ( sortBys[i] != this.sortHistory[i] ) {\n return false;\n }\n }\n return true;\n };\n\n // returns a function used for sorting\n function getItemSorter( sortBys, sortAsc ) {\n return function sorter( itemA, itemB ) {\n // cycle through all sortKeys\n for ( var i = 0; i < sortBys.length; i++ ) {\n var sortBy = sortBys[i];\n var a = itemA.sortData[ sortBy ];\n var b = itemB.sortData[ sortBy ];\n if ( a > b || a < b ) {\n // if sortAsc is an object, use the value given the sortBy key\n var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;\n var direction = isAscending ? 1 : -1;\n return ( a > b ? 1 : -1 ) * direction;\n }\n }\n return 0;\n };\n }\n\n // -------------------------- methods -------------------------- //\n\n // get layout mode\n proto._mode = function() {\n var layoutMode = this.options.layoutMode;\n var mode = this.modes[ layoutMode ];\n if ( !mode ) {\n // TODO console.error\n throw new Error( 'No layout mode: ' + layoutMode );\n }\n // HACK sync mode's options\n // any options set after init for layout mode need to be synced\n mode.options = this.options[ layoutMode ];\n return mode;\n };\n\n proto._resetLayout = function() {\n // trigger original reset layout\n Outlayer.prototype._resetLayout.call( this );\n this._mode()._resetLayout();\n };\n\n proto._getItemLayoutPosition = function( item ) {\n return this._mode()._getItemLayoutPosition( item );\n };\n\n proto._manageStamp = function( stamp ) {\n this._mode()._manageStamp( stamp );\n };\n\n proto._getContainerSize = function() {\n return this._mode()._getContainerSize();\n };\n\n proto.needsResizeLayout = function() {\n return this._mode().needsResizeLayout();\n };\n\n // -------------------------- adding & removing -------------------------- //\n\n // HEADS UP overwrites default Outlayer appended\n proto.appended = function( elems ) {\n var items = this.addItems( elems );\n if ( !items.length ) {\n return;\n }\n // filter, layout, reveal new items\n var filteredItems = this._filterRevealAdded( items );\n // add to filteredItems\n this.filteredItems = this.filteredItems.concat( filteredItems );\n };\n\n // HEADS UP overwrites default Outlayer prepended\n proto.prepended = function( elems ) {\n var items = this._itemize( elems );\n if ( !items.length ) {\n return;\n }\n // start new layout\n this._resetLayout();\n this._manageStamps();\n // filter, layout, reveal new items\n var filteredItems = this._filterRevealAdded( items );\n // layout previous items\n this.layoutItems( this.filteredItems );\n // add to items and filteredItems\n this.filteredItems = filteredItems.concat( this.filteredItems );\n this.items = items.concat( this.items );\n };\n\n proto._filterRevealAdded = function( items ) {\n var filtered = this._filter( items );\n this.hide( filtered.needHide );\n // reveal all new items\n this.reveal( filtered.matches );\n // layout new items, no transition\n this.layoutItems( filtered.matches, true );\n return filtered.matches;\n };\n\n /**\n * Filter, sort, and layout newly-appended item elements\n * @param {Array or NodeList or Element} elems\n */\n proto.insert = function( elems ) {\n var items = this.addItems( elems );\n if ( !items.length ) {\n return;\n }\n // append item elements\n var i, item;\n var len = items.length;\n for ( i=0; i < len; i++ ) {\n item = items[i];\n this.element.appendChild( item.element );\n }\n // filter new stuff\n var filteredInsertItems = this._filter( items ).matches;\n // set flag\n for ( i=0; i < len; i++ ) {\n items[i].isLayoutInstant = true;\n }\n this.arrange();\n // reset flag\n for ( i=0; i < len; i++ ) {\n delete items[i].isLayoutInstant;\n }\n this.reveal( filteredInsertItems );\n };\n\n var _remove = proto.remove;\n proto.remove = function( elems ) {\n elems = utils.makeArray( elems );\n var removeItems = this.getItems( elems );\n // do regular thing\n _remove.call( this, elems );\n // bail if no items to remove\n var len = removeItems && removeItems.length;\n // remove elems from filteredItems\n for ( var i=0; len && i < len; i++ ) {\n var item = removeItems[i];\n // remove item from collection\n utils.removeFrom( this.filteredItems, item );\n }\n };\n\n proto.shuffle = function() {\n // update random sortData\n for ( var i=0; i < this.items.length; i++ ) {\n var item = this.items[i];\n item.sortData.random = Math.random();\n }\n this.options.sortBy = 'random';\n this._sort();\n this._layout();\n };\n\n /**\n * trigger fn without transition\n * kind of hacky to have this in the first place\n * @param {Function} fn\n * @param {Array} args\n * @returns ret\n * @private\n */\n proto._noTransition = function( fn, args ) {\n // save transitionDuration before disabling\n var transitionDuration = this.options.transitionDuration;\n // disable transition\n this.options.transitionDuration = 0;\n // do it\n var returnValue = fn.apply( this, args );\n // re-enable transition for reveal\n this.options.transitionDuration = transitionDuration;\n return returnValue;\n };\n\n // ----- helper methods ----- //\n\n /**\n * getter method for getting filtered item elements\n * @returns {Array} elems - collection of item elements\n */\n proto.getFilteredItemElements = function() {\n return this.filteredItems.map( function( item ) {\n return item.element;\n });\n };\n\n // ----- ----- //\n\n return Isotope;\n\n}));\n\n\n\n/***/ }),\n\n/***/ \"Gz0TuoFFs6JdDvtR2PYZ\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar matches = __webpack_require__(\"C2mk7N9JzKWlcOYJrkfi\")\n\n/**\n * closest : closest(el, selector)\n * Looks for the closest ancestor of element `el` that matches `selector`.\n * Compare with [$.fn.closest](http://api.jquery.com/closest/).\n *\n * var closest = require('dom101/closest');\n *\n * closest(input, 'label');\n */\n\nfunction closest (el, sel) {\n if (!el) return\n if (matches(el, sel)) {\n return el\n } else {\n return closest(el.parentNode, sel)\n }\n}\n\nmodule.exports = closest\n\n\n/***/ }),\n\n/***/ \"MKJaVdnD9jF7rk6rW6AJ\":\n/***/ (function(module, exports) {\n\n/**\n * on : on(el, event, fn)\n * Adds an event handler.\n *\n * var on = require('dom101/on');\n *\n * on(el, 'click', function () {\n * ...\n * });\n */\n\nfunction on (el, event, handler) {\n if (el.addEventListener) {\n el.addEventListener(event, handler)\n } else {\n el.attachEvent('on' + event, function () {\n handler.call(el)\n })\n }\n}\n\nmodule.exports = on\n\n\n/***/ }),\n\n/***/ \"O7wD3s+p+jjyw5ivWGEg\":\n/***/ (function(module, exports) {\n\n/**\n * each : each(list, fn)\n * Iterates through `list` (an array or an object). This is useful when dealing\n * with NodeLists like `document.querySelectorAll`.\n *\n * var each = require('dom101/each');\n * var qa = require('dom101/query-selector-all');\n *\n * each(qa('.button'), function (el) {\n * addClass('el', 'selected');\n * });\n */\n\nfunction each (list, fn) {\n var i\n var len = list.length\n var idx\n\n if (typeof len === 'number') {\n for (i = 0; i < len; i++) {\n fn(list[i], i)\n }\n } else {\n idx = 0\n for (i in list) {\n if (list.hasOwnProperty(i)) {\n fn(list[i], i, idx++)\n }\n }\n }\n\n return list\n}\n\nmodule.exports = each\n\n\n/***/ }),\n\n/***/ \"XxGrbZud7DE4W4TdQZtc\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nvar _remove = __webpack_require__(\"wYegCzKWCG2ZRJZfGEZa\");\n\nvar _remove2 = _interopRequireDefault(_remove);\n\nvar _removeClass = __webpack_require__(\"bq+j3PCtCSGVXgg8xWPw\");\n\nvar _removeClass2 = _interopRequireDefault(_removeClass);\n\nvar _data = __webpack_require__(\"CjZN/azBHJxH2NsOjfdD\");\n\nvar _dismiss = __webpack_require__(\"2QOxTCxkuzN0PP2kJ2jn\");\n\nvar _preview = __webpack_require__(\"BF4TFfJ+K+wsuHfLZ/S3\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n(0, _onmount2.default)('[data-js-dismissable]', function () {\n var id = (0, _data.getData)(this, 'js-dismissable').id || '';\n\n if ((0, _preview.isPreview)() || (0, _dismiss.isDismissed)(id)) {\n (0, _remove2.default)(this);\n } else {\n (0, _removeClass2.default)(this, '-hide');\n }\n});\n\n/***/ }),\n\n/***/ \"ahJreyGRfWuLMDCl+A3L\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.appendMany = appendMany;\nexports.nextUntil = nextUntil;\nexports.before = before;\nexports.findChildren = findChildren;\nexports.createDiv = createDiv;\n\nvar _matches = __webpack_require__(\"C2mk7N9JzKWlcOYJrkfi\");\n\nvar _matches2 = _interopRequireDefault(_matches);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\n/*\n * Just like jQuery.append\n */\n\nfunction appendMany(el, children) {\n children.forEach(function (child) {\n el.appendChild(child);\n });\n}\n\n/*\n * Just like jQuery.nextUntil\n */\n\nfunction nextUntil(el, selector) {\n var nextEl = el.nextSibling;\n return nextUntilTick(nextEl, selector, []);\n}\n\nfunction nextUntilTick(el, selector, acc) {\n if (!el) return acc;\n\n var isMatch = (0, _matches2.default)(el, selector);\n if (isMatch) return acc;\n\n return nextUntilTick(el.nextSibling, selector, [].concat(_toConsumableArray(acc), [el]));\n}\n\n/*\n * Just like jQuery.before\n */\n\nfunction before(reference, newNode) {\n reference.parentNode.insertBefore(newNode, reference);\n}\n\n/*\n * Like jQuery.children('selector')\n */\n\nfunction findChildren(el, selector) {\n return [].slice.call(el.children).filter(function (child) {\n return (0, _matches2.default)(child, selector);\n });\n}\n\n/**\n * Creates a div\n * @private\n *\n * @example\n *\n * createDiv({ class: 'foo' })\n */\n\nfunction createDiv(props) {\n var d = document.createElement('div');\n Object.keys(props).forEach(function (key) {\n d.setAttribute(key, props[key]);\n });\n return d;\n}\n\n/***/ }),\n\n/***/ \"azEBDvunS5n/qbuQInIF\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _closest = __webpack_require__(\"Gz0TuoFFs6JdDvtR2PYZ\");\n\nvar _closest2 = _interopRequireDefault(_closest);\n\nvar _remove = __webpack_require__(\"wYegCzKWCG2ZRJZfGEZa\");\n\nvar _remove2 = _interopRequireDefault(_remove);\n\nvar _on = __webpack_require__(\"MKJaVdnD9jF7rk6rW6AJ\");\n\nvar _on2 = _interopRequireDefault(_on);\n\nvar _data = __webpack_require__(\"CjZN/azBHJxH2NsOjfdD\");\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nvar _dismiss = __webpack_require__(\"2QOxTCxkuzN0PP2kJ2jn\");\n\nvar Dismiss = _interopRequireWildcard(_dismiss);\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Dismiss button\n */\n\n(0, _onmount2.default)('[data-js-dismiss]', function () {\n var parent = (0, _closest2.default)(this, '[data-js-dismissable]');\n var dismissable = (0, _data.getData)(parent, 'js-dismissable');\n var id = dismissable && dismissable.id || '';\n\n (0, _on2.default)(this, 'click', function (e) {\n Dismiss.setDismissed(id);\n e.preventDefault();\n if (parent) (0, _remove2.default)(parent);\n });\n});\n\n/***/ }),\n\n/***/ \"bq+j3PCtCSGVXgg8xWPw\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar each = __webpack_require__(\"O7wD3s+p+jjyw5ivWGEg\")\n\n/**\n * removeClass : removeClass(el, className)\n * Removes a classname.\n *\n * var removeClass = require('dom101/remove-class');\n *\n * el.className = 'selected active';\n * removeClass(el, 'active');\n *\n * el.className\n * => \"selected\"\n */\n\nfunction removeClass (el, className) {\n if (!className) return\n\n if (Array.isArray(className)) {\n each(className, function (className) {\n removeClass(el, className)\n })\n\n return\n }\n\n if (el.classList) {\n var classNames = className.split(' ').filter(Boolean)\n each(classNames, function (className) {\n el.classList.remove(className)\n })\n } else {\n var expr =\n new RegExp('(^|\\\\b)' + className.split(' ').join('|') + '(\\\\b|$)', 'gi')\n\n el.className = el.className.replace(expr, ' ')\n }\n}\n\nmodule.exports = removeClass\n\n\n/***/ }),\n\n/***/ \"cBdQffYQOU2SCSRXjSUx\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar map = {\n\t\"./anchors.js\": \"lpgA2dewefHNQWX4X3Mh\",\n\t\"./dismiss.js\": \"azEBDvunS5n/qbuQInIF\",\n\t\"./dismissable.js\": \"XxGrbZud7DE4W4TdQZtc\",\n\t\"./disqus.js\": \"BuWMdGeXUEK0GmkN01pU\",\n\t\"./h3-section-list.js\": \"E+dCGfS1pT5WowYv7jpv\",\n\t\"./main-body.js\": \"g3wkw0XZUos0Eo8rU7p6\",\n\t\"./no-preview.js\": \"k6EYej2Qda8Mq9A5Oeqn\",\n\t\"./search-form.js\": \"D3SYMdNAenu80VOO7/Dv\",\n\t\"./search-input.js\": \"zNHHVy5XxvKjnqTgwxy7\",\n\t\"./searchable-header.js\": \"veOabZWTWtixkn1TyITD\",\n\t\"./searchable-item.js\": \"tcev71HWHlq3Ur/sw7Ir\"\n};\nfunction webpackContext(req) {\n\treturn __webpack_require__(webpackContextResolve(req));\n};\nfunction webpackContextResolve(req) {\n\tvar id = map[req];\n\tif(!(id + 1)) // check for number or string\n\t\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n\treturn id;\n};\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"cBdQffYQOU2SCSRXjSUx\";\n\n/***/ }),\n\n/***/ \"cYqQDyTPtD7lV79ovj4Y\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = inject;\nexports.injectEmbed = injectEmbed;\nexports.injectCount = injectCount;\n/**\n * Injects disqus's scripts into the page.\n *\n * @example\n * inject('devhints.disqus.com')\n */\n\nfunction inject(host) {\n injectEmbed(host);\n injectCount(host);\n}\n\nfunction injectEmbed(host) {\n var d = document;\n var s = d.createElement('script');\n s.src = 'https://' + host + '/embed.js';\n s.setAttribute('data-timestamp', +new Date());(d.head || d.body).appendChild(s);\n}\n\nfunction injectCount(host) {\n var d = document;\n var s = d.createElement('script');\n s.src = 'https://' + host + '/count.js';\n s.id = 'dsq-count-scr';\n s.async = true;(d.head || d.body).appendChild(s);\n}\n\n/***/ }),\n\n/***/ \"djrEhtin0g5nRB/RnnLU\":\n/***/ (function(module, exports) {\n\n/**\n * prepend : prepend(el, child)\n * Prepends a `child` into a parent `el`. Compare with `$.fn.prepend`.\n *\n * var prepend = require('dom101/prepend');\n *\n * prepend(el, child);\n */\n\nfunction prepend (el, child) {\n if (el.firstChild) {\n el.insertBefore(child, el.firstChild)\n } else {\n el.appendChild(child)\n }\n}\n\nmodule.exports = prepend\n\n\n/***/ }),\n\n/***/ \"g2okcHDGBNRpe9zqR9sR\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* blank */\n\n\n/***/ }),\n\n/***/ \"g3wkw0XZUos0Eo8rU7p6\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n/***/ }),\n\n/***/ \"j059HZGO2uzpV/UZMXr3\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = qs;\nexports.qsdecode = qsdecode;\n/*\n * Helper: minimal qs implementation\n */\n\nfunction qs(search) {\n search = search.substr(1);\n var parts = search.split('&').map(function (p) {\n return p.split('=');\n });\n return parts.reduce(function (result, part) {\n result[part[0]] = qsdecode(part[1]);\n return result;\n }, {});\n}\n\nfunction qsdecode(string) {\n if (!string) string = '';\n string = string.replace(/\\+/g, ' ');\n return string;\n}\n\n/***/ }),\n\n/***/ \"k6EYej2Qda8Mq9A5Oeqn\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _remove = __webpack_require__(\"wYegCzKWCG2ZRJZfGEZa\");\n\nvar _remove2 = _interopRequireDefault(_remove);\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nvar _addClass = __webpack_require__(\"lGfezzQL7fc5RE8kg33g\");\n\nvar _addClass2 = _interopRequireDefault(_addClass);\n\nvar _preview = __webpack_require__(\"BF4TFfJ+K+wsuHfLZ/S3\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/*\n * Behavior: Things to remove when preview mode is on\n */\n\n(0, _onmount2.default)('[data-js-no-preview]', function (b) {\n if ((0, _preview.isPreview)()) {\n (0, _remove2.default)(this);\n (0, _addClass2.default)(document.documentElement, 'PreviewMode');\n }\n});\n\n/***/ }),\n\n/***/ \"lGfezzQL7fc5RE8kg33g\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar each = __webpack_require__(\"O7wD3s+p+jjyw5ivWGEg\")\n\n/**\n * addClass : addClass(el, className)\n * Adds a class name to an element. Compare with `$.fn.addClass`.\n *\n * var addClass = require('dom101/add-class');\n *\n * addClass(el, 'active');\n */\n\nfunction addClass (el, className) {\n if (!className) return\n\n if (Array.isArray(className)) {\n each(className, function (className) {\n addClass(el, className)\n })\n\n return\n }\n\n if (el.classList) {\n var classNames = className.split(' ').filter(Boolean)\n each(classNames, function (className) {\n el.classList.add(className)\n })\n } else {\n el.className += ' ' + className\n }\n}\n\nmodule.exports = addClass\n\n\n/***/ }),\n\n/***/ \"lpgA2dewefHNQWX4X3Mh\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nvar _prepend = __webpack_require__(\"djrEhtin0g5nRB/RnnLU\");\n\nvar _prepend2 = _interopRequireDefault(_prepend);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar DEFAULTS = {\n // select elements to put anchor on\n rule: 'h2[id]',\n // class name for anchor\n className: 'local-anchor anchor',\n // text of anchor\n text: '#',\n // append before or after innerText?\n shouldAppend: false\n\n /*\n * Behavior: Add local anchors\n */\n\n};(0, _onmount2.default)('[data-js-anchors]', function () {\n var data = JSON.parse(this.getAttribute('data-js-anchors') || '{}');\n var rules = Array.isArray(data) ? data.length ? data : [DEFAULTS] : [Object.assign({}, DEFAULTS, data)];\n\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = rules[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var _ref = _step.value;\n var rule = _ref.rule;\n var className = _ref.className;\n var text = _ref.text;\n var shouldAppend = _ref.shouldAppend;\n var _iteratorNormalCompletion2 = true;\n var _didIteratorError2 = false;\n var _iteratorError2 = undefined;\n\n try {\n for (var _iterator2 = this.querySelectorAll(rule)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {\n var el = _step2.value;\n\n if (!el.hasAttribute('id')) {\n continue;\n }\n\n var id = el.getAttribute('id');\n var anchor = document.createElement('a');\n anchor.setAttribute('href', '#' + id);\n anchor.setAttribute('class', className);\n anchor.innerText = String(text || DEFAULTS.text);\n\n if (shouldAppend) {\n el.appendChild(anchor);\n } else {\n (0, _prepend2.default)(el, anchor);\n }\n }\n } catch (err) {\n _didIteratorError2 = true;\n _iteratorError2 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion2 && _iterator2.return) {\n _iterator2.return();\n }\n } finally {\n if (_didIteratorError2) {\n throw _iteratorError2;\n }\n }\n }\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n});\n\n/***/ }),\n\n/***/ \"tcev71HWHlq3Ur/sw7Ir\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nvar _permutate = __webpack_require__(\"GOdGag34TlRuHa2OZoh9\");\n\nvar _permutate2 = _interopRequireDefault(_permutate);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Sets search indices (`data-search-index` attribute)\n */\n\n(0, _onmount2.default)('[data-js-searchable-item]', function () {\n var data = JSON.parse(this.getAttribute('data-js-searchable-item') || '{}');\n var words = (0, _permutate2.default)(data);\n\n this.setAttribute('data-search-index', words.join(' '));\n});\n\n/***/ }),\n\n/***/ \"tqbVxj9+xGAhlFrQpyTS\":\n/***/ (function(module, exports) {\n\n/**\n * ready : ready(fn)\n * Executes `fn` when the DOM is ready. If the DOM is already ready, the given\n * callback will be called immediately.\n *\n * var ready = require('dom101/ready');\n *\n * ready(function () {\n * ...\n * });\n */\n\nfunction ready (fn) {\n if (isReady()) {\n return fn()\n } else if (document.addEventListener) {\n document.addEventListener('DOMContentLoaded', fn)\n } else {\n document.attachEvent('onreadystatechange', function () {\n if (isReady()) fn()\n })\n }\n}\n\nfunction isReady () {\n return (document.readyState === 'complete' || document.readyState === 'interactive')\n}\n\nmodule.exports = ready\n\n\n/***/ }),\n\n/***/ \"veOabZWTWtixkn1TyITD\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nvar _dom = __webpack_require__(\"ahJreyGRfWuLMDCl+A3L\");\n\nvar _matches = __webpack_require__(\"C2mk7N9JzKWlcOYJrkfi\");\n\nvar _matches2 = _interopRequireDefault(_matches);\n\n__webpack_require__(\"tcev71HWHlq3Ur/sw7Ir\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Propagate item search indices to headers\n */\n\n(0, _onmount2.default)('[data-js-searchable-header]', function () {\n var els = (0, _dom.nextUntil)(this, '[data-js-searchable-header]').filter(function (el) {\n return (0, _matches2.default)(el, '[data-search-index]');\n });\n\n var keywords = els.map(function (n) {\n return n.getAttribute('data-search-index');\n }).join(' ').split(' ');\n\n this.setAttribute('data-search-index', keywords.join(' '));\n});\n\n// Ensure that search-index is set first\n\n/***/ }),\n\n/***/ \"wYegCzKWCG2ZRJZfGEZa\":\n/***/ (function(module, exports) {\n\n/**\n * remove : remove(el)\n * Removes an element from the DOM.\n *\n * var remove = require('dom101/remove');\n *\n * remove(el);\n */\n\nfunction remove (el) {\n el && el.parentNode && el.parentNode.removeChild(el)\n}\n\nmodule.exports = remove\n\n\n/***/ }),\n\n/***/ \"yfX/NEeqeNrvWENPWWKS\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/* global define */\nvoid (function (root, factory) {\n if (true) !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :\n\t\t\t\t__WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))\n else if (typeof exports === 'object') module.exports = factory()\n else {\n if (window.jQuery) window.jQuery.onmount = factory()\n else root.onmount = factory()\n }\n}(this, function ($) {\n /*\n * Internal: Registry.\n */\n\n var handlers, behaviors, selectors, log\n\n /*\n * Internal: IDs for auto-incrementing.\n */\n\n var bid = 0 /* behavior ID */\n var cid = 0 /* component ID */\n\n /**\n * (Module) Adds a behavior, or triggers behaviors.\n *\n * When no parameters are passed, it triggers all behaviors. When one\n * parameter is passed, it triggers the given behavior. Otherwise, it adds a\n * behavior.\n *\n * // define a behavior\n * $.onmount('.select-box', function () {\n * $(this).on('...')\n * })\n *\n * // define a behavior with exit\n * $.onmount('.select-box', function () {\n * $(document).on('...')\n * }, function () {\n * $(document).off('...')\n * })\n *\n * // retrigger a onmount\n * $.onmount('.select-box')\n *\n * // retriggers all behaviors\n * $.onmount()\n */\n\n function onmount (selector, init, exit, options) {\n if (typeof exit === 'object') {\n options = exit\n exit = undefined\n }\n\n if (arguments.length === 0 || isjQuery(selector) || isEvent(selector)) {\n // onmount() - trigger all behaviors. Also account for cases such as\n // $($.onmount), where it's triggered with a jQuery event object.\n onmount.poll()\n } else if (arguments.length === 1) {\n // onmount(selector) - trigger for a given selector.\n onmount.poll(selector)\n } else {\n // onmount(sel, fn, [fn]) - register a new behavior.\n var be = new Behavior(selector, init, exit, options)\n behaviors.push(be)\n be.register()\n }\n\n return this\n }\n\n /*\n * Use jQuery (or a jQuery-like) when available. This will allow\n * the use of jQuery selectors.\n */\n\n onmount.$ = window.jQuery || window.Zepto || window.Ender\n\n /*\n * Detect MutationObserver support for `onmount.observe()`.\n * You may even add a polyfill here via\n * `onmount.MutationObserver = require('mutation-observer')`.\n */\n\n onmount.MutationObserver =\n window.MutationObserver ||\n window.WebKitMutationObserver ||\n window.MozMutationObserver\n\n /**\n * Set this to true if you want to see debug messages.\n */\n\n onmount.debug = false\n\n /**\n * Internal: triggers behaviors for a selector or for all.\n *\n * onmount.poll()\n * onmount.poll('.js-button')\n */\n\n onmount.poll = function poll (selector) {\n if (selector) selector = onmount.selectify(selector)\n var functions = (selector ? selectors[selector] : handlers) || []\n each(functions, function (fn) { fn() })\n }\n\n /**\n * Observes automatically using MutationObserver events.\n *\n * onmount.observe()\n */\n\n onmount.observe = function observe () {\n var MutationObserver = onmount.MutationObserver\n if (typeof MutationObserver === 'undefined') return\n\n var obs = new MutationObserver(function (mutations) {\n each(behaviors, function (be) {\n each(mutations, function (mutation) {\n each(mutation.addedNodes, function (el) {\n if (matches(el, be.selector)) be.visitEnter(el)\n })\n\n each(mutation.removedNodes, function (el) {\n if (matches(el, be.selector)) be.doExit(el)\n })\n })\n })\n })\n\n obs.observe(document, { subtree: true, childList: true })\n onmount.observer = obs\n\n // trigger everything before going\n onmount()\n return true\n }\n\n /**\n * Turns off observation first issued by `onmount.observe()`.\n */\n\n onmount.unobserve = function unobserve () {\n if (!this.observer) return\n this.observer.disconnect()\n delete this.observer\n }\n\n /**\n * Forces teardown of all behaviors currently applied.\n */\n\n onmount.teardown = function teardown () {\n each(behaviors, function (be) {\n each(be.loaded, function (el, i) {\n if (el) be.doExit(el, i)\n })\n })\n }\n\n /**\n * Clears all behaviors. Useful for tests.\n * This will NOT call exit handlers.\n */\n\n onmount.reset = function reset () {\n handlers = onmount.handlers = []\n selectors = onmount.selectors = {}\n behaviors = onmount.behaviors = []\n }\n\n /**\n * Internal: Converts `@role` to `[role~=\"role\"]` if needed. You can override\n * this by reimplementing `onmount.selectify`.\n *\n * selectify('@hi') //=> '[role=\"hi\"]'\n * selectify('.btn') //=> '.btn'\n */\n\n onmount.selectify = function selectify (selector) {\n if (selector[0] === '@') {\n return '[role~=\"' + selector.substr(1).replace(/\"/g, '\\\\\"') + '\"]'\n }\n return selector\n }\n\n /**\n * Internal: behavior class\n */\n\n function Behavior (selector, init, exit, options) {\n this.id = 'b' + bid++\n this.init = init\n this.exit = exit\n this.selector = onmount.selectify(selector)\n this.loaded = [] // keep track of dom elements loaded for this behavior\n this.key = '__onmount:' + bid // leave the state in el['__onmount:12']\n this.detectMutate = options && options.detectMutate\n }\n\n /**\n * Internal: initialize this behavior by registering itself to the internal\n * `selectors` map. This allows you to call `onmount(selector)` later on.\n */\n\n Behavior.prototype.register = function () {\n var be = this\n var loaded = this.loaded\n var selector = this.selector\n\n register(selector, function () {\n var list = query(selector)\n\n // This is the function invoked on `onmount(selector)`.\n // Clean up old ones (if they're not in the DOM anymore).\n each(loaded, function (element, i) {\n be.visitExit(element, i, list)\n })\n\n // Clean up new ones (if they're not loaded yet).\n eachOf(list, function (element) {\n be.visitEnter(element)\n })\n })\n }\n\n /**\n * Internal: visits the element `el` and turns it on if applicable.\n */\n\n Behavior.prototype.visitEnter = function (el) {\n if (el[this.key]) return\n var options = { id: 'c' + cid, selector: this.selector }\n if (this.init.call(el, options) !== false) {\n if (onmount.debug) log('enter', this.selector, el)\n el[this.key] = options\n this.loaded.push(el)\n cid++\n }\n }\n\n /**\n * Internal: visits the element `el` and sees if it needs its exit handler\n * called.\n */\n\n Behavior.prototype.visitExit = function (el, i, list) {\n if (!el) return\n if (this.detectMutate) {\n if (!has(list, el)) return this.doExit(el, i)\n } else {\n if (!isAttached(el)) return this.doExit(el, i)\n }\n }\n\n /**\n * Internal: calls the exit handler for the behavior for element `el` (if\n * available), and marks the behavior/element as uninitialized.\n */\n\n Behavior.prototype.doExit = function (el, i) {\n if (typeof i === 'undefined') i = this.loaded.indexOf(el)\n this.loaded[i] = undefined\n if (this.exit && this.exit.call(el, el[this.key]) !== false) {\n if (onmount.debug) log('exit', this.selector, el)\n delete el[this.key]\n }\n }\n\n /**\n * Internal: check if an element is still attached to its document.\n */\n\n function isAttached (el) {\n while (el) {\n if (el === document.documentElement) return true\n el = el.parentElement\n }\n }\n\n /**\n * Internal: reimplementation of `$('...')`. If jQuery is available,\n * use it (I guess to preserve IE compatibility and to enable special jQuery\n * attribute selectors). Use with `eachOf()` or `has()`.\n */\n\n function query (selector, fn) {\n if (onmount.$) return onmount.$(selector)\n return document.querySelectorAll(selector)\n }\n\n /**\n * Internal: iterates through a `query()` result.\n */\n\n function eachOf (list, fn) {\n if (onmount.$) return list.each(function (i) { fn(this, i) })\n return each(list, fn)\n }\n\n /**\n * Interanl: checks if given element `el` is in the query result `list`.\n */\n\n function has (list, el) {\n if (onmount.$) return list.index(el) > -1\n return list.indexOf(el) > -1\n }\n\n /**\n * Internal: registers a behavior handler for a selector.\n */\n\n function register (selector, fn) {\n if (!selectors[selector]) selectors[selector] = []\n selectors[selector].push(fn)\n handlers.push(fn)\n }\n\n /**\n * Checks if a given element `el` matches `selector`.\n * Compare with [$.fn.is](http://api.jquery.com/is/).\n *\n * var matches = require('dom101/matches');\n *\n * matches(button, ':focus');\n */\n\n function matches (el, selector) {\n var _matches = el.matches ||\n el.matchesSelector ||\n el.msMatchesSelector ||\n el.mozMatchesSelector ||\n el.webkitMatchesSelector ||\n el.oMatchesSelector\n\n if (onmount.$) {\n return onmount.$(el).is(selector)\n } else if (_matches) {\n return _matches.call(el, selector)\n } else if (el.parentNode) {\n // IE8 and below\n var nodes = el.parentNode.querySelectorAll(selector)\n for (var i = nodes.length; i--; 0) {\n if (nodes[i] === el) return true\n }\n return false\n }\n }\n\n /**\n * Iterates through `list` (an array or an object). This is useful when dealing\n * with NodeLists like `document.querySelectorAll`.\n *\n * var each = require('dom101/each');\n * var qa = require('dom101/query-selector-all');\n *\n * each(qa('.button'), function (el) {\n * addClass('el', 'selected');\n * });\n */\n\n function each (list, fn) {\n var i\n var len = list.length\n\n if (len === +len) {\n for (i = 0; i < len; i++) { fn(list[i], i) }\n } else {\n for (i in list) {\n if (list.hasOwnProperty(i)) fn(list[i], i)\n }\n }\n\n return list\n }\n\n /**\n * Internal: Check if a given object is jQuery\n */\n\n function isjQuery ($) {\n return typeof $ === 'function' && $.fn && $.noConflict\n }\n\n function isEvent (e) {\n return typeof e === 'object' && e.target\n }\n\n /**\n * Internal: logging\n */\n\n var styles = {\n enter: 'background-color:#dfd;font-weight:bold;color:#141',\n exit: 'background-color:#fdd;font-weight:bold;color:#411'\n }\n\n if (~navigator.userAgent.indexOf('Mozilla')) {\n log = function (type, selector, el) {\n console.log('%c %s ', styles[type], selector, el)\n }\n } else {\n log = function (type, selector, el) {\n console.log('(onmount)', type, selector)\n }\n }\n\n /*\n * Export\n */\n\n onmount.reset()\n return onmount\n}))\n\n\n/***/ }),\n\n/***/ \"z+w/DGZianwIMo5d4qOD\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n// 3rd party libs\nwindow.Prism = __webpack_require__(\"+HohgKHTHTXOIAa8uoqY\");\n\n// All the others\nfunction requireAll(r) {\n r.keys().forEach(r);\n}\nrequireAll(__webpack_require__(\"2tov+8o2NrZdw/Lg8JZA\"));\nrequireAll(__webpack_require__(\"cBdQffYQOU2SCSRXjSUx\"));\n\n/***/ }),\n\n/***/ \"zNHHVy5XxvKjnqTgwxy7\":\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _onmount = __webpack_require__(\"yfX/NEeqeNrvWENPWWKS\");\n\nvar _onmount2 = _interopRequireDefault(_onmount);\n\nvar _search = __webpack_require__(\"DfTyEU8lscjHXmCMlptO\");\n\nvar Search = _interopRequireWildcard(_search);\n\nvar _qs = __webpack_require__(\"j059HZGO2uzpV/UZMXr3\");\n\nvar _qs2 = _interopRequireDefault(_qs);\n\nvar _on = __webpack_require__(\"MKJaVdnD9jF7rk6rW6AJ\");\n\nvar _on2 = _interopRequireDefault(_on);\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n(0, _onmount2.default)('[data-js-search-input]', function () {\n var _this = this;\n\n (0, _on2.default)(this, 'input', function () {\n var val = _this.value;\n\n if (val === '') {\n Search.showAll();\n } else {\n Search.show(val);\n }\n });\n\n var query = ((0, _qs2.default)(window.location.search) || {}).q;\n if (query && query.length) {\n this.value = query;\n setTimeout(function () {\n Search.show(query);\n });\n }\n});\n\n/***/ })\n\n},[\"z+w/DGZianwIMo5d4qOD\"]);\n\n\n// WEBPACK FOOTER //\n// app.js","/**\n * Updates a local storage key. If it doesn't exist, it defaults to an empty\n * object.\n *\n * @example\n * update('dismissed', (data) => {\n * data.lol = true\n * return data\n * })\n */\n\nexport function update (key, fn) {\n if (!window.localStorage) return\n let data = JSON.parse(window.localStorage[key] || '{}')\n data = fn(data)\n window.localStorage[key] = JSON.stringify(data)\n}\n\n/**\n * Fetches a local storage key.\n *\n * @example\n * const data = fetch('dismissed')\n */\n\nexport function fetch (key) {\n if (!window.localStorage) return\n return JSON.parse(window.localStorage[key] || '{}')\n}\n\n\n\n// WEBPACK FOOTER //\n// ./_js/helpers/store.js","import * as Store from './store'\n\n/**\n * Dismisses an announcement.\n *\n * @example\n * setDismissed('2017-09-02-happy-birthday')\n */\n\nexport function setDismissed (id) {\n Store.update('dismissed', function (data) {\n data[id] = true\n return data\n })\n}\n\n/**\n * Checks if an announcement has been dismissed before.\n *\n * @example\n * setDismissed('2017-09-02-happy-birthday')\n * isDismissed('2017-09-02-happy-birthday') => true\n */\n\nexport function isDismissed (id) {\n const data = Store.fetch('dismissed')\n return data && data[id]\n}\n\n\n\n// WEBPACK FOOTER //\n// ./_js/helpers/dismiss.js","var map = {\n\t\"./onmount.js\": \"6hLKOGpXaWUwTDQA5TL2\"\n};\nfunction webpackContext(req) {\n\treturn __webpack_require__(webpackContextResolve(req));\n};\nfunction webpackContextResolve(req) {\n\tvar id = map[req];\n\tif(!(id + 1)) // check for number or string\n\t\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n\treturn id;\n};\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"2tov+8o2NrZdw/Lg8JZA\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./_js/initializers \\.js$\n// module id = 2tov+8o2NrZdw/Lg8JZA\n// module chunks = 0","import ready from 'dom101/ready'\nimport onmount from 'onmount'\n\n/**\n * Behavior: Wrapping\n */\n\nready(() => {\n setTimeout(() => { onmount() })\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/initializers/onmount.js","/**\n * Checks if we're in preview mode (?preview=1).\n */\n\nexport function isPreview () {\n return window.location.search.indexOf('preview=1') !== -1\n}\n\n\n\n// WEBPACK FOOTER //\n// ./_js/helpers/preview.js","import onmount from 'onmount'\nimport injectDisqus from '../helpers/inject_disqus'\n\n/**\n * Delay disqus by some time. It's at the bottom of the page, there's no need\n * for it to load fast. This will give more time to load more critical assets.\n */\n\nconst DISQUS_DELAY = 100\n\n/**\n * Injects Disqus onto the page.\n */\n\nonmount('[data-js-disqus]', function () {\n const data = JSON.parse(this.getAttribute('data-js-disqus'))\n const $parent = this.parentNode\n $parent.setAttribute('hidden', true)\n\n window.disqus_config = function () {\n this.page.url = data.url\n this.page.identifier = data.identifier\n }\n\n // Disqus takes a while to load, don't do it so eagerly.\n window.addEventListener('load', () => {\n setTimeout(() => {\n injectDisqus(data.host)\n $parent.removeAttribute('hidden')\n }, DISQUS_DELAY)\n })\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/behaviors/disqus.js","/**\n * matches : matches(el, selector)\n * Checks if a given element `el` matches `selector`.\n * Compare with [$.fn.is](http://api.jquery.com/is/).\n *\n * var matches = require('dom101/matches');\n *\n * matches(button, ':focus');\n */\n\nfunction matches (el, selector) {\n var _matches = el.matches ||\n el.matchesSelector ||\n el.msMatchesSelector ||\n el.mozMatchesSelector ||\n el.webkitMatchesSelector ||\n el.oMatchesSelector\n\n if (_matches) {\n return _matches.call(el, selector)\n } else if (el.parentNode) {\n // IE8 and below\n var nodes = el.parentNode.querySelectorAll(selector)\n for (var i = nodes.length; i--; 0) {\n if (nodes[i] === el) return true\n }\n return false\n }\n}\n\nmodule.exports = matches\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/dom101/matches.js\n// module id = C2mk7N9JzKWlcOYJrkfi\n// module chunks = 0","/**\n * Stores and retrieves data from an element. Works like jQuery.data().\n */\n\nexport function data (el, key, val) {\n if (typeof val !== 'undefined') {\n return getData(el, key)\n } else {\n return setData(el, key, val)\n }\n}\n\nexport function getData (el, key) {\n const str = el.getAttribute('data-' + key)\n return JSON.parse(str || '{}')\n}\n\nexport function setData (el, key, val) {\n el.setAttribute('data-' + key, JSON.stringify(val))\n}\n\n\n\n// WEBPACK FOOTER //\n// ./_js/helpers/data.js","import onmount from 'onmount'\nimport on from 'dom101/on'\n\n/**\n * Submitting the search form\n */\n\nonmount('[data-js-search-form]', function () {\n on(this, 'submit', e => {\n e.preventDefault()\n\n const link = document.querySelector('a[data-search-index]:visible')\n const href = link && link.getAttribute('href')\n\n if (href) window.location = href\n })\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/behaviors/search-form.js","import { splitwords } from './permutate'\nimport qsa from 'dom101/query-selector-all'\n\n/**\n * Show everything.\n *\n * @example\n * Search.showAll()\n */\n\nexport function showAll () {\n qsa('[data-search-index]').forEach(el => {\n el.removeAttribute('aria-hidden')\n })\n}\n\n/**\n * Search for a given keyword.\n *\n * @example\n * Search.show('hello')\n */\n\nexport function show (val) {\n const keywords = splitwords(val)\n\n if (!keywords.length) return showAll()\n\n const selectors = keywords\n .map(k => `[data-search-index~=${JSON.stringify(k)}]`)\n .join('')\n\n qsa('[data-search-index]').forEach(el => {\n el.setAttribute('aria-hidden', true)\n })\n\n qsa(selectors).forEach(el => {\n el.removeAttribute('aria-hidden')\n })\n}\n\n\n\n// WEBPACK FOOTER //\n// ./_js/helpers/search.js","/* eslint-disable no-new */\n\nimport Isotope from 'isotope-layout/dist/isotope.pkgd.js'\nimport onmount from 'onmount'\nimport on from 'dom101/on'\nimport qsa from 'dom101/query-selector-all'\n\n/*\n * Behavior: Isotope\n */\n\nonmount('[data-js-h3-section-list]', function () {\n const iso = new Isotope(this, {\n itemSelector: '.h3-section',\n transitionDuration: 0\n })\n\n const images = qsa('img', this)\n\n images.forEach(image => {\n on(image, 'load', () => {\n iso.layout()\n })\n })\n\n // Insurance against weirdness on pages like devhints.io/vim, where the\n // critical path CSS may look different from the final CSS (because of the\n // tables).\n on(window, 'load', () => {\n iso.layout()\n })\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/behaviors/h3-section-list.js","/**\n * querySelectorAll : querySelectorAll(query, [element])\n * Convenience function to access `document.querySelectorAll`. Unlike the\n * default version, this always returns an array.\n *\n * If a 2nd parameter `element` is given, it only searches for descendants of\n * that element.\n *\n * var each = require('dom101/each');\n * var qsa = require('dom101/query-selector-all');\n *\n * qsa('.button').each(el => {\n * addClass('el', 'selected');\n * };\n */\n\nfunction querySelectorAll (query, context) {\n return Array.prototype.slice.call(\n (context || document).querySelectorAll(query)\n )\n}\n\nmodule.exports = querySelectorAll\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/dom101/query-selector-all.js\n// module id = EvxNxLK9yKFmn1U14Kvw\n// module chunks = 0","/**\n * Permutates a searcheable item.\n *\n * permutate({\n * slug: 'hello-world',\n * category: 'greetings'\n * })\n */\n\nexport default function permutate (data) {\n let words = []\n if (data.slug) {\n words = words.concat(permutateString(data.slug))\n }\n if (data.category) {\n words = words.concat(permutateString(data.category))\n }\n return words\n}\n\n/**\n * Permutates strings.\n *\n * @example\n * permutateString('hi joe')\n * => ['h', 'hi', 'j', 'jo', 'joe']\n */\n\nexport function permutateString (str) {\n let words = []\n let inputs = splitwords(str)\n\n inputs.forEach(word => {\n words = words.concat(permutateWord(word))\n })\n\n return words\n}\n\n/**\n * Permutates a word.\n *\n * @example\n * permutateWord('hello')\n * => ['h', 'he', 'hel', 'hell', 'hello']\n */\n\nexport function permutateWord (str) {\n let words = []\n const len = str.length\n for (var i = 1; i <= len; ++i) {\n words.push(str.substr(0, i))\n }\n return words\n}\n\n/**\n * Helper for splitting to words.\n *\n * @example\n * splitWords('Hello, world!')\n * => ['hello', 'world']\n */\n\nexport function splitwords (str) {\n const words = str.toLowerCase()\n .split(/[ /\\-_]/)\n .filter(k => k && k.length !== 0)\n\n return words\n}\n\n\n\n// WEBPACK FOOTER //\n// ./_js/helpers/permutate.js","/*!\n * Isotope PACKAGED v3.0.4\n *\n * Licensed GPLv3 for open source use\n * or Isotope Commercial License for commercial use\n *\n * http://isotope.metafizzy.co\n * Copyright 2017 Metafizzy\n */\n\n/**\n * Bridget makes jQuery widgets\n * v2.0.1\n * MIT license\n */\n\n/* jshint browser: true, strict: true, undef: true, unused: true */\n\n( function( window, factory ) {\n // universal module definition\n /*jshint strict: false */ /* globals define, module, require */\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {\n return factory( window, jQuery );\n });\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n window,\n require('jquery')\n );\n } else {\n // browser global\n window.jQueryBridget = factory(\n window,\n window.jQuery\n );\n }\n\n}( window, function factory( window, jQuery ) {\n'use strict';\n\n// ----- utils ----- //\n\nvar arraySlice = Array.prototype.slice;\n\n// helper function for logging errors\n// $.error breaks jQuery chaining\nvar console = window.console;\nvar logError = typeof console == 'undefined' ? function() {} :\n function( message ) {\n console.error( message );\n };\n\n// ----- jQueryBridget ----- //\n\nfunction jQueryBridget( namespace, PluginClass, $ ) {\n $ = $ || jQuery || window.jQuery;\n if ( !$ ) {\n return;\n }\n\n // add option method -> $().plugin('option', {...})\n if ( !PluginClass.prototype.option ) {\n // option setter\n PluginClass.prototype.option = function( opts ) {\n // bail out if not an object\n if ( !$.isPlainObject( opts ) ){\n return;\n }\n this.options = $.extend( true, this.options, opts );\n };\n }\n\n // make jQuery plugin\n $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {\n if ( typeof arg0 == 'string' ) {\n // method call $().plugin( 'methodName', { options } )\n // shift arguments by 1\n var args = arraySlice.call( arguments, 1 );\n return methodCall( this, arg0, args );\n }\n // just $().plugin({ options })\n plainCall( this, arg0 );\n return this;\n };\n\n // $().plugin('methodName')\n function methodCall( $elems, methodName, args ) {\n var returnValue;\n var pluginMethodStr = '$().' + namespace + '(\"' + methodName + '\")';\n\n $elems.each( function( i, elem ) {\n // get instance\n var instance = $.data( elem, namespace );\n if ( !instance ) {\n logError( namespace + ' not initialized. Cannot call methods, i.e. ' +\n pluginMethodStr );\n return;\n }\n\n var method = instance[ methodName ];\n if ( !method || methodName.charAt(0) == '_' ) {\n logError( pluginMethodStr + ' is not a valid method' );\n return;\n }\n\n // apply method, get return value\n var value = method.apply( instance, args );\n // set return value if value is returned, use only first value\n returnValue = returnValue === undefined ? value : returnValue;\n });\n\n return returnValue !== undefined ? returnValue : $elems;\n }\n\n function plainCall( $elems, options ) {\n $elems.each( function( i, elem ) {\n var instance = $.data( elem, namespace );\n if ( instance ) {\n // set options & init\n instance.option( options );\n instance._init();\n } else {\n // initialize new instance\n instance = new PluginClass( elem, options );\n $.data( elem, namespace, instance );\n }\n });\n }\n\n updateJQuery( $ );\n\n}\n\n// ----- updateJQuery ----- //\n\n// set $.bridget for v1 backwards compatibility\nfunction updateJQuery( $ ) {\n if ( !$ || ( $ && $.bridget ) ) {\n return;\n }\n $.bridget = jQueryBridget;\n}\n\nupdateJQuery( jQuery || window.jQuery );\n\n// ----- ----- //\n\nreturn jQueryBridget;\n\n}));\n\n/**\n * EvEmitter v1.0.3\n * Lil' event emitter\n * MIT License\n */\n\n/* jshint unused: true, undef: true, strict: true */\n\n( function( global, factory ) {\n // universal module definition\n /* jshint strict: false */ /* globals define, module, window */\n if ( typeof define == 'function' && define.amd ) {\n // AMD - RequireJS\n define( 'ev-emitter/ev-emitter',factory );\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS - Browserify, Webpack\n module.exports = factory();\n } else {\n // Browser globals\n global.EvEmitter = factory();\n }\n\n}( typeof window != 'undefined' ? window : this, function() {\n\n\n\nfunction EvEmitter() {}\n\nvar proto = EvEmitter.prototype;\n\nproto.on = function( eventName, listener ) {\n if ( !eventName || !listener ) {\n return;\n }\n // set events hash\n var events = this._events = this._events || {};\n // set listeners array\n var listeners = events[ eventName ] = events[ eventName ] || [];\n // only add once\n if ( listeners.indexOf( listener ) == -1 ) {\n listeners.push( listener );\n }\n\n return this;\n};\n\nproto.once = function( eventName, listener ) {\n if ( !eventName || !listener ) {\n return;\n }\n // add event\n this.on( eventName, listener );\n // set once flag\n // set onceEvents hash\n var onceEvents = this._onceEvents = this._onceEvents || {};\n // set onceListeners object\n var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};\n // set flag\n onceListeners[ listener ] = true;\n\n return this;\n};\n\nproto.off = function( eventName, listener ) {\n var listeners = this._events && this._events[ eventName ];\n if ( !listeners || !listeners.length ) {\n return;\n }\n var index = listeners.indexOf( listener );\n if ( index != -1 ) {\n listeners.splice( index, 1 );\n }\n\n return this;\n};\n\nproto.emitEvent = function( eventName, args ) {\n var listeners = this._events && this._events[ eventName ];\n if ( !listeners || !listeners.length ) {\n return;\n }\n var i = 0;\n var listener = listeners[i];\n args = args || [];\n // once stuff\n var onceListeners = this._onceEvents && this._onceEvents[ eventName ];\n\n while ( listener ) {\n var isOnce = onceListeners && onceListeners[ listener ];\n if ( isOnce ) {\n // remove listener\n // remove before trigger to prevent recursion\n this.off( eventName, listener );\n // unset once flag\n delete onceListeners[ listener ];\n }\n // trigger listener\n listener.apply( this, args );\n // get next listener\n i += isOnce ? 0 : 1;\n listener = listeners[i];\n }\n\n return this;\n};\n\nreturn EvEmitter;\n\n}));\n\n/*!\n * getSize v2.0.2\n * measure size of elements\n * MIT license\n */\n\n/*jshint browser: true, strict: true, undef: true, unused: true */\n/*global define: false, module: false, console: false */\n\n( function( window, factory ) {\n 'use strict';\n\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'get-size/get-size',[],function() {\n return factory();\n });\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory();\n } else {\n // browser global\n window.getSize = factory();\n }\n\n})( window, function factory() {\n'use strict';\n\n// -------------------------- helpers -------------------------- //\n\n// get a number from a string, not a percentage\nfunction getStyleSize( value ) {\n var num = parseFloat( value );\n // not a percent like '100%', and a number\n var isValid = value.indexOf('%') == -1 && !isNaN( num );\n return isValid && num;\n}\n\nfunction noop() {}\n\nvar logError = typeof console == 'undefined' ? noop :\n function( message ) {\n console.error( message );\n };\n\n// -------------------------- measurements -------------------------- //\n\nvar measurements = [\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'paddingBottom',\n 'marginLeft',\n 'marginRight',\n 'marginTop',\n 'marginBottom',\n 'borderLeftWidth',\n 'borderRightWidth',\n 'borderTopWidth',\n 'borderBottomWidth'\n];\n\nvar measurementsLength = measurements.length;\n\nfunction getZeroSize() {\n var size = {\n width: 0,\n height: 0,\n innerWidth: 0,\n innerHeight: 0,\n outerWidth: 0,\n outerHeight: 0\n };\n for ( var i=0; i < measurementsLength; i++ ) {\n var measurement = measurements[i];\n size[ measurement ] = 0;\n }\n return size;\n}\n\n// -------------------------- getStyle -------------------------- //\n\n/**\n * getStyle, get style of element, check for Firefox bug\n * https://bugzilla.mozilla.org/show_bug.cgi?id=548397\n */\nfunction getStyle( elem ) {\n var style = getComputedStyle( elem );\n if ( !style ) {\n logError( 'Style returned ' + style +\n '. Are you running this code in a hidden iframe on Firefox? ' +\n 'See http://bit.ly/getsizebug1' );\n }\n return style;\n}\n\n// -------------------------- setup -------------------------- //\n\nvar isSetup = false;\n\nvar isBoxSizeOuter;\n\n/**\n * setup\n * check isBoxSizerOuter\n * do on first getSize() rather than on page load for Firefox bug\n */\nfunction setup() {\n // setup once\n if ( isSetup ) {\n return;\n }\n isSetup = true;\n\n // -------------------------- box sizing -------------------------- //\n\n /**\n * WebKit measures the outer-width on style.width on border-box elems\n * IE & Firefox<29 measures the inner-width\n */\n var div = document.createElement('div');\n div.style.width = '200px';\n div.style.padding = '1px 2px 3px 4px';\n div.style.borderStyle = 'solid';\n div.style.borderWidth = '1px 2px 3px 4px';\n div.style.boxSizing = 'border-box';\n\n var body = document.body || document.documentElement;\n body.appendChild( div );\n var style = getStyle( div );\n\n getSize.isBoxSizeOuter = isBoxSizeOuter = getStyleSize( style.width ) == 200;\n body.removeChild( div );\n\n}\n\n// -------------------------- getSize -------------------------- //\n\nfunction getSize( elem ) {\n setup();\n\n // use querySeletor if elem is string\n if ( typeof elem == 'string' ) {\n elem = document.querySelector( elem );\n }\n\n // do not proceed on non-objects\n if ( !elem || typeof elem != 'object' || !elem.nodeType ) {\n return;\n }\n\n var style = getStyle( elem );\n\n // if hidden, everything is 0\n if ( style.display == 'none' ) {\n return getZeroSize();\n }\n\n var size = {};\n size.width = elem.offsetWidth;\n size.height = elem.offsetHeight;\n\n var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';\n\n // get all measurements\n for ( var i=0; i < measurementsLength; i++ ) {\n var measurement = measurements[i];\n var value = style[ measurement ];\n var num = parseFloat( value );\n // any 'auto', 'medium' value will be 0\n size[ measurement ] = !isNaN( num ) ? num : 0;\n }\n\n var paddingWidth = size.paddingLeft + size.paddingRight;\n var paddingHeight = size.paddingTop + size.paddingBottom;\n var marginWidth = size.marginLeft + size.marginRight;\n var marginHeight = size.marginTop + size.marginBottom;\n var borderWidth = size.borderLeftWidth + size.borderRightWidth;\n var borderHeight = size.borderTopWidth + size.borderBottomWidth;\n\n var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;\n\n // overwrite width and height if we can get it from style\n var styleWidth = getStyleSize( style.width );\n if ( styleWidth !== false ) {\n size.width = styleWidth +\n // add padding and border unless it's already including it\n ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );\n }\n\n var styleHeight = getStyleSize( style.height );\n if ( styleHeight !== false ) {\n size.height = styleHeight +\n // add padding and border unless it's already including it\n ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );\n }\n\n size.innerWidth = size.width - ( paddingWidth + borderWidth );\n size.innerHeight = size.height - ( paddingHeight + borderHeight );\n\n size.outerWidth = size.width + marginWidth;\n size.outerHeight = size.height + marginHeight;\n\n return size;\n}\n\nreturn getSize;\n\n});\n\n/**\n * matchesSelector v2.0.2\n * matchesSelector( element, '.selector' )\n * MIT license\n */\n\n/*jshint browser: true, strict: true, undef: true, unused: true */\n\n( function( window, factory ) {\n /*global define: false, module: false */\n 'use strict';\n // universal module definition\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'desandro-matches-selector/matches-selector',factory );\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory();\n } else {\n // browser global\n window.matchesSelector = factory();\n }\n\n}( window, function factory() {\n 'use strict';\n\n var matchesMethod = ( function() {\n var ElemProto = window.Element.prototype;\n // check for the standard method name first\n if ( ElemProto.matches ) {\n return 'matches';\n }\n // check un-prefixed\n if ( ElemProto.matchesSelector ) {\n return 'matchesSelector';\n }\n // check vendor prefixes\n var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];\n\n for ( var i=0; i < prefixes.length; i++ ) {\n var prefix = prefixes[i];\n var method = prefix + 'MatchesSelector';\n if ( ElemProto[ method ] ) {\n return method;\n }\n }\n })();\n\n return function matchesSelector( elem, selector ) {\n return elem[ matchesMethod ]( selector );\n };\n\n}));\n\n/**\n * Fizzy UI utils v2.0.5\n * MIT license\n */\n\n/*jshint browser: true, undef: true, unused: true, strict: true */\n\n( function( window, factory ) {\n // universal module definition\n /*jshint strict: false */ /*globals define, module, require */\n\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'fizzy-ui-utils/utils',[\n 'desandro-matches-selector/matches-selector'\n ], function( matchesSelector ) {\n return factory( window, matchesSelector );\n });\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n window,\n require('desandro-matches-selector')\n );\n } else {\n // browser global\n window.fizzyUIUtils = factory(\n window,\n window.matchesSelector\n );\n }\n\n}( window, function factory( window, matchesSelector ) {\n\n\n\nvar utils = {};\n\n// ----- extend ----- //\n\n// extends objects\nutils.extend = function( a, b ) {\n for ( var prop in b ) {\n a[ prop ] = b[ prop ];\n }\n return a;\n};\n\n// ----- modulo ----- //\n\nutils.modulo = function( num, div ) {\n return ( ( num % div ) + div ) % div;\n};\n\n// ----- makeArray ----- //\n\n// turn element or nodeList into an array\nutils.makeArray = function( obj ) {\n var ary = [];\n if ( Array.isArray( obj ) ) {\n // use object if already an array\n ary = obj;\n } else if ( obj && typeof obj == 'object' &&\n typeof obj.length == 'number' ) {\n // convert nodeList to array\n for ( var i=0; i < obj.length; i++ ) {\n ary.push( obj[i] );\n }\n } else {\n // array of single index\n ary.push( obj );\n }\n return ary;\n};\n\n// ----- removeFrom ----- //\n\nutils.removeFrom = function( ary, obj ) {\n var index = ary.indexOf( obj );\n if ( index != -1 ) {\n ary.splice( index, 1 );\n }\n};\n\n// ----- getParent ----- //\n\nutils.getParent = function( elem, selector ) {\n while ( elem.parentNode && elem != document.body ) {\n elem = elem.parentNode;\n if ( matchesSelector( elem, selector ) ) {\n return elem;\n }\n }\n};\n\n// ----- getQueryElement ----- //\n\n// use element as selector string\nutils.getQueryElement = function( elem ) {\n if ( typeof elem == 'string' ) {\n return document.querySelector( elem );\n }\n return elem;\n};\n\n// ----- handleEvent ----- //\n\n// enable .ontype to trigger from .addEventListener( elem, 'type' )\nutils.handleEvent = function( event ) {\n var method = 'on' + event.type;\n if ( this[ method ] ) {\n this[ method ]( event );\n }\n};\n\n// ----- filterFindElements ----- //\n\nutils.filterFindElements = function( elems, selector ) {\n // make array of elems\n elems = utils.makeArray( elems );\n var ffElems = [];\n\n elems.forEach( function( elem ) {\n // check that elem is an actual element\n if ( !( elem instanceof HTMLElement ) ) {\n return;\n }\n // add elem if no selector\n if ( !selector ) {\n ffElems.push( elem );\n return;\n }\n // filter & find items if we have a selector\n // filter\n if ( matchesSelector( elem, selector ) ) {\n ffElems.push( elem );\n }\n // find children\n var childElems = elem.querySelectorAll( selector );\n // concat childElems to filterFound array\n for ( var i=0; i < childElems.length; i++ ) {\n ffElems.push( childElems[i] );\n }\n });\n\n return ffElems;\n};\n\n// ----- debounceMethod ----- //\n\nutils.debounceMethod = function( _class, methodName, threshold ) {\n // original method\n var method = _class.prototype[ methodName ];\n var timeoutName = methodName + 'Timeout';\n\n _class.prototype[ methodName ] = function() {\n var timeout = this[ timeoutName ];\n if ( timeout ) {\n clearTimeout( timeout );\n }\n var args = arguments;\n\n var _this = this;\n this[ timeoutName ] = setTimeout( function() {\n method.apply( _this, args );\n delete _this[ timeoutName ];\n }, threshold || 100 );\n };\n};\n\n// ----- docReady ----- //\n\nutils.docReady = function( callback ) {\n var readyState = document.readyState;\n if ( readyState == 'complete' || readyState == 'interactive' ) {\n // do async to allow for other scripts to run. metafizzy/flickity#441\n setTimeout( callback );\n } else {\n document.addEventListener( 'DOMContentLoaded', callback );\n }\n};\n\n// ----- htmlInit ----- //\n\n// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/\nutils.toDashed = function( str ) {\n return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {\n return $1 + '-' + $2;\n }).toLowerCase();\n};\n\nvar console = window.console;\n/**\n * allow user to initialize classes via [data-namespace] or .js-namespace class\n * htmlInit( Widget, 'widgetName' )\n * options are parsed from data-namespace-options\n */\nutils.htmlInit = function( WidgetClass, namespace ) {\n utils.docReady( function() {\n var dashedNamespace = utils.toDashed( namespace );\n var dataAttr = 'data-' + dashedNamespace;\n var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );\n var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );\n var elems = utils.makeArray( dataAttrElems )\n .concat( utils.makeArray( jsDashElems ) );\n var dataOptionsAttr = dataAttr + '-options';\n var jQuery = window.jQuery;\n\n elems.forEach( function( elem ) {\n var attr = elem.getAttribute( dataAttr ) ||\n elem.getAttribute( dataOptionsAttr );\n var options;\n try {\n options = attr && JSON.parse( attr );\n } catch ( error ) {\n // log error, do not initialize\n if ( console ) {\n console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +\n ': ' + error );\n }\n return;\n }\n // initialize\n var instance = new WidgetClass( elem, options );\n // make available via $().data('namespace')\n if ( jQuery ) {\n jQuery.data( elem, namespace, instance );\n }\n });\n\n });\n};\n\n// ----- ----- //\n\nreturn utils;\n\n}));\n\n/**\n * Outlayer Item\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /* globals define, module, require */\n if ( typeof define == 'function' && define.amd ) {\n // AMD - RequireJS\n define( 'outlayer/item',[\n 'ev-emitter/ev-emitter',\n 'get-size/get-size'\n ],\n factory\n );\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS - Browserify, Webpack\n module.exports = factory(\n require('ev-emitter'),\n require('get-size')\n );\n } else {\n // browser global\n window.Outlayer = {};\n window.Outlayer.Item = factory(\n window.EvEmitter,\n window.getSize\n );\n }\n\n}( window, function factory( EvEmitter, getSize ) {\n'use strict';\n\n// ----- helpers ----- //\n\nfunction isEmptyObj( obj ) {\n for ( var prop in obj ) {\n return false;\n }\n prop = null;\n return true;\n}\n\n// -------------------------- CSS3 support -------------------------- //\n\n\nvar docElemStyle = document.documentElement.style;\n\nvar transitionProperty = typeof docElemStyle.transition == 'string' ?\n 'transition' : 'WebkitTransition';\nvar transformProperty = typeof docElemStyle.transform == 'string' ?\n 'transform' : 'WebkitTransform';\n\nvar transitionEndEvent = {\n WebkitTransition: 'webkitTransitionEnd',\n transition: 'transitionend'\n}[ transitionProperty ];\n\n// cache all vendor properties that could have vendor prefix\nvar vendorProperties = {\n transform: transformProperty,\n transition: transitionProperty,\n transitionDuration: transitionProperty + 'Duration',\n transitionProperty: transitionProperty + 'Property',\n transitionDelay: transitionProperty + 'Delay'\n};\n\n// -------------------------- Item -------------------------- //\n\nfunction Item( element, layout ) {\n if ( !element ) {\n return;\n }\n\n this.element = element;\n // parent layout class, i.e. Masonry, Isotope, or Packery\n this.layout = layout;\n this.position = {\n x: 0,\n y: 0\n };\n\n this._create();\n}\n\n// inherit EvEmitter\nvar proto = Item.prototype = Object.create( EvEmitter.prototype );\nproto.constructor = Item;\n\nproto._create = function() {\n // transition objects\n this._transn = {\n ingProperties: {},\n clean: {},\n onEnd: {}\n };\n\n this.css({\n position: 'absolute'\n });\n};\n\n// trigger specified handler for event type\nproto.handleEvent = function( event ) {\n var method = 'on' + event.type;\n if ( this[ method ] ) {\n this[ method ]( event );\n }\n};\n\nproto.getSize = function() {\n this.size = getSize( this.element );\n};\n\n/**\n * apply CSS styles to element\n * @param {Object} style\n */\nproto.css = function( style ) {\n var elemStyle = this.element.style;\n\n for ( var prop in style ) {\n // use vendor property if available\n var supportedProp = vendorProperties[ prop ] || prop;\n elemStyle[ supportedProp ] = style[ prop ];\n }\n};\n\n // measure position, and sets it\nproto.getPosition = function() {\n var style = getComputedStyle( this.element );\n var isOriginLeft = this.layout._getOption('originLeft');\n var isOriginTop = this.layout._getOption('originTop');\n var xValue = style[ isOriginLeft ? 'left' : 'right' ];\n var yValue = style[ isOriginTop ? 'top' : 'bottom' ];\n // convert percent to pixels\n var layoutSize = this.layout.size;\n var x = xValue.indexOf('%') != -1 ?\n ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 );\n var y = yValue.indexOf('%') != -1 ?\n ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 );\n\n // clean up 'auto' or other non-integer values\n x = isNaN( x ) ? 0 : x;\n y = isNaN( y ) ? 0 : y;\n // remove padding from measurement\n x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;\n y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;\n\n this.position.x = x;\n this.position.y = y;\n};\n\n// set settled position, apply padding\nproto.layoutPosition = function() {\n var layoutSize = this.layout.size;\n var style = {};\n var isOriginLeft = this.layout._getOption('originLeft');\n var isOriginTop = this.layout._getOption('originTop');\n\n // x\n var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';\n var xProperty = isOriginLeft ? 'left' : 'right';\n var xResetProperty = isOriginLeft ? 'right' : 'left';\n\n var x = this.position.x + layoutSize[ xPadding ];\n // set in percentage or pixels\n style[ xProperty ] = this.getXValue( x );\n // reset other property\n style[ xResetProperty ] = '';\n\n // y\n var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';\n var yProperty = isOriginTop ? 'top' : 'bottom';\n var yResetProperty = isOriginTop ? 'bottom' : 'top';\n\n var y = this.position.y + layoutSize[ yPadding ];\n // set in percentage or pixels\n style[ yProperty ] = this.getYValue( y );\n // reset other property\n style[ yResetProperty ] = '';\n\n this.css( style );\n this.emitEvent( 'layout', [ this ] );\n};\n\nproto.getXValue = function( x ) {\n var isHorizontal = this.layout._getOption('horizontal');\n return this.layout.options.percentPosition && !isHorizontal ?\n ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';\n};\n\nproto.getYValue = function( y ) {\n var isHorizontal = this.layout._getOption('horizontal');\n return this.layout.options.percentPosition && isHorizontal ?\n ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';\n};\n\nproto._transitionTo = function( x, y ) {\n this.getPosition();\n // get current x & y from top/left\n var curX = this.position.x;\n var curY = this.position.y;\n\n var compareX = parseInt( x, 10 );\n var compareY = parseInt( y, 10 );\n var didNotMove = compareX === this.position.x && compareY === this.position.y;\n\n // save end position\n this.setPosition( x, y );\n\n // if did not move and not transitioning, just go to layout\n if ( didNotMove && !this.isTransitioning ) {\n this.layoutPosition();\n return;\n }\n\n var transX = x - curX;\n var transY = y - curY;\n var transitionStyle = {};\n transitionStyle.transform = this.getTranslate( transX, transY );\n\n this.transition({\n to: transitionStyle,\n onTransitionEnd: {\n transform: this.layoutPosition\n },\n isCleaning: true\n });\n};\n\nproto.getTranslate = function( x, y ) {\n // flip cooridinates if origin on right or bottom\n var isOriginLeft = this.layout._getOption('originLeft');\n var isOriginTop = this.layout._getOption('originTop');\n x = isOriginLeft ? x : -x;\n y = isOriginTop ? y : -y;\n return 'translate3d(' + x + 'px, ' + y + 'px, 0)';\n};\n\n// non transition + transform support\nproto.goTo = function( x, y ) {\n this.setPosition( x, y );\n this.layoutPosition();\n};\n\nproto.moveTo = proto._transitionTo;\n\nproto.setPosition = function( x, y ) {\n this.position.x = parseInt( x, 10 );\n this.position.y = parseInt( y, 10 );\n};\n\n// ----- transition ----- //\n\n/**\n * @param {Object} style - CSS\n * @param {Function} onTransitionEnd\n */\n\n// non transition, just trigger callback\nproto._nonTransition = function( args ) {\n this.css( args.to );\n if ( args.isCleaning ) {\n this._removeStyles( args.to );\n }\n for ( var prop in args.onTransitionEnd ) {\n args.onTransitionEnd[ prop ].call( this );\n }\n};\n\n/**\n * proper transition\n * @param {Object} args - arguments\n * @param {Object} to - style to transition to\n * @param {Object} from - style to start transition from\n * @param {Boolean} isCleaning - removes transition styles after transition\n * @param {Function} onTransitionEnd - callback\n */\nproto.transition = function( args ) {\n // redirect to nonTransition if no transition duration\n if ( !parseFloat( this.layout.options.transitionDuration ) ) {\n this._nonTransition( args );\n return;\n }\n\n var _transition = this._transn;\n // keep track of onTransitionEnd callback by css property\n for ( var prop in args.onTransitionEnd ) {\n _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];\n }\n // keep track of properties that are transitioning\n for ( prop in args.to ) {\n _transition.ingProperties[ prop ] = true;\n // keep track of properties to clean up when transition is done\n if ( args.isCleaning ) {\n _transition.clean[ prop ] = true;\n }\n }\n\n // set from styles\n if ( args.from ) {\n this.css( args.from );\n // force redraw. http://blog.alexmaccaw.com/css-transitions\n var h = this.element.offsetHeight;\n // hack for JSHint to hush about unused var\n h = null;\n }\n // enable transition\n this.enableTransition( args.to );\n // set styles that are transitioning\n this.css( args.to );\n\n this.isTransitioning = true;\n\n};\n\n// dash before all cap letters, including first for\n// WebkitTransform => -webkit-transform\nfunction toDashedAll( str ) {\n return str.replace( /([A-Z])/g, function( $1 ) {\n return '-' + $1.toLowerCase();\n });\n}\n\nvar transitionProps = 'opacity,' + toDashedAll( transformProperty );\n\nproto.enableTransition = function(/* style */) {\n // HACK changing transitionProperty during a transition\n // will cause transition to jump\n if ( this.isTransitioning ) {\n return;\n }\n\n // make `transition: foo, bar, baz` from style object\n // HACK un-comment this when enableTransition can work\n // while a transition is happening\n // var transitionValues = [];\n // for ( var prop in style ) {\n // // dash-ify camelCased properties like WebkitTransition\n // prop = vendorProperties[ prop ] || prop;\n // transitionValues.push( toDashedAll( prop ) );\n // }\n // munge number to millisecond, to match stagger\n var duration = this.layout.options.transitionDuration;\n duration = typeof duration == 'number' ? duration + 'ms' : duration;\n // enable transition styles\n this.css({\n transitionProperty: transitionProps,\n transitionDuration: duration,\n transitionDelay: this.staggerDelay || 0\n });\n // listen for transition end event\n this.element.addEventListener( transitionEndEvent, this, false );\n};\n\n// ----- events ----- //\n\nproto.onwebkitTransitionEnd = function( event ) {\n this.ontransitionend( event );\n};\n\nproto.onotransitionend = function( event ) {\n this.ontransitionend( event );\n};\n\n// properties that I munge to make my life easier\nvar dashedVendorProperties = {\n '-webkit-transform': 'transform'\n};\n\nproto.ontransitionend = function( event ) {\n // disregard bubbled events from children\n if ( event.target !== this.element ) {\n return;\n }\n var _transition = this._transn;\n // get property name of transitioned property, convert to prefix-free\n var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;\n\n // remove property that has completed transitioning\n delete _transition.ingProperties[ propertyName ];\n // check if any properties are still transitioning\n if ( isEmptyObj( _transition.ingProperties ) ) {\n // all properties have completed transitioning\n this.disableTransition();\n }\n // clean style\n if ( propertyName in _transition.clean ) {\n // clean up style\n this.element.style[ event.propertyName ] = '';\n delete _transition.clean[ propertyName ];\n }\n // trigger onTransitionEnd callback\n if ( propertyName in _transition.onEnd ) {\n var onTransitionEnd = _transition.onEnd[ propertyName ];\n onTransitionEnd.call( this );\n delete _transition.onEnd[ propertyName ];\n }\n\n this.emitEvent( 'transitionEnd', [ this ] );\n};\n\nproto.disableTransition = function() {\n this.removeTransitionStyles();\n this.element.removeEventListener( transitionEndEvent, this, false );\n this.isTransitioning = false;\n};\n\n/**\n * removes style property from element\n * @param {Object} style\n**/\nproto._removeStyles = function( style ) {\n // clean up transition styles\n var cleanStyle = {};\n for ( var prop in style ) {\n cleanStyle[ prop ] = '';\n }\n this.css( cleanStyle );\n};\n\nvar cleanTransitionStyle = {\n transitionProperty: '',\n transitionDuration: '',\n transitionDelay: ''\n};\n\nproto.removeTransitionStyles = function() {\n // remove transition\n this.css( cleanTransitionStyle );\n};\n\n// ----- stagger ----- //\n\nproto.stagger = function( delay ) {\n delay = isNaN( delay ) ? 0 : delay;\n this.staggerDelay = delay + 'ms';\n};\n\n// ----- show/hide/remove ----- //\n\n// remove element from DOM\nproto.removeElem = function() {\n this.element.parentNode.removeChild( this.element );\n // remove display: none\n this.css({ display: '' });\n this.emitEvent( 'remove', [ this ] );\n};\n\nproto.remove = function() {\n // just remove element if no transition support or no transition\n if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {\n this.removeElem();\n return;\n }\n\n // start transition\n this.once( 'transitionEnd', function() {\n this.removeElem();\n });\n this.hide();\n};\n\nproto.reveal = function() {\n delete this.isHidden;\n // remove display: none\n this.css({ display: '' });\n\n var options = this.layout.options;\n\n var onTransitionEnd = {};\n var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');\n onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;\n\n this.transition({\n from: options.hiddenStyle,\n to: options.visibleStyle,\n isCleaning: true,\n onTransitionEnd: onTransitionEnd\n });\n};\n\nproto.onRevealTransitionEnd = function() {\n // check if still visible\n // during transition, item may have been hidden\n if ( !this.isHidden ) {\n this.emitEvent('reveal');\n }\n};\n\n/**\n * get style property use for hide/reveal transition end\n * @param {String} styleProperty - hiddenStyle/visibleStyle\n * @returns {String}\n */\nproto.getHideRevealTransitionEndProperty = function( styleProperty ) {\n var optionStyle = this.layout.options[ styleProperty ];\n // use opacity\n if ( optionStyle.opacity ) {\n return 'opacity';\n }\n // get first property\n for ( var prop in optionStyle ) {\n return prop;\n }\n};\n\nproto.hide = function() {\n // set flag\n this.isHidden = true;\n // remove display: none\n this.css({ display: '' });\n\n var options = this.layout.options;\n\n var onTransitionEnd = {};\n var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');\n onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;\n\n this.transition({\n from: options.visibleStyle,\n to: options.hiddenStyle,\n // keep hidden stuff hidden\n isCleaning: true,\n onTransitionEnd: onTransitionEnd\n });\n};\n\nproto.onHideTransitionEnd = function() {\n // check if still hidden\n // during transition, item may have been un-hidden\n if ( this.isHidden ) {\n this.css({ display: 'none' });\n this.emitEvent('hide');\n }\n};\n\nproto.destroy = function() {\n this.css({\n position: '',\n left: '',\n right: '',\n top: '',\n bottom: '',\n transition: '',\n transform: ''\n });\n};\n\nreturn Item;\n\n}));\n\n/*!\n * Outlayer v2.1.0\n * the brains and guts of a layout library\n * MIT license\n */\n\n( function( window, factory ) {\n 'use strict';\n // universal module definition\n /* jshint strict: false */ /* globals define, module, require */\n if ( typeof define == 'function' && define.amd ) {\n // AMD - RequireJS\n define( 'outlayer/outlayer',[\n 'ev-emitter/ev-emitter',\n 'get-size/get-size',\n 'fizzy-ui-utils/utils',\n './item'\n ],\n function( EvEmitter, getSize, utils, Item ) {\n return factory( window, EvEmitter, getSize, utils, Item);\n }\n );\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS - Browserify, Webpack\n module.exports = factory(\n window,\n require('ev-emitter'),\n require('get-size'),\n require('fizzy-ui-utils'),\n require('./item')\n );\n } else {\n // browser global\n window.Outlayer = factory(\n window,\n window.EvEmitter,\n window.getSize,\n window.fizzyUIUtils,\n window.Outlayer.Item\n );\n }\n\n}( window, function factory( window, EvEmitter, getSize, utils, Item ) {\n'use strict';\n\n// ----- vars ----- //\n\nvar console = window.console;\nvar jQuery = window.jQuery;\nvar noop = function() {};\n\n// -------------------------- Outlayer -------------------------- //\n\n// globally unique identifiers\nvar GUID = 0;\n// internal store of all Outlayer intances\nvar instances = {};\n\n\n/**\n * @param {Element, String} element\n * @param {Object} options\n * @constructor\n */\nfunction Outlayer( element, options ) {\n var queryElement = utils.getQueryElement( element );\n if ( !queryElement ) {\n if ( console ) {\n console.error( 'Bad element for ' + this.constructor.namespace +\n ': ' + ( queryElement || element ) );\n }\n return;\n }\n this.element = queryElement;\n // add jQuery\n if ( jQuery ) {\n this.$element = jQuery( this.element );\n }\n\n // options\n this.options = utils.extend( {}, this.constructor.defaults );\n this.option( options );\n\n // add id for Outlayer.getFromElement\n var id = ++GUID;\n this.element.outlayerGUID = id; // expando\n instances[ id ] = this; // associate via id\n\n // kick it off\n this._create();\n\n var isInitLayout = this._getOption('initLayout');\n if ( isInitLayout ) {\n this.layout();\n }\n}\n\n// settings are for internal use only\nOutlayer.namespace = 'outlayer';\nOutlayer.Item = Item;\n\n// default options\nOutlayer.defaults = {\n containerStyle: {\n position: 'relative'\n },\n initLayout: true,\n originLeft: true,\n originTop: true,\n resize: true,\n resizeContainer: true,\n // item options\n transitionDuration: '0.4s',\n hiddenStyle: {\n opacity: 0,\n transform: 'scale(0.001)'\n },\n visibleStyle: {\n opacity: 1,\n transform: 'scale(1)'\n }\n};\n\nvar proto = Outlayer.prototype;\n// inherit EvEmitter\nutils.extend( proto, EvEmitter.prototype );\n\n/**\n * set options\n * @param {Object} opts\n */\nproto.option = function( opts ) {\n utils.extend( this.options, opts );\n};\n\n/**\n * get backwards compatible option value, check old name\n */\nproto._getOption = function( option ) {\n var oldOption = this.constructor.compatOptions[ option ];\n return oldOption && this.options[ oldOption ] !== undefined ?\n this.options[ oldOption ] : this.options[ option ];\n};\n\nOutlayer.compatOptions = {\n // currentName: oldName\n initLayout: 'isInitLayout',\n horizontal: 'isHorizontal',\n layoutInstant: 'isLayoutInstant',\n originLeft: 'isOriginLeft',\n originTop: 'isOriginTop',\n resize: 'isResizeBound',\n resizeContainer: 'isResizingContainer'\n};\n\nproto._create = function() {\n // get items from children\n this.reloadItems();\n // elements that affect layout, but are not laid out\n this.stamps = [];\n this.stamp( this.options.stamp );\n // set container style\n utils.extend( this.element.style, this.options.containerStyle );\n\n // bind resize method\n var canBindResize = this._getOption('resize');\n if ( canBindResize ) {\n this.bindResize();\n }\n};\n\n// goes through all children again and gets bricks in proper order\nproto.reloadItems = function() {\n // collection of item elements\n this.items = this._itemize( this.element.children );\n};\n\n\n/**\n * turn elements into Outlayer.Items to be used in layout\n * @param {Array or NodeList or HTMLElement} elems\n * @returns {Array} items - collection of new Outlayer Items\n */\nproto._itemize = function( elems ) {\n\n var itemElems = this._filterFindItemElements( elems );\n var Item = this.constructor.Item;\n\n // create new Outlayer Items for collection\n var items = [];\n for ( var i=0; i < itemElems.length; i++ ) {\n var elem = itemElems[i];\n var item = new Item( elem, this );\n items.push( item );\n }\n\n return items;\n};\n\n/**\n * get item elements to be used in layout\n * @param {Array or NodeList or HTMLElement} elems\n * @returns {Array} items - item elements\n */\nproto._filterFindItemElements = function( elems ) {\n return utils.filterFindElements( elems, this.options.itemSelector );\n};\n\n/**\n * getter method for getting item elements\n * @returns {Array} elems - collection of item elements\n */\nproto.getItemElements = function() {\n return this.items.map( function( item ) {\n return item.element;\n });\n};\n\n// ----- init & layout ----- //\n\n/**\n * lays out all items\n */\nproto.layout = function() {\n this._resetLayout();\n this._manageStamps();\n\n // don't animate first layout\n var layoutInstant = this._getOption('layoutInstant');\n var isInstant = layoutInstant !== undefined ?\n layoutInstant : !this._isLayoutInited;\n this.layoutItems( this.items, isInstant );\n\n // flag for initalized\n this._isLayoutInited = true;\n};\n\n// _init is alias for layout\nproto._init = proto.layout;\n\n/**\n * logic before any new layout\n */\nproto._resetLayout = function() {\n this.getSize();\n};\n\n\nproto.getSize = function() {\n this.size = getSize( this.element );\n};\n\n/**\n * get measurement from option, for columnWidth, rowHeight, gutter\n * if option is String -> get element from selector string, & get size of element\n * if option is Element -> get size of element\n * else use option as a number\n *\n * @param {String} measurement\n * @param {String} size - width or height\n * @private\n */\nproto._getMeasurement = function( measurement, size ) {\n var option = this.options[ measurement ];\n var elem;\n if ( !option ) {\n // default to 0\n this[ measurement ] = 0;\n } else {\n // use option as an element\n if ( typeof option == 'string' ) {\n elem = this.element.querySelector( option );\n } else if ( option instanceof HTMLElement ) {\n elem = option;\n }\n // use size of element, if element\n this[ measurement ] = elem ? getSize( elem )[ size ] : option;\n }\n};\n\n/**\n * layout a collection of item elements\n * @api public\n */\nproto.layoutItems = function( items, isInstant ) {\n items = this._getItemsForLayout( items );\n\n this._layoutItems( items, isInstant );\n\n this._postLayout();\n};\n\n/**\n * get the items to be laid out\n * you may want to skip over some items\n * @param {Array} items\n * @returns {Array} items\n */\nproto._getItemsForLayout = function( items ) {\n return items.filter( function( item ) {\n return !item.isIgnored;\n });\n};\n\n/**\n * layout items\n * @param {Array} items\n * @param {Boolean} isInstant\n */\nproto._layoutItems = function( items, isInstant ) {\n this._emitCompleteOnItems( 'layout', items );\n\n if ( !items || !items.length ) {\n // no items, emit event with empty array\n return;\n }\n\n var queue = [];\n\n items.forEach( function( item ) {\n // get x/y object from method\n var position = this._getItemLayoutPosition( item );\n // enqueue\n position.item = item;\n position.isInstant = isInstant || item.isLayoutInstant;\n queue.push( position );\n }, this );\n\n this._processLayoutQueue( queue );\n};\n\n/**\n * get item layout position\n * @param {Outlayer.Item} item\n * @returns {Object} x and y position\n */\nproto._getItemLayoutPosition = function( /* item */ ) {\n return {\n x: 0,\n y: 0\n };\n};\n\n/**\n * iterate over array and position each item\n * Reason being - separating this logic prevents 'layout invalidation'\n * thx @paul_irish\n * @param {Array} queue\n */\nproto._processLayoutQueue = function( queue ) {\n this.updateStagger();\n queue.forEach( function( obj, i ) {\n this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );\n }, this );\n};\n\n// set stagger from option in milliseconds number\nproto.updateStagger = function() {\n var stagger = this.options.stagger;\n if ( stagger === null || stagger === undefined ) {\n this.stagger = 0;\n return;\n }\n this.stagger = getMilliseconds( stagger );\n return this.stagger;\n};\n\n/**\n * Sets position of item in DOM\n * @param {Outlayer.Item} item\n * @param {Number} x - horizontal position\n * @param {Number} y - vertical position\n * @param {Boolean} isInstant - disables transitions\n */\nproto._positionItem = function( item, x, y, isInstant, i ) {\n if ( isInstant ) {\n // if not transition, just set CSS\n item.goTo( x, y );\n } else {\n item.stagger( i * this.stagger );\n item.moveTo( x, y );\n }\n};\n\n/**\n * Any logic you want to do after each layout,\n * i.e. size the container\n */\nproto._postLayout = function() {\n this.resizeContainer();\n};\n\nproto.resizeContainer = function() {\n var isResizingContainer = this._getOption('resizeContainer');\n if ( !isResizingContainer ) {\n return;\n }\n var size = this._getContainerSize();\n if ( size ) {\n this._setContainerMeasure( size.width, true );\n this._setContainerMeasure( size.height, false );\n }\n};\n\n/**\n * Sets width or height of container if returned\n * @returns {Object} size\n * @param {Number} width\n * @param {Number} height\n */\nproto._getContainerSize = noop;\n\n/**\n * @param {Number} measure - size of width or height\n * @param {Boolean} isWidth\n */\nproto._setContainerMeasure = function( measure, isWidth ) {\n if ( measure === undefined ) {\n return;\n }\n\n var elemSize = this.size;\n // add padding and border width if border box\n if ( elemSize.isBorderBox ) {\n measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +\n elemSize.borderLeftWidth + elemSize.borderRightWidth :\n elemSize.paddingBottom + elemSize.paddingTop +\n elemSize.borderTopWidth + elemSize.borderBottomWidth;\n }\n\n measure = Math.max( measure, 0 );\n this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';\n};\n\n/**\n * emit eventComplete on a collection of items events\n * @param {String} eventName\n * @param {Array} items - Outlayer.Items\n */\nproto._emitCompleteOnItems = function( eventName, items ) {\n var _this = this;\n function onComplete() {\n _this.dispatchEvent( eventName + 'Complete', null, [ items ] );\n }\n\n var count = items.length;\n if ( !items || !count ) {\n onComplete();\n return;\n }\n\n var doneCount = 0;\n function tick() {\n doneCount++;\n if ( doneCount == count ) {\n onComplete();\n }\n }\n\n // bind callback\n items.forEach( function( item ) {\n item.once( eventName, tick );\n });\n};\n\n/**\n * emits events via EvEmitter and jQuery events\n * @param {String} type - name of event\n * @param {Event} event - original event\n * @param {Array} args - extra arguments\n */\nproto.dispatchEvent = function( type, event, args ) {\n // add original event to arguments\n var emitArgs = event ? [ event ].concat( args ) : args;\n this.emitEvent( type, emitArgs );\n\n if ( jQuery ) {\n // set this.$element\n this.$element = this.$element || jQuery( this.element );\n if ( event ) {\n // create jQuery event\n var $event = jQuery.Event( event );\n $event.type = type;\n this.$element.trigger( $event, args );\n } else {\n // just trigger with type if no event available\n this.$element.trigger( type, args );\n }\n }\n};\n\n// -------------------------- ignore & stamps -------------------------- //\n\n\n/**\n * keep item in collection, but do not lay it out\n * ignored items do not get skipped in layout\n * @param {Element} elem\n */\nproto.ignore = function( elem ) {\n var item = this.getItem( elem );\n if ( item ) {\n item.isIgnored = true;\n }\n};\n\n/**\n * return item to layout collection\n * @param {Element} elem\n */\nproto.unignore = function( elem ) {\n var item = this.getItem( elem );\n if ( item ) {\n delete item.isIgnored;\n }\n};\n\n/**\n * adds elements to stamps\n * @param {NodeList, Array, Element, or String} elems\n */\nproto.stamp = function( elems ) {\n elems = this._find( elems );\n if ( !elems ) {\n return;\n }\n\n this.stamps = this.stamps.concat( elems );\n // ignore\n elems.forEach( this.ignore, this );\n};\n\n/**\n * removes elements to stamps\n * @param {NodeList, Array, or Element} elems\n */\nproto.unstamp = function( elems ) {\n elems = this._find( elems );\n if ( !elems ){\n return;\n }\n\n elems.forEach( function( elem ) {\n // filter out removed stamp elements\n utils.removeFrom( this.stamps, elem );\n this.unignore( elem );\n }, this );\n};\n\n/**\n * finds child elements\n * @param {NodeList, Array, Element, or String} elems\n * @returns {Array} elems\n */\nproto._find = function( elems ) {\n if ( !elems ) {\n return;\n }\n // if string, use argument as selector string\n if ( typeof elems == 'string' ) {\n elems = this.element.querySelectorAll( elems );\n }\n elems = utils.makeArray( elems );\n return elems;\n};\n\nproto._manageStamps = function() {\n if ( !this.stamps || !this.stamps.length ) {\n return;\n }\n\n this._getBoundingRect();\n\n this.stamps.forEach( this._manageStamp, this );\n};\n\n// update boundingLeft / Top\nproto._getBoundingRect = function() {\n // get bounding rect for container element\n var boundingRect = this.element.getBoundingClientRect();\n var size = this.size;\n this._boundingRect = {\n left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,\n top: boundingRect.top + size.paddingTop + size.borderTopWidth,\n right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),\n bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )\n };\n};\n\n/**\n * @param {Element} stamp\n**/\nproto._manageStamp = noop;\n\n/**\n * get x/y position of element relative to container element\n * @param {Element} elem\n * @returns {Object} offset - has left, top, right, bottom\n */\nproto._getElementOffset = function( elem ) {\n var boundingRect = elem.getBoundingClientRect();\n var thisRect = this._boundingRect;\n var size = getSize( elem );\n var offset = {\n left: boundingRect.left - thisRect.left - size.marginLeft,\n top: boundingRect.top - thisRect.top - size.marginTop,\n right: thisRect.right - boundingRect.right - size.marginRight,\n bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom\n };\n return offset;\n};\n\n// -------------------------- resize -------------------------- //\n\n// enable event handlers for listeners\n// i.e. resize -> onresize\nproto.handleEvent = utils.handleEvent;\n\n/**\n * Bind layout to window resizing\n */\nproto.bindResize = function() {\n window.addEventListener( 'resize', this );\n this.isResizeBound = true;\n};\n\n/**\n * Unbind layout to window resizing\n */\nproto.unbindResize = function() {\n window.removeEventListener( 'resize', this );\n this.isResizeBound = false;\n};\n\nproto.onresize = function() {\n this.resize();\n};\n\nutils.debounceMethod( Outlayer, 'onresize', 100 );\n\nproto.resize = function() {\n // don't trigger if size did not change\n // or if resize was unbound. See #9\n if ( !this.isResizeBound || !this.needsResizeLayout() ) {\n return;\n }\n\n this.layout();\n};\n\n/**\n * check if layout is needed post layout\n * @returns Boolean\n */\nproto.needsResizeLayout = function() {\n var size = getSize( this.element );\n // check that this.size and size are there\n // IE8 triggers resize on body size change, so they might not be\n var hasSizes = this.size && size;\n return hasSizes && size.innerWidth !== this.size.innerWidth;\n};\n\n// -------------------------- methods -------------------------- //\n\n/**\n * add items to Outlayer instance\n * @param {Array or NodeList or Element} elems\n * @returns {Array} items - Outlayer.Items\n**/\nproto.addItems = function( elems ) {\n var items = this._itemize( elems );\n // add items to collection\n if ( items.length ) {\n this.items = this.items.concat( items );\n }\n return items;\n};\n\n/**\n * Layout newly-appended item elements\n * @param {Array or NodeList or Element} elems\n */\nproto.appended = function( elems ) {\n var items = this.addItems( elems );\n if ( !items.length ) {\n return;\n }\n // layout and reveal just the new items\n this.layoutItems( items, true );\n this.reveal( items );\n};\n\n/**\n * Layout prepended elements\n * @param {Array or NodeList or Element} elems\n */\nproto.prepended = function( elems ) {\n var items = this._itemize( elems );\n if ( !items.length ) {\n return;\n }\n // add items to beginning of collection\n var previousItems = this.items.slice(0);\n this.items = items.concat( previousItems );\n // start new layout\n this._resetLayout();\n this._manageStamps();\n // layout new stuff without transition\n this.layoutItems( items, true );\n this.reveal( items );\n // layout previous items\n this.layoutItems( previousItems );\n};\n\n/**\n * reveal a collection of items\n * @param {Array of Outlayer.Items} items\n */\nproto.reveal = function( items ) {\n this._emitCompleteOnItems( 'reveal', items );\n if ( !items || !items.length ) {\n return;\n }\n var stagger = this.updateStagger();\n items.forEach( function( item, i ) {\n item.stagger( i * stagger );\n item.reveal();\n });\n};\n\n/**\n * hide a collection of items\n * @param {Array of Outlayer.Items} items\n */\nproto.hide = function( items ) {\n this._emitCompleteOnItems( 'hide', items );\n if ( !items || !items.length ) {\n return;\n }\n var stagger = this.updateStagger();\n items.forEach( function( item, i ) {\n item.stagger( i * stagger );\n item.hide();\n });\n};\n\n/**\n * reveal item elements\n * @param {Array}, {Element}, {NodeList} items\n */\nproto.revealItemElements = function( elems ) {\n var items = this.getItems( elems );\n this.reveal( items );\n};\n\n/**\n * hide item elements\n * @param {Array}, {Element}, {NodeList} items\n */\nproto.hideItemElements = function( elems ) {\n var items = this.getItems( elems );\n this.hide( items );\n};\n\n/**\n * get Outlayer.Item, given an Element\n * @param {Element} elem\n * @param {Function} callback\n * @returns {Outlayer.Item} item\n */\nproto.getItem = function( elem ) {\n // loop through items to get the one that matches\n for ( var i=0; i < this.items.length; i++ ) {\n var item = this.items[i];\n if ( item.element == elem ) {\n // return item\n return item;\n }\n }\n};\n\n/**\n * get collection of Outlayer.Items, given Elements\n * @param {Array} elems\n * @returns {Array} items - Outlayer.Items\n */\nproto.getItems = function( elems ) {\n elems = utils.makeArray( elems );\n var items = [];\n elems.forEach( function( elem ) {\n var item = this.getItem( elem );\n if ( item ) {\n items.push( item );\n }\n }, this );\n\n return items;\n};\n\n/**\n * remove element(s) from instance and DOM\n * @param {Array or NodeList or Element} elems\n */\nproto.remove = function( elems ) {\n var removeItems = this.getItems( elems );\n\n this._emitCompleteOnItems( 'remove', removeItems );\n\n // bail if no items to remove\n if ( !removeItems || !removeItems.length ) {\n return;\n }\n\n removeItems.forEach( function( item ) {\n item.remove();\n // remove item from collection\n utils.removeFrom( this.items, item );\n }, this );\n};\n\n// ----- destroy ----- //\n\n// remove and disable Outlayer instance\nproto.destroy = function() {\n // clean up dynamic styles\n var style = this.element.style;\n style.height = '';\n style.position = '';\n style.width = '';\n // destroy items\n this.items.forEach( function( item ) {\n item.destroy();\n });\n\n this.unbindResize();\n\n var id = this.element.outlayerGUID;\n delete instances[ id ]; // remove reference to instance by id\n delete this.element.outlayerGUID;\n // remove data for jQuery\n if ( jQuery ) {\n jQuery.removeData( this.element, this.constructor.namespace );\n }\n\n};\n\n// -------------------------- data -------------------------- //\n\n/**\n * get Outlayer instance from element\n * @param {Element} elem\n * @returns {Outlayer}\n */\nOutlayer.data = function( elem ) {\n elem = utils.getQueryElement( elem );\n var id = elem && elem.outlayerGUID;\n return id && instances[ id ];\n};\n\n\n// -------------------------- create Outlayer class -------------------------- //\n\n/**\n * create a layout class\n * @param {String} namespace\n */\nOutlayer.create = function( namespace, options ) {\n // sub-class Outlayer\n var Layout = subclass( Outlayer );\n // apply new options and compatOptions\n Layout.defaults = utils.extend( {}, Outlayer.defaults );\n utils.extend( Layout.defaults, options );\n Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions );\n\n Layout.namespace = namespace;\n\n Layout.data = Outlayer.data;\n\n // sub-class Item\n Layout.Item = subclass( Item );\n\n // -------------------------- declarative -------------------------- //\n\n utils.htmlInit( Layout, namespace );\n\n // -------------------------- jQuery bridge -------------------------- //\n\n // make into jQuery plugin\n if ( jQuery && jQuery.bridget ) {\n jQuery.bridget( namespace, Layout );\n }\n\n return Layout;\n};\n\nfunction subclass( Parent ) {\n function SubClass() {\n Parent.apply( this, arguments );\n }\n\n SubClass.prototype = Object.create( Parent.prototype );\n SubClass.prototype.constructor = SubClass;\n\n return SubClass;\n}\n\n// ----- helpers ----- //\n\n// how many milliseconds are in each unit\nvar msUnits = {\n ms: 1,\n s: 1000\n};\n\n// munge time-like parameter into millisecond number\n// '0.4s' -> 40\nfunction getMilliseconds( time ) {\n if ( typeof time == 'number' ) {\n return time;\n }\n var matches = time.match( /(^\\d*\\.?\\d*)(\\w*)/ );\n var num = matches && matches[1];\n var unit = matches && matches[2];\n if ( !num.length ) {\n return 0;\n }\n num = parseFloat( num );\n var mult = msUnits[ unit ] || 1;\n return num * mult;\n}\n\n// ----- fin ----- //\n\n// back in global\nOutlayer.Item = Item;\n\nreturn Outlayer;\n\n}));\n\n/**\n * Isotope Item\n**/\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'isotope/js/item',[\n 'outlayer/outlayer'\n ],\n factory );\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('outlayer')\n );\n } else {\n // browser global\n window.Isotope = window.Isotope || {};\n window.Isotope.Item = factory(\n window.Outlayer\n );\n }\n\n}( window, function factory( Outlayer ) {\n'use strict';\n\n// -------------------------- Item -------------------------- //\n\n// sub-class Outlayer Item\nfunction Item() {\n Outlayer.Item.apply( this, arguments );\n}\n\nvar proto = Item.prototype = Object.create( Outlayer.Item.prototype );\n\nvar _create = proto._create;\nproto._create = function() {\n // assign id, used for original-order sorting\n this.id = this.layout.itemGUID++;\n _create.call( this );\n this.sortData = {};\n};\n\nproto.updateSortData = function() {\n if ( this.isIgnored ) {\n return;\n }\n // default sorters\n this.sortData.id = this.id;\n // for backward compatibility\n this.sortData['original-order'] = this.id;\n this.sortData.random = Math.random();\n // go thru getSortData obj and apply the sorters\n var getSortData = this.layout.options.getSortData;\n var sorters = this.layout._sorters;\n for ( var key in getSortData ) {\n var sorter = sorters[ key ];\n this.sortData[ key ] = sorter( this.element, this );\n }\n};\n\nvar _destroy = proto.destroy;\nproto.destroy = function() {\n // call super\n _destroy.apply( this, arguments );\n // reset display, #741\n this.css({\n display: ''\n });\n};\n\nreturn Item;\n\n}));\n\n/**\n * Isotope LayoutMode\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'isotope/js/layout-mode',[\n 'get-size/get-size',\n 'outlayer/outlayer'\n ],\n factory );\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('get-size'),\n require('outlayer')\n );\n } else {\n // browser global\n window.Isotope = window.Isotope || {};\n window.Isotope.LayoutMode = factory(\n window.getSize,\n window.Outlayer\n );\n }\n\n}( window, function factory( getSize, Outlayer ) {\n 'use strict';\n\n // layout mode class\n function LayoutMode( isotope ) {\n this.isotope = isotope;\n // link properties\n if ( isotope ) {\n this.options = isotope.options[ this.namespace ];\n this.element = isotope.element;\n this.items = isotope.filteredItems;\n this.size = isotope.size;\n }\n }\n\n var proto = LayoutMode.prototype;\n\n /**\n * some methods should just defer to default Outlayer method\n * and reference the Isotope instance as `this`\n **/\n var facadeMethods = [\n '_resetLayout',\n '_getItemLayoutPosition',\n '_manageStamp',\n '_getContainerSize',\n '_getElementOffset',\n 'needsResizeLayout',\n '_getOption'\n ];\n\n facadeMethods.forEach( function( methodName ) {\n proto[ methodName ] = function() {\n return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );\n };\n });\n\n // ----- ----- //\n\n // for horizontal layout modes, check vertical size\n proto.needsVerticalResizeLayout = function() {\n // don't trigger if size did not change\n var size = getSize( this.isotope.element );\n // check that this.size and size are there\n // IE8 triggers resize on body size change, so they might not be\n var hasSizes = this.isotope.size && size;\n return hasSizes && size.innerHeight != this.isotope.size.innerHeight;\n };\n\n // ----- measurements ----- //\n\n proto._getMeasurement = function() {\n this.isotope._getMeasurement.apply( this, arguments );\n };\n\n proto.getColumnWidth = function() {\n this.getSegmentSize( 'column', 'Width' );\n };\n\n proto.getRowHeight = function() {\n this.getSegmentSize( 'row', 'Height' );\n };\n\n /**\n * get columnWidth or rowHeight\n * segment: 'column' or 'row'\n * size 'Width' or 'Height'\n **/\n proto.getSegmentSize = function( segment, size ) {\n var segmentName = segment + size;\n var outerSize = 'outer' + size;\n // columnWidth / outerWidth // rowHeight / outerHeight\n this._getMeasurement( segmentName, outerSize );\n // got rowHeight or columnWidth, we can chill\n if ( this[ segmentName ] ) {\n return;\n }\n // fall back to item of first element\n var firstItemSize = this.getFirstItemSize();\n this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||\n // or size of container\n this.isotope.size[ 'inner' + size ];\n };\n\n proto.getFirstItemSize = function() {\n var firstItem = this.isotope.filteredItems[0];\n return firstItem && firstItem.element && getSize( firstItem.element );\n };\n\n // ----- methods that should reference isotope ----- //\n\n proto.layout = function() {\n this.isotope.layout.apply( this.isotope, arguments );\n };\n\n proto.getSize = function() {\n this.isotope.getSize();\n this.size = this.isotope.size;\n };\n\n // -------------------------- create -------------------------- //\n\n LayoutMode.modes = {};\n\n LayoutMode.create = function( namespace, options ) {\n\n function Mode() {\n LayoutMode.apply( this, arguments );\n }\n\n Mode.prototype = Object.create( proto );\n Mode.prototype.constructor = Mode;\n\n // default options\n if ( options ) {\n Mode.options = options;\n }\n\n Mode.prototype.namespace = namespace;\n // register in Isotope\n LayoutMode.modes[ namespace ] = Mode;\n\n return Mode;\n };\n\n return LayoutMode;\n\n}));\n\n/*!\n * Masonry v4.2.0\n * Cascading grid layout library\n * http://masonry.desandro.com\n * MIT License\n * by David DeSandro\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'masonry/masonry',[\n 'outlayer/outlayer',\n 'get-size/get-size'\n ],\n factory );\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('outlayer'),\n require('get-size')\n );\n } else {\n // browser global\n window.Masonry = factory(\n window.Outlayer,\n window.getSize\n );\n }\n\n}( window, function factory( Outlayer, getSize ) {\n\n\n\n// -------------------------- masonryDefinition -------------------------- //\n\n // create an Outlayer layout class\n var Masonry = Outlayer.create('masonry');\n // isFitWidth -> fitWidth\n Masonry.compatOptions.fitWidth = 'isFitWidth';\n\n var proto = Masonry.prototype;\n\n proto._resetLayout = function() {\n this.getSize();\n this._getMeasurement( 'columnWidth', 'outerWidth' );\n this._getMeasurement( 'gutter', 'outerWidth' );\n this.measureColumns();\n\n // reset column Y\n this.colYs = [];\n for ( var i=0; i < this.cols; i++ ) {\n this.colYs.push( 0 );\n }\n\n this.maxY = 0;\n this.horizontalColIndex = 0;\n };\n\n proto.measureColumns = function() {\n this.getContainerWidth();\n // if columnWidth is 0, default to outerWidth of first item\n if ( !this.columnWidth ) {\n var firstItem = this.items[0];\n var firstItemElem = firstItem && firstItem.element;\n // columnWidth fall back to item of first element\n this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||\n // if first elem has no width, default to size of container\n this.containerWidth;\n }\n\n var columnWidth = this.columnWidth += this.gutter;\n\n // calculate columns\n var containerWidth = this.containerWidth + this.gutter;\n var cols = containerWidth / columnWidth;\n // fix rounding errors, typically with gutters\n var excess = columnWidth - containerWidth % columnWidth;\n // if overshoot is less than a pixel, round up, otherwise floor it\n var mathMethod = excess && excess < 1 ? 'round' : 'floor';\n cols = Math[ mathMethod ]( cols );\n this.cols = Math.max( cols, 1 );\n };\n\n proto.getContainerWidth = function() {\n // container is parent if fit width\n var isFitWidth = this._getOption('fitWidth');\n var container = isFitWidth ? this.element.parentNode : this.element;\n // check that this.size and size are there\n // IE8 triggers resize on body size change, so they might not be\n var size = getSize( container );\n this.containerWidth = size && size.innerWidth;\n };\n\n proto._getItemLayoutPosition = function( item ) {\n item.getSize();\n // how many columns does this brick span\n var remainder = item.size.outerWidth % this.columnWidth;\n var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';\n // round if off by 1 pixel, otherwise use ceil\n var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );\n colSpan = Math.min( colSpan, this.cols );\n // use horizontal or top column position\n var colPosMethod = this.options.horizontalOrder ?\n '_getHorizontalColPosition' : '_getTopColPosition';\n var colPosition = this[ colPosMethod ]( colSpan, item );\n // position the brick\n var position = {\n x: this.columnWidth * colPosition.col,\n y: colPosition.y\n };\n // apply setHeight to necessary columns\n var setHeight = colPosition.y + item.size.outerHeight;\n var setMax = colSpan + colPosition.col;\n for ( var i = colPosition.col; i < setMax; i++ ) {\n this.colYs[i] = setHeight;\n }\n\n return position;\n };\n\n proto._getTopColPosition = function( colSpan ) {\n var colGroup = this._getTopColGroup( colSpan );\n // get the minimum Y value from the columns\n var minimumY = Math.min.apply( Math, colGroup );\n\n return {\n col: colGroup.indexOf( minimumY ),\n y: minimumY,\n };\n };\n\n /**\n * @param {Number} colSpan - number of columns the element spans\n * @returns {Array} colGroup\n */\n proto._getTopColGroup = function( colSpan ) {\n if ( colSpan < 2 ) {\n // if brick spans only one column, use all the column Ys\n return this.colYs;\n }\n\n var colGroup = [];\n // how many different places could this brick fit horizontally\n var groupCount = this.cols + 1 - colSpan;\n // for each group potential horizontal position\n for ( var i = 0; i < groupCount; i++ ) {\n colGroup[i] = this._getColGroupY( i, colSpan );\n }\n return colGroup;\n };\n\n proto._getColGroupY = function( col, colSpan ) {\n if ( colSpan < 2 ) {\n return this.colYs[ col ];\n }\n // make an array of colY values for that one group\n var groupColYs = this.colYs.slice( col, col + colSpan );\n // and get the max value of the array\n return Math.max.apply( Math, groupColYs );\n };\n\n // get column position based on horizontal index. #873\n proto._getHorizontalColPosition = function( colSpan, item ) {\n var col = this.horizontalColIndex % this.cols;\n var isOver = colSpan > 1 && col + colSpan > this.cols;\n // shift to next row if item can't fit on current row\n col = isOver ? 0 : col;\n // don't let zero-size items take up space\n var hasSize = item.size.outerWidth && item.size.outerHeight;\n this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;\n\n return {\n col: col,\n y: this._getColGroupY( col, colSpan ),\n };\n };\n\n proto._manageStamp = function( stamp ) {\n var stampSize = getSize( stamp );\n var offset = this._getElementOffset( stamp );\n // get the columns that this stamp affects\n var isOriginLeft = this._getOption('originLeft');\n var firstX = isOriginLeft ? offset.left : offset.right;\n var lastX = firstX + stampSize.outerWidth;\n var firstCol = Math.floor( firstX / this.columnWidth );\n firstCol = Math.max( 0, firstCol );\n var lastCol = Math.floor( lastX / this.columnWidth );\n // lastCol should not go over if multiple of columnWidth #425\n lastCol -= lastX % this.columnWidth ? 0 : 1;\n lastCol = Math.min( this.cols - 1, lastCol );\n // set colYs to bottom of the stamp\n\n var isOriginTop = this._getOption('originTop');\n var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +\n stampSize.outerHeight;\n for ( var i = firstCol; i <= lastCol; i++ ) {\n this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );\n }\n };\n\n proto._getContainerSize = function() {\n this.maxY = Math.max.apply( Math, this.colYs );\n var size = {\n height: this.maxY\n };\n\n if ( this._getOption('fitWidth') ) {\n size.width = this._getContainerFitWidth();\n }\n\n return size;\n };\n\n proto._getContainerFitWidth = function() {\n var unusedCols = 0;\n // count unused columns\n var i = this.cols;\n while ( --i ) {\n if ( this.colYs[i] !== 0 ) {\n break;\n }\n unusedCols++;\n }\n // fit container to columns that have been used\n return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;\n };\n\n proto.needsResizeLayout = function() {\n var previousWidth = this.containerWidth;\n this.getContainerWidth();\n return previousWidth != this.containerWidth;\n };\n\n return Masonry;\n\n}));\n\n/*!\n * Masonry layout mode\n * sub-classes Masonry\n * http://masonry.desandro.com\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'isotope/js/layout-modes/masonry',[\n '../layout-mode',\n 'masonry/masonry'\n ],\n factory );\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('../layout-mode'),\n require('masonry-layout')\n );\n } else {\n // browser global\n factory(\n window.Isotope.LayoutMode,\n window.Masonry\n );\n }\n\n}( window, function factory( LayoutMode, Masonry ) {\n'use strict';\n\n// -------------------------- masonryDefinition -------------------------- //\n\n // create an Outlayer layout class\n var MasonryMode = LayoutMode.create('masonry');\n\n var proto = MasonryMode.prototype;\n\n var keepModeMethods = {\n _getElementOffset: true,\n layout: true,\n _getMeasurement: true\n };\n\n // inherit Masonry prototype\n for ( var method in Masonry.prototype ) {\n // do not inherit mode methods\n if ( !keepModeMethods[ method ] ) {\n proto[ method ] = Masonry.prototype[ method ];\n }\n }\n\n var measureColumns = proto.measureColumns;\n proto.measureColumns = function() {\n // set items, used if measuring first item\n this.items = this.isotope.filteredItems;\n measureColumns.call( this );\n };\n\n // point to mode options for fitWidth\n var _getOption = proto._getOption;\n proto._getOption = function( option ) {\n if ( option == 'fitWidth' ) {\n return this.options.isFitWidth !== undefined ?\n this.options.isFitWidth : this.options.fitWidth;\n }\n return _getOption.apply( this.isotope, arguments );\n };\n\n return MasonryMode;\n\n}));\n\n/**\n * fitRows layout mode\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'isotope/js/layout-modes/fit-rows',[\n '../layout-mode'\n ],\n factory );\n } else if ( typeof exports == 'object' ) {\n // CommonJS\n module.exports = factory(\n require('../layout-mode')\n );\n } else {\n // browser global\n factory(\n window.Isotope.LayoutMode\n );\n }\n\n}( window, function factory( LayoutMode ) {\n'use strict';\n\nvar FitRows = LayoutMode.create('fitRows');\n\nvar proto = FitRows.prototype;\n\nproto._resetLayout = function() {\n this.x = 0;\n this.y = 0;\n this.maxY = 0;\n this._getMeasurement( 'gutter', 'outerWidth' );\n};\n\nproto._getItemLayoutPosition = function( item ) {\n item.getSize();\n\n var itemWidth = item.size.outerWidth + this.gutter;\n // if this element cannot fit in the current row\n var containerWidth = this.isotope.size.innerWidth + this.gutter;\n if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {\n this.x = 0;\n this.y = this.maxY;\n }\n\n var position = {\n x: this.x,\n y: this.y\n };\n\n this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );\n this.x += itemWidth;\n\n return position;\n};\n\nproto._getContainerSize = function() {\n return { height: this.maxY };\n};\n\nreturn FitRows;\n\n}));\n\n/**\n * vertical layout mode\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'isotope/js/layout-modes/vertical',[\n '../layout-mode'\n ],\n factory );\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('../layout-mode')\n );\n } else {\n // browser global\n factory(\n window.Isotope.LayoutMode\n );\n }\n\n}( window, function factory( LayoutMode ) {\n'use strict';\n\nvar Vertical = LayoutMode.create( 'vertical', {\n horizontalAlignment: 0\n});\n\nvar proto = Vertical.prototype;\n\nproto._resetLayout = function() {\n this.y = 0;\n};\n\nproto._getItemLayoutPosition = function( item ) {\n item.getSize();\n var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *\n this.options.horizontalAlignment;\n var y = this.y;\n this.y += item.size.outerHeight;\n return { x: x, y: y };\n};\n\nproto._getContainerSize = function() {\n return { height: this.y };\n};\n\nreturn Vertical;\n\n}));\n\n/*!\n * Isotope v3.0.4\n *\n * Licensed GPLv3 for open source use\n * or Isotope Commercial License for commercial use\n *\n * http://isotope.metafizzy.co\n * Copyright 2017 Metafizzy\n */\n\n( function( window, factory ) {\n // universal module definition\n /* jshint strict: false */ /*globals define, module, require */\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( [\n 'outlayer/outlayer',\n 'get-size/get-size',\n 'desandro-matches-selector/matches-selector',\n 'fizzy-ui-utils/utils',\n 'isotope/js/item',\n 'isotope/js/layout-mode',\n // include default layout modes\n 'isotope/js/layout-modes/masonry',\n 'isotope/js/layout-modes/fit-rows',\n 'isotope/js/layout-modes/vertical'\n ],\n function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {\n return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );\n });\n } else if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n window,\n require('outlayer'),\n require('get-size'),\n require('desandro-matches-selector'),\n require('fizzy-ui-utils'),\n require('isotope/js/item'),\n require('isotope/js/layout-mode'),\n // include default layout modes\n require('isotope/js/layout-modes/masonry'),\n require('isotope/js/layout-modes/fit-rows'),\n require('isotope/js/layout-modes/vertical')\n );\n } else {\n // browser global\n window.Isotope = factory(\n window,\n window.Outlayer,\n window.getSize,\n window.matchesSelector,\n window.fizzyUIUtils,\n window.Isotope.Item,\n window.Isotope.LayoutMode\n );\n }\n\n}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,\n Item, LayoutMode ) {\n\n\n\n// -------------------------- vars -------------------------- //\n\nvar jQuery = window.jQuery;\n\n// -------------------------- helpers -------------------------- //\n\nvar trim = String.prototype.trim ?\n function( str ) {\n return str.trim();\n } :\n function( str ) {\n return str.replace( /^\\s+|\\s+$/g, '' );\n };\n\n// -------------------------- isotopeDefinition -------------------------- //\n\n // create an Outlayer layout class\n var Isotope = Outlayer.create( 'isotope', {\n layoutMode: 'masonry',\n isJQueryFiltering: true,\n sortAscending: true\n });\n\n Isotope.Item = Item;\n Isotope.LayoutMode = LayoutMode;\n\n var proto = Isotope.prototype;\n\n proto._create = function() {\n this.itemGUID = 0;\n // functions that sort items\n this._sorters = {};\n this._getSorters();\n // call super\n Outlayer.prototype._create.call( this );\n\n // create layout modes\n this.modes = {};\n // start filteredItems with all items\n this.filteredItems = this.items;\n // keep of track of sortBys\n this.sortHistory = [ 'original-order' ];\n // create from registered layout modes\n for ( var name in LayoutMode.modes ) {\n this._initLayoutMode( name );\n }\n };\n\n proto.reloadItems = function() {\n // reset item ID counter\n this.itemGUID = 0;\n // call super\n Outlayer.prototype.reloadItems.call( this );\n };\n\n proto._itemize = function() {\n var items = Outlayer.prototype._itemize.apply( this, arguments );\n // assign ID for original-order\n for ( var i=0; i < items.length; i++ ) {\n var item = items[i];\n item.id = this.itemGUID++;\n }\n this._updateItemsSortData( items );\n return items;\n };\n\n\n // -------------------------- layout -------------------------- //\n\n proto._initLayoutMode = function( name ) {\n var Mode = LayoutMode.modes[ name ];\n // set mode options\n // HACK extend initial options, back-fill in default options\n var initialOpts = this.options[ name ] || {};\n this.options[ name ] = Mode.options ?\n utils.extend( Mode.options, initialOpts ) : initialOpts;\n // init layout mode instance\n this.modes[ name ] = new Mode( this );\n };\n\n\n proto.layout = function() {\n // if first time doing layout, do all magic\n if ( !this._isLayoutInited && this._getOption('initLayout') ) {\n this.arrange();\n return;\n }\n this._layout();\n };\n\n // private method to be used in layout() & magic()\n proto._layout = function() {\n // don't animate first layout\n var isInstant = this._getIsInstant();\n // layout flow\n this._resetLayout();\n this._manageStamps();\n this.layoutItems( this.filteredItems, isInstant );\n\n // flag for initalized\n this._isLayoutInited = true;\n };\n\n // filter + sort + layout\n proto.arrange = function( opts ) {\n // set any options pass\n this.option( opts );\n this._getIsInstant();\n // filter, sort, and layout\n\n // filter\n var filtered = this._filter( this.items );\n this.filteredItems = filtered.matches;\n\n this._bindArrangeComplete();\n\n if ( this._isInstant ) {\n this._noTransition( this._hideReveal, [ filtered ] );\n } else {\n this._hideReveal( filtered );\n }\n\n this._sort();\n this._layout();\n };\n // alias to _init for main plugin method\n proto._init = proto.arrange;\n\n proto._hideReveal = function( filtered ) {\n this.reveal( filtered.needReveal );\n this.hide( filtered.needHide );\n };\n\n // HACK\n // Don't animate/transition first layout\n // Or don't animate/transition other layouts\n proto._getIsInstant = function() {\n var isLayoutInstant = this._getOption('layoutInstant');\n var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :\n !this._isLayoutInited;\n this._isInstant = isInstant;\n return isInstant;\n };\n\n // listen for layoutComplete, hideComplete and revealComplete\n // to trigger arrangeComplete\n proto._bindArrangeComplete = function() {\n // listen for 3 events to trigger arrangeComplete\n var isLayoutComplete, isHideComplete, isRevealComplete;\n var _this = this;\n function arrangeParallelCallback() {\n if ( isLayoutComplete && isHideComplete && isRevealComplete ) {\n _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );\n }\n }\n this.once( 'layoutComplete', function() {\n isLayoutComplete = true;\n arrangeParallelCallback();\n });\n this.once( 'hideComplete', function() {\n isHideComplete = true;\n arrangeParallelCallback();\n });\n this.once( 'revealComplete', function() {\n isRevealComplete = true;\n arrangeParallelCallback();\n });\n };\n\n // -------------------------- filter -------------------------- //\n\n proto._filter = function( items ) {\n var filter = this.options.filter;\n filter = filter || '*';\n var matches = [];\n var hiddenMatched = [];\n var visibleUnmatched = [];\n\n var test = this._getFilterTest( filter );\n\n // test each item\n for ( var i=0; i < items.length; i++ ) {\n var item = items[i];\n if ( item.isIgnored ) {\n continue;\n }\n // add item to either matched or unmatched group\n var isMatched = test( item );\n // item.isFilterMatched = isMatched;\n // add to matches if its a match\n if ( isMatched ) {\n matches.push( item );\n }\n // add to additional group if item needs to be hidden or revealed\n if ( isMatched && item.isHidden ) {\n hiddenMatched.push( item );\n } else if ( !isMatched && !item.isHidden ) {\n visibleUnmatched.push( item );\n }\n }\n\n // return collections of items to be manipulated\n return {\n matches: matches,\n needReveal: hiddenMatched,\n needHide: visibleUnmatched\n };\n };\n\n // get a jQuery, function, or a matchesSelector test given the filter\n proto._getFilterTest = function( filter ) {\n if ( jQuery && this.options.isJQueryFiltering ) {\n // use jQuery\n return function( item ) {\n return jQuery( item.element ).is( filter );\n };\n }\n if ( typeof filter == 'function' ) {\n // use filter as function\n return function( item ) {\n return filter( item.element );\n };\n }\n // default, use filter as selector string\n return function( item ) {\n return matchesSelector( item.element, filter );\n };\n };\n\n // -------------------------- sorting -------------------------- //\n\n /**\n * @params {Array} elems\n * @public\n */\n proto.updateSortData = function( elems ) {\n // get items\n var items;\n if ( elems ) {\n elems = utils.makeArray( elems );\n items = this.getItems( elems );\n } else {\n // update all items if no elems provided\n items = this.items;\n }\n\n this._getSorters();\n this._updateItemsSortData( items );\n };\n\n proto._getSorters = function() {\n var getSortData = this.options.getSortData;\n for ( var key in getSortData ) {\n var sorter = getSortData[ key ];\n this._sorters[ key ] = mungeSorter( sorter );\n }\n };\n\n /**\n * @params {Array} items - of Isotope.Items\n * @private\n */\n proto._updateItemsSortData = function( items ) {\n // do not update if no items\n var len = items && items.length;\n\n for ( var i=0; len && i < len; i++ ) {\n var item = items[i];\n item.updateSortData();\n }\n };\n\n // ----- munge sorter ----- //\n\n // encapsulate this, as we just need mungeSorter\n // other functions in here are just for munging\n var mungeSorter = ( function() {\n // add a magic layer to sorters for convienent shorthands\n // `.foo-bar` will use the text of .foo-bar querySelector\n // `[foo-bar]` will use attribute\n // you can also add parser\n // `.foo-bar parseInt` will parse that as a number\n function mungeSorter( sorter ) {\n // if not a string, return function or whatever it is\n if ( typeof sorter != 'string' ) {\n return sorter;\n }\n // parse the sorter string\n var args = trim( sorter ).split(' ');\n var query = args[0];\n // check if query looks like [an-attribute]\n var attrMatch = query.match( /^\\[(.+)\\]$/ );\n var attr = attrMatch && attrMatch[1];\n var getValue = getValueGetter( attr, query );\n // use second argument as a parser\n var parser = Isotope.sortDataParsers[ args[1] ];\n // parse the value, if there was a parser\n sorter = parser ? function( elem ) {\n return elem && parser( getValue( elem ) );\n } :\n // otherwise just return value\n function( elem ) {\n return elem && getValue( elem );\n };\n\n return sorter;\n }\n\n // get an attribute getter, or get text of the querySelector\n function getValueGetter( attr, query ) {\n // if query looks like [foo-bar], get attribute\n if ( attr ) {\n return function getAttribute( elem ) {\n return elem.getAttribute( attr );\n };\n }\n\n // otherwise, assume its a querySelector, and get its text\n return function getChildText( elem ) {\n var child = elem.querySelector( query );\n return child && child.textContent;\n };\n }\n\n return mungeSorter;\n })();\n\n // parsers used in getSortData shortcut strings\n Isotope.sortDataParsers = {\n 'parseInt': function( val ) {\n return parseInt( val, 10 );\n },\n 'parseFloat': function( val ) {\n return parseFloat( val );\n }\n };\n\n // ----- sort method ----- //\n\n // sort filteredItem order\n proto._sort = function() {\n if ( !this.options.sortBy ) {\n return;\n }\n // keep track of sortBy History\n var sortBys = utils.makeArray( this.options.sortBy );\n if ( !this._getIsSameSortBy( sortBys ) ) {\n // concat all sortBy and sortHistory, add to front, oldest goes in last\n this.sortHistory = sortBys.concat( this.sortHistory );\n }\n // sort magic\n var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending );\n this.filteredItems.sort( itemSorter );\n };\n\n // check if sortBys is same as start of sortHistory\n proto._getIsSameSortBy = function( sortBys ) {\n for ( var i=0; i < sortBys.length; i++ ) {\n if ( sortBys[i] != this.sortHistory[i] ) {\n return false;\n }\n }\n return true;\n };\n\n // returns a function used for sorting\n function getItemSorter( sortBys, sortAsc ) {\n return function sorter( itemA, itemB ) {\n // cycle through all sortKeys\n for ( var i = 0; i < sortBys.length; i++ ) {\n var sortBy = sortBys[i];\n var a = itemA.sortData[ sortBy ];\n var b = itemB.sortData[ sortBy ];\n if ( a > b || a < b ) {\n // if sortAsc is an object, use the value given the sortBy key\n var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;\n var direction = isAscending ? 1 : -1;\n return ( a > b ? 1 : -1 ) * direction;\n }\n }\n return 0;\n };\n }\n\n // -------------------------- methods -------------------------- //\n\n // get layout mode\n proto._mode = function() {\n var layoutMode = this.options.layoutMode;\n var mode = this.modes[ layoutMode ];\n if ( !mode ) {\n // TODO console.error\n throw new Error( 'No layout mode: ' + layoutMode );\n }\n // HACK sync mode's options\n // any options set after init for layout mode need to be synced\n mode.options = this.options[ layoutMode ];\n return mode;\n };\n\n proto._resetLayout = function() {\n // trigger original reset layout\n Outlayer.prototype._resetLayout.call( this );\n this._mode()._resetLayout();\n };\n\n proto._getItemLayoutPosition = function( item ) {\n return this._mode()._getItemLayoutPosition( item );\n };\n\n proto._manageStamp = function( stamp ) {\n this._mode()._manageStamp( stamp );\n };\n\n proto._getContainerSize = function() {\n return this._mode()._getContainerSize();\n };\n\n proto.needsResizeLayout = function() {\n return this._mode().needsResizeLayout();\n };\n\n // -------------------------- adding & removing -------------------------- //\n\n // HEADS UP overwrites default Outlayer appended\n proto.appended = function( elems ) {\n var items = this.addItems( elems );\n if ( !items.length ) {\n return;\n }\n // filter, layout, reveal new items\n var filteredItems = this._filterRevealAdded( items );\n // add to filteredItems\n this.filteredItems = this.filteredItems.concat( filteredItems );\n };\n\n // HEADS UP overwrites default Outlayer prepended\n proto.prepended = function( elems ) {\n var items = this._itemize( elems );\n if ( !items.length ) {\n return;\n }\n // start new layout\n this._resetLayout();\n this._manageStamps();\n // filter, layout, reveal new items\n var filteredItems = this._filterRevealAdded( items );\n // layout previous items\n this.layoutItems( this.filteredItems );\n // add to items and filteredItems\n this.filteredItems = filteredItems.concat( this.filteredItems );\n this.items = items.concat( this.items );\n };\n\n proto._filterRevealAdded = function( items ) {\n var filtered = this._filter( items );\n this.hide( filtered.needHide );\n // reveal all new items\n this.reveal( filtered.matches );\n // layout new items, no transition\n this.layoutItems( filtered.matches, true );\n return filtered.matches;\n };\n\n /**\n * Filter, sort, and layout newly-appended item elements\n * @param {Array or NodeList or Element} elems\n */\n proto.insert = function( elems ) {\n var items = this.addItems( elems );\n if ( !items.length ) {\n return;\n }\n // append item elements\n var i, item;\n var len = items.length;\n for ( i=0; i < len; i++ ) {\n item = items[i];\n this.element.appendChild( item.element );\n }\n // filter new stuff\n var filteredInsertItems = this._filter( items ).matches;\n // set flag\n for ( i=0; i < len; i++ ) {\n items[i].isLayoutInstant = true;\n }\n this.arrange();\n // reset flag\n for ( i=0; i < len; i++ ) {\n delete items[i].isLayoutInstant;\n }\n this.reveal( filteredInsertItems );\n };\n\n var _remove = proto.remove;\n proto.remove = function( elems ) {\n elems = utils.makeArray( elems );\n var removeItems = this.getItems( elems );\n // do regular thing\n _remove.call( this, elems );\n // bail if no items to remove\n var len = removeItems && removeItems.length;\n // remove elems from filteredItems\n for ( var i=0; len && i < len; i++ ) {\n var item = removeItems[i];\n // remove item from collection\n utils.removeFrom( this.filteredItems, item );\n }\n };\n\n proto.shuffle = function() {\n // update random sortData\n for ( var i=0; i < this.items.length; i++ ) {\n var item = this.items[i];\n item.sortData.random = Math.random();\n }\n this.options.sortBy = 'random';\n this._sort();\n this._layout();\n };\n\n /**\n * trigger fn without transition\n * kind of hacky to have this in the first place\n * @param {Function} fn\n * @param {Array} args\n * @returns ret\n * @private\n */\n proto._noTransition = function( fn, args ) {\n // save transitionDuration before disabling\n var transitionDuration = this.options.transitionDuration;\n // disable transition\n this.options.transitionDuration = 0;\n // do it\n var returnValue = fn.apply( this, args );\n // re-enable transition for reveal\n this.options.transitionDuration = transitionDuration;\n return returnValue;\n };\n\n // ----- helper methods ----- //\n\n /**\n * getter method for getting filtered item elements\n * @returns {Array} elems - collection of item elements\n */\n proto.getFilteredItemElements = function() {\n return this.filteredItems.map( function( item ) {\n return item.element;\n });\n };\n\n // ----- ----- //\n\n return Isotope;\n\n}));\n\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/isotope-layout/dist/isotope.pkgd.js\n// module id = GbzL7C/QFmiBZDICkla+\n// module chunks = 0","var matches = require('./matches')\n\n/**\n * closest : closest(el, selector)\n * Looks for the closest ancestor of element `el` that matches `selector`.\n * Compare with [$.fn.closest](http://api.jquery.com/closest/).\n *\n * var closest = require('dom101/closest');\n *\n * closest(input, 'label');\n */\n\nfunction closest (el, sel) {\n if (!el) return\n if (matches(el, sel)) {\n return el\n } else {\n return closest(el.parentNode, sel)\n }\n}\n\nmodule.exports = closest\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/dom101/closest.js\n// module id = Gz0TuoFFs6JdDvtR2PYZ\n// module chunks = 0","/**\n * on : on(el, event, fn)\n * Adds an event handler.\n *\n * var on = require('dom101/on');\n *\n * on(el, 'click', function () {\n * ...\n * });\n */\n\nfunction on (el, event, handler) {\n if (el.addEventListener) {\n el.addEventListener(event, handler)\n } else {\n el.attachEvent('on' + event, function () {\n handler.call(el)\n })\n }\n}\n\nmodule.exports = on\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/dom101/on.js\n// module id = MKJaVdnD9jF7rk6rW6AJ\n// module chunks = 0","/**\n * each : each(list, fn)\n * Iterates through `list` (an array or an object). This is useful when dealing\n * with NodeLists like `document.querySelectorAll`.\n *\n * var each = require('dom101/each');\n * var qa = require('dom101/query-selector-all');\n *\n * each(qa('.button'), function (el) {\n * addClass('el', 'selected');\n * });\n */\n\nfunction each (list, fn) {\n var i\n var len = list.length\n var idx\n\n if (typeof len === 'number') {\n for (i = 0; i < len; i++) {\n fn(list[i], i)\n }\n } else {\n idx = 0\n for (i in list) {\n if (list.hasOwnProperty(i)) {\n fn(list[i], i, idx++)\n }\n }\n }\n\n return list\n}\n\nmodule.exports = each\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/dom101/each.js\n// module id = O7wD3s+p+jjyw5ivWGEg\n// module chunks = 0","import onmount from 'onmount'\nimport remove from 'dom101/remove'\nimport removeClass from 'dom101/remove-class'\n\nimport { getData } from '../helpers/data'\nimport { isDismissed } from '../helpers/dismiss'\nimport { isPreview } from '../helpers/preview'\n\nonmount('[data-js-dismissable]', function () {\n const id = getData(this, 'js-dismissable').id || ''\n\n if (isPreview() || isDismissed(id)) {\n remove(this)\n } else {\n removeClass(this, '-hide')\n }\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/behaviors/dismissable.js","import matches from 'dom101/matches'\n\n/*\n * Just like jQuery.append\n */\n\nexport function appendMany (el, children) {\n children.forEach(child => { el.appendChild(child) })\n}\n\n/*\n * Just like jQuery.nextUntil\n */\n\nexport function nextUntil (el, selector) {\n const nextEl = el.nextSibling\n return nextUntilTick(nextEl, selector, [])\n}\n\nfunction nextUntilTick (el, selector, acc) {\n if (!el) return acc\n\n const isMatch = matches(el, selector)\n if (isMatch) return acc\n\n return nextUntilTick(el.nextSibling, selector, [ ...acc, el ])\n}\n\n/*\n * Just like jQuery.before\n */\n\nexport function before (reference, newNode) {\n reference.parentNode.insertBefore(newNode, reference)\n}\n\n/*\n * Like jQuery.children('selector')\n */\n\nexport function findChildren (el, selector) {\n return [].slice.call(el.children)\n .filter(child => matches(child, selector))\n}\n\n/**\n * Creates a div\n * @private\n *\n * @example\n *\n * createDiv({ class: 'foo' })\n */\n\nexport function createDiv (props) {\n const d = document.createElement('div')\n Object.keys(props).forEach(key => {\n d.setAttribute(key, props[key])\n })\n return d\n}\n\n\n\n// WEBPACK FOOTER //\n// ./_js/helpers/dom.js","import closest from 'dom101/closest'\nimport remove from 'dom101/remove'\nimport on from 'dom101/on'\nimport { getData } from '../helpers/data'\nimport onmount from 'onmount'\nimport * as Dismiss from '../helpers/dismiss'\n\n/**\n * Dismiss button\n */\n\nonmount('[data-js-dismiss]', function () {\n const parent = closest(this, '[data-js-dismissable]')\n const dismissable = getData(parent, 'js-dismissable')\n const id = (dismissable && dismissable.id) || ''\n\n on(this, 'click', e => {\n Dismiss.setDismissed(id)\n e.preventDefault()\n if (parent) remove(parent)\n })\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/behaviors/dismiss.js","var each = require('./each')\n\n/**\n * removeClass : removeClass(el, className)\n * Removes a classname.\n *\n * var removeClass = require('dom101/remove-class');\n *\n * el.className = 'selected active';\n * removeClass(el, 'active');\n *\n * el.className\n * => \"selected\"\n */\n\nfunction removeClass (el, className) {\n if (!className) return\n\n if (Array.isArray(className)) {\n each(className, function (className) {\n removeClass(el, className)\n })\n\n return\n }\n\n if (el.classList) {\n var classNames = className.split(' ').filter(Boolean)\n each(classNames, function (className) {\n el.classList.remove(className)\n })\n } else {\n var expr =\n new RegExp('(^|\\\\b)' + className.split(' ').join('|') + '(\\\\b|$)', 'gi')\n\n el.className = el.className.replace(expr, ' ')\n }\n}\n\nmodule.exports = removeClass\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/dom101/remove-class.js\n// module id = bq+j3PCtCSGVXgg8xWPw\n// module chunks = 0","var map = {\n\t\"./anchors.js\": \"lpgA2dewefHNQWX4X3Mh\",\n\t\"./dismiss.js\": \"azEBDvunS5n/qbuQInIF\",\n\t\"./dismissable.js\": \"XxGrbZud7DE4W4TdQZtc\",\n\t\"./disqus.js\": \"BuWMdGeXUEK0GmkN01pU\",\n\t\"./h3-section-list.js\": \"E+dCGfS1pT5WowYv7jpv\",\n\t\"./main-body.js\": \"g3wkw0XZUos0Eo8rU7p6\",\n\t\"./no-preview.js\": \"k6EYej2Qda8Mq9A5Oeqn\",\n\t\"./search-form.js\": \"D3SYMdNAenu80VOO7/Dv\",\n\t\"./search-input.js\": \"zNHHVy5XxvKjnqTgwxy7\",\n\t\"./searchable-header.js\": \"veOabZWTWtixkn1TyITD\",\n\t\"./searchable-item.js\": \"tcev71HWHlq3Ur/sw7Ir\"\n};\nfunction webpackContext(req) {\n\treturn __webpack_require__(webpackContextResolve(req));\n};\nfunction webpackContextResolve(req) {\n\tvar id = map[req];\n\tif(!(id + 1)) // check for number or string\n\t\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n\treturn id;\n};\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"cBdQffYQOU2SCSRXjSUx\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./_js/behaviors \\.js$\n// module id = cBdQffYQOU2SCSRXjSUx\n// module chunks = 0","/**\n * Injects disqus's scripts into the page.\n *\n * @example\n * inject('devhints.disqus.com')\n */\n\nexport default function inject (host) {\n injectEmbed(host)\n injectCount(host)\n}\n\nexport function injectEmbed (host) {\n const d = document\n const s = d.createElement('script')\n s.src = `https://${host}/embed.js`\n s.setAttribute('data-timestamp', +new Date())\n ;(d.head || d.body).appendChild(s)\n}\n\nexport function injectCount (host) {\n const d = document\n const s = d.createElement('script')\n s.src = `https://${host}/count.js`\n s.id = 'dsq-count-scr'\n s.async = true\n ;(d.head || d.body).appendChild(s)\n}\n\n\n\n// WEBPACK FOOTER //\n// ./_js/helpers/inject_disqus.js","/**\n * prepend : prepend(el, child)\n * Prepends a `child` into a parent `el`. Compare with `$.fn.prepend`.\n *\n * var prepend = require('dom101/prepend');\n *\n * prepend(el, child);\n */\n\nfunction prepend (el, child) {\n if (el.firstChild) {\n el.insertBefore(child, el.firstChild)\n } else {\n el.appendChild(child)\n }\n}\n\nmodule.exports = prepend\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/dom101/prepend.js\n// module id = djrEhtin0g5nRB/RnnLU\n// module chunks = 0","/*\n * Helper: minimal qs implementation\n */\n\nexport default function qs (search) {\n search = search.substr(1)\n const parts = search.split('&').map(p => p.split('='))\n return parts.reduce((result, part) => {\n result[part[0]] = qsdecode(part[1])\n return result\n }, {})\n}\n\nexport function qsdecode (string) {\n if (!string) string = ''\n string = string.replace(/\\+/g, ' ')\n return string\n}\n\n\n\n// WEBPACK FOOTER //\n// ./_js/helpers/qs.js","import remove from 'dom101/remove'\nimport onmount from 'onmount'\nimport addClass from 'dom101/add-class'\n\nimport { isPreview } from '../helpers/preview'\n\n/*\n * Behavior: Things to remove when preview mode is on\n */\n\nonmount('[data-js-no-preview]', function (b) {\n if (isPreview()) {\n remove(this)\n addClass(document.documentElement, 'PreviewMode')\n }\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/behaviors/no-preview.js","var each = require('./each')\n\n/**\n * addClass : addClass(el, className)\n * Adds a class name to an element. Compare with `$.fn.addClass`.\n *\n * var addClass = require('dom101/add-class');\n *\n * addClass(el, 'active');\n */\n\nfunction addClass (el, className) {\n if (!className) return\n\n if (Array.isArray(className)) {\n each(className, function (className) {\n addClass(el, className)\n })\n\n return\n }\n\n if (el.classList) {\n var classNames = className.split(' ').filter(Boolean)\n each(classNames, function (className) {\n el.classList.add(className)\n })\n } else {\n el.className += ' ' + className\n }\n}\n\nmodule.exports = addClass\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/dom101/add-class.js\n// module id = lGfezzQL7fc5RE8kg33g\n// module chunks = 0","import onmount from 'onmount'\nimport prepend from 'dom101/prepend'\n\nconst DEFAULTS = {\n // select elements to put anchor on\n rule: 'h2[id]',\n // class name for anchor\n className: 'local-anchor anchor',\n // text of anchor\n text: '#',\n // append before or after innerText?\n shouldAppend: false,\n}\n\n/*\n * Behavior: Add local anchors\n */\n\nonmount('[data-js-anchors]', function () {\n const data = JSON.parse(this.getAttribute('data-js-anchors') || '{}')\n const rules = Array.isArray(data)\n ? (data.length ? data : [DEFAULTS])\n : [Object.assign({}, DEFAULTS, data)]\n\n for (const { rule, className, text, shouldAppend } of rules) {\n for (const el of this.querySelectorAll(rule)) {\n if (!el.hasAttribute('id')) {\n continue\n }\n\n const id = el.getAttribute('id')\n const anchor = document.createElement('a')\n anchor.setAttribute('href', `#${id}`)\n anchor.setAttribute('class', className)\n anchor.innerText = String(text || DEFAULTS.text)\n\n if (shouldAppend) {\n el.appendChild(anchor)\n } else {\n prepend(el, anchor)\n }\n }\n }\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/behaviors/anchors.js","import onmount from 'onmount'\nimport permutate from '../helpers/permutate'\n\n/**\n * Sets search indices (`data-search-index` attribute)\n */\n\nonmount('[data-js-searchable-item]', function () {\n const data = JSON.parse(this.getAttribute('data-js-searchable-item') || '{}')\n const words = permutate(data)\n\n this.setAttribute('data-search-index', words.join(' '))\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/behaviors/searchable-item.js","/**\n * ready : ready(fn)\n * Executes `fn` when the DOM is ready. If the DOM is already ready, the given\n * callback will be called immediately.\n *\n * var ready = require('dom101/ready');\n *\n * ready(function () {\n * ...\n * });\n */\n\nfunction ready (fn) {\n if (isReady()) {\n return fn()\n } else if (document.addEventListener) {\n document.addEventListener('DOMContentLoaded', fn)\n } else {\n document.attachEvent('onreadystatechange', function () {\n if (isReady()) fn()\n })\n }\n}\n\nfunction isReady () {\n return (document.readyState === 'complete' || document.readyState === 'interactive')\n}\n\nmodule.exports = ready\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/dom101/ready.js\n// module id = tqbVxj9+xGAhlFrQpyTS\n// module chunks = 0","import onmount from 'onmount'\nimport { nextUntil } from '../helpers/dom'\nimport matches from 'dom101/matches'\n\n// Ensure that search-index is set first\nimport './searchable-item'\n\n/**\n * Propagate item search indices to headers\n */\n\nonmount('[data-js-searchable-header]', function () {\n const els = nextUntil(this, '[data-js-searchable-header]')\n .filter(el => matches(el, '[data-search-index]'))\n\n const keywords = els\n .map(n => n.getAttribute('data-search-index'))\n .join(' ')\n .split(' ')\n\n this.setAttribute('data-search-index', keywords.join(' '))\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/behaviors/searchable-header.js","/**\n * remove : remove(el)\n * Removes an element from the DOM.\n *\n * var remove = require('dom101/remove');\n *\n * remove(el);\n */\n\nfunction remove (el) {\n el && el.parentNode && el.parentNode.removeChild(el)\n}\n\nmodule.exports = remove\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/dom101/remove.js\n// module id = wYegCzKWCG2ZRJZfGEZa\n// module chunks = 0","/* global define */\nvoid (function (root, factory) {\n if (typeof define === 'function' && define.amd) define(factory)\n else if (typeof exports === 'object') module.exports = factory()\n else {\n if (window.jQuery) window.jQuery.onmount = factory()\n else root.onmount = factory()\n }\n}(this, function ($) {\n /*\n * Internal: Registry.\n */\n\n var handlers, behaviors, selectors, log\n\n /*\n * Internal: IDs for auto-incrementing.\n */\n\n var bid = 0 /* behavior ID */\n var cid = 0 /* component ID */\n\n /**\n * (Module) Adds a behavior, or triggers behaviors.\n *\n * When no parameters are passed, it triggers all behaviors. When one\n * parameter is passed, it triggers the given behavior. Otherwise, it adds a\n * behavior.\n *\n * // define a behavior\n * $.onmount('.select-box', function () {\n * $(this).on('...')\n * })\n *\n * // define a behavior with exit\n * $.onmount('.select-box', function () {\n * $(document).on('...')\n * }, function () {\n * $(document).off('...')\n * })\n *\n * // retrigger a onmount\n * $.onmount('.select-box')\n *\n * // retriggers all behaviors\n * $.onmount()\n */\n\n function onmount (selector, init, exit, options) {\n if (typeof exit === 'object') {\n options = exit\n exit = undefined\n }\n\n if (arguments.length === 0 || isjQuery(selector) || isEvent(selector)) {\n // onmount() - trigger all behaviors. Also account for cases such as\n // $($.onmount), where it's triggered with a jQuery event object.\n onmount.poll()\n } else if (arguments.length === 1) {\n // onmount(selector) - trigger for a given selector.\n onmount.poll(selector)\n } else {\n // onmount(sel, fn, [fn]) - register a new behavior.\n var be = new Behavior(selector, init, exit, options)\n behaviors.push(be)\n be.register()\n }\n\n return this\n }\n\n /*\n * Use jQuery (or a jQuery-like) when available. This will allow\n * the use of jQuery selectors.\n */\n\n onmount.$ = window.jQuery || window.Zepto || window.Ender\n\n /*\n * Detect MutationObserver support for `onmount.observe()`.\n * You may even add a polyfill here via\n * `onmount.MutationObserver = require('mutation-observer')`.\n */\n\n onmount.MutationObserver =\n window.MutationObserver ||\n window.WebKitMutationObserver ||\n window.MozMutationObserver\n\n /**\n * Set this to true if you want to see debug messages.\n */\n\n onmount.debug = false\n\n /**\n * Internal: triggers behaviors for a selector or for all.\n *\n * onmount.poll()\n * onmount.poll('.js-button')\n */\n\n onmount.poll = function poll (selector) {\n if (selector) selector = onmount.selectify(selector)\n var functions = (selector ? selectors[selector] : handlers) || []\n each(functions, function (fn) { fn() })\n }\n\n /**\n * Observes automatically using MutationObserver events.\n *\n * onmount.observe()\n */\n\n onmount.observe = function observe () {\n var MutationObserver = onmount.MutationObserver\n if (typeof MutationObserver === 'undefined') return\n\n var obs = new MutationObserver(function (mutations) {\n each(behaviors, function (be) {\n each(mutations, function (mutation) {\n each(mutation.addedNodes, function (el) {\n if (matches(el, be.selector)) be.visitEnter(el)\n })\n\n each(mutation.removedNodes, function (el) {\n if (matches(el, be.selector)) be.doExit(el)\n })\n })\n })\n })\n\n obs.observe(document, { subtree: true, childList: true })\n onmount.observer = obs\n\n // trigger everything before going\n onmount()\n return true\n }\n\n /**\n * Turns off observation first issued by `onmount.observe()`.\n */\n\n onmount.unobserve = function unobserve () {\n if (!this.observer) return\n this.observer.disconnect()\n delete this.observer\n }\n\n /**\n * Forces teardown of all behaviors currently applied.\n */\n\n onmount.teardown = function teardown () {\n each(behaviors, function (be) {\n each(be.loaded, function (el, i) {\n if (el) be.doExit(el, i)\n })\n })\n }\n\n /**\n * Clears all behaviors. Useful for tests.\n * This will NOT call exit handlers.\n */\n\n onmount.reset = function reset () {\n handlers = onmount.handlers = []\n selectors = onmount.selectors = {}\n behaviors = onmount.behaviors = []\n }\n\n /**\n * Internal: Converts `@role` to `[role~=\"role\"]` if needed. You can override\n * this by reimplementing `onmount.selectify`.\n *\n * selectify('@hi') //=> '[role=\"hi\"]'\n * selectify('.btn') //=> '.btn'\n */\n\n onmount.selectify = function selectify (selector) {\n if (selector[0] === '@') {\n return '[role~=\"' + selector.substr(1).replace(/\"/g, '\\\\\"') + '\"]'\n }\n return selector\n }\n\n /**\n * Internal: behavior class\n */\n\n function Behavior (selector, init, exit, options) {\n this.id = 'b' + bid++\n this.init = init\n this.exit = exit\n this.selector = onmount.selectify(selector)\n this.loaded = [] // keep track of dom elements loaded for this behavior\n this.key = '__onmount:' + bid // leave the state in el['__onmount:12']\n this.detectMutate = options && options.detectMutate\n }\n\n /**\n * Internal: initialize this behavior by registering itself to the internal\n * `selectors` map. This allows you to call `onmount(selector)` later on.\n */\n\n Behavior.prototype.register = function () {\n var be = this\n var loaded = this.loaded\n var selector = this.selector\n\n register(selector, function () {\n var list = query(selector)\n\n // This is the function invoked on `onmount(selector)`.\n // Clean up old ones (if they're not in the DOM anymore).\n each(loaded, function (element, i) {\n be.visitExit(element, i, list)\n })\n\n // Clean up new ones (if they're not loaded yet).\n eachOf(list, function (element) {\n be.visitEnter(element)\n })\n })\n }\n\n /**\n * Internal: visits the element `el` and turns it on if applicable.\n */\n\n Behavior.prototype.visitEnter = function (el) {\n if (el[this.key]) return\n var options = { id: 'c' + cid, selector: this.selector }\n if (this.init.call(el, options) !== false) {\n if (onmount.debug) log('enter', this.selector, el)\n el[this.key] = options\n this.loaded.push(el)\n cid++\n }\n }\n\n /**\n * Internal: visits the element `el` and sees if it needs its exit handler\n * called.\n */\n\n Behavior.prototype.visitExit = function (el, i, list) {\n if (!el) return\n if (this.detectMutate) {\n if (!has(list, el)) return this.doExit(el, i)\n } else {\n if (!isAttached(el)) return this.doExit(el, i)\n }\n }\n\n /**\n * Internal: calls the exit handler for the behavior for element `el` (if\n * available), and marks the behavior/element as uninitialized.\n */\n\n Behavior.prototype.doExit = function (el, i) {\n if (typeof i === 'undefined') i = this.loaded.indexOf(el)\n this.loaded[i] = undefined\n if (this.exit && this.exit.call(el, el[this.key]) !== false) {\n if (onmount.debug) log('exit', this.selector, el)\n delete el[this.key]\n }\n }\n\n /**\n * Internal: check if an element is still attached to its document.\n */\n\n function isAttached (el) {\n while (el) {\n if (el === document.documentElement) return true\n el = el.parentElement\n }\n }\n\n /**\n * Internal: reimplementation of `$('...')`. If jQuery is available,\n * use it (I guess to preserve IE compatibility and to enable special jQuery\n * attribute selectors). Use with `eachOf()` or `has()`.\n */\n\n function query (selector, fn) {\n if (onmount.$) return onmount.$(selector)\n return document.querySelectorAll(selector)\n }\n\n /**\n * Internal: iterates through a `query()` result.\n */\n\n function eachOf (list, fn) {\n if (onmount.$) return list.each(function (i) { fn(this, i) })\n return each(list, fn)\n }\n\n /**\n * Interanl: checks if given element `el` is in the query result `list`.\n */\n\n function has (list, el) {\n if (onmount.$) return list.index(el) > -1\n return list.indexOf(el) > -1\n }\n\n /**\n * Internal: registers a behavior handler for a selector.\n */\n\n function register (selector, fn) {\n if (!selectors[selector]) selectors[selector] = []\n selectors[selector].push(fn)\n handlers.push(fn)\n }\n\n /**\n * Checks if a given element `el` matches `selector`.\n * Compare with [$.fn.is](http://api.jquery.com/is/).\n *\n * var matches = require('dom101/matches');\n *\n * matches(button, ':focus');\n */\n\n function matches (el, selector) {\n var _matches = el.matches ||\n el.matchesSelector ||\n el.msMatchesSelector ||\n el.mozMatchesSelector ||\n el.webkitMatchesSelector ||\n el.oMatchesSelector\n\n if (onmount.$) {\n return onmount.$(el).is(selector)\n } else if (_matches) {\n return _matches.call(el, selector)\n } else if (el.parentNode) {\n // IE8 and below\n var nodes = el.parentNode.querySelectorAll(selector)\n for (var i = nodes.length; i--; 0) {\n if (nodes[i] === el) return true\n }\n return false\n }\n }\n\n /**\n * Iterates through `list` (an array or an object). This is useful when dealing\n * with NodeLists like `document.querySelectorAll`.\n *\n * var each = require('dom101/each');\n * var qa = require('dom101/query-selector-all');\n *\n * each(qa('.button'), function (el) {\n * addClass('el', 'selected');\n * });\n */\n\n function each (list, fn) {\n var i\n var len = list.length\n\n if (len === +len) {\n for (i = 0; i < len; i++) { fn(list[i], i) }\n } else {\n for (i in list) {\n if (list.hasOwnProperty(i)) fn(list[i], i)\n }\n }\n\n return list\n }\n\n /**\n * Internal: Check if a given object is jQuery\n */\n\n function isjQuery ($) {\n return typeof $ === 'function' && $.fn && $.noConflict\n }\n\n function isEvent (e) {\n return typeof e === 'object' && e.target\n }\n\n /**\n * Internal: logging\n */\n\n var styles = {\n enter: 'background-color:#dfd;font-weight:bold;color:#141',\n exit: 'background-color:#fdd;font-weight:bold;color:#411'\n }\n\n if (~navigator.userAgent.indexOf('Mozilla')) {\n log = function (type, selector, el) {\n console.log('%c %s ', styles[type], selector, el)\n }\n } else {\n log = function (type, selector, el) {\n console.log('(onmount)', type, selector)\n }\n }\n\n /*\n * Export\n */\n\n onmount.reset()\n return onmount\n}))\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/onmount/index.js\n// module id = yfX/NEeqeNrvWENPWWKS\n// module chunks = 0","// 3rd party libs\nwindow.Prism = require('prismjs')\n\n// All the others\nfunction requireAll (r) { r.keys().forEach(r) }\nrequireAll(require.context('./initializers/', true, /\\.js$/))\nrequireAll(require.context('./behaviors/', true, /\\.js$/))\n\n\n\n// WEBPACK FOOTER //\n// ./_js/app.js","import onmount from 'onmount'\nimport * as Search from '../helpers/search'\nimport qs from '../helpers/qs'\nimport on from 'dom101/on'\n\nonmount('[data-js-search-input]', function () {\n on(this, 'input', () => {\n const val = this.value\n\n if (val === '') {\n Search.showAll()\n } else {\n Search.show(val)\n }\n })\n\n const query = (qs(window.location.search) || {}).q\n if (query && query.length) {\n this.value = query\n setTimeout(() => { Search.show(query) })\n }\n})\n\n\n\n// WEBPACK FOOTER //\n// ./_js/behaviors/search-input.js"],"sourceRoot":""}
\ No newline at end of file
diff --git a/assets/packed/vendor.js b/assets/packed/vendor.js
new file mode 100644
index 000000000..83edb8ddc
--- /dev/null
+++ b/assets/packed/vendor.js
@@ -0,0 +1,2 @@
+!function(t){function e(r){if(n[r])return n[r].exports;var a=n[r]={i:r,l:!1,exports:{}};return t[r].call(a.exports,a,a.exports,e),a.l=!0,a.exports}var r=window.webpackJsonp;window.webpackJsonp=function(n,i,o){for(var s,l,f,u=0,c=[];ut.length)return;if(!(x instanceof l)){p.lastIndex=0;var k=p.exec(x),S=1;if(!k&&m&&w!=e.length-1){if(p.lastIndex=v,!(k=p.exec(t)))break;for(var j=k.index+(d?k[1].length:0),Y=k.index+k[0].length,z=w,A=v,X=e.length;z=A&&(++w,v=A);if(e[w]instanceof l||e[z-1].greedy)continue;S=z-w,x=t.slice(v,A),k.index-=v}if(k){d&&(g=k[1].length);var j=k.index+g,k=k[0].slice(g),Y=j+k.length,P=x.slice(0,j),C=x.slice(Y),T=[w,S];P&&(++w,v+=P.length,T.push(P));var E=new l(f,h?n.tokenize(k,h):k,b,k,m);if(T.push(E),C&&T.push(C),Array.prototype.splice.apply(e,T),1!=S&&n.matchGrammar(t,e,r,w,v,!0,f),o)break}else if(o)break}}}}},tokenize:function(t,e,r){var a=[t],i=e.rest;if(i){for(var o in i)e[o]=i[o];delete e.rest}return n.matchGrammar(t,a,e,0,0,!1),a},hooks:{all:{},add:function(t,e){var r=n.hooks.all;r[t]=r[t]||[],r[t].push(e)},run:function(t,e){var r=n.hooks.all[t];if(r&&r.length)for(var a,i=0;a=r[i++];)a(e)}}},a=n.Token=function(t,e,r,n,a){this.type=t,this.content=e,this.alias=r,this.length=0|(n||"").length,this.greedy=!!a};if(a.stringify=function(t,e,r){if("string"==typeof t)return t;if("Array"===n.util.type(t))return t.map(function(r){return a.stringify(r,e,t)}).join("");var i={type:t.type,content:a.stringify(t.content,e,r),tag:"span",classes:["token",t.type],attributes:{},language:e,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),t.alias){var o="Array"===n.util.type(t.alias)?t.alias:[t.alias];Array.prototype.push.apply(i.classes,o)}n.hooks.run("wrap",i);var s=Object.keys(i.attributes).map(function(t){return t+'="'+(i.attributes[t]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+(s?" "+s:"")+">"+i.content+""+i.tag+">"},!r.document)return r.addEventListener?(r.addEventListener("message",function(t){var e=JSON.parse(t.data),a=e.language,i=e.code,o=e.immediateClose;r.postMessage(n.highlight(i,n.languages[a],a)),o&&r.close()},!1),r.Prism):r.Prism;var i=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return i&&(n.filename=i.src,n.manual||i.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),r.Prism}();void 0!==t&&t.exports&&(t.exports=n),void 0!==e&&(e.Prism=n),n.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\s\S])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\s\S]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/?[\da-z]{1,8};/i},n.languages.markup.tag.inside["attr-value"].inside.entity=n.languages.markup.entity,n.hooks.add("wrap",function(t){"entity"===t.type&&(t.attributes.title=t.content.replace(/&/,"&"))}),n.languages.xml=n.languages.markup,n.languages.html=n.languages.markup,n.languages.mathml=n.languages.markup,n.languages.svg=n.languages.markup,n.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:{pattern:/("|')(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},n.languages.css.atrule.inside.rest=n.util.clone(n.languages.css),n.languages.markup&&(n.languages.insertBefore("markup","tag",{style:{pattern:/(