├── favicon.ico ├── assets ├── ad.png ├── icons │ ├── icon_32.png │ ├── icon_48.png │ ├── icon_128.png │ ├── icon_144.png │ ├── icon_152.png │ └── icon_256.png ├── images │ ├── profile.png │ └── profile.webp └── manifest.json ├── img └── blog │ ├── 1 │ ├── 1.png │ └── 2.png │ ├── 2 │ ├── ie.jpg │ ├── firefox.jpg │ └── opera.jpg │ ├── 6 │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ └── viewport.gif │ ├── 7 │ ├── 1.png │ ├── 2.png │ └── 3.png │ ├── 10 │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ └── 5.png │ ├── 11 │ └── Style_Switcher.gif │ ├── 12 │ └── border-radius.png │ ├── 13 │ └── dn1.png │ ├── 14 │ ├── 1.gif │ ├── 2.gif │ ├── 3.gif │ ├── viewportvsbody.jpg │ └── viewportvsbody2.png │ ├── 15 │ ├── 1.3.2.png │ ├── 1.4.1.png │ ├── 1.4.4.gif │ ├── 2.1.1.gif │ ├── 2.2.1.gif │ ├── 2.4.3.png │ ├── 2.4.5.gif │ ├── 3.3.1.png │ └── 3.3.2.png │ ├── 16 │ ├── not.png │ ├── empty.png │ ├── first.png │ ├── lang1.png │ ├── lang2.png │ ├── lang3.png │ └── target.gif │ ├── 19 │ ├── 1-border.jpg │ ├── 1-margin.jpg │ ├── 2-border.jpg │ ├── 1-content.jpg │ ├── 1-padding.jpg │ ├── 2-content.jpg │ └── 2-padding.jpg │ ├── 20 │ ├── navigation.png │ └── navigation-tab.gif │ ├── 21 │ ├── wo-mousemove.gif │ └── with-mousemove.gif │ ├── 22 │ ├── display-position.png │ └── visibility-opacity.png │ ├── 25 │ ├── 1.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 3.1.png │ ├── 3.2.png │ ├── clear-left.png │ └── clear-only-left.png │ ├── 26 │ └── hsl.png │ ├── 27 │ ├── events.png │ ├── tweet.png │ └── campaigns.png │ ├── 28 │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── float-problem.gif │ └── float-solution.gif │ ├── 29 │ └── fitfam.png │ ├── 30 │ ├── style-js.png │ ├── style-nojs.png │ └── styleception.png │ ├── 31 │ └── divsectionarticle.jpg │ ├── 34 │ ├── 1.jpg │ ├── 2.png │ ├── 3.png │ └── 4.png │ └── 36 │ ├── outset.gif │ ├── repeat.gif │ ├── slice-1.png │ ├── slice-2.png │ ├── slice-3.png │ ├── slice-4.png │ ├── width-1.png │ └── width-2.png ├── .gitignore ├── README.md ├── partials ├── icon-menu.hbs ├── icon-bookmark.hbs ├── site-nav.hbs ├── pagination.hbs ├── post-excerpt.hbs ├── site-search.hbs ├── ad.hbs ├── disqus.hbs ├── post-suggestions.hbs ├── icon-rss.hbs ├── post-share.hbs ├── icon-cancel.hbs ├── icon-search.hbs ├── icon-facebook.hbs ├── icon-twitter.hbs ├── site-sidebar.hbs ├── icon-youtube.hbs ├── subscribe.hbs ├── icon-reddit.hbs └── bitsofcode-logo.hbs ├── index.hbs ├── src ├── scss │ ├── offline.scss │ ├── _ads.scss │ ├── _variables.scss │ ├── _form.scss │ ├── global.scss │ ├── _subscribe.scss │ ├── _ghost-required.scss │ ├── _reset.scss │ ├── _utils.scss │ ├── _typography.scss │ ├── _syntax-highlighting.scss │ ├── _layout.scss │ └── _post.scss ├── js │ ├── global │ │ ├── main.js │ │ ├── register-sw.js │ │ └── dialog.js │ ├── post │ │ ├── save-article.js │ │ └── prisim.js │ └── search.js └── sw.js ├── tag.hbs ├── page.hbs ├── page-subscribe.hbs ├── release.js ├── package.json ├── page-search.hbs ├── post.hbs ├── gulpfile.js ├── page-offline.hbs └── default.hbs /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/favicon.ico -------------------------------------------------------------------------------- /assets/ad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/assets/ad.png -------------------------------------------------------------------------------- /img/blog/1/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/1/1.png -------------------------------------------------------------------------------- /img/blog/1/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/1/2.png -------------------------------------------------------------------------------- /img/blog/10/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/10/1.png -------------------------------------------------------------------------------- /img/blog/10/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/10/2.png -------------------------------------------------------------------------------- /img/blog/10/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/10/3.png -------------------------------------------------------------------------------- /img/blog/10/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/10/4.png -------------------------------------------------------------------------------- /img/blog/10/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/10/5.png -------------------------------------------------------------------------------- /img/blog/14/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/14/1.gif -------------------------------------------------------------------------------- /img/blog/14/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/14/2.gif -------------------------------------------------------------------------------- /img/blog/14/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/14/3.gif -------------------------------------------------------------------------------- /img/blog/2/ie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/2/ie.jpg -------------------------------------------------------------------------------- /img/blog/25/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/25/1.png -------------------------------------------------------------------------------- /img/blog/25/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/25/4.png -------------------------------------------------------------------------------- /img/blog/25/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/25/5.png -------------------------------------------------------------------------------- /img/blog/25/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/25/6.png -------------------------------------------------------------------------------- /img/blog/28/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/28/1.png -------------------------------------------------------------------------------- /img/blog/28/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/28/2.png -------------------------------------------------------------------------------- /img/blog/28/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/28/3.png -------------------------------------------------------------------------------- /img/blog/34/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/34/1.jpg -------------------------------------------------------------------------------- /img/blog/34/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/34/2.png -------------------------------------------------------------------------------- /img/blog/34/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/34/3.png -------------------------------------------------------------------------------- /img/blog/34/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/34/4.png -------------------------------------------------------------------------------- /img/blog/6/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/6/1.png -------------------------------------------------------------------------------- /img/blog/6/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/6/2.png -------------------------------------------------------------------------------- /img/blog/6/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/6/3.png -------------------------------------------------------------------------------- /img/blog/6/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/6/4.png -------------------------------------------------------------------------------- /img/blog/7/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/7/1.png -------------------------------------------------------------------------------- /img/blog/7/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/7/2.png -------------------------------------------------------------------------------- /img/blog/7/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/7/3.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | # built 4 | assets/built 5 | /sw.js 6 | bitsofcode-ghost.zip 7 | -------------------------------------------------------------------------------- /img/blog/13/dn1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/13/dn1.png -------------------------------------------------------------------------------- /img/blog/16/not.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/16/not.png -------------------------------------------------------------------------------- /img/blog/25/3.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/25/3.1.png -------------------------------------------------------------------------------- /img/blog/25/3.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/25/3.2.png -------------------------------------------------------------------------------- /img/blog/26/hsl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/26/hsl.png -------------------------------------------------------------------------------- /img/blog/15/1.3.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/15/1.3.2.png -------------------------------------------------------------------------------- /img/blog/15/1.4.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/15/1.4.1.png -------------------------------------------------------------------------------- /img/blog/15/1.4.4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/15/1.4.4.gif -------------------------------------------------------------------------------- /img/blog/15/2.1.1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/15/2.1.1.gif -------------------------------------------------------------------------------- /img/blog/15/2.2.1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/15/2.2.1.gif -------------------------------------------------------------------------------- /img/blog/15/2.4.3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/15/2.4.3.png -------------------------------------------------------------------------------- /img/blog/15/2.4.5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/15/2.4.5.gif -------------------------------------------------------------------------------- /img/blog/15/3.3.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/15/3.3.1.png -------------------------------------------------------------------------------- /img/blog/15/3.3.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/15/3.3.2.png -------------------------------------------------------------------------------- /img/blog/16/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/16/empty.png -------------------------------------------------------------------------------- /img/blog/16/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/16/first.png -------------------------------------------------------------------------------- /img/blog/16/lang1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/16/lang1.png -------------------------------------------------------------------------------- /img/blog/16/lang2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/16/lang2.png -------------------------------------------------------------------------------- /img/blog/16/lang3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/16/lang3.png -------------------------------------------------------------------------------- /img/blog/16/target.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/16/target.gif -------------------------------------------------------------------------------- /img/blog/2/firefox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/2/firefox.jpg -------------------------------------------------------------------------------- /img/blog/2/opera.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/2/opera.jpg -------------------------------------------------------------------------------- /img/blog/27/events.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/27/events.png -------------------------------------------------------------------------------- /img/blog/27/tweet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/27/tweet.png -------------------------------------------------------------------------------- /img/blog/29/fitfam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/29/fitfam.png -------------------------------------------------------------------------------- /img/blog/36/outset.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/36/outset.gif -------------------------------------------------------------------------------- /img/blog/36/repeat.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/36/repeat.gif -------------------------------------------------------------------------------- /assets/icons/icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/assets/icons/icon_32.png -------------------------------------------------------------------------------- /assets/icons/icon_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/assets/icons/icon_48.png -------------------------------------------------------------------------------- /img/blog/19/1-border.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/19/1-border.jpg -------------------------------------------------------------------------------- /img/blog/19/1-margin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/19/1-margin.jpg -------------------------------------------------------------------------------- /img/blog/19/2-border.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/19/2-border.jpg -------------------------------------------------------------------------------- /img/blog/30/style-js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/30/style-js.png -------------------------------------------------------------------------------- /img/blog/36/slice-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/36/slice-1.png -------------------------------------------------------------------------------- /img/blog/36/slice-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/36/slice-2.png -------------------------------------------------------------------------------- /img/blog/36/slice-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/36/slice-3.png -------------------------------------------------------------------------------- /img/blog/36/slice-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/36/slice-4.png -------------------------------------------------------------------------------- /img/blog/36/width-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/36/width-1.png -------------------------------------------------------------------------------- /img/blog/36/width-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/36/width-2.png -------------------------------------------------------------------------------- /img/blog/6/viewport.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/6/viewport.gif -------------------------------------------------------------------------------- /assets/icons/icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/assets/icons/icon_128.png -------------------------------------------------------------------------------- /assets/icons/icon_144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/assets/icons/icon_144.png -------------------------------------------------------------------------------- /assets/icons/icon_152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/assets/icons/icon_152.png -------------------------------------------------------------------------------- /assets/icons/icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/assets/icons/icon_256.png -------------------------------------------------------------------------------- /assets/images/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/assets/images/profile.png -------------------------------------------------------------------------------- /assets/images/profile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/assets/images/profile.webp -------------------------------------------------------------------------------- /img/blog/19/1-content.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/19/1-content.jpg -------------------------------------------------------------------------------- /img/blog/19/1-padding.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/19/1-padding.jpg -------------------------------------------------------------------------------- /img/blog/19/2-content.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/19/2-content.jpg -------------------------------------------------------------------------------- /img/blog/19/2-padding.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/19/2-padding.jpg -------------------------------------------------------------------------------- /img/blog/20/navigation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/20/navigation.png -------------------------------------------------------------------------------- /img/blog/25/clear-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/25/clear-left.png -------------------------------------------------------------------------------- /img/blog/27/campaigns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/27/campaigns.png -------------------------------------------------------------------------------- /img/blog/30/style-nojs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/30/style-nojs.png -------------------------------------------------------------------------------- /img/blog/12/border-radius.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/12/border-radius.png -------------------------------------------------------------------------------- /img/blog/21/wo-mousemove.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/21/wo-mousemove.gif -------------------------------------------------------------------------------- /img/blog/28/float-problem.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/28/float-problem.gif -------------------------------------------------------------------------------- /img/blog/30/styleception.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/30/styleception.png -------------------------------------------------------------------------------- /img/blog/11/Style_Switcher.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/11/Style_Switcher.gif -------------------------------------------------------------------------------- /img/blog/14/viewportvsbody.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/14/viewportvsbody.jpg -------------------------------------------------------------------------------- /img/blog/14/viewportvsbody2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/14/viewportvsbody2.png -------------------------------------------------------------------------------- /img/blog/20/navigation-tab.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/20/navigation-tab.gif -------------------------------------------------------------------------------- /img/blog/21/with-mousemove.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/21/with-mousemove.gif -------------------------------------------------------------------------------- /img/blog/22/display-position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/22/display-position.png -------------------------------------------------------------------------------- /img/blog/25/clear-only-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/25/clear-only-left.png -------------------------------------------------------------------------------- /img/blog/28/float-solution.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/28/float-solution.gif -------------------------------------------------------------------------------- /img/blog/22/visibility-opacity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/22/visibility-opacity.png -------------------------------------------------------------------------------- /img/blog/31/divsectionarticle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ireade/bitsofcode-ghost/HEAD/img/blog/31/divsectionarticle.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ghost theme for bitsofcode 2 | 3 | **I'm making this open source for learning purposes, please don't copy it :)** 4 | -------------------------------------------------------------------------------- /partials/icon-menu.hbs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /index.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | 3 |
4 |

Latest Posts

5 | {{#foreach posts}} 6 | {{> post-excerpt}} 7 | {{/foreach}} 8 | 9 | {{> subscribe}} 10 | 11 | {{pagination}} 12 |
13 | 14 | -------------------------------------------------------------------------------- /src/scss/offline.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | @import "reset"; 4 | @import "variables"; 5 | @import "typography"; 6 | @import "utils"; 7 | @import "layout"; 8 | @import "post"; 9 | 10 | .site__header .wrapper { 11 | justify-content: center; 12 | } 13 | -------------------------------------------------------------------------------- /tag.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | 3 |
4 |
5 |

Posts in category: "{{tag.name}}"

6 |
7 | 8 | {{#foreach posts}} 9 | {{> post-excerpt}} 10 | {{/foreach}} 11 | 12 | {{> subscribe}} 13 | 14 | {{pagination}} 15 |
16 | -------------------------------------------------------------------------------- /page.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | {{#post}} 3 |
4 |
5 |

{{title}}

6 |
7 | 8 |
9 | {{ content }} 10 |
11 | 12 |
13 | {{/post}} -------------------------------------------------------------------------------- /partials/icon-bookmark.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /partials/site-nav.hbs: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/js/global/main.js: -------------------------------------------------------------------------------- 1 | /* Console message */ 2 | 3 | var consoleMessages = [ 4 | "Hi there :)", 5 | "👀 I 👀 see 👀 you 👀", 6 | "Hope you're having a great day 😊", 7 | "How do you comfort a JavaScript bug? You console it 😎" 8 | ]; 9 | var consoleMessage = consoleMessages[Math.floor(Math.random() * consoleMessages.length)]; 10 | console.log(consoleMessage); 11 | -------------------------------------------------------------------------------- /src/scss/_ads.scss: -------------------------------------------------------------------------------- 1 | 2 | .ad { 3 | text-align: center; 4 | 5 | img { 6 | @extend .show-broken; 7 | } 8 | } 9 | 10 | #carbonads .carbon-text { 11 | display: block; 12 | font-size: 1.3rem; 13 | margin-top: 10px; 14 | margin-bottom: 10px 15 | } 16 | 17 | #carbonads .carbon-poweredby { 18 | font-size: 1.3rem; 19 | font-style: italic 20 | } 21 | -------------------------------------------------------------------------------- /src/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | 2 | $colour-theme: #ffdb3a; 3 | $colour-bg: #f5f5f5; 4 | $colour-border: #e6e6e6; 5 | 6 | $font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Oxygen-Sans, Ubuntu, Cantarell, sans-serif; 7 | $font-family-monospace: "Dank Mono", Inconsolata, Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; 8 | 9 | $font-weight-bold: 600; 10 | -------------------------------------------------------------------------------- /page-subscribe.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | {{#post}} 3 |
4 |
5 |

{{title}}

6 |
7 | 8 |
9 | {{ content }} 10 |
11 | 12 | {{> subscribe}} 13 | 14 |
15 | {{/post}} 16 | 17 | 18 | -------------------------------------------------------------------------------- /partials/pagination.hbs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/js/global/register-sw.js: -------------------------------------------------------------------------------- 1 | if ('serviceWorker' in navigator) { 2 | window.addEventListener('load', () => { 3 | navigator.serviceWorker.register("/sw.js?refresh=true", {scope: "/"}) 4 | .then((registration) => { 5 | console.log("Yay service worker registered!"); 6 | if (registration.waiting) registration.update(); 7 | }) 8 | .catch((err) => console.log("Boo, service worker not registered:(", err)) 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /partials/post-excerpt.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | {{ title }} 5 |

6 | 12 |
13 | 14 |
15 | {{ excerpt words="50" }}... 16 |
17 |
-------------------------------------------------------------------------------- /partials/site-search.hbs: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /partials/ad.hbs: -------------------------------------------------------------------------------- 1 |
2 | 17 |
-------------------------------------------------------------------------------- /src/scss/_form.scss: -------------------------------------------------------------------------------- 1 | .search-form { 2 | display: block; 3 | } 4 | 5 | form { 6 | input { 7 | height: 40px; 8 | border-radius: 3px; 9 | } 10 | 11 | input:not([type="submit"]) { 12 | width: 100%; 13 | 14 | } 15 | } 16 | 17 | /* Search form */ 18 | 19 | .search-form__input { 20 | display: block; 21 | -webkit-appearance: none; 22 | border: 0; 23 | border-radius: 3px; 24 | border: 2px solid #e6e6e6; 25 | padding-left: 10px; 26 | padding-right: 10px; 27 | } 28 | 29 | .search-form__input:focus, 30 | .search-form__input:active { 31 | border-color: $colour-theme; 32 | } 33 | 34 | 35 | /* Subscribe form */ 36 | 37 | 38 | /* Translate form */ 39 | -------------------------------------------------------------------------------- /release.js: -------------------------------------------------------------------------------- 1 | var smartZip = require("smart-zip"); 2 | var replace = require("replace"); 3 | var newVersionNumber = process.argv[2]; 4 | 5 | if (!newVersionNumber) return console.error("Version number not specified"); 6 | console.log("New version: ", newVersionNumber) 7 | 8 | replace({ 9 | regex: /version([\s\S]*?),/, 10 | replacement: "version\": \"" + newVersionNumber + "\",", 11 | paths: ['package.json'], 12 | recursive: true, 13 | silent: true 14 | }); 15 | 16 | var regexExcludes = ['README.md', 'node_modules', 'src', 'gulpfile.js', 'release.js', '.gitignore', '.git', 'package-lock.json']; 17 | smartZip.zip('./', 'bitsofcode-ghost.zip', false, regexExcludes, function (error) { 18 | if (error) { 19 | throw error; 20 | } 21 | console.log('Completed'); 22 | }); 23 | -------------------------------------------------------------------------------- /partials/disqus.hbs: -------------------------------------------------------------------------------- 1 |
2 | 15 | 16 | blog comments powered by Disqus -------------------------------------------------------------------------------- /partials/post-suggestions.hbs: -------------------------------------------------------------------------------- 1 |
2 |

More Posts

3 | 4 | {{#prev_post}} 5 |
6 |

7 | 8 |
9 | {{title}} 10 |
11 |

12 | 13 |
14 | {{/prev_post}} 15 | 16 | {{#next_post}} 17 |
18 |

19 | 20 |
21 | {{title}} 22 |
23 |

24 | 25 |
26 | {{/next_post}} 27 | 28 |
-------------------------------------------------------------------------------- /assets/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bitsofcode", 3 | "short_name": "bitsofcode", 4 | "description": "Articles on Frontend Development written by Ire Aderinokun, Frontend Developer and User Interface Designer.", 5 | "theme_color": "#ffdb3a", 6 | "background_color": "#f5f5f5", 7 | "display": "standalone", 8 | "orientation": "portrait", 9 | "start_url": "/", 10 | "lang": "en-US", 11 | "scope": "/", 12 | "icons": [ 13 | { 14 | "src": "/assets/icons/icon_32.png", 15 | "sizes": "32x32", 16 | "type": "image/png" 17 | }, 18 | { 19 | "src": "/assets/icons/icon_48.png", 20 | "sizes": "48x48", 21 | "type": "image/png" 22 | }, 23 | { 24 | "src": "/assets/icons/icon_128.png", 25 | "sizes": "128x128", 26 | "type": "image/png" 27 | }, 28 | { 29 | "src": "/assets/icons/icon_256.png", 30 | "sizes": "256x256", 31 | "type": "image/png" 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /partials/icon-rss.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /partials/post-share.hbs: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /partials/icon-cancel.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bitsofcode", 3 | "version": "3.4.0", 4 | "description": "Ghost Theme for bitsofcode", 5 | "keywords": [ 6 | "ghost-theme" 7 | ], 8 | "main": "gulpfile.js", 9 | "`browserslist`": [ 10 | "last 2 versions", 11 | "Explorer >= 11" 12 | ], 13 | "scripts": { 14 | "start": "gulp", 15 | "release": "open . && node release.js", 16 | "server": "cd ../../../ && ghost start" 17 | }, 18 | "author": { 19 | "name": "Ire Aderinokun", 20 | "email": "ire@bitsofco.de", 21 | "url": "https://ireaderinokun.com" 22 | }, 23 | "license": "ISC", 24 | "devDependencies": { 25 | "@babel/core": "^7.1.6", 26 | "@babel/preset-env": "^7.1.6", 27 | "@babel/preset-es2015": "^7.0.0-beta.53", 28 | "autoprefixer": "^9.3.1", 29 | "gulp": "^3.9.1", 30 | "gulp-babel": "^8.0.0", 31 | "gulp-clean-css": "^4.0.0", 32 | "gulp-concat": "^2.6.1", 33 | "gulp-postcss": "^8.0.0", 34 | "gulp-sass": "^4.0.2", 35 | "gulp-uglify": "^3.0.1", 36 | "postcss-scss": "^2.0.0", 37 | "replace": "^0.3.0", 38 | "smart-zip": "0.0.9" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /partials/icon-search.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /page-search.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | {{#post}} 3 |
4 |
5 |

Search

6 |
7 | 8 |
9 | 13 | 14 |
15 | 16 | 17 |
18 | 19 | 20 | Use the search form above to search for articles. 21 | 22 | 23 |
24 |
25 |
26 |
27 | 28 | 29 | {{/post}} 30 | -------------------------------------------------------------------------------- /src/scss/global.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | @import "ghost-required"; 4 | 5 | @import "reset"; 6 | @import "variables"; 7 | @import "typography"; 8 | @import "utils"; 9 | @import "layout"; 10 | @import "post"; 11 | @import "ads"; 12 | @import "syntax-highlighting"; 13 | @import "subscribe"; 14 | @import "form"; 15 | 16 | 17 | .social ul { 18 | display: flex; 19 | justify-content: center 20 | } 21 | 22 | .social ul li { 23 | margin-left: 7px; 24 | margin-right: 7px 25 | } 26 | 27 | .social ul li svg { 28 | height: 15px; 29 | width: auto 30 | } 31 | 32 | .dialog-overlay { 33 | z-index: 15; 34 | position: fixed; 35 | top: 0; 36 | left: 0; 37 | width: 100%; 38 | width: 100vw; 39 | height: 100%; 40 | background-color: rgba(255, 255, 255, .9) 41 | } 42 | 43 | .dialog { 44 | z-index: 20; 45 | position: fixed; 46 | top: 0; 47 | left: 0; 48 | height: 100%; 49 | width: 100%; 50 | width: 100vw; 51 | text-align: center; 52 | display: flex; 53 | justify-content: center; 54 | align-items: center 55 | } 56 | 57 | .dialog-overlay[aria-hidden=true], 58 | .dialog[aria-hidden=true] { 59 | display: none 60 | } 61 | 62 | 63 | 64 | .message--count { 65 | display: block 66 | } 67 | 68 | .message--count span { 69 | font-weight: 600 70 | } 71 | 72 | -------------------------------------------------------------------------------- /post.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | {{#post}} 3 |
4 |
5 |

{{title}}

6 | 16 |
17 | 18 |
19 | {{ content }} 20 |
21 | 22 | 27 | 28 | {{> disqus}} 29 | 30 |
31 | 32 | 33 | 35 | {{/post}} 36 | -------------------------------------------------------------------------------- /partials/icon-facebook.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /partials/icon-twitter.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /partials/site-sidebar.hbs: -------------------------------------------------------------------------------- 1 | 39 | -------------------------------------------------------------------------------- /src/scss/_subscribe.scss: -------------------------------------------------------------------------------- 1 | /* Subscribe ****************************/ 2 | 3 | .subscribe-form { 4 | background: #fff; 5 | margin-bottom: 30px; 6 | padding: 20px; 7 | position: relative 8 | } 9 | 10 | @media screen and (min-width:500px) { 11 | .subscribe-form__description { 12 | max-width: 60% 13 | } 14 | } 15 | 16 | .subscribe-form__image { 17 | position: absolute; 18 | right: 10px; 19 | bottom: 0; 20 | width: 25%; 21 | z-index: 1; 22 | 23 | img { 24 | width: 100%; 25 | } 26 | } 27 | 28 | @media screen and (min-width:500px) { 29 | .subscribe-form__image { 30 | width: 20% 31 | } 32 | } 33 | 34 | .subscribe-form__fields { 35 | display: flex; 36 | justify-content: space-between; 37 | flex-wrap: wrap; 38 | position: relative; 39 | z-index: 2 40 | } 41 | 42 | .subscribe-form__field input { 43 | border: 0 44 | } 45 | 46 | .subscribe-form__field--input { 47 | width: 75%; 48 | margin-bottom: 10px 49 | } 50 | 51 | @media screen and (min-width:500px) { 52 | .subscribe-form__field--input { 53 | width: 35%; 54 | margin-bottom: 0 55 | } 56 | } 57 | 58 | .subscribe-form__field--input input { 59 | background-color: #e6e6e6; 60 | padding-left: 10px; 61 | padding-right: 10px; 62 | } 63 | 64 | .subscribe-form__field--submit { 65 | width: 100%; 66 | max-width: 130px 67 | } 68 | 69 | @media screen and (min-width:500px) { 70 | .subscribe-form__field--submit { 71 | width: 25% 72 | } 73 | } 74 | 75 | .subscribe-form__field--submit input { 76 | background-color: $colour-theme; 77 | font-size: 1.4rem; 78 | font-weight: 600; 79 | box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .17); 80 | cursor: pointer; 81 | } -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const gutil = require('gulp-util'); 3 | 4 | 5 | /* ************* 6 | CSS 7 | ************* */ 8 | 9 | const sass = require('gulp-sass'); 10 | const postcss = require('gulp-postcss'); 11 | const scss = require('postcss-scss'); 12 | const autoprefixer = require('autoprefixer'); 13 | const cleanCSS = require('gulp-clean-css'); 14 | 15 | const sassMainFile = ['src/scss/global.scss', 'src/scss/offline.scss']; 16 | const sassFiles = 'src/scss/**/*.scss'; 17 | 18 | gulp.task('css', function () { 19 | gulp.src(sassMainFile) 20 | .pipe(postcss([autoprefixer()], { syntax: scss })) 21 | .pipe(sass({ outputStyle: 'compressed' }).on('error', gutil.log)) 22 | .pipe(cleanCSS()) 23 | .pipe(gulp.dest('assets/built')); 24 | }); 25 | 26 | 27 | 28 | /* ************* 29 | JS 30 | ************* */ 31 | 32 | const concat = require('gulp-concat'); 33 | const uglify = require('gulp-uglify'); 34 | const babel = require('gulp-babel'); 35 | 36 | const jsFiles = 'src/**/*.js'; 37 | 38 | gulp.task('js', function () { 39 | gulp.src('src/js/post/*.js') 40 | .pipe(babel({ presets: ['@babel/env'] })) 41 | .pipe(concat('post.js')) 42 | .pipe(uglify()) 43 | .pipe(gulp.dest('assets/built')); 44 | 45 | gulp.src('src/js/global/*.js') 46 | .pipe(babel({ presets: ['@babel/env'] })) 47 | .pipe(concat('global.js')) 48 | .pipe(uglify()) 49 | .pipe(gulp.dest('assets/built')); 50 | 51 | gulp.src('src/js/*.js') 52 | .pipe(babel({ presets: ['@babel/env'] })) 53 | .pipe(uglify()) 54 | .pipe(gulp.dest('assets/built')); 55 | 56 | gulp.src('src/sw.js') 57 | .pipe(gulp.dest('')); 58 | }); 59 | 60 | gulp.task('watch', function () { 61 | gulp.watch(sassFiles, ['css']); 62 | gulp.watch(jsFiles, ['js']); 63 | }); 64 | 65 | gulp.task('build', ['css', 'js']); 66 | 67 | gulp.task('default', ['css', 'js', 'watch']); 68 | -------------------------------------------------------------------------------- /src/sw.js: -------------------------------------------------------------------------------- 1 | const precacheVersion = 2; 2 | const precacheName = 'precache-v' + precacheVersion; 3 | const precacheFiles = [ 4 | "/assets/images/profile.png", 5 | "/assets/images/profile.webp", 6 | "/assets/built/offline.css", 7 | "/offline/" 8 | ]; 9 | 10 | self.addEventListener('install', (e) => { 11 | console.log('[ServiceWorker] Installed'); 12 | self.skipWaiting(); 13 | 14 | e.waitUntil( 15 | caches.open(precacheName).then((cache) => { 16 | console.log('[ServiceWorker] Precaching files'); 17 | return cache.addAll(precacheFiles); 18 | }) // end caches.open() 19 | ); // end e.waitUntil 20 | }); 21 | 22 | self.addEventListener('activate', (e) => { 23 | console.log('[ServiceWorker] Activated'); 24 | 25 | e.waitUntil( 26 | caches.keys().then((cacheNames) => { 27 | return Promise.all(cacheNames.map((thisCacheName) => { 28 | 29 | if (thisCacheName.includes("precache") && thisCacheName !== precacheName) { 30 | console.log('[ServiceWorker] Removing cached files from old cache - ', thisCacheName); 31 | return caches.delete(thisCacheName); 32 | } 33 | 34 | })); 35 | }) // end caches.keys() 36 | ); // end e.waitUntil 37 | }); 38 | 39 | self.addEventListener('fetch', (e) => { 40 | 41 | const requestURL = new URL(e.request.url); 42 | if (!e.request.referrer.includes(requestURL.hostname)) { 43 | return e.respondWith(fetch(e.request)); 44 | } 45 | 46 | e.respondWith( 47 | caches.match(e.request) 48 | .then((response) => { 49 | 50 | if (response) { 51 | console.log("[ServiceWorker] Found in cache", e.request.url); 52 | return response; 53 | } 54 | 55 | return fetch(e.request) 56 | .then((fetchResponse) => fetchResponse) 57 | .catch((err) => { 58 | // If offline 59 | const isHTMLPage = e.request.method === "GET" && e.request.headers.get("accept").includes("text/html"); 60 | if (isHTMLPage) return caches.match("/offline/"); 61 | }); 62 | 63 | }) // end caches.match(e.request) 64 | ); // end e.respondWith 65 | }); 66 | -------------------------------------------------------------------------------- /partials/icon-youtube.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /page-offline.hbs: -------------------------------------------------------------------------------- 1 | {{#post}} 2 | 3 | 4 | 5 | 6 | {{title}} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 46 | 47 |
48 |
49 |
50 |
51 |
52 |

{{title}}

53 |
54 | 55 |
56 | {{ content }} 57 |
58 |
59 |
60 |
61 |
62 | 63 | 64 | {{/post}} 65 | -------------------------------------------------------------------------------- /partials/subscribe.hbs: -------------------------------------------------------------------------------- 1 | 2 |
3 |
6 |
7 |

Subscribe to the Newsletter

8 | 9 | 10 | 15 | 16 | 39 |
40 |
41 |
42 | 43 | -------------------------------------------------------------------------------- /src/scss/_ghost-required.scss: -------------------------------------------------------------------------------- 1 | .kg-width-wide img { 2 | max-width: 85vw; 3 | } 4 | 5 | .kg-width-full img { 6 | max-width: 100vw; 7 | } 8 | 9 | .kg-width-wide { 10 | position: relative; 11 | width: 85vw; 12 | min-width: 100%; 13 | margin: auto calc(50% - 50vw); 14 | transform: translateX(calc(50vw - 50%)); 15 | } 16 | 17 | .kg-width-full { 18 | position: relative; 19 | width: 100vw; 20 | left: 50%; 21 | right: 50%; 22 | margin-left: -50vw; 23 | margin-right: -50vw; 24 | } 25 | 26 | .kg-gallery-container { 27 | display: flex; 28 | flex-direction: column; 29 | max-width: 1040px; 30 | width: 100vw; 31 | } 32 | 33 | .kg-gallery-row { 34 | display: flex; 35 | flex-direction: row; 36 | justify-content: center; 37 | } 38 | 39 | .kg-gallery-image img { 40 | display: block; 41 | margin: 0; 42 | width: 100%; 43 | height: 100%; 44 | } 45 | 46 | 47 | .kg-bookmark-card { 48 | width: 100%; 49 | position: relative; 50 | } 51 | 52 | .kg-bookmark-container { 53 | display: flex; 54 | flex-wrap: wrap; 55 | flex-direction: row-reverse; 56 | color: currentColor; 57 | font-family: inherit; 58 | text-decoration: none; 59 | border: 1px solid rgba(0, 0, 0, 0.1); 60 | } 61 | 62 | .kg-bookmark-container:hover { 63 | text-decoration: none; 64 | } 65 | 66 | .kg-bookmark-content { 67 | flex-basis: 0; 68 | flex-grow: 999; 69 | padding: 20px; 70 | order: 1; 71 | } 72 | 73 | .kg-bookmark-title { 74 | font-weight: 600; 75 | } 76 | 77 | .kg-bookmark-metadata, 78 | .kg-bookmark-description { 79 | margin-top: .5em; 80 | } 81 | 82 | .kg-bookmark-metadata { 83 | align-items: center; 84 | white-space: nowrap; 85 | overflow: hidden; 86 | text-overflow: ellipsis; 87 | } 88 | 89 | .kg-bookmark-description { 90 | display: -webkit-box; 91 | -webkit-box-orient: vertical; 92 | -webkit-line-clamp: 2; 93 | overflow: hidden; 94 | } 95 | 96 | .kg-bookmark-icon { 97 | display: inline-block; 98 | width: 1em; 99 | height: 1em; 100 | vertical-align: text-bottom; 101 | margin-right: .5em; 102 | margin-bottom: .05em; 103 | } 104 | 105 | .kg-bookmark-thumbnail { 106 | display: flex; 107 | flex-basis: 24rem; 108 | flex-grow: 1; 109 | } 110 | 111 | .kg-bookmark-thumbnail img { 112 | max-width: 100%; 113 | height: auto; 114 | vertical-align: bottom; 115 | object-fit: cover; 116 | } 117 | 118 | .kg-bookmark-author { 119 | white-space: nowrap; 120 | text-overflow: ellipsis; 121 | overflow: hidden; 122 | } 123 | 124 | .kg-bookmark-publisher::before { 125 | content: "•"; 126 | margin: 0 .5em; 127 | } 128 | 129 | -------------------------------------------------------------------------------- /src/js/post/save-article.js: -------------------------------------------------------------------------------- 1 | 2 | if ('serviceWorker' in navigator && 'caches' in window) { 3 | 4 | const saveArticleButton = document.getElementById("save"); 5 | const articlePath = window.location.pathname; 6 | const cacheName = 'article-' + articlePath.replace(/\//g, ""); 7 | const article = { 8 | path: articlePath, 9 | title: document.querySelector(".post__title").textContent 10 | }; 11 | 12 | saveArticleButton.removeAttribute("hidden"); 13 | 14 | function checkIfArticleIsInCache() { 15 | return caches.keys().then((keys) => keys.includes(cacheName)); 16 | } 17 | 18 | function saveArticleToCache() { 19 | const version = document.querySelector(".versionedAsset").href.split("?v=")[1]; 20 | const assets = [ 21 | `/assets/built/global.css?v=${version}`, 22 | `/assets/built/global.js?v=${version}`, 23 | `/assets/built/post.js?v=${version}` 24 | ]; 25 | 26 | return caches.open(cacheName).then((cache) => cache.addAll([articlePath, ...assets])); 27 | } 28 | 29 | function saveArticleToLocalStorage() { 30 | const articles = JSON.parse(localStorage.getItem("articles") || "[]"); 31 | 32 | articles.push(article); 33 | 34 | localStorage.setItem("articles", JSON.stringify(articles)); 35 | 36 | return Promise.resolve(); 37 | } 38 | 39 | function removeArticleFromCache() { 40 | return caches.delete(cacheName); 41 | } 42 | 43 | function removeArticleFromLocalStorage() { 44 | let articles = JSON.parse(localStorage.getItem("articles") || "[]"); 45 | 46 | articles = articles.filter((a) => { 47 | if (a.path !== article.path) return a; 48 | }); 49 | 50 | localStorage.setItem("articles", JSON.stringify(articles)); 51 | 52 | return Promise.resolve(); 53 | } 54 | 55 | function updateButton(isCached) { 56 | saveArticleButton.querySelector('.label').textContent = isCached ? "Saved! Click to remove article" : "Save Article for Offline"; 57 | 58 | if (isCached) saveArticleButton.classList.add('saved'); 59 | else saveArticleButton.classList.remove('saved'); 60 | } 61 | 62 | saveArticleButton.addEventListener("click", (e) => { 63 | checkIfArticleIsInCache() 64 | .then((isCached) => { 65 | if (isCached) { 66 | removeArticleFromCache() 67 | .then(() => removeArticleFromLocalStorage()) 68 | .then(() => updateButton(false)); 69 | } else { 70 | saveArticleToCache() 71 | .then(() => saveArticleToLocalStorage()) 72 | .then(() => updateButton(true)); 73 | }; 74 | }); 75 | }); 76 | 77 | checkIfArticleIsInCache().then(updateButton); 78 | } -------------------------------------------------------------------------------- /src/js/global/dialog.js: -------------------------------------------------------------------------------- 1 | /* Navigation Dialod */ 2 | 3 | for (var changeAnchorToButton = function (e) { 4 | var t = document.createElement("button"); 5 | t.setAttribute("type", "button"), t.innerHTML = e.innerHTML, e.id && (t.id = e.id); 6 | for (var s = 0; s < e.classList.length; s++) t.classList.add(e.classList[s]); 7 | var n = e.parentNode; 8 | n.replaceChild(t, e) 9 | }, anchorButtons = document.getElementsByClassName("anchorButton"), i = 0; i < anchorButtons.length; i++) changeAnchorToButton(anchorButtons[i]); 10 | 11 | function Dialog(e, t, s, n) { 12 | this.dialogEl = e, this.overlayEl = t, this.focusedElBeforeOpen; 13 | var o = this.dialogEl.querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]'); 14 | this.focusableEls = Array.prototype.slice.call(o), this.firstFocusableEl = this.focusableEls[0], this.lastFocusableEl = this.focusableEls[this.focusableEls.length - 1], this.addEventListeners(s, n), this.close() 15 | } 16 | 17 | Dialog.prototype.open = function () { 18 | var e = this; 19 | this.dialogEl.removeAttribute("aria-hidden"), this.overlayEl.removeAttribute("aria-hidden"), this.focusedElBeforeOpen = document.activeElement, this.dialogEl.addEventListener("keydown", function (t) { 20 | e.handleKeyDown(t) 21 | }), this.overlayEl.addEventListener("click", function () { 22 | e.close() 23 | }), this.firstFocusableEl.focus() 24 | }; 25 | 26 | Dialog.prototype.close = function () { 27 | this.dialogEl.setAttribute("aria-hidden", !0), this.overlayEl.setAttribute("aria-hidden", !0), this.focusedElBeforeOpen && this.focusedElBeforeOpen.focus() 28 | }; 29 | 30 | Dialog.prototype.handleKeyDown = function (e) { 31 | function t() { 32 | document.activeElement === n.firstFocusableEl && (e.preventDefault(), n.lastFocusableEl.focus()) 33 | } 34 | 35 | function s() { 36 | document.activeElement === n.lastFocusableEl && (e.preventDefault(), n.firstFocusableEl.focus()) 37 | } 38 | var n = this, 39 | o = 9, 40 | r = 27; 41 | switch (e.keyCode) { 42 | case o: 43 | if (1 === n.focusableEls.length) return void e.preventDefault(); 44 | e.shiftKey ? t() : s(); 45 | break; 46 | case r: 47 | n.close() 48 | } 49 | } 50 | 51 | Dialog.prototype.addEventListeners = function (e, t) { 52 | for (var s = this, n = document.querySelectorAll(e), o = 0; o < n.length; o++) n[o].addEventListener("click", function () { 53 | s.open() 54 | }); 55 | for (var r = document.querySelectorAll(t), o = 0; o < r.length; o++) r[o].addEventListener("click", function () { 56 | s.close() 57 | }) 58 | }; 59 | 60 | var dialogOverlay = document.querySelector(".dialog-overlay"), 61 | navDialogEl = document.querySelector(".dialog--nav"); 62 | 63 | new Dialog(navDialogEl, dialogOverlay, ".site__nav__open", ".site__nav__close"); 64 | -------------------------------------------------------------------------------- /src/scss/_reset.scss: -------------------------------------------------------------------------------- 1 | /* *********************************** 2 | * 3 | * Ire's CSS Reset & Base 4 | * 5 | * *********************************** */ 6 | 7 | /* Reset margin, padding, border 8 | * *********************************** */ 9 | 10 | html, body, 11 | h1, h2, h3, h4, h5, h6, 12 | a, p, span, 13 | em, small, strong, 14 | sub, sup, 15 | mark, del, ins, 16 | abbr, dfn, 17 | blockquote, q, cite, 18 | code, pre, 19 | ol, ul, li, dl, dt, dd, 20 | div, section, article, 21 | main, aside, nav, 22 | header, hgroup, footer, 23 | img, figure, figcaption, 24 | address, time, 25 | audio, video, 26 | canvas, iframe, 27 | details, summary, 28 | fieldset, form, label, legend, 29 | table, caption, 30 | tbody, tfoot, thead, 31 | tr, th, td { 32 | margin: 0; 33 | padding: 0; 34 | border: 0; 35 | } 36 | 37 | /* Typography 38 | * *********************************** */ 39 | 40 | html { 41 | font-size: 62.5%; 42 | } 43 | 44 | body { 45 | font-size: 1.6rem; 46 | line-height: 1.4; 47 | } 48 | 49 | * { 50 | font: inherit; 51 | } 52 | 53 | strong { 54 | font-weight: bold; 55 | } 56 | 57 | em { 58 | font-style: italic; 59 | } 60 | 61 | small, 62 | sup, 63 | sub { 64 | font-size: small; 65 | } 66 | 67 | a, 68 | a:visited { 69 | color: inherit; 70 | } 71 | 72 | /* Layout 73 | * *********************************** */ 74 | 75 | article, 76 | aside, 77 | footer, 78 | header, 79 | nav, 80 | section, 81 | main { 82 | display: block; 83 | } 84 | 85 | * { 86 | box-sizing: border-box; 87 | } 88 | 89 | *:before, 90 | *:after { 91 | box-sizing: inherit; 92 | } 93 | 94 | /* Elements 95 | * *********************************** */ 96 | 97 | table { 98 | border-collapse: collapse; 99 | border-spacing: 0; 100 | } 101 | 102 | ol, 103 | ul { 104 | list-style: none; 105 | } 106 | 107 | img, 108 | video { 109 | max-width: 100%; 110 | } 111 | 112 | img { 113 | border-style: none; 114 | } 115 | 116 | blockquote, 117 | q { 118 | quotes: none; 119 | } 120 | 121 | blockquote:after, 122 | blockquote:before, 123 | q:after, 124 | q:before { 125 | content: ""; 126 | content: none; 127 | } 128 | 129 | /* Attributes & states 130 | * *********************************** */ 131 | 132 | [hidden] { 133 | display: none !important; 134 | } 135 | 136 | [disabled] { 137 | cursor: not-allowed; 138 | } 139 | 140 | :focus:not(:focus-visible) { 141 | outline: none; 142 | } 143 | 144 | /* Utility classes 145 | * *********************************** */ 146 | 147 | .sr-only { 148 | position: absolute; 149 | clip: rect(1px, 1px, 1px, 1px); 150 | left: -9999px; 151 | top: -9999px; 152 | } 153 | 154 | .clearfix::after { 155 | content: ""; 156 | clear: both; 157 | display: table; 158 | } 159 | -------------------------------------------------------------------------------- /default.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{meta_title}} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 44 | 45 | {{ghost_head}} 46 | 47 | 48 | 49 | 67 | 68 | {{> site-nav}} 69 | 70 | 71 |
72 |
73 |
{{{body}}}
74 | {{> site-sidebar}} 75 |
76 |
77 | 78 | 84 | 85 | 86 | 87 | 88 | {{ghost_foot}} 89 | 90 | -------------------------------------------------------------------------------- /src/scss/_utils.scss: -------------------------------------------------------------------------------- 1 | 2 | .no-ul, 3 | .no-ul a { 4 | text-decoration: none 5 | } 6 | 7 | .ta-center { 8 | text-align: center 9 | } 10 | 11 | .ta-right { 12 | text-align: right 13 | } 14 | 15 | .ta-left { 16 | text-align: left 17 | } 18 | 19 | .fw-100 { 20 | font-weight: 100 21 | } 22 | 23 | .fw-200 { 24 | font-weight: 200 25 | } 26 | 27 | .fw-300 { 28 | font-weight: 300 29 | } 30 | 31 | .fw-400 { 32 | font-weight: 400 33 | } 34 | 35 | .fw-500 { 36 | font-weight: 500 37 | } 38 | 39 | .fw-600 { 40 | font-weight: 600 41 | } 42 | 43 | .fw-700 { 44 | font-weight: 700 45 | } 46 | 47 | .fw-800 { 48 | font-weight: 800 49 | } 50 | 51 | .fw-900 { 52 | font-weight: 900 53 | } 54 | 55 | .fs-i { 56 | font-style: italic 57 | } 58 | 59 | .fs-o { 60 | font-style: oblique 61 | } 62 | 63 | .fs-n { 64 | font-style: normal 65 | } 66 | 67 | .m-t-xsm { 68 | margin-top: 5px 69 | } 70 | 71 | .m-r-xsm { 72 | margin-right: 5px 73 | } 74 | 75 | .m-b-xsm { 76 | margin-bottom: 5px 77 | } 78 | 79 | .m-l-xsm { 80 | margin-left: 5px 81 | } 82 | 83 | .m-a-xsm { 84 | margin: 5px 85 | } 86 | 87 | .m-t-sm { 88 | margin-top: 10px 89 | } 90 | 91 | .m-r-sm { 92 | margin-right: 10px 93 | } 94 | 95 | .m-b-sm { 96 | margin-bottom: 10px 97 | } 98 | 99 | .m-l-sm { 100 | margin-left: 10px 101 | } 102 | 103 | .m-a-sm { 104 | margin: 10px 105 | } 106 | 107 | .m-t-md { 108 | margin-top: 25px 109 | } 110 | 111 | .m-r-md { 112 | margin-right: 25px 113 | } 114 | 115 | .m-b-md { 116 | margin-bottom: 25px 117 | } 118 | 119 | .m-l-md { 120 | margin-left: 25px 121 | } 122 | 123 | .m-a-md { 124 | margin: 25px 125 | } 126 | 127 | .m-t-lg { 128 | margin-top: 50px 129 | } 130 | 131 | .m-r-lg { 132 | margin-right: 50px 133 | } 134 | 135 | .m-b-lg { 136 | margin-bottom: 50px 137 | } 138 | 139 | .m-l-lg { 140 | margin-left: 50px 141 | } 142 | 143 | .m-a-lg { 144 | margin: 50px 145 | } 146 | 147 | .m-t-xlg { 148 | margin-top: 80px 149 | } 150 | 151 | .m-r-xlg { 152 | margin-right: 80px 153 | } 154 | 155 | .m-b-xlg { 156 | margin-bottom: 80px 157 | } 158 | 159 | .m-l-xlg { 160 | margin-left: 80px 161 | } 162 | 163 | .m-a-xlg { 164 | margin: 80px 165 | } 166 | 167 | .p-t-xsm { 168 | padding-top: 5px 169 | } 170 | 171 | .p-r-xsm { 172 | padding-right: 5px 173 | } 174 | 175 | .p-b-xsm { 176 | padding-bottom: 5px 177 | } 178 | 179 | .p-l-xsm { 180 | padding-left: 5px 181 | } 182 | 183 | .p-a-xsm { 184 | padding: 5px 185 | } 186 | 187 | .p-t-sm { 188 | padding-top: 10px 189 | } 190 | 191 | .p-r-sm { 192 | padding-right: 10px 193 | } 194 | 195 | .p-b-sm { 196 | padding-bottom: 10px 197 | } 198 | 199 | .p-l-sm { 200 | padding-left: 10px 201 | } 202 | 203 | .p-a-sm { 204 | padding: 10px 205 | } 206 | 207 | .p-t-md { 208 | padding-top: 25px 209 | } 210 | 211 | .p-r-md { 212 | padding-right: 25px 213 | } 214 | 215 | .p-b-md { 216 | padding-bottom: 25px 217 | } 218 | 219 | .p-l-md { 220 | padding-left: 25px 221 | } 222 | 223 | .p-a-md { 224 | padding: 25px 225 | } 226 | 227 | .p-t-lg { 228 | padding-top: 50px 229 | } 230 | 231 | .p-r-lg { 232 | padding-right: 50px 233 | } 234 | 235 | .p-b-lg { 236 | padding-bottom: 50px 237 | } 238 | 239 | .p-l-lg { 240 | padding-left: 50px 241 | } 242 | 243 | .p-a-lg { 244 | padding: 50px 245 | } 246 | 247 | .p-t-xlg { 248 | padding-top: 80px 249 | } 250 | 251 | .p-r-xlg { 252 | padding-right: 80px 253 | } 254 | 255 | .p-b-xlg { 256 | padding-bottom: 80px 257 | } 258 | 259 | .p-l-xlg { 260 | padding-left: 80px 261 | } 262 | 263 | .p-a-xlg { 264 | padding: 80px 265 | } 266 | -------------------------------------------------------------------------------- /src/scss/_typography.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 1.5rem; 3 | line-height: 1.6; 4 | font-family: $font-family; 5 | font-weight: 300; 6 | } 7 | 8 | small { 9 | font-size: 1.3rem; 10 | } 11 | 12 | strong { 13 | font-weight: $font-weight-bold; 14 | } 15 | 16 | mark { 17 | background-color: $colour-theme; 18 | } 19 | 20 | .h1 { 21 | font-size: 2.6rem; 22 | font-weight: $font-weight-bold; 23 | } 24 | 25 | .h2, 26 | .post__content h2 { 27 | font-size: 2.3rem; 28 | font-weight: $font-weight-bold; 29 | } 30 | 31 | .h3, 32 | .post__content h3 { 33 | font-size: 1.9rem; 34 | font-weight: $font-weight-bold; 35 | } 36 | 37 | .h4, 38 | .post__content h4 { 39 | font-size: 1.8rem; 40 | font-weight: $font-weight-bold; 41 | } 42 | 43 | .focus--theme { 44 | outline: 0; 45 | } 46 | 47 | .focus--theme:focus, 48 | .focus--theme:hover { 49 | color: $colour-theme 50 | } 51 | 52 | .focus--theme:focus .fill, 53 | .focus--theme:hover .fill { 54 | fill: $colour-theme 55 | } 56 | 57 | * { 58 | outline-color: $colour-theme 59 | } 60 | 61 | p::selection { 62 | background: $colour-theme 63 | } 64 | 65 | p::-moz-selection { 66 | background: $colour-theme 67 | } 68 | 69 | a::selection { 70 | background: $colour-theme 71 | } 72 | 73 | a::-moz-selection { 74 | background: $colour-theme 75 | } 76 | 77 | h1::selection { 78 | background: $colour-theme 79 | } 80 | 81 | h1::-moz-selection { 82 | background: $colour-theme 83 | } 84 | 85 | h2::selection { 86 | background: $colour-theme 87 | } 88 | 89 | h2::-moz-selection { 90 | background: $colour-theme 91 | } 92 | 93 | h3::selection { 94 | background: $colour-theme 95 | } 96 | 97 | h3::-moz-selection { 98 | background: $colour-theme 99 | } 100 | 101 | h4::selection { 102 | background: $colour-theme 103 | } 104 | 105 | h4::-moz-selection { 106 | background: $colour-theme 107 | } 108 | 109 | div::selection { 110 | background: $colour-theme 111 | } 112 | 113 | div::-moz-selection { 114 | background: $colour-theme 115 | } 116 | 117 | code::selection { 118 | background: $colour-theme 119 | } 120 | 121 | code::-moz-selection { 122 | background: $colour-theme 123 | } 124 | 125 | pre::selection { 126 | background: $colour-theme 127 | } 128 | 129 | pre::-moz-selection { 130 | background: $colour-theme 131 | } 132 | 133 | strong::selection { 134 | background: $colour-theme 135 | } 136 | 137 | strong::-moz-selection { 138 | background: $colour-theme 139 | } 140 | 141 | em::selection { 142 | background: $colour-theme 143 | } 144 | 145 | em::-moz-selection { 146 | background: $colour-theme 147 | } 148 | 149 | li::selection { 150 | background: $colour-theme 151 | } 152 | 153 | li::-moz-selection { 154 | background: $colour-theme 155 | } 156 | 157 | table::selection { 158 | background: $colour-theme 159 | } 160 | 161 | table::-moz-selection { 162 | background: $colour-theme 163 | } 164 | 165 | img::selection { 166 | background: $colour-theme 167 | } 168 | 169 | img::-moz-selection { 170 | background: $colour-theme 171 | } 172 | 173 | img { 174 | position: relative; 175 | font-size: 1.4rem; 176 | font-style: italic 177 | } 178 | 179 | img:after { 180 | content: "Uh Oh! This image is broken! (" attr(alt) ")"; 181 | display: block; 182 | position: absolute; 183 | top: 0; 184 | left: 0; 185 | min-height: 100%; 186 | height: auto; 187 | width: 100%; 188 | padding: 5px 10px; 189 | border: 2px solid #e6e6e6; 190 | background-color: #f5f5f5; 191 | z-index: 1 192 | } 193 | 194 | img.show-broken { 195 | font-style: normal; 196 | } 197 | 198 | img.show-broken:after { 199 | content: ""; 200 | border: 0; 201 | background-color: initial; 202 | z-index: initial; 203 | padding: 0; 204 | position: relative; 205 | } 206 | -------------------------------------------------------------------------------- /src/js/search.js: -------------------------------------------------------------------------------- 1 | function SearchGhost(options) { 2 | 3 | this.searchForm = options.searchForm; 4 | this.messageEl = options.messageEl; 5 | this.resultsEl = options.resultsEl; 6 | 7 | this.getPosts().catch(() => { 8 | this.messageEl.classList.remove("message--default"); 9 | this.messageEl.classList.add("message--danger"); 10 | this.messageEl.textContent = `Unable to fetch posts to search.`; 11 | }); 12 | 13 | this.searchForm.addEventListener("submit", this.onSubmit.bind(this)); 14 | } 15 | 16 | SearchGhost.prototype.getPosts = function () { 17 | const api = new GhostContentAPI({ 18 | url: 'https://bitsofcode.ghost.io', 19 | key: '78111c135ca4238e88a63c5f48', 20 | version: "v3" 21 | }); 22 | 23 | return api.posts 24 | .browse({ 25 | limit: 'all', 26 | include: 'tags', 27 | fields: "title,published_at,html,url,slug" 28 | }) 29 | .then((posts) => { 30 | console.log(posts) 31 | this.posts = posts 32 | }); 33 | }; 34 | 35 | SearchGhost.prototype.searchPosts = function (query) { 36 | const regex = new RegExp(query, "gi"); 37 | 38 | const priority1 = []; 39 | const priority2 = []; 40 | const priority3 = []; 41 | 42 | this.posts.forEach((post) => { 43 | const titleMatch = post.title.match(regex); 44 | const tagsMatch = post.tags ? post.tags.some((tag) => tag.name.match(regex)) : false; 45 | const contentMatch = post.html.match(regex); 46 | 47 | if (titleMatch) priority1.push(post); 48 | else if (tagsMatch) return priority2.push(post); 49 | else if (contentMatch) return priority3.push(post); 50 | }); 51 | 52 | return [ ...priority1, ...priority2, ...priority3 ]; 53 | }; 54 | 55 | SearchGhost.prototype.buildPostExcerpt = function (post, query) { 56 | 57 | function highlightQuery(string) { 58 | const regex = new RegExp(query, "gi"); 59 | return string.replace(regex, (match) => `${match}`); 60 | } 61 | 62 | function getExcerpt(html) { 63 | const cleanHTML = html.replace(/<(?:.|\n)*?>/gm, ""); 64 | const excerpt = highlightQuery(cleanHTML.substring(0, 300)); 65 | return excerpt + "..."; 66 | } 67 | 68 | function getPrettyDate(published_at) { 69 | const prettyMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; 70 | 71 | const date = published_at.split("T")[0]; 72 | const year = date.split("-")[0]; 73 | const month = prettyMonths[parseInt(date.split("-")[1]) - 1]; 74 | const day = date.split("-")[2]; 75 | 76 | return `${month} ${day}, ${year}`; 77 | } 78 | 79 | function getTags(tags) { 80 | if (!tags || tags.length == 0) return ""; 81 | return ` 82 | ${tags.map((tag) => ` ${highlightQuery(tag.name)}`)} 83 | `; 84 | } 85 | 86 | return ` 87 |
88 |
89 |

90 | ${highlightQuery(post.title)} 91 |

92 | 96 |
97 |
98 | ${getExcerpt(post.html)} 99 |
100 |
`; 101 | }; 102 | 103 | SearchGhost.prototype.onSubmit = function (e) { 104 | 105 | e.preventDefault(); 106 | 107 | const query = e.target.querySelector("[name='query']").value; 108 | 109 | if (!query) { 110 | this.messageEl.textContent = "Please enter a search query"; 111 | return false; 112 | } 113 | 114 | this.messageEl.textContent = `Searching for posts related to "${query}"...`; 115 | 116 | const relevantPosts = this.searchPosts(query); 117 | const postExcerpts = relevantPosts.map((post) => this.buildPostExcerpt(post, query)).join(""); 118 | 119 | this.messageEl.classList.remove("message--default"); 120 | this.messageEl.classList.add("message--count"); 121 | this.messageEl.innerHTML = `${relevantPosts.length} posts were found.`; 122 | 123 | this.resultsEl.innerHTML = postExcerpts; 124 | } 125 | 126 | new SearchGhost({ 127 | searchForm: document.getElementById("search-form"), 128 | messageEl: document.getElementById("search-results-message"), 129 | resultsEl: document.getElementById("search-results") 130 | }); 131 | -------------------------------------------------------------------------------- /src/scss/_syntax-highlighting.scss: -------------------------------------------------------------------------------- 1 | 2 | code[class*=language-], 3 | pre, 4 | pre[class*=language-] { 5 | color: #fff; 6 | background: 0 0; 7 | font-family: $font-family-monospace; 8 | text-align: left; 9 | white-space: pre; 10 | word-spacing: normal; 11 | word-break: normal; 12 | word-wrap: normal; 13 | line-height: 1.5; 14 | -moz-tab-size: 4; 15 | -o-tab-size: 4; 16 | tab-size: 4; 17 | -webkit-hyphens: none; 18 | -moz-hyphens: none; 19 | -ms-hyphens: none; 20 | hyphens: none; 21 | font-size: 1.5rem 22 | } 23 | 24 | :not(pre)>code[class*=language-], 25 | pre, 26 | pre[class*=language-] { 27 | background: #3c3c3c 28 | } 29 | 30 | pre, 31 | pre[class*=language-] { 32 | overflow: auto; 33 | border: 0; 34 | border-radius: 3px; 35 | padding: 1.5rem; 36 | margin-top: 2rem; 37 | margin-bottom: 2rem 38 | } 39 | 40 | pre[class*=language-]::-moz-selection { 41 | background: #27292a 42 | } 43 | 44 | pre[class*=language-]::selection { 45 | background: #27292a 46 | } 47 | 48 | code[class*=language-]::-moz-selection, 49 | code[class*=language-]::-moz-selection, 50 | pre[class*=language-]::-moz-selection, 51 | pre[class*=language-]::-moz-selection { 52 | text-shadow: none; 53 | background: rgba(237, 237, 237, .15) 54 | } 55 | 56 | code[class*=language-]::selection, 57 | code[class*=language-]::selection, 58 | pre[class*=language-]::selection, 59 | pre[class*=language-]::selection { 60 | text-shadow: none; 61 | background: rgba(237, 237, 237, .15) 62 | } 63 | 64 | :not(pre)>code[class*=language-] { 65 | border-radius: .3em; 66 | border: .13em solid #545454; 67 | box-shadow: 1px 1px .3em -.1em #000 inset; 68 | padding: .15em .2em .05em; 69 | white-space: normal 70 | } 71 | 72 | .token.cdata, 73 | .token.comment, 74 | .token.doctype, 75 | .token.prolog { 76 | color: rgba(255, 255, 255, 0.55); 77 | } 78 | 79 | .token.punctuation { 80 | opacity: .7 81 | } 82 | 83 | .namespace { 84 | opacity: .7 85 | } 86 | 87 | .token.boolean, 88 | .token.deleted, 89 | .token.number { 90 | color: #67b3dd 91 | } 92 | 93 | .token.builtin, 94 | .token.constant, 95 | .token.keyword, 96 | .token.selector, 97 | .token.symbol, 98 | .token.tag { 99 | color: $colour-theme 100 | } 101 | 102 | .language-css .token.string, 103 | .style .token.string, 104 | .token.char, 105 | .token.entity, 106 | .token.inserted, 107 | .token.operator, 108 | .token.url, 109 | .token.variable { 110 | color: #919e6b; 111 | color: #67b3dd 112 | } 113 | 114 | .token.attr-name, 115 | .token.attr-value, 116 | .token.function, 117 | .token.property { 118 | color: #fd3b56; 119 | color: #f28596 120 | } 121 | 122 | .token.atrule { 123 | color: #7386a5 124 | } 125 | 126 | .token.important, 127 | .token.regex { 128 | color: #e9c163 129 | } 130 | 131 | .token.bold, 132 | .token.important { 133 | font-weight: 700 134 | } 135 | 136 | .token.italic { 137 | font-style: italic 138 | } 139 | 140 | .token.entity { 141 | cursor: help 142 | } 143 | 144 | pre[data-line] { 145 | padding: 1em 0 1em 3em; 146 | position: relative 147 | } 148 | 149 | .token { 150 | position: relative; 151 | z-index: 1 152 | } 153 | 154 | .line-highlight { 155 | background: rgba(84, 84, 84, .25); 156 | background: linear-gradient(to right, rgba(84, 84, 84, .1) 70%, rgba(84, 84, 84, 0)); 157 | border-bottom: 1px dashed #545454; 158 | border-top: 1px dashed #545454; 159 | left: 0; 160 | line-height: inherit; 161 | margin-top: .75em; 162 | padding: inherit 0; 163 | pointer-events: none; 164 | position: absolute; 165 | right: 0; 166 | white-space: pre; 167 | z-index: 0 168 | } 169 | 170 | .line-highlight:before, 171 | .line-highlight[data-end]:after { 172 | background-color: #8794a6; 173 | border-radius: 999px; 174 | box-shadow: 0 1px #fff; 175 | color: #f5f2f0; 176 | content: attr(data-start); 177 | font: 700 65%/1.5 sans-serif; 178 | left: .6em; 179 | min-width: 1em; 180 | padding: 0 .5em; 181 | position: absolute; 182 | text-align: center; 183 | text-shadow: none; 184 | top: .4em; 185 | vertical-align: .3em 186 | } 187 | 188 | .line-highlight[data-end]:after { 189 | bottom: .4em; 190 | content: attr(data-end); 191 | top: auto 192 | } 193 | 194 | pre[data-line] { 195 | position: relative; 196 | padding: 1em 0 1em 3em 197 | } 198 | 199 | .line-highlight { 200 | position: absolute; 201 | left: 0; 202 | right: 0; 203 | padding: inherit 0; 204 | margin-top: 1em; 205 | background: rgba(153, 122, 102, .08); 206 | background: linear-gradient(to right, rgba(153, 122, 102, .1) 70%, rgba(153, 122, 102, 0)); 207 | pointer-events: none; 208 | line-height: inherit; 209 | white-space: pre 210 | } 211 | 212 | .line-highlight:before, 213 | .line-highlight[data-end]:after { 214 | content: attr(data-start); 215 | position: absolute; 216 | top: .4em; 217 | left: .6em; 218 | min-width: 1em; 219 | padding: 0 .5em; 220 | background-color: rgba(153, 122, 102, .4); 221 | color: #f5f2f0; 222 | font: 700 65%/1.5 sans-serif; 223 | text-align: center; 224 | vertical-align: .3em; 225 | border-radius: 999px; 226 | text-shadow: none; 227 | box-shadow: 0 1px #fff 228 | } 229 | 230 | .line-highlight[data-end]:after { 231 | content: attr(data-end); 232 | top: auto; 233 | bottom: .4em 234 | } 235 | -------------------------------------------------------------------------------- /src/scss/_layout.scss: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background: $colour-bg; 4 | border: 3px solid $colour-theme; 5 | min-height: 100vh 6 | } 7 | 8 | @media screen and (min-width:400px) { 9 | body { 10 | border: 5px solid $colour-theme 11 | } 12 | } 13 | 14 | .wrapper { 15 | width: 90%; 16 | max-width: 980px; 17 | margin-left: auto; 18 | margin-right: auto 19 | } 20 | 21 | .wrapper--flex { 22 | display: flex; 23 | min-height: 100% 24 | } 25 | 26 | .site__header { 27 | height: 60px; 28 | border-bottom: 2px solid $colour-border; 29 | margin-bottom: 40px 30 | } 31 | 32 | @media screen and (min-width:500px) { 33 | .site__header { 34 | margin-bottom: 70px 35 | } 36 | } 37 | 38 | .site__header .wrapper--flex { 39 | justify-content: space-between; 40 | align-items: center 41 | } 42 | 43 | .site__title a { 44 | outline: 0 45 | } 46 | 47 | .no-btn { 48 | border: 0; 49 | background: 0 0; 50 | font-family: $font-family; 51 | font-size: 1.5rem; 52 | cursor: pointer; 53 | padding: 0; 54 | width: auto 55 | } 56 | 57 | .site__nav ul { 58 | display: flex; 59 | flex-wrap: wrap; 60 | width: 100%; 61 | margin-top: 30px 62 | } 63 | 64 | .site__nav li { 65 | width: 100%; 66 | font-size: 2.4rem; 67 | font-weight: 600; 68 | margin-bottom: 10px 69 | } 70 | 71 | .site__nav li a { 72 | text-decoration: none; 73 | outline: 0 74 | } 75 | 76 | .site__nav li a:focus, 77 | .site__nav li a:hover { 78 | color: $colour-theme 79 | } 80 | 81 | .site__nav li a[href*="patreon.com"] { 82 | position: relative 83 | } 84 | 85 | .site__nav li a[href*="patreon.com"]:after { 86 | content: "↗"; 87 | position: absolute; 88 | right: -25px; 89 | top: 7px; 90 | font-size: 2rem; 91 | line-height: 1 92 | } 93 | 94 | .dialog:not([aria-hidden=true]) .site__nav li { 95 | animation-name: navItemFadeIn; 96 | animation-duration: .5s; 97 | animation-fill-mode: both; 98 | animation-direction: normal 99 | } 100 | 101 | .dialog:not([aria-hidden=true]) .site__nav li:nth-child(2) { 102 | animation-delay: .2s 103 | } 104 | 105 | .dialog:not([aria-hidden=true]) .site__nav li:nth-child(3) { 106 | animation-delay: .4s 107 | } 108 | 109 | .dialog:not([aria-hidden=true]) .site__nav li:nth-child(4) { 110 | animation-delay: .6s 111 | } 112 | 113 | .dialog:not([aria-hidden=true]) .site__nav li:nth-child(5) { 114 | animation-delay: .8s 115 | } 116 | 117 | .dialog:not([aria-hidden=true]) .site__nav li:nth-child(6) { 118 | animation-delay: 1s 119 | } 120 | 121 | .dialog:not([aria-hidden=true]) .site__nav li:nth-child(7) { 122 | animation-delay: 1.2s 123 | } 124 | 125 | @keyframes navItemFadeIn { 126 | from { 127 | transform: translateY(0); 128 | opacity: 0 129 | } 130 | to { 131 | transform: translateY(-10px); 132 | opacity: 1 133 | } 134 | } 135 | 136 | .site__footer { 137 | border-top: 2px solid #e6e6e6; 138 | text-align: center 139 | } 140 | 141 | .site__footer__nav ul { 142 | text-align: center 143 | } 144 | 145 | .site__footer__nav li { 146 | display: inline-block; 147 | position: relative; 148 | padding-right: 10px; 149 | padding-left: 10px 150 | } 151 | 152 | .site__footer__nav li:not(:last-child):after { 153 | content: ""; 154 | height: 5px; 155 | width: 5px; 156 | background: #3c3c3c; 157 | border-radius: 50%; 158 | position: absolute; 159 | right: -5px; 160 | top: 8px 161 | } 162 | 163 | .site__footer__nav a { 164 | font-weight: 600 165 | } 166 | 167 | .site__footer__nav a[href*="patreon.com"] { 168 | background: $colour-theme 169 | } 170 | 171 | .site__body { 172 | margin-bottom: 50px 173 | } 174 | 175 | .site__body .wrapper--flex { 176 | display: flex; 177 | justify-content: space-between; 178 | flex-wrap: wrap 179 | } 180 | 181 | .site__main { 182 | width: 100%; 183 | min-height: calc(100vh - 350px); 184 | margin-bottom: 30px 185 | } 186 | 187 | @media screen and (min-width:850px) { 188 | .site__main { 189 | width: 65% 190 | } 191 | } 192 | 193 | .site__sidebar { 194 | width: 100% 195 | } 196 | 197 | @media screen and (min-width:850px) { 198 | .site__sidebar { 199 | width: 30% 200 | } 201 | } 202 | 203 | #logo { 204 | height: 16px; 205 | width: auto; 206 | overflow: visible 207 | } 208 | 209 | .site__title a:focus .logo-section-left, 210 | .site__title a:focus .logo-section-middle, 211 | .site__title a:focus .logo-section-right, 212 | .site__title a:hover .logo-section-left, 213 | .site__title a:hover .logo-section-middle, 214 | .site__title a:hover .logo-section-right { 215 | animation-duration: 3s; 216 | animation-timing-function: ease-in-out; 217 | animation-iteration-count: infinite 218 | } 219 | 220 | .site__title a:focus .logo-section-left, 221 | .site__title a:hover .logo-section-left { 222 | animation-name: logoSectionLeft 223 | } 224 | 225 | .site__title a:focus .logo-section-middle, 226 | .site__title a:hover .logo-section-middle { 227 | animation-name: logoSectionMiddle 228 | } 229 | 230 | .site__title a:focus .logo-section-right, 231 | .site__title a:hover .logo-section-right { 232 | animation-name: logoSectionRight 233 | } 234 | 235 | @keyframes logoSectionLeft { 236 | 0% { 237 | transform: none 238 | } 239 | 12.5% { 240 | transform: translateX(-15px) 241 | } 242 | 25%, 243 | 50% { 244 | transform: none 245 | } 246 | 62.5% { 247 | transform: translateX(-15px) 248 | } 249 | 67%, 250 | 72% { 251 | transform: translateX(-15px) rotate(-10deg) 252 | } 253 | 82% { 254 | transform: translateX(-15px) rotate(-15deg) 255 | } 256 | 87.5% { 257 | transform: translateX(-15px) 258 | } 259 | 100% { 260 | transform: none 261 | } 262 | } 263 | 264 | @keyframes logoSectionMiddle { 265 | 0% { 266 | transform: none 267 | } 268 | 12.5% { 269 | transform: translateX(-15px) 270 | } 271 | 25% { 272 | transform: none 273 | } 274 | 37.5% { 275 | transform: translateX(15px) 276 | } 277 | 50%, 278 | 62.5% { 279 | transform: none 280 | } 281 | 67%, 282 | 72% { 283 | transform: rotate(7deg) 284 | } 285 | 82% { 286 | transform: rotate(12deg) 287 | } 288 | 100%, 289 | 87.5% { 290 | transform: none 291 | } 292 | } 293 | 294 | @keyframes logoSectionRight { 295 | 0%, 296 | 25% { 297 | transform: none 298 | } 299 | 37.5% { 300 | transform: translateX(15px) 301 | } 302 | 50% { 303 | transform: none 304 | } 305 | 62.5% { 306 | transform: translateX(15px) 307 | } 308 | 67%, 309 | 72% { 310 | transform: translateX(15px) rotate(-7deg) 311 | } 312 | 82% { 313 | transform: translateX(15px) rotate(-12deg) 314 | } 315 | 87.5% { 316 | transform: translateX(15px) 317 | } 318 | 100% { 319 | transform: none 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /partials/icon-reddit.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/scss/_post.scss: -------------------------------------------------------------------------------- 1 | /* Excerpt ****************************/ 2 | 3 | .excerpt { 4 | padding-bottom: 30px; 5 | margin-bottom: 30px 6 | } 7 | 8 | .excerpt:not(:last-of-type) { 9 | border-bottom: 2px solid #e6e6e6 10 | } 11 | 12 | /* Suggestions ****************************/ 13 | 14 | .post__suggestions { 15 | display: flex; 16 | justify-content: space-between 17 | } 18 | 19 | .post__suggestion { 20 | width: 100% 21 | } 22 | 23 | @media screen and (min-width:400px) { 24 | .post__suggestion { 25 | width: 50% 26 | } 27 | } 28 | 29 | .post__suggestion:only-of-type { 30 | width: 100% 31 | } 32 | 33 | .post__suggestion:last-child { 34 | text-align: right 35 | } 36 | 37 | /* Meta ****************************/ 38 | 39 | .post__meta > *:not(:last-child) { 40 | margin-right: 10px; 41 | padding-right: 10px; 42 | position: relative 43 | } 44 | 45 | .post__meta > *:not(:last-child):after { 46 | content: ""; 47 | height: 5px; 48 | width: 5px; 49 | background: #3c3c3c; 50 | border-radius: 50%; 51 | position: absolute; 52 | right: -5px; 53 | top: 6px 54 | } 55 | 56 | 57 | /* Content ****************************/ 58 | 59 | .post__content { 60 | border-bottom: 2px solid #e6e6e6; 61 | line-height: 1.7; 62 | font-size: 1.65rem; 63 | 64 | p { 65 | margin-bottom: 1rem; 66 | } 67 | 68 | small { 69 | font-size: 1.45rem 70 | } 71 | 72 | a > code, 73 | h2 > code, 74 | h3 > code, 75 | li > code, 76 | p > code, 77 | span > code, 78 | td > code, 79 | th > code { 80 | font-family: $font-family-monospace; 81 | font-weight: 600 82 | } 83 | 84 | p > code { 85 | font-size: 0.9em; 86 | } 87 | } 88 | 89 | .post__content h2 { 90 | margin-top: 4rem; 91 | margin-bottom: 1rem 92 | } 93 | 94 | .post__content h3 { 95 | margin-top: 3rem; 96 | margin-bottom: 1rem 97 | } 98 | 99 | .post__content h4 { 100 | margin-top: 3rem; 101 | margin-bottom: 1rem 102 | } 103 | 104 | .h4, .post__content h4 { 105 | font-size: 1.6rem; 106 | } 107 | 108 | .post__content ol, 109 | .post__content ul { 110 | margin-left: 4rem; 111 | margin-top: 3rem; 112 | margin-bottom: 3rem 113 | } 114 | 115 | .post__content ol ol, 116 | .post__content ol ul, 117 | .post__content ul ol, 118 | .post__content ul ul { 119 | margin-top: 5px; 120 | margin-bottom: 5px 121 | } 122 | 123 | .post__content ul { 124 | list-style-type: disc 125 | } 126 | 127 | .post__content ol { 128 | list-style-type: decimal; 129 | } 130 | 131 | .post__content ins { 132 | text-decoration: none; 133 | margin-bottom: 2em; 134 | display: block; 135 | font-style: italic; 136 | 137 | border-left: 5px solid #e6e6e6; 138 | padding-left: 1.5rem; 139 | 140 | } 141 | 142 | .post__content blockquote { 143 | border-left: 5px solid $colour-theme; 144 | padding-top: 1rem; 145 | padding-bottom: 1rem; 146 | padding-left: 1.5rem; 147 | margin-top: 3rem; 148 | margin-bottom: 3rem 149 | } 150 | 151 | .post__content blockquote p { 152 | margin: 0; 153 | font-style: italic 154 | } 155 | 156 | .post__content cite { 157 | margin-top: -1rem; 158 | display: block; 159 | padding-left: 3rem; 160 | padding-bottom: 1rem 161 | } 162 | 163 | .post__content cite:before { 164 | content: "—"; 165 | padding-right: 1rem 166 | } 167 | 168 | .post__content blockquote cite { 169 | padding: 0 170 | } 171 | 172 | .post__content table { 173 | border: 0; 174 | width: 100%; 175 | margin-top: 3rem; 176 | margin-bottom: 3rem; 177 | font-size: 1.55rem 178 | } 179 | 180 | .post__content table thead { 181 | font-weight: 600; 182 | text-align: left; 183 | background-color: #e6e6e6 184 | } 185 | 186 | .post__content table thead th, 187 | .post__content table thead tr { 188 | padding: 10px 189 | } 190 | 191 | .post__content table tr { 192 | border-bottom: 2px solid #e6e6e6 193 | } 194 | 195 | .post__content table td { 196 | padding: 10px 197 | } 198 | 199 | /* Images */ 200 | 201 | .post__content img { 202 | display: inline-block; 203 | } 204 | 205 | .post__content img:not(.d-ib) { 206 | width: 100%; 207 | height: auto; 208 | margin-top: 3rem; 209 | margin-bottom: 3rem 210 | } 211 | 212 | .post__content img.d-ib { 213 | max-width: 100%; 214 | height: auto; 215 | display: inline-block; 216 | margin: 0 auto; 217 | padding: 0 10px 10px 218 | } 219 | 220 | @media (min-width: 600px) { 221 | .post__content img.float-left { 222 | float: left; 223 | max-width: 40%; 224 | margin-top: 0; 225 | margin-right: 2em; 226 | } 227 | } 228 | 229 | .post__content .img-inline img { 230 | display: inline-block; 231 | margin: 0 10px 20px 232 | } 233 | 234 | .post__content .img-inline { 235 | text-align: center 236 | } 237 | 238 | .post__content .img-subheading { 239 | font-size: 1.4rem; 240 | font-style: italic; 241 | text-align: center; 242 | display: block; 243 | margin-top: -20px; 244 | margin-bottom: 20px 245 | } 246 | 247 | .post__content figcaption { 248 | font-size: 1.4rem; 249 | font-style: italic; 250 | text-align: center; 251 | display: block; 252 | margin-top: -20px; 253 | margin-bottom: 20px 254 | } 255 | 256 | .post__content video { 257 | max-width: 100%; 258 | margin-top: 3rem; 259 | margin-bottom: 3rem 260 | } 261 | 262 | .post__content video[autoplay] { 263 | width: 100% 264 | } 265 | 266 | .post__content .ta-center { 267 | text-align: center 268 | } 269 | 270 | .post__content blockquote.twitter-tweet { 271 | display: block; 272 | margin: 0 auto 273 | } 274 | 275 | .post__content #twitter-widget-0 { 276 | margin: 10px auto 277 | } 278 | 279 | .post__content .twitter-tweet-container [data-tweet-id="788425374589972481"] { 280 | width: 300px!important 281 | } 282 | 283 | .post__content .youtube-container { 284 | position: relative; 285 | padding-bottom: 56.25%; 286 | padding-top: 30px; 287 | height: 0; 288 | overflow: hidden; 289 | width: 100%; 290 | margin-bottom: 1.5em 291 | } 292 | 293 | .post__content .youtube-container iframe { 294 | position: absolute; 295 | top: 0; 296 | left: 0; 297 | width: 100%; 298 | height: 100% 299 | } 300 | 301 | .post__content .email-display { 302 | display: none 303 | } 304 | 305 | .post__content hr { 306 | border: 0; 307 | border-bottom: 2px solid #e6e6e6; 308 | margin-bottom: 3rem; 309 | } 310 | 311 | /* Additions to code blocks */ 312 | 313 | .post__content { 314 | .code-addendum, 315 | .code-heading, 316 | .code-result { 317 | font-family: $font-family; 318 | font-weight: 400; 319 | position: relative; 320 | } 321 | 322 | .code-addendum, 323 | .code-heading { 324 | font-size: 1.2rem; 325 | color: #fff; 326 | 327 | padding-left: 10px; 328 | padding-right: 10px; 329 | } 330 | 331 | .code-addendum, 332 | .code-result { 333 | 334 | margin-top: -1.4em; 335 | margin-bottom: 2rem; 336 | border-bottom-left-radius: 3px; 337 | border-bottom-right-radius: 3px; 338 | 339 | } 340 | } 341 | 342 | // Code block addendum 343 | 344 | .post__content .code-addendum { 345 | &.warning { 346 | background-color: #dd4a68 347 | } 348 | 349 | &.success { 350 | background-color: #27ae60 351 | } 352 | } 353 | 354 | // Code block hading 355 | 356 | .post__content .code-heading { 357 | margin-bottom: -22px; 358 | margin-top: 2rem; 359 | border-top-left-radius: 3px; 360 | border-top-right-radius: 3px; 361 | padding-top: 3px; 362 | padding-bottom: 3px; 363 | background-color: #000; 364 | 365 | p { 366 | margin: 0; 367 | } 368 | } 369 | 370 | // Code block result 371 | 372 | .post__content .code-result { 373 | padding-top: 2em; 374 | padding-bottom: 1em; 375 | } 376 | 377 | // Checkmark 378 | 379 | .post__content span.checkmark { 380 | font-size: 1.8rem; 381 | font-weight: 600; 382 | text-align: center; 383 | display: block; 384 | } 385 | 386 | .post__content span.checkmark.green { 387 | color: #3d7d3d; 388 | } 389 | 390 | .post__content span.checkmark.red { 391 | color: #c3405b; 392 | } 393 | 394 | /* Post-specific styles ****************************/ 395 | 396 | .post__content table.pseudo-selectors td, 397 | .post__content table.pseudo-selectors th { 398 | width: 50%; 399 | text-align: center; 400 | } 401 | 402 | .post__content #target-test { 403 | background-color: transparent; 404 | border-bottom: 3px solid $colour-theme; 405 | font-weight: 700; 406 | } 407 | 408 | .post__content #target-test:target { 409 | background-color: $colour-theme 410 | } 411 | 412 | /* Footnote */ 413 | 414 | .footnotes { 415 | margin-top: 2em; 416 | margin-bottom: -2em; 417 | padding-top: 2em; 418 | border-top: 2px solid #e6e6e6; 419 | } 420 | 421 | 422 | /* DOM tree */ 423 | 424 | ul.dom-tree, 425 | ul.dom-tree ul, 426 | ul.dom-tree li { 427 | padding: 0; 428 | margin: 0; 429 | list-style: none; 430 | } 431 | 432 | ul.dom-tree { 433 | display: block; 434 | margin-top: 2rem; 435 | margin-bottom: 2rem; 436 | } 437 | 438 | ul.dom-tree ul { 439 | padding-left: 2em; 440 | } 441 | 442 | ul.dom-tree li { 443 | position: relative; 444 | } 445 | 446 | ul.dom-tree ul li:first-child::before { 447 | content: ""; 448 | position: absolute; 449 | top: -1em; 450 | height: 2em; 451 | left: -0.75em; 452 | width: 1em; 453 | border-style: none none solid solid; 454 | border-width: 0.1em; 455 | border-color: #3c3c3c; 456 | } 457 | 458 | ul.dom-tree li:not(:last-child)::after { 459 | content: ""; 460 | position: absolute; 461 | top: 0; 462 | bottom: -0.6em; 463 | left: -0.75em; 464 | width: 1em; 465 | border-style: none none solid solid; 466 | border-width: 0.1em; 467 | border-color: #3c3c3c; 468 | } 469 | 470 | ul.dom-tree li span { 471 | background-color: #3c3c3c; 472 | color: #fff; 473 | padding: 0 7px; 474 | margin-bottom: 10px; 475 | display: inline-block; 476 | border-radius: 3px; 477 | min-width: 2em; 478 | text-align: center; 479 | } 480 | 481 | ul.dom-tree li span > span { 482 | padding: 0; 483 | margin: 0; 484 | border: 0; 485 | border-radius: 0; 486 | 487 | color: #f28596; 488 | font-size: 0.85em; 489 | padding-left: 0.5em; 490 | } 491 | 492 | /* Share ****************************/ 493 | 494 | .post__share { 495 | display: flex; 496 | margin-top: -15px; 497 | margin-bottom: 30px 498 | } 499 | 500 | /* Footer ****************************/ 501 | 502 | .post__footer { 503 | border-bottom: 2px solid #e6e6e6 504 | } 505 | 506 | .page__content { 507 | border-bottom: 0 508 | } 509 | 510 | .box { 511 | border: 2px solid #e6e6e6; 512 | border-radius: 3px 513 | } 514 | 515 | .pagination { 516 | position: relative; 517 | text-align: center; 518 | display: flex; 519 | justify-content: space-between 520 | } 521 | 522 | /* Save for offline ****************************/ 523 | 524 | #save { 525 | background: none; 526 | border: 0; 527 | font-family: inherit; 528 | font-size: 1.3rem; 529 | font-weight: 600; 530 | cursor: pointer; 531 | padding-left: 0; 532 | position: relative; 533 | 534 | .icon { 535 | vertical-align: sub; 536 | } 537 | 538 | .label { 539 | position: absolute; 540 | width: 300px; 541 | height: 100%; 542 | top: 0; 543 | left: 100%; 544 | z-index: 1; 545 | text-align: left; 546 | background-color: $colour-bg; 547 | opacity: 0; 548 | 549 | transform: translate(-9999px, -9999px); 550 | transition: opacity 0.5s; 551 | } 552 | } 553 | 554 | #save:hover .label, 555 | #save:focus .label { 556 | transform: none; 557 | opacity: 1; 558 | } 559 | 560 | #save.saved path { 561 | fill: #90cd4e; 562 | } 563 | -------------------------------------------------------------------------------- /partials/bitsofcode-logo.hbs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/js/post/prisim.js: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism-dark&languages=markup+css+clike+javascript+bash+ruby+git+handlebars+jade+json+markdown+php+jsx+sass+scss+typescript+yaml&plugins=line-highlight */ 2 | var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,util:{encode:function(e){return e instanceof a?new a(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(v instanceof a)){u.lastIndex=0;var b=u.exec(v),k=1;if(!b&&h&&m!=r.length-1){if(u.lastIndex=y,b=u.exec(e),!b)break;for(var w=b.index+(c?b[1].length:0),_=b.index+b[0].length,P=m,A=y,j=r.length;j>P&&_>A;++P)A+=r[P].length,w>=A&&(++m,y=A);if(r[m]instanceof a||r[P-1].greedy)continue;k=P-m,v=e.slice(y,A),b.index-=y}if(b){c&&(f=b[1].length);var w=b.index+f,b=b[0].slice(f),_=w+b.length,x=v.slice(0,w),O=v.slice(_),S=[m,k];x&&S.push(x);var N=new a(i,g?n.tokenize(b,g):b,d,b,h);S.push(N),O&&S.push(O),Array.prototype.splice.apply(r,S)}}}}}return r},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,l=0;r=a[l++];)r(t)}}},a=n.Token=function(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!r};if(a.stringify=function(e,t,r){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return a.stringify(n,t,e)}).join("");var l={type:e.type,content:a.stringify(e.content,t,r),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:r};if("comment"==l.type&&(l.attributes.spellcheck="true"),e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+""},!_self.document)return _self.addEventListener?(_self.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,r=t.code,l=t.immediateClose;_self.postMessage(n.highlight(r,n.languages[a],a)),l&&_self.close()},!1),_self.Prism):_self.Prism;var r=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return r&&(n.filename=r.src,!document.addEventListener||n.manual||r.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); 3 | Prism.languages.markup={comment://,prolog:/<\?[\w\W]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup; 4 | Prism.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:{pattern:/("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.util.clone(Prism.languages.css),Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/()[\w\W]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css"}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); 5 | Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!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+)|(?:catch\s+\())[a-z0-9_\.\\]+/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":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; 6 | Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(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|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*\*?|\/|~|\^|%|\.{3}/}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[.+?]|\\.|[^\/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\\\|\\?[^\\])*?`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\w\W]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript"}}),Prism.languages.js=Prism.languages.javascript; 7 | !function(e){var t={variable:[{pattern:/\$?\(\([\w\W]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\w\W]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee]-?\d+)?)\b/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[a-z0-9_#\?\*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)(?:"|')?(\w+?)(?:"|')?\s*\r?\n(?:[\s\S])*?\r?\n\2/g,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\\\|\\?[^\\])*?\1/g,greedy:!0,inside:t}],variable:t.variable,"function":{pattern:/(^|\s|;|\||&)(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|\s|;|\||&)/,lookbehind:!0},keyword:{pattern:/(^|\s|;|\||&)(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|\s|;|\||&)/,lookbehind:!0},"boolean":{pattern:/(^|\s|;|\||&)(?:true|false)(?=$|\s|;|\||&)/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var a=t.variable[1].inside;a["function"]=e.languages.bash["function"],a.keyword=e.languages.bash.keyword,a.boolean=e.languages.bash.boolean,a.operator=e.languages.bash.operator,a.punctuation=e.languages.bash.punctuation}(Prism); 8 | !function(e){e.languages.ruby=e.languages.extend("clike",{comment:/#(?!\{[^\r\n]*?\}).*/,keyword:/\b(alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|false|for|if|in|module|new|next|nil|not|or|raise|redo|require|rescue|retry|return|self|super|then|throw|true|undef|unless|until|when|while|yield)\b/});var n={pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"tag"},rest:e.util.clone(e.languages.ruby)}};e.languages.insertBefore("ruby","keyword",{regex:[{pattern:/%r([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\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])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}],variable:/[@$]+[a-zA-Z_][a-zA-Z_0-9]*(?:[?!]|\b)/,symbol:/:[a-zA-Z_][a-zA-Z_0-9]*(?:[?!]|\b)/}),e.languages.insertBefore("ruby","number",{builtin:/\b(Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|File|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][a-zA-Z_0-9]*(?:[?!]|\b)/}),e.languages.ruby.string=[{pattern:/%[qQiIwWxs]?([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\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|\r)|\\?.)*?\1/,greedy:!0,inside:{interpolation:n}}]}(Prism); 9 | Prism.languages.git={comment:/^#.*/m,deleted:/^[-–].*/m,inserted:/^\+.*/m,string:/("|')(\\?.)*?\1/m,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s(--|-)\w+/m}},coord:/^@@.*@@$/m,commit_sha1:/^commit \w{40}$/m}; 10 | !function(e){var a=/\{\{\{[\w\W]+?\}\}\}|\{\{[\w\W]+?\}\}/g;e.languages.handlebars=e.languages.extend("markup",{handlebars:{pattern:a,inside:{delimiter:{pattern:/^\{\{\{?|\}\}\}?$/i,alias:"punctuation"},string:/(["'])(\\?.)*?\1/,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?)\b/,"boolean":/\b(true|false)\b/,block:{pattern:/^(\s*~?\s*)[#\/]\S+?(?=\s*~?\s*$|\s)/i,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\w\W]+/}},punctuation:/[!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~\s]+/}}}),e.languages.insertBefore("handlebars","tag",{"handlebars-comment":{pattern:/\{\{![\w\W]*?\}\}/,alias:["handlebars","comment"]}}),e.hooks.add("before-highlight",function(e){"handlebars"===e.language&&(e.tokenStack=[],e.backupCode=e.code,e.code=e.code.replace(a,function(a){return e.tokenStack.push(a),"___HANDLEBARS"+e.tokenStack.length+"___"}))}),e.hooks.add("before-insert",function(e){"handlebars"===e.language&&(e.code=e.backupCode,delete e.backupCode)}),e.hooks.add("after-highlight",function(a){if("handlebars"===a.language){for(var n,t=0;n=a.tokenStack[t];t++)a.highlightedCode=a.highlightedCode.replace("___HANDLEBARS"+(t+1)+"___",e.highlight(n,a.grammar,"handlebars").replace(/\$/g,"$$$$"));a.element.innerHTML=a.highlightedCode}})}(Prism); 11 | !function(e){e.languages.jade={comment:{pattern:/(^([\t ]*))\/\/.*((?:\r?\n|\r)\2[\t ]+.+)*/m,lookbehind:!0},"multiline-script":{pattern:/(^([\t ]*)script\b.*\.[\t ]*)((?:\r?\n|\r(?!\n))(?:\2[\t ]+.+|\s*?(?=\r?\n|\r)))+/m,lookbehind:!0,inside:{rest:e.languages.javascript}},filter:{pattern:/(^([\t ]*)):.+((?:\r?\n|\r(?!\n))(?:\2[\t ]+.+|\s*?(?=\r?\n|\r)))+/m,lookbehind:!0,inside:{"filter-name":{pattern:/^:[\w-]+/,alias:"variable"}}},"multiline-plain-text":{pattern:/(^([\t ]*)[\w\-#.]+\.[\t ]*)((?:\r?\n|\r(?!\n))(?:\2[\t ]+.+|\s*?(?=\r?\n|\r)))+/m,lookbehind:!0},markup:{pattern:/(^[\t ]*)<.+/m,lookbehind:!0,inside:{rest:e.languages.markup}},doctype:{pattern:/((?:^|\n)[\t ]*)doctype(?: .+)?/,lookbehind:!0},"flow-control":{pattern:/(^[\t ]*)(?:if|unless|else|case|when|default|each|while)\b(?: .+)?/m,lookbehind:!0,inside:{each:{pattern:/^each .+? in\b/,inside:{keyword:/\b(?:each|in)\b/,punctuation:/,/}},branch:{pattern:/^(?:if|unless|else|case|when|default|while)\b/,alias:"keyword"},rest:e.languages.javascript}},keyword:{pattern:/(^[\t ]*)(?:block|extends|include|append|prepend)\b.+/m,lookbehind:!0},mixin:[{pattern:/(^[\t ]*)mixin .+/m,lookbehind:!0,inside:{keyword:/^mixin/,"function":/\w+(?=\s*\(|\s*$)/,punctuation:/[(),.]/}},{pattern:/(^[\t ]*)\+.+/m,lookbehind:!0,inside:{name:{pattern:/^\+\w+/,alias:"function"},rest:e.languages.javascript}}],script:{pattern:/(^[\t ]*script(?:(?:&[^(]+)?\([^)]+\))*[\t ]+).+/m,lookbehind:!0,inside:{rest:e.languages.javascript}},"plain-text":{pattern:/(^[\t ]*(?!-)[\w\-#.]*[\w\-](?:(?:&[^(]+)?\([^)]+\))*\/?[\t ]+).+/m,lookbehind:!0},tag:{pattern:/(^[\t ]*)(?!-)[\w\-#.]*[\w\-](?:(?:&[^(]+)?\([^)]+\))*\/?:?/m,lookbehind:!0,inside:{attributes:[{pattern:/&[^(]+\([^)]+\)/,inside:{rest:e.languages.javascript}},{pattern:/\([^)]+\)/,inside:{"attr-value":{pattern:/(=\s*)(?:\{[^}]*\}|[^,)\r\n]+)/,lookbehind:!0,inside:{rest:e.languages.javascript}},"attr-name":/[\w-]+(?=\s*!?=|\s*[,)])/,punctuation:/[!=(),]+/}}],punctuation:/:/}},code:[{pattern:/(^[\t ]*(?:-|!?=)).+/m,lookbehind:!0,inside:{rest:e.languages.javascript}}],punctuation:/[.\-!=|]+/};for(var t="(^([\\t ]*)):{{filter_name}}((?:\\r?\\n|\\r(?!\\n))(?:\\2[\\t ]+.+|\\s*?(?=\\r?\\n|\\r)))+",n=[{filter:"atpl",language:"twig"},{filter:"coffee",language:"coffeescript"},"ejs","handlebars","hogan","less","livescript","markdown","mustache","plates",{filter:"sass",language:"scss"},"stylus","swig"],a={},i=0,r=n.length;r>i;i++){var s=n[i];s="string"==typeof s?{filter:s,language:s}:s,e.languages[s.language]&&(a["filter-"+s.filter]={pattern:RegExp(t.replace("{{filter_name}}",s.filter),"m"),lookbehind:!0,inside:{"filter-name":{pattern:/^:[\w-]+/,alias:"variable"},rest:e.languages[s.language]}})}e.languages.insertBefore("jade","filter",a)}(Prism); 12 | Prism.languages.json={property:/"(?:\\.|[^\\"])*"(?=\s*:)/gi,string:/"(?!:)(?:\\.|[^\\"])*"(?!:)/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?)\b/g,punctuation:/[{}[\]);,]/g,operator:/:/g,"boolean":/\b(true|false)\b/gi,"null":/\bnull\b/gi},Prism.languages.jsonp=Prism.languages.json; 13 | Prism.languages.markdown=Prism.languages.extend("markup",{}),Prism.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},code:[{pattern:/^(?: {4}|\t).+/m,alias:"keyword"},{pattern:/``.+?``|`[^`\n]+`/,alias:"keyword"}],title:[{pattern:/\w+.*(?:\r?\n|\r)(?:==+|--+)/,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])([\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:/(^|[^\\])(\*\*|__)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^\*\*|^__|\*\*$|__$/}},italic:{pattern:/(^|[^\\])([*_])(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^[*_]|[*_]$/}},url:{pattern:/!?\[[^\]]+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[[^\]\n]*\])/,inside:{variable:{pattern:/(!?\[)[^\]]+(?=\]$)/,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),Prism.languages.markdown.bold.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.italic.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.bold.inside.italic=Prism.util.clone(Prism.languages.markdown.italic),Prism.languages.markdown.italic.inside.bold=Prism.util.clone(Prism.languages.markdown.bold); 14 | Prism.languages.php=Prism.languages.extend("clike",{keyword:/\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i,constant:/\b[A-Z0-9_]{2,}\b/,comment:{pattern:/(^|[^\\])(?:\/\*[\w\W]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0}}),Prism.languages.insertBefore("php","class-name",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),Prism.languages.insertBefore("php","keyword",{delimiter:/\?>|<\?(?:php)?/i,variable:/\$\w+\b/i,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),Prism.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}}),Prism.languages.markup&&(Prism.hooks.add("before-highlight",function(e){"php"===e.language&&(e.tokenStack=[],e.backupCode=e.code,e.code=e.code.replace(/(?:<\?php|<\?)[\w\W]*?(?:\?>)/gi,function(a){return e.tokenStack.push(a),"{{{PHP"+e.tokenStack.length+"}}}"}))}),Prism.hooks.add("before-insert",function(e){"php"===e.language&&(e.code=e.backupCode,delete e.backupCode)}),Prism.hooks.add("after-highlight",function(e){if("php"===e.language){for(var a,n=0;a=e.tokenStack[n];n++)e.highlightedCode=e.highlightedCode.replace("{{{PHP"+(n+1)+"}}}",Prism.highlight(a,e.grammar,"php").replace(/\$/g,"$$$$"));e.element.innerHTML=e.highlightedCode}}),Prism.hooks.add("wrap",function(e){"php"===e.language&&"markup"===e.type&&(e.content=e.content.replace(/(\{\{\{PHP[0-9]+\}\}\})/g,'$1'))}),Prism.languages.insertBefore("php","comment",{markup:{pattern:/<[^?]\/?(.*?)>/,inside:Prism.languages.markup},php:/\{\{\{PHP[0-9]+\}\}\}/})); 15 | !function(a){var e=a.util.clone(a.languages.javascript);a.languages.jsx=a.languages.extend("markup",e),a.languages.jsx.tag.pattern=/<\/?[\w\.:-]+\s*(?:\s+(?:[\w\.:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+|(\{[\w\W]*?\})))?|\{\.{3}\w+\})\s*)*\/?>/i,a.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,a.languages.insertBefore("inside","attr-name",{spread:{pattern:/\{\.{3}\w+\}/,inside:{punctuation:/\{|\}|\./,"attr-value":/\w+/}}},a.languages.jsx.tag);var s=a.util.clone(a.languages.jsx);delete s.punctuation,s=a.languages.insertBefore("jsx","operator",{punctuation:/=(?={)|[{}[\];(),.:]/},{jsx:s}),a.languages.insertBefore("inside","attr-value",{script:{pattern:/=(\{(?:\{[^}]*\}|[^}])+\})/i,inside:s,alias:"language-javascript"}},a.languages.jsx.tag)}(Prism); 16 | !function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t]+.+)*/m,lookbehind:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,inside:{atrule:/(?:@[\w-]+|[+=])/m}}}),delete e.languages.sass.atrule;var a=/((\$[-_\w]+)|(#\{\$[-_\w]+\}))/i,t=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|or|not)\b/,{pattern:/(\s+)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,inside:{punctuation:/:/,variable:a,operator:t}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s]+.*)/m,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:a,operator:t,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,delete e.languages.sass.selector,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/([ \t]*)\S(?:,?[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,?[^,\r\n]+)*)*/,lookbehind:!0}})}(Prism); 17 | Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\w\W]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-]+(?:\([^()]+\)|[^(])*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)*url(?=\()/i,selector:{pattern:/(?=\S)[^@;\{\}\(\)]?([^@;\{\}\(\)]|&|#\{\$[-_\w]+\})+(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/m,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-_\w]+/,variable:/\$[-_\w]+|#\{\$[-_\w]+\}/}}}),Prism.languages.insertBefore("scss","atrule",{keyword:[/@(?:if|else(?: if)?|for|each|while|import|extend|debug|warn|mixin|include|function|return|content)/i,{pattern:/( +)(?:from|through)(?= )/,lookbehind:!0}]}),Prism.languages.scss.property={pattern:/(?:[\w-]|\$[-_\w]+|#\{\$[-_\w]+\})+(?=\s*:)/i,inside:{variable:/\$[-_\w]+|#\{\$[-_\w]+\}/}},Prism.languages.insertBefore("scss","important",{variable:/\$[-_\w]+|#\{\$[-_\w]+\}/}),Prism.languages.insertBefore("scss","function",{placeholder:{pattern:/%[-_\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},"boolean":/\b(?:true|false)\b/,"null":/\bnull\b/,operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|or|not)(?=\s)/,lookbehind:!0}}),Prism.languages.scss.atrule.inside.rest=Prism.util.clone(Prism.languages.scss); 18 | Prism.languages.typescript=Prism.languages.extend("javascript",{keyword:/\b(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|var|void|while|with|yield|false|true|module|declare|constructor|string|Function|any|number|boolean|Array|enum|symbol|namespace|abstract|require|type)\b/}),Prism.languages.ts=Prism.languages.typescript; 19 | Prism.languages.yaml={scalar:{pattern:/([\-:]\s*(![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\3[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(\d{4}-\d\d?-\d\d?([tT]|[ \t]+)\d\d?:\d{2}:\d{2}(\.\d*)?[ \t]*(Z|[-+]\d\d?(:\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(:\d{2}(\.\d*)?)?)(?=[ \t]*($|,|]|}))/m,lookbehind:!0,alias:"number"},"boolean":{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},"null":{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')(?=[ \t]*($|,|]|}))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)[+\-]?(0x[\da-f]+|0o[0-7]+|(\d+\.?\d*|\.?\d+)(e[\+\-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./}; 20 | !function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function t(e,t){return t=" "+t+" ",(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)>-1}function n(e,n,i){for(var o,a=n.replace(/\s+/g,"").split(","),d=+e.getAttribute("data-line-offset")||0,l=r()?parseInt:parseFloat,c=l(getComputedStyle(e).lineHeight),s=0;o=a[s++];){o=o.split("-");var u=+o[0],m=+o[1]||u,h=document.createElement("div");h.textContent=Array(m-u+2).join(" \n"),h.setAttribute("aria-hidden","true"),h.className=(i||"")+" line-highlight",t(e,"line-numbers")||(h.setAttribute("data-start",u),m>u&&h.setAttribute("data-end",m)),h.style.top=(u-d-1)*c+"px",t(e,"line-numbers")?e.appendChild(h):(e.querySelector("code")||e).appendChild(h)}}function i(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var i=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(i&&!document.getElementById(t)){var r=t.slice(0,t.lastIndexOf(".")),o=document.getElementById(r);o&&(o.hasAttribute("data-line")||o.setAttribute("data-line",""),n(o,i,"temporary "),document.querySelector(".temporary.line-highlight").scrollIntoView())}}if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var r=function(){var e;return function(){if("undefined"==typeof 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}}(),o=0;Prism.hooks.add("before-sanity-check",function(t){var n=t.element.parentNode,i=n&&n.getAttribute("data-line");if(n&&i&&/pre/i.test(n.nodeName)){var r=0;e(".line-highlight",n).forEach(function(e){r+=e.textContent.length,e.parentNode.removeChild(e)}),r&&/^( \n)+$/.test(t.code.slice(-r))&&(t.code=t.code.slice(0,-r))}}),Prism.hooks.add("complete",function(e){var t=e.element.parentNode,r=t&&t.getAttribute("data-line");t&&r&&/pre/i.test(t.nodeName)&&(clearTimeout(o),n(t,r),o=setTimeout(i,1))}),window.addEventListener&&window.addEventListener("hashchange",i)}}(); 21 | --------------------------------------------------------------------------------