├── .gitignore
├── LICENSE
├── README.md
├── archetypes
├── default.md
└── page.md
├── assets
└── src
│ ├── images
│ ├── apple-touch-icon.png
│ └── favicon.ico
│ ├── scripts
│ ├── _external
│ │ ├── baguetteBox.js
│ │ ├── headroom.js
│ │ └── lazyload.js
│ └── main.js
│ └── styles
│ ├── _chroma_friendly.scss
│ ├── _components
│ ├── base.scss
│ ├── content.scss
│ ├── elements.scss
│ ├── footer.scss
│ ├── homepage.scss
│ └── navbar.scss
│ ├── _external
│ ├── baguetteBox.css
│ ├── milligram.css
│ └── normalize.css
│ ├── _settings.scss
│ └── styles.scss
├── exampleSite
├── config.toml
└── content
│ ├── _index.md
│ ├── categories
│ └── _index.md
│ ├── media
│ ├── _index.md
│ ├── image-1.jpg
│ └── video.mp4
│ ├── photos.md
│ ├── posts
│ ├── 2014
│ │ ├── creating-a-new-theme.md
│ │ ├── goisforlovers.md
│ │ ├── hugoisforlovers.md
│ │ └── migrate-from-jekyll.md
│ ├── 2016
│ │ └── lorem-ipsum.md
│ ├── 2017
│ │ ├── code.md
│ │ ├── gist.md
│ │ ├── images.md
│ │ ├── instagram.md
│ │ ├── speakerdeck.md
│ │ ├── tables.md
│ │ ├── twitter.md
│ │ ├── typography.md
│ │ ├── video.md
│ │ ├── vimeo.md
│ │ └── youtube.md
│ ├── 2019
│ │ └── numbered_list.md
│ └── _index.md
│ ├── projects.md
│ └── tags
│ └── _index.md
├── i18n
├── en.toml
└── pl.toml
├── images
├── screenshot.png
└── tn.png
├── layouts
├── 404.html
├── _default
│ ├── baseof.html
│ ├── list.html
│ ├── rss.xml
│ ├── single.html
│ ├── taxonomy.html
│ └── terms.html
├── index.html
├── page
│ └── single.html
├── partials
│ ├── footer.html
│ ├── head.html
│ ├── navbar.html
│ └── posts_list.html
├── shortcodes
│ ├── adsense.html
│ ├── image.html
│ ├── speakerdeck.html
│ ├── video.html
│ ├── vimeo.html
│ └── youtube.html
└── sitemap.xml
├── resources
└── _gen
│ ├── assets
│ ├── css
│ │ └── assets
│ │ │ └── css
│ │ │ ├── external.css_d3f53f09220d597dac26fe7840c31fc9.content
│ │ │ └── external.css_d3f53f09220d597dac26fe7840c31fc9.json
│ ├── js
│ │ └── assets
│ │ │ └── js
│ │ │ ├── scripts.js_d3f53f09220d597dac26fe7840c31fc9.content
│ │ │ └── scripts.js_d3f53f09220d597dac26fe7840c31fc9.json
│ └── scss
│ │ └── src
│ │ └── styles
│ │ ├── styles.scss_6e769e1f8b8c9ae08c3b967a8651114c.content
│ │ └── styles.scss_6e769e1f8b8c9ae08c3b967a8651114c.json
│ └── images
│ └── media
│ ├── image-1_hu3d03a01dcc18bc5be0e67db3d8d209a6_1073788_320x0_resize_q75_box.jpg
│ ├── image-1_hu3d03a01dcc18bc5be0e67db3d8d209a6_1073788_480x0_resize_q75_box.jpg
│ └── image-1_hu3d03a01dcc18bc5be0e67db3d8d209a6_1073788_768x0_resize_q75_box.jpg
└── theme.toml
/.gitignore:
--------------------------------------------------------------------------------
1 | assets/node_modules
2 | exampleSite/public
3 | exampleSite/resources
4 | exampleSite/themes
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Przemysław Kołodziejczyk
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Simplicity
2 |
3 | Very simple, clean and readable (I think so) Hugo theme.
4 |
5 | #### Responsive design
6 | It works on mobile, tablet and desktop.
7 | #### Responsive images
8 | It generates several image sizes during the build process and displays the best one for given device/resolution.
9 | #### Lazy loading images
10 | This theme uses [LazyLoad](https://github.com/verlok/lazyload) to speed up your web application by loading images as they enter the viewport.
11 | #### Clean typography
12 | It should be a pleasure to read your blog, right?
13 | #### Additional shortcodes
14 | Shortcodes for Google Adsense, images, Speaker Deck, Video, Vimeo, Youtube.
15 | #### Google Adsense
16 | You can use the shortcode to insert Adsense Ad wherever you want.
17 | #### Google Analytics
18 | Just add a Google Analytics code to turn it on.
19 | #### Lightbox
20 | Image shortcode allows to turn on [baguetteBox.js](https://feimosi.github.io/baguetteBox.js/) for given image.
21 | #### Syntax highlighting.
22 | Built-in Chroma Native color theme.
23 | #### Auto-hide/show header
24 | This theme uses [headroom.js](http://wicky.nillia.ms/headroom.js/) script.
25 | #### Page scroll indicator
26 | Displays progress bar on the top of the page when user scrolls the page.
27 | #### Disqus
28 | Just add a Disqus shortname to enable comments.
29 | #### Categories
30 | A separate page with a list of all categories and list of posts for a selected category.
31 | #### Tags
32 | A separate page with a list of all categories and list of posts for a selected tag.
33 | #### RSS
34 | Custom RSS template without an e-mail address.
35 | #### Sitemap
36 | Custom sitemap template to prevent rendering content from media directory.
37 | #### Social icons
38 | Add information about your social profile in the config file to display it on the homepage. Supported services: email, Facebook, Github, Google+, LinkedIn, Messenger, Spotify, Stackoverflow, Telegram, Twitter.
39 | #### Gravatar support
40 | Just add your Gravatar email to the config file to display your avatar on the home page.
41 | #### and more
42 | - OpenGraph support
43 | - Schema Structured Data
44 | - Twitter card
45 | - Display license in footer
46 | - No JS frameworks, no CSS frameworks, no jQuery
47 |
48 | # Demo
49 |
50 | You can preview this theme on my blogs - [eshlox.net](https://eshlox.net) or [eshlox.pl](https://eshlox.pl).
51 |
52 | ## Table of Contents
53 |
54 | - [Table of Contents](#table-of-contents)
55 | - [Getting Started](#getting-started)
56 | - [exampleSite](#examplesite)
57 | - [config.toml](#configtoml)
58 | - [favicons](#favicons)
59 | - [Shortcodes](#shortcodes)
60 | - [figure](#figure)
61 | - [Development](#development)
62 | - [Browsers support](#browsers-support)
63 | - [License](#license)
64 |
65 | ## Getting Started
66 |
67 | Run the following commands in your Hugo site directory to download the theme:
68 |
69 | ```
70 | mkdir themes
71 | cd themes
72 | git clone https://github.com/eshlox/simplicity.git
73 | ```
74 |
75 | ### exampleSite
76 |
77 | Look inside `exampleSite` directory to find out how to configure your site.
78 |
79 | That's how the structure looks like:
80 |
81 | ```
82 | exampleSite/
83 | ├── config.toml
84 | ├── content
85 | │ ├── _index.md
86 | │ ├── categories
87 | │ │ └── _index.md
88 | │ ├── media
89 | │ │ ├── _index.md
90 | │ │ ├── image-1.jpg
91 | │ │ └── video.mp4
92 | │ ├── photos.md
93 | │ ├── posts
94 | │ │ ├── 2014
95 | │ │ │ ├── creating-a-new-theme.md
96 | │ │ │ ├── goisforlovers.md
97 | │ │ │ ├── hugoisforlovers.md
98 | │ │ │ └── migrate-from-jekyll.md
99 | │ │ ├── 2016
100 | │ │ │ └── lorem-ipsum.md
101 | │ │ ├── 2017
102 | │ │ │ ├── images.md
103 | │ │ │ └── typography.md
104 | │ │ └── _index.md
105 | │ ├── projects.md
106 | │ └── tags
107 | │ └── _index.md
108 | └── resources
109 | └── _gen
110 | └── images
111 | └── media
112 | ├── image-1_hu3d03a01dcc18bc5be0e67db3d8d209a6_1073788_320x0_resize_q75_box.jpg
113 | ├── image-1_hu3d03a01dcc18bc5be0e67db3d8d209a6_1073788_480x0_resize_q75_box.jpg
114 | └── image-1_hu3d03a01dcc18bc5be0e67db3d8d209a6_1073788_768x0_resize_q75_box.jpg
115 | ```
116 |
117 | Every `_index.md` file contains a title, language and slug.
118 |
119 | ### config.toml
120 |
121 | Copy `config.toml` from `exampleSite` to the root directory of your Hugo site and modify it according to your needs.
122 |
123 | ### favicons
124 |
125 | This theme contains default favicon with `S` letter. If you want to change it, create a directory `assets/src/images` inside the root of your Hugo site and put your favicon files there. They should have names: `favicon.ico` and `apple-touch-icon.png`.
126 |
127 | ## Shortcodes
128 |
129 | This theme includes additional shortcodes.
130 |
131 | ### Adsense
132 |
133 | Add Adsense configuration and use `{{< adsense >}}` in your post to display an ad.
134 |
135 | ### Image
136 |
137 | All images should be stored in `content/images` directory. Each subdirectory should contain `_index.md` file with this content:
138 |
139 | ```
140 | ---
141 | title: Media Folder
142 | ---
143 |
144 | ```
145 |
146 | Insert responsive image with title:
147 |
148 | `{{< image src="media/image-1.jpg" title="Photo by Ales Krivec on Unsplash" >}}`
149 |
150 | Full page width image:
151 |
152 | `{{< image src="media/image-1.jpg" title="Photo by Ales Krivec on Unsplash" full="true">}}`
153 |
154 | Lightbox:
155 |
156 | `{{< image src="media/image-1.jpg" lightbox="true" >}}`
157 |
158 | Rounded corners:
159 |
160 | `{{< image src="media/image-1.jpg" round="50" >}}`
161 |
162 | Insert image without resizing (the same image for all devices/resolutions).
163 |
164 | `{{< image src="media/image-1.jpg" resize="false" >}}`
165 |
166 | ### Speaker Deck
167 |
168 | `{{< speakerdeck 50021f75cf1db900020005e7 >}}`
169 |
170 | ### Video
171 |
172 | `{{< video src="media/video.mp4" >}}`
173 |
174 | ### Responsive Vimeo
175 |
176 | `{{< vimeo 265143954 >}}`
177 |
178 | ### Responsive Youtube
179 |
180 | `{{< vimeo 265143954 >}}`
181 |
182 | ## Development
183 |
184 | 1. Install dependencies.
185 |
186 | ```cd assets && yarn install```
187 |
188 | 2. Run development server.
189 |
190 | ```hugo server --source=exampleSite --themesDir=../..```
191 |
192 | ## Browsers support
193 |
194 | Dekstop:
195 |
196 | - Firefox (latest)
197 | - Chrome (latest)
198 | - Safari (latest)
199 |
200 | Mobile:
201 |
202 | - Firefox (latest)
203 | - Chrome (latest)
204 | - Safari (latest)
205 |
206 | It probably works in other browsers but it hasn't been tested yet.
207 |
208 | ## Licence
209 |
210 | This theme is released under the MIT license. Please read the [license](https://github.com/eshlox/simplicity/blob/master/LICENSE) for more information.
211 |
--------------------------------------------------------------------------------
/archetypes/default.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "{{ replace .TranslationBaseName "-" " " | title }}"
3 | date: {{ .Date }}
4 | categories: []
5 | tags: []
6 | language: en
7 | slug:
8 | draft: true
9 | ---
10 |
--------------------------------------------------------------------------------
/archetypes/page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "{{ replace .TranslationBaseName "-" " " | title }}"
3 | language: en
4 | slug:
5 | draft: true
6 | ---
7 |
--------------------------------------------------------------------------------
/assets/src/images/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eshlox/simplicity/8696b3b61946d89bb0cd1fc1920940544f1758e9/assets/src/images/apple-touch-icon.png
--------------------------------------------------------------------------------
/assets/src/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eshlox/simplicity/8696b3b61946d89bb0cd1fc1920940544f1758e9/assets/src/images/favicon.ico
--------------------------------------------------------------------------------
/assets/src/scripts/_external/baguetteBox.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * baguetteBox.js
3 | * @author feimosi
4 | * @version 1.11.0
5 | * @url https://github.com/feimosi/baguetteBox.js
6 | */
7 |
8 | /* global define, module */
9 |
10 | (function (root, factory) {
11 | 'use strict';
12 | if (typeof define === 'function' && define.amd) {
13 | define(factory);
14 | } else if (typeof exports === 'object') {
15 | module.exports = factory();
16 | } else {
17 | root.baguetteBox = factory();
18 | }
19 | }(this, function () {
20 | 'use strict';
21 |
22 | // SVG shapes used on the buttons
23 | var leftArrow = '' +
24 | ' ' +
26 | ' ',
27 | rightArrow = '' +
28 | ' ' +
30 | ' ',
31 | closeX = '' +
32 | '' +
33 | ' ' +
34 | ' ' +
35 | ' ';
36 | // Global options and their defaults
37 | var options = {},
38 | defaults = {
39 | captions: true,
40 | buttons: 'auto',
41 | fullScreen: false,
42 | noScrollbars: false,
43 | bodyClass: 'baguetteBox-open',
44 | titleTag: false,
45 | async: false,
46 | preload: 2,
47 | animation: 'slideIn',
48 | afterShow: null,
49 | afterHide: null,
50 | onChange: null,
51 | overlayBackgroundColor: 'rgba(0,0,0,.8)'
52 | };
53 | // Object containing information about features compatibility
54 | var supports = {};
55 | // DOM Elements references
56 | var overlay, slider, previousButton, nextButton, closeButton;
57 | // An array with all images in the current gallery
58 | var currentGallery = [];
59 | // Current image index inside the slider
60 | var currentIndex = 0;
61 | // Visibility of the overlay
62 | var isOverlayVisible = false;
63 | // Touch event start position (for slide gesture)
64 | var touch = {};
65 | // If set to true ignore touch events because animation was already fired
66 | var touchFlag = false;
67 | // Regex pattern to match image files
68 | var regex = /.+\.(gif|jpe?g|png|webp)/i;
69 | // Object of all used galleries
70 | var data = {};
71 | // Array containing temporary images DOM elements
72 | var imagesElements = [];
73 | // The last focused element before opening the overlay
74 | var documentLastFocus = null;
75 | var overlayClickHandler = function(event) {
76 | // Close the overlay when user clicks directly on the background
77 | if (event.target.id.indexOf('baguette-img') !== -1) {
78 | hideOverlay();
79 | }
80 | };
81 | var previousButtonClickHandler = function(event) {
82 | event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; // eslint-disable-line no-unused-expressions
83 | showPreviousImage();
84 | };
85 | var nextButtonClickHandler = function(event) {
86 | event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; // eslint-disable-line no-unused-expressions
87 | showNextImage();
88 | };
89 | var closeButtonClickHandler = function(event) {
90 | event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; // eslint-disable-line no-unused-expressions
91 | hideOverlay();
92 | };
93 | var touchstartHandler = function(event) {
94 | touch.count++;
95 | if (touch.count > 1) {
96 | touch.multitouch = true;
97 | }
98 | // Save x and y axis position
99 | touch.startX = event.changedTouches[0].pageX;
100 | touch.startY = event.changedTouches[0].pageY;
101 | };
102 | var touchmoveHandler = function(event) {
103 | // If action was already triggered or multitouch return
104 | if (touchFlag || touch.multitouch) {
105 | return;
106 | }
107 | event.preventDefault ? event.preventDefault() : event.returnValue = false; // eslint-disable-line no-unused-expressions
108 | var touchEvent = event.touches[0] || event.changedTouches[0];
109 | // Move at least 40 pixels to trigger the action
110 | if (touchEvent.pageX - touch.startX > 40) {
111 | touchFlag = true;
112 | showPreviousImage();
113 | } else if (touchEvent.pageX - touch.startX < -40) {
114 | touchFlag = true;
115 | showNextImage();
116 | // Move 100 pixels up to close the overlay
117 | } else if (touch.startY - touchEvent.pageY > 100) {
118 | hideOverlay();
119 | }
120 | };
121 | var touchendHandler = function() {
122 | touch.count--;
123 | if (touch.count <= 0) {
124 | touch.multitouch = false;
125 | }
126 | touchFlag = false;
127 | };
128 | var contextmenuHandler = function() {
129 | touchendHandler();
130 | };
131 |
132 | var trapFocusInsideOverlay = function(event) {
133 | if (overlay.style.display === 'block' && (overlay.contains && !overlay.contains(event.target))) {
134 | event.stopPropagation();
135 | initFocus();
136 | }
137 | };
138 |
139 | // forEach polyfill for IE8
140 | // http://stackoverflow.com/a/14827443/1077846
141 | /* eslint-disable */
142 | if (![].forEach) {
143 | Array.prototype.forEach = function(callback, thisArg) {
144 | for (var i = 0; i < this.length; i++) {
145 | callback.call(thisArg, this[i], i, this);
146 | }
147 | };
148 | }
149 |
150 | // filter polyfill for IE8
151 | // https://gist.github.com/eliperelman/1031656
152 | if (![].filter) {
153 | Array.prototype.filter = function(a, b, c, d, e) {
154 | c = this;
155 | d = [];
156 | for (e = 0; e < c.length; e++)
157 | a.call(b, c[e], e, c) && d.push(c[e]);
158 | return d;
159 | };
160 | }
161 | /* eslint-enable */
162 |
163 | // Script entry point
164 | function run(selector, userOptions) {
165 | // Fill supports object
166 | supports.transforms = testTransformsSupport();
167 | supports.svg = testSvgSupport();
168 | supports.passiveEvents = testPassiveEventsSupport();
169 |
170 | buildOverlay();
171 | removeFromCache(selector);
172 | return bindImageClickListeners(selector, userOptions);
173 | }
174 |
175 | function bindImageClickListeners(selector, userOptions) {
176 | // For each gallery bind a click event to every image inside it
177 | var galleryNodeList = document.querySelectorAll(selector);
178 | var selectorData = {
179 | galleries: [],
180 | nodeList: galleryNodeList
181 | };
182 | data[selector] = selectorData;
183 |
184 | [].forEach.call(galleryNodeList, function(galleryElement) {
185 | if (userOptions && userOptions.filter) {
186 | regex = userOptions.filter;
187 | }
188 |
189 | // Get nodes from gallery elements or single-element galleries
190 | var tagsNodeList = [];
191 | if (galleryElement.tagName === 'A') {
192 | tagsNodeList = [galleryElement];
193 | } else {
194 | tagsNodeList = galleryElement.getElementsByTagName('a');
195 | }
196 |
197 | // Filter 'a' elements from those not linking to images
198 | tagsNodeList = [].filter.call(tagsNodeList, function(element) {
199 | if (element.className.indexOf(userOptions && userOptions.ignoreClass) === -1) {
200 | return regex.test(element.href);
201 | }
202 | });
203 | if (tagsNodeList.length === 0) {
204 | return;
205 | }
206 |
207 | var gallery = [];
208 | [].forEach.call(tagsNodeList, function(imageElement, imageIndex) {
209 | var imageElementClickHandler = function(event) {
210 | event.preventDefault ? event.preventDefault() : event.returnValue = false; // eslint-disable-line no-unused-expressions
211 | prepareOverlay(gallery, userOptions);
212 | showOverlay(imageIndex);
213 | };
214 | var imageItem = {
215 | eventHandler: imageElementClickHandler,
216 | imageElement: imageElement
217 | };
218 | bind(imageElement, 'click', imageElementClickHandler);
219 | gallery.push(imageItem);
220 | });
221 | selectorData.galleries.push(gallery);
222 | });
223 |
224 | return selectorData.galleries;
225 | }
226 |
227 | function clearCachedData() {
228 | for (var selector in data) {
229 | if (data.hasOwnProperty(selector)) {
230 | removeFromCache(selector);
231 | }
232 | }
233 | }
234 |
235 | function removeFromCache(selector) {
236 | if (!data.hasOwnProperty(selector)) {
237 | return;
238 | }
239 | var galleries = data[selector].galleries;
240 | [].forEach.call(galleries, function(gallery) {
241 | [].forEach.call(gallery, function(imageItem) {
242 | unbind(imageItem.imageElement, 'click', imageItem.eventHandler);
243 | });
244 |
245 | if (currentGallery === gallery) {
246 | currentGallery = [];
247 | }
248 | });
249 |
250 | delete data[selector];
251 | }
252 |
253 | function buildOverlay() {
254 | overlay = getByID('baguetteBox-overlay');
255 | // Check if the overlay already exists
256 | if (overlay) {
257 | slider = getByID('baguetteBox-slider');
258 | previousButton = getByID('previous-button');
259 | nextButton = getByID('next-button');
260 | closeButton = getByID('close-button');
261 | return;
262 | }
263 | // Create overlay element
264 | overlay = create('div');
265 | overlay.setAttribute('role', 'dialog');
266 | overlay.id = 'baguetteBox-overlay';
267 | document.getElementsByTagName('body')[0].appendChild(overlay);
268 | // Create gallery slider element
269 | slider = create('div');
270 | slider.id = 'baguetteBox-slider';
271 | overlay.appendChild(slider);
272 | // Create all necessary buttons
273 | previousButton = create('button');
274 | previousButton.setAttribute('type', 'button');
275 | previousButton.id = 'previous-button';
276 | previousButton.setAttribute('aria-label', 'Previous');
277 | previousButton.innerHTML = supports.svg ? leftArrow : '<';
278 | overlay.appendChild(previousButton);
279 |
280 | nextButton = create('button');
281 | nextButton.setAttribute('type', 'button');
282 | nextButton.id = 'next-button';
283 | nextButton.setAttribute('aria-label', 'Next');
284 | nextButton.innerHTML = supports.svg ? rightArrow : '>';
285 | overlay.appendChild(nextButton);
286 |
287 | closeButton = create('button');
288 | closeButton.setAttribute('type', 'button');
289 | closeButton.id = 'close-button';
290 | closeButton.setAttribute('aria-label', 'Close');
291 | closeButton.innerHTML = supports.svg ? closeX : '×';
292 | overlay.appendChild(closeButton);
293 |
294 | previousButton.className = nextButton.className = closeButton.className = 'baguetteBox-button';
295 |
296 | bindEvents();
297 | }
298 |
299 | function keyDownHandler(event) {
300 | switch (event.keyCode) {
301 | case 37: // Left arrow
302 | showPreviousImage();
303 | break;
304 | case 39: // Right arrow
305 | showNextImage();
306 | break;
307 | case 27: // Esc
308 | hideOverlay();
309 | break;
310 | case 36: // Home
311 | showFirstImage(event);
312 | break;
313 | case 35: // End
314 | showLastImage(event);
315 | break;
316 | }
317 | }
318 |
319 | function bindEvents() {
320 | var options = supports.passiveEvents ? { passive: true } : null;
321 | bind(overlay, 'click', overlayClickHandler);
322 | bind(previousButton, 'click', previousButtonClickHandler);
323 | bind(nextButton, 'click', nextButtonClickHandler);
324 | bind(closeButton, 'click', closeButtonClickHandler);
325 | bind(slider, 'contextmenu', contextmenuHandler);
326 | bind(overlay, 'touchstart', touchstartHandler, options);
327 | bind(overlay, 'touchmove', touchmoveHandler, options);
328 | bind(overlay, 'touchend', touchendHandler);
329 | bind(document, 'focus', trapFocusInsideOverlay, true);
330 | }
331 |
332 | function unbindEvents() {
333 | var options = supports.passiveEvents ? { passive: true } : null;
334 | unbind(overlay, 'click', overlayClickHandler);
335 | unbind(previousButton, 'click', previousButtonClickHandler);
336 | unbind(nextButton, 'click', nextButtonClickHandler);
337 | unbind(closeButton, 'click', closeButtonClickHandler);
338 | unbind(slider, 'contextmenu', contextmenuHandler);
339 | unbind(overlay, 'touchstart', touchstartHandler, options);
340 | unbind(overlay, 'touchmove', touchmoveHandler, options);
341 | unbind(overlay, 'touchend', touchendHandler);
342 | unbind(document, 'focus', trapFocusInsideOverlay, true);
343 | }
344 |
345 | function prepareOverlay(gallery, userOptions) {
346 | // If the same gallery is being opened prevent from loading it once again
347 | if (currentGallery === gallery) {
348 | return;
349 | }
350 | currentGallery = gallery;
351 | // Update gallery specific options
352 | setOptions(userOptions);
353 | // Empty slider of previous contents (more effective than .innerHTML = "")
354 | while (slider.firstChild) {
355 | slider.removeChild(slider.firstChild);
356 | }
357 | imagesElements.length = 0;
358 |
359 | var imagesFiguresIds = [];
360 | var imagesCaptionsIds = [];
361 | // Prepare and append images containers and populate figure and captions IDs arrays
362 | for (var i = 0, fullImage; i < gallery.length; i++) {
363 | fullImage = create('div');
364 | fullImage.className = 'full-image';
365 | fullImage.id = 'baguette-img-' + i;
366 | imagesElements.push(fullImage);
367 |
368 | imagesFiguresIds.push('baguetteBox-figure-' + i);
369 | imagesCaptionsIds.push('baguetteBox-figcaption-' + i);
370 | slider.appendChild(imagesElements[i]);
371 | }
372 | overlay.setAttribute('aria-labelledby', imagesFiguresIds.join(' '));
373 | overlay.setAttribute('aria-describedby', imagesCaptionsIds.join(' '));
374 | }
375 |
376 | function setOptions(newOptions) {
377 | if (!newOptions) {
378 | newOptions = {};
379 | }
380 | // Fill options object
381 | for (var item in defaults) {
382 | options[item] = defaults[item];
383 | if (typeof newOptions[item] !== 'undefined') {
384 | options[item] = newOptions[item];
385 | }
386 | }
387 | /* Apply new options */
388 | // Change transition for proper animation
389 | slider.style.transition = slider.style.webkitTransition = (options.animation === 'fadeIn' ? 'opacity .4s ease' :
390 | options.animation === 'slideIn' ? '' : 'none');
391 | // Hide buttons if necessary
392 | if (options.buttons === 'auto' && ('ontouchstart' in window || currentGallery.length === 1)) {
393 | options.buttons = false;
394 | }
395 | // Set buttons style to hide or display them
396 | previousButton.style.display = nextButton.style.display = (options.buttons ? '' : 'none');
397 | // Set overlay color
398 | try {
399 | overlay.style.backgroundColor = options.overlayBackgroundColor;
400 | } catch (e) {
401 | // Silence the error and continue
402 | }
403 | }
404 |
405 | function showOverlay(chosenImageIndex) {
406 | if (options.noScrollbars) {
407 | document.documentElement.style.overflowY = 'hidden';
408 | document.body.style.overflowY = 'scroll';
409 | }
410 | if (overlay.style.display === 'block') {
411 | return;
412 | }
413 |
414 | bind(document, 'keydown', keyDownHandler);
415 | currentIndex = chosenImageIndex;
416 | touch = {
417 | count: 0,
418 | startX: null,
419 | startY: null
420 | };
421 | loadImage(currentIndex, function() {
422 | preloadNext(currentIndex);
423 | preloadPrev(currentIndex);
424 | });
425 |
426 | updateOffset();
427 | overlay.style.display = 'block';
428 | if (options.fullScreen) {
429 | enterFullScreen();
430 | }
431 | // Fade in overlay
432 | setTimeout(function() {
433 | overlay.className = 'visible';
434 | if (options.bodyClass && document.body.classList) {
435 | document.body.classList.add(options.bodyClass);
436 | }
437 | if (options.afterShow) {
438 | options.afterShow();
439 | }
440 | }, 50);
441 | if (options.onChange) {
442 | options.onChange(currentIndex, imagesElements.length);
443 | }
444 | documentLastFocus = document.activeElement;
445 | initFocus();
446 | isOverlayVisible = true;
447 | }
448 |
449 | function initFocus() {
450 | if (options.buttons) {
451 | previousButton.focus();
452 | } else {
453 | closeButton.focus();
454 | }
455 | }
456 |
457 | function enterFullScreen() {
458 | if (overlay.requestFullscreen) {
459 | overlay.requestFullscreen();
460 | } else if (overlay.webkitRequestFullscreen) {
461 | overlay.webkitRequestFullscreen();
462 | } else if (overlay.mozRequestFullScreen) {
463 | overlay.mozRequestFullScreen();
464 | }
465 | }
466 |
467 | function exitFullscreen() {
468 | if (document.exitFullscreen) {
469 | document.exitFullscreen();
470 | } else if (document.mozCancelFullScreen) {
471 | document.mozCancelFullScreen();
472 | } else if (document.webkitExitFullscreen) {
473 | document.webkitExitFullscreen();
474 | }
475 | }
476 |
477 | function hideOverlay() {
478 | if (options.noScrollbars) {
479 | document.documentElement.style.overflowY = 'auto';
480 | document.body.style.overflowY = 'auto';
481 | }
482 | if (overlay.style.display === 'none') {
483 | return;
484 | }
485 |
486 | unbind(document, 'keydown', keyDownHandler);
487 | // Fade out and hide the overlay
488 | overlay.className = '';
489 | setTimeout(function() {
490 | overlay.style.display = 'none';
491 | if (document.fullscreen) {
492 | exitFullscreen();
493 | }
494 | if (options.bodyClass && document.body.classList) {
495 | document.body.classList.remove(options.bodyClass);
496 | }
497 | if (options.afterHide) {
498 | options.afterHide();
499 | }
500 | documentLastFocus && documentLastFocus.focus();
501 | isOverlayVisible = false;
502 | }, 500);
503 | }
504 |
505 | function loadImage(index, callback) {
506 | var imageContainer = imagesElements[index];
507 | var galleryItem = currentGallery[index];
508 |
509 | // Return if the index exceeds prepared images in the overlay
510 | // or if the current gallery has been changed / closed
511 | if (typeof imageContainer === 'undefined' || typeof galleryItem === 'undefined') {
512 | return;
513 | }
514 |
515 | // If image is already loaded run callback and return
516 | if (imageContainer.getElementsByTagName('img')[0]) {
517 | if (callback) {
518 | callback();
519 | }
520 | return;
521 | }
522 |
523 | // Get element reference, optional caption and source path
524 | var imageElement = galleryItem.imageElement;
525 | var thumbnailElement = imageElement.getElementsByTagName('img')[0];
526 | var imageCaption = typeof options.captions === 'function' ?
527 | options.captions.call(currentGallery, imageElement) :
528 | imageElement.getAttribute('data-caption') || imageElement.title;
529 | var imageSrc = getImageSrc(imageElement);
530 |
531 | // Prepare figure element
532 | var figure = create('figure');
533 | figure.id = 'baguetteBox-figure-' + index;
534 | figure.innerHTML = '
' +
535 | '
' +
536 | '
' +
537 | '
';
538 | // Insert caption if available
539 | if (options.captions && imageCaption) {
540 | var figcaption = create('figcaption');
541 | figcaption.id = 'baguetteBox-figcaption-' + index;
542 | figcaption.innerHTML = imageCaption;
543 | figure.appendChild(figcaption);
544 | }
545 | imageContainer.appendChild(figure);
546 |
547 | // Prepare gallery img element
548 | var image = create('img');
549 | image.onload = function() {
550 | // Remove loader element
551 | var spinner = document.querySelector('#baguette-img-' + index + ' .baguetteBox-spinner');
552 | figure.removeChild(spinner);
553 | if (!options.async && callback) {
554 | callback();
555 | }
556 | };
557 | image.setAttribute('src', imageSrc);
558 | image.alt = thumbnailElement ? thumbnailElement.alt || '' : '';
559 | if (options.titleTag && imageCaption) {
560 | image.title = imageCaption;
561 | }
562 | figure.appendChild(image);
563 |
564 | // Run callback
565 | if (options.async && callback) {
566 | callback();
567 | }
568 | }
569 |
570 | // Get image source location, mostly used for responsive images
571 | function getImageSrc(image) {
572 | // Set default image path from href
573 | var result = image.href;
574 | // If dataset is supported find the most suitable image
575 | if (image.dataset) {
576 | var srcs = [];
577 | // Get all possible image versions depending on the resolution
578 | for (var item in image.dataset) {
579 | if (item.substring(0, 3) === 'at-' && !isNaN(item.substring(3))) {
580 | srcs[item.replace('at-', '')] = image.dataset[item];
581 | }
582 | }
583 | // Sort resolutions ascending
584 | var keys = Object.keys(srcs).sort(function(a, b) {
585 | return parseInt(a, 10) < parseInt(b, 10) ? -1 : 1;
586 | });
587 | // Get real screen resolution
588 | var width = window.innerWidth * window.devicePixelRatio;
589 | // Find the first image bigger than or equal to the current width
590 | var i = 0;
591 | while (i < keys.length - 1 && keys[i] < width) {
592 | i++;
593 | }
594 | result = srcs[keys[i]] || result;
595 | }
596 | return result;
597 | }
598 |
599 | // Return false at the right end of the gallery
600 | function showNextImage() {
601 | return show(currentIndex + 1);
602 | }
603 |
604 | // Return false at the left end of the gallery
605 | function showPreviousImage() {
606 | return show(currentIndex - 1);
607 | }
608 |
609 | // Return false at the left end of the gallery
610 | function showFirstImage(event) {
611 | if (event) {
612 | event.preventDefault();
613 | }
614 | return show(0);
615 | }
616 |
617 | // Return false at the right end of the gallery
618 | function showLastImage(event) {
619 | if (event) {
620 | event.preventDefault();
621 | }
622 | return show(currentGallery.length - 1);
623 | }
624 |
625 | /**
626 | * Move the gallery to a specific index
627 | * @param `index` {number} - the position of the image
628 | * @param `gallery` {array} - gallery which should be opened, if omitted assumes the currently opened one
629 | * @return {boolean} - true on success or false if the index is invalid
630 | */
631 | function show(index, gallery) {
632 | if (!isOverlayVisible && index >= 0 && index < gallery.length) {
633 | prepareOverlay(gallery, options);
634 | showOverlay(index);
635 | return true;
636 | }
637 | if (index < 0) {
638 | if (options.animation) {
639 | bounceAnimation('left');
640 | }
641 | return false;
642 | }
643 | if (index >= imagesElements.length) {
644 | if (options.animation) {
645 | bounceAnimation('right');
646 | }
647 | return false;
648 | }
649 |
650 | currentIndex = index;
651 | loadImage(currentIndex, function() {
652 | preloadNext(currentIndex);
653 | preloadPrev(currentIndex);
654 | });
655 | updateOffset();
656 |
657 | if (options.onChange) {
658 | options.onChange(currentIndex, imagesElements.length);
659 | }
660 |
661 | return true;
662 | }
663 |
664 | /**
665 | * Triggers the bounce animation
666 | * @param {('left'|'right')} direction - Direction of the movement
667 | */
668 | function bounceAnimation(direction) {
669 | slider.className = 'bounce-from-' + direction;
670 | setTimeout(function() {
671 | slider.className = '';
672 | }, 400);
673 | }
674 |
675 | function updateOffset() {
676 | var offset = -currentIndex * 100 + '%';
677 | if (options.animation === 'fadeIn') {
678 | slider.style.opacity = 0;
679 | setTimeout(function() {
680 | supports.transforms ?
681 | slider.style.transform = slider.style.webkitTransform = 'translate3d(' + offset + ',0,0)'
682 | : slider.style.left = offset;
683 | slider.style.opacity = 1;
684 | }, 400);
685 | } else {
686 | supports.transforms ?
687 | slider.style.transform = slider.style.webkitTransform = 'translate3d(' + offset + ',0,0)'
688 | : slider.style.left = offset;
689 | }
690 | }
691 |
692 | // CSS 3D Transforms test
693 | function testTransformsSupport() {
694 | var div = create('div');
695 | return typeof div.style.perspective !== 'undefined' || typeof div.style.webkitPerspective !== 'undefined';
696 | }
697 |
698 | // Inline SVG test
699 | function testSvgSupport() {
700 | var div = create('div');
701 | div.innerHTML = ' ';
702 | return (div.firstChild && div.firstChild.namespaceURI) === 'http://www.w3.org/2000/svg';
703 | }
704 |
705 | // Borrowed from https://github.com/seiyria/bootstrap-slider/pull/680/files
706 | /* eslint-disable getter-return */
707 | function testPassiveEventsSupport() {
708 | var passiveEvents = false;
709 | try {
710 | var opts = Object.defineProperty({}, 'passive', {
711 | get: function() {
712 | passiveEvents = true;
713 | }
714 | });
715 | window.addEventListener('test', null, opts);
716 | } catch (e) { /* Silence the error and continue */ }
717 |
718 | return passiveEvents;
719 | }
720 | /* eslint-enable getter-return */
721 |
722 | function preloadNext(index) {
723 | if (index - currentIndex >= options.preload) {
724 | return;
725 | }
726 | loadImage(index + 1, function() {
727 | preloadNext(index + 1);
728 | });
729 | }
730 |
731 | function preloadPrev(index) {
732 | if (currentIndex - index >= options.preload) {
733 | return;
734 | }
735 | loadImage(index - 1, function() {
736 | preloadPrev(index - 1);
737 | });
738 | }
739 |
740 | function bind(element, event, callback, options) {
741 | if (element.addEventListener) {
742 | element.addEventListener(event, callback, options);
743 | } else {
744 | // IE8 fallback
745 | element.attachEvent('on' + event, function(event) {
746 | // `event` and `event.target` are not provided in IE8
747 | event = event || window.event;
748 | event.target = event.target || event.srcElement;
749 | callback(event);
750 | });
751 | }
752 | }
753 |
754 | function unbind(element, event, callback, options) {
755 | if (element.removeEventListener) {
756 | element.removeEventListener(event, callback, options);
757 | } else {
758 | // IE8 fallback
759 | element.detachEvent('on' + event, callback);
760 | }
761 | }
762 |
763 | function getByID(id) {
764 | return document.getElementById(id);
765 | }
766 |
767 | function create(element) {
768 | return document.createElement(element);
769 | }
770 |
771 | function destroyPlugin() {
772 | unbindEvents();
773 | clearCachedData();
774 | unbind(document, 'keydown', keyDownHandler);
775 | document.getElementsByTagName('body')[0].removeChild(document.getElementById('baguetteBox-overlay'));
776 | data = {};
777 | currentGallery = [];
778 | currentIndex = 0;
779 | }
780 |
781 | return {
782 | run: run,
783 | show: show,
784 | showNext: showNextImage,
785 | showPrevious: showPreviousImage,
786 | hide: hideOverlay,
787 | destroy: destroyPlugin
788 | };
789 | }));
790 |
--------------------------------------------------------------------------------
/assets/src/scripts/_external/headroom.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * headroom.js v0.9.4 - Give your page some headroom. Hide your header until you need it
3 | * Copyright (c) 2017 Nick Williams - http://wicky.nillia.ms/headroom.js
4 | * License: MIT
5 | */
6 |
7 | (function(root, factory) {
8 | 'use strict';
9 |
10 | if (typeof define === 'function' && define.amd) {
11 | // AMD. Register as an anonymous module.
12 | define([], factory);
13 | }
14 | else if (typeof exports === 'object') {
15 | // COMMONJS
16 | module.exports = factory();
17 | }
18 | else {
19 | // BROWSER
20 | root.Headroom = factory();
21 | }
22 | }(this, function() {
23 | 'use strict';
24 |
25 | /* exported features */
26 |
27 | var features = {
28 | bind : !!(function(){}.bind),
29 | classList : 'classList' in document.documentElement,
30 | rAF : !!(window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame)
31 | };
32 | window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
33 |
34 | /**
35 | * Handles debouncing of events via requestAnimationFrame
36 | * @see http://www.html5rocks.com/en/tutorials/speed/animations/
37 | * @param {Function} callback The callback to handle whichever event
38 | */
39 | function Debouncer (callback) {
40 | this.callback = callback;
41 | this.ticking = false;
42 | }
43 | Debouncer.prototype = {
44 | constructor : Debouncer,
45 |
46 | /**
47 | * dispatches the event to the supplied callback
48 | * @private
49 | */
50 | update : function() {
51 | this.callback && this.callback();
52 | this.ticking = false;
53 | },
54 |
55 | /**
56 | * ensures events don't get stacked
57 | * @private
58 | */
59 | requestTick : function() {
60 | if(!this.ticking) {
61 | requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this)));
62 | this.ticking = true;
63 | }
64 | },
65 |
66 | /**
67 | * Attach this as the event listeners
68 | */
69 | handleEvent : function() {
70 | this.requestTick();
71 | }
72 | };
73 | /**
74 | * Check if object is part of the DOM
75 | * @constructor
76 | * @param {Object} obj element to check
77 | */
78 | function isDOMElement(obj) {
79 | return obj && typeof window !== 'undefined' && (obj === window || obj.nodeType);
80 | }
81 |
82 | /**
83 | * Helper function for extending objects
84 | */
85 | function extend (object /*, objectN ... */) {
86 | if(arguments.length <= 0) {
87 | throw new Error('Missing arguments in extend function');
88 | }
89 |
90 | var result = object || {},
91 | key,
92 | i;
93 |
94 | for (i = 1; i < arguments.length; i++) {
95 | var replacement = arguments[i] || {};
96 |
97 | for (key in replacement) {
98 | // Recurse into object except if the object is a DOM element
99 | if(typeof result[key] === 'object' && ! isDOMElement(result[key])) {
100 | result[key] = extend(result[key], replacement[key]);
101 | }
102 | else {
103 | result[key] = result[key] || replacement[key];
104 | }
105 | }
106 | }
107 |
108 | return result;
109 | }
110 |
111 | /**
112 | * Helper function for normalizing tolerance option to object format
113 | */
114 | function normalizeTolerance (t) {
115 | return t === Object(t) ? t : { down : t, up : t };
116 | }
117 |
118 | /**
119 | * UI enhancement for fixed headers.
120 | * Hides header when scrolling down
121 | * Shows header when scrolling up
122 | * @constructor
123 | * @param {DOMElement} elem the header element
124 | * @param {Object} options options for the widget
125 | */
126 | function Headroom (elem, options) {
127 | options = extend(options, Headroom.options);
128 |
129 | this.lastKnownScrollY = 0;
130 | this.elem = elem;
131 | this.tolerance = normalizeTolerance(options.tolerance);
132 | this.classes = options.classes;
133 | this.offset = options.offset;
134 | this.scroller = options.scroller;
135 | this.initialised = false;
136 | this.onPin = options.onPin;
137 | this.onUnpin = options.onUnpin;
138 | this.onTop = options.onTop;
139 | this.onNotTop = options.onNotTop;
140 | this.onBottom = options.onBottom;
141 | this.onNotBottom = options.onNotBottom;
142 | }
143 | Headroom.prototype = {
144 | constructor : Headroom,
145 |
146 | /**
147 | * Initialises the widget
148 | */
149 | init : function() {
150 | if(!Headroom.cutsTheMustard) {
151 | return;
152 | }
153 |
154 | this.debouncer = new Debouncer(this.update.bind(this));
155 | this.elem.classList.add(this.classes.initial);
156 |
157 | // defer event registration to handle browser
158 | // potentially restoring previous scroll position
159 | setTimeout(this.attachEvent.bind(this), 100);
160 |
161 | return this;
162 | },
163 |
164 | /**
165 | * Unattaches events and removes any classes that were added
166 | */
167 | destroy : function() {
168 | var classes = this.classes;
169 |
170 | this.initialised = false;
171 |
172 | for (var key in classes) {
173 | if(classes.hasOwnProperty(key)) {
174 | this.elem.classList.remove(classes[key]);
175 | }
176 | }
177 |
178 | this.scroller.removeEventListener('scroll', this.debouncer, false);
179 | },
180 |
181 | /**
182 | * Attaches the scroll event
183 | * @private
184 | */
185 | attachEvent : function() {
186 | if(!this.initialised){
187 | this.lastKnownScrollY = this.getScrollY();
188 | this.initialised = true;
189 | this.scroller.addEventListener('scroll', this.debouncer, false);
190 |
191 | this.debouncer.handleEvent();
192 | }
193 | },
194 |
195 | /**
196 | * Unpins the header if it's currently pinned
197 | */
198 | unpin : function() {
199 | var classList = this.elem.classList,
200 | classes = this.classes;
201 |
202 | if(classList.contains(classes.pinned) || !classList.contains(classes.unpinned)) {
203 | classList.add(classes.unpinned);
204 | classList.remove(classes.pinned);
205 | this.onUnpin && this.onUnpin.call(this);
206 | }
207 | },
208 |
209 | /**
210 | * Pins the header if it's currently unpinned
211 | */
212 | pin : function() {
213 | var classList = this.elem.classList,
214 | classes = this.classes;
215 |
216 | if(classList.contains(classes.unpinned)) {
217 | classList.remove(classes.unpinned);
218 | classList.add(classes.pinned);
219 | this.onPin && this.onPin.call(this);
220 | }
221 | },
222 |
223 | /**
224 | * Handles the top states
225 | */
226 | top : function() {
227 | var classList = this.elem.classList,
228 | classes = this.classes;
229 |
230 | if(!classList.contains(classes.top)) {
231 | classList.add(classes.top);
232 | classList.remove(classes.notTop);
233 | this.onTop && this.onTop.call(this);
234 | }
235 | },
236 |
237 | /**
238 | * Handles the not top state
239 | */
240 | notTop : function() {
241 | var classList = this.elem.classList,
242 | classes = this.classes;
243 |
244 | if(!classList.contains(classes.notTop)) {
245 | classList.add(classes.notTop);
246 | classList.remove(classes.top);
247 | this.onNotTop && this.onNotTop.call(this);
248 | }
249 | },
250 |
251 | bottom : function() {
252 | var classList = this.elem.classList,
253 | classes = this.classes;
254 |
255 | if(!classList.contains(classes.bottom)) {
256 | classList.add(classes.bottom);
257 | classList.remove(classes.notBottom);
258 | this.onBottom && this.onBottom.call(this);
259 | }
260 | },
261 |
262 | /**
263 | * Handles the not top state
264 | */
265 | notBottom : function() {
266 | var classList = this.elem.classList,
267 | classes = this.classes;
268 |
269 | if(!classList.contains(classes.notBottom)) {
270 | classList.add(classes.notBottom);
271 | classList.remove(classes.bottom);
272 | this.onNotBottom && this.onNotBottom.call(this);
273 | }
274 | },
275 |
276 | /**
277 | * Gets the Y scroll position
278 | * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
279 | * @return {Number} pixels the page has scrolled along the Y-axis
280 | */
281 | getScrollY : function() {
282 | return (this.scroller.pageYOffset !== undefined)
283 | ? this.scroller.pageYOffset
284 | : (this.scroller.scrollTop !== undefined)
285 | ? this.scroller.scrollTop
286 | : (document.documentElement || document.body.parentNode || document.body).scrollTop;
287 | },
288 |
289 | /**
290 | * Gets the height of the viewport
291 | * @see http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript
292 | * @return {int} the height of the viewport in pixels
293 | */
294 | getViewportHeight : function () {
295 | return window.innerHeight
296 | || document.documentElement.clientHeight
297 | || document.body.clientHeight;
298 | },
299 |
300 | /**
301 | * Gets the physical height of the DOM element
302 | * @param {Object} elm the element to calculate the physical height of which
303 | * @return {int} the physical height of the element in pixels
304 | */
305 | getElementPhysicalHeight : function (elm) {
306 | return Math.max(
307 | elm.offsetHeight,
308 | elm.clientHeight
309 | );
310 | },
311 |
312 | /**
313 | * Gets the physical height of the scroller element
314 | * @return {int} the physical height of the scroller element in pixels
315 | */
316 | getScrollerPhysicalHeight : function () {
317 | return (this.scroller === window || this.scroller === document.body)
318 | ? this.getViewportHeight()
319 | : this.getElementPhysicalHeight(this.scroller);
320 | },
321 |
322 | /**
323 | * Gets the height of the document
324 | * @see http://james.padolsey.com/javascript/get-document-height-cross-browser/
325 | * @return {int} the height of the document in pixels
326 | */
327 | getDocumentHeight : function () {
328 | var body = document.body,
329 | documentElement = document.documentElement;
330 |
331 | return Math.max(
332 | body.scrollHeight, documentElement.scrollHeight,
333 | body.offsetHeight, documentElement.offsetHeight,
334 | body.clientHeight, documentElement.clientHeight
335 | );
336 | },
337 |
338 | /**
339 | * Gets the height of the DOM element
340 | * @param {Object} elm the element to calculate the height of which
341 | * @return {int} the height of the element in pixels
342 | */
343 | getElementHeight : function (elm) {
344 | return Math.max(
345 | elm.scrollHeight,
346 | elm.offsetHeight,
347 | elm.clientHeight
348 | );
349 | },
350 |
351 | /**
352 | * Gets the height of the scroller element
353 | * @return {int} the height of the scroller element in pixels
354 | */
355 | getScrollerHeight : function () {
356 | return (this.scroller === window || this.scroller === document.body)
357 | ? this.getDocumentHeight()
358 | : this.getElementHeight(this.scroller);
359 | },
360 |
361 | /**
362 | * determines if the scroll position is outside of document boundaries
363 | * @param {int} currentScrollY the current y scroll position
364 | * @return {bool} true if out of bounds, false otherwise
365 | */
366 | isOutOfBounds : function (currentScrollY) {
367 | var pastTop = currentScrollY < 0,
368 | pastBottom = currentScrollY + this.getScrollerPhysicalHeight() > this.getScrollerHeight();
369 |
370 | return pastTop || pastBottom;
371 | },
372 |
373 | /**
374 | * determines if the tolerance has been exceeded
375 | * @param {int} currentScrollY the current scroll y position
376 | * @return {bool} true if tolerance exceeded, false otherwise
377 | */
378 | toleranceExceeded : function (currentScrollY, direction) {
379 | return Math.abs(currentScrollY-this.lastKnownScrollY) >= this.tolerance[direction];
380 | },
381 |
382 | /**
383 | * determine if it is appropriate to unpin
384 | * @param {int} currentScrollY the current y scroll position
385 | * @param {bool} toleranceExceeded has the tolerance been exceeded?
386 | * @return {bool} true if should unpin, false otherwise
387 | */
388 | shouldUnpin : function (currentScrollY, toleranceExceeded) {
389 | var scrollingDown = currentScrollY > this.lastKnownScrollY,
390 | pastOffset = currentScrollY >= this.offset;
391 |
392 | return scrollingDown && pastOffset && toleranceExceeded;
393 | },
394 |
395 | /**
396 | * determine if it is appropriate to pin
397 | * @param {int} currentScrollY the current y scroll position
398 | * @param {bool} toleranceExceeded has the tolerance been exceeded?
399 | * @return {bool} true if should pin, false otherwise
400 | */
401 | shouldPin : function (currentScrollY, toleranceExceeded) {
402 | var scrollingUp = currentScrollY < this.lastKnownScrollY,
403 | pastOffset = currentScrollY <= this.offset;
404 |
405 | return (scrollingUp && toleranceExceeded) || pastOffset;
406 | },
407 |
408 | /**
409 | * Handles updating the state of the widget
410 | */
411 | update : function() {
412 | var currentScrollY = this.getScrollY(),
413 | scrollDirection = currentScrollY > this.lastKnownScrollY ? 'down' : 'up',
414 | toleranceExceeded = this.toleranceExceeded(currentScrollY, scrollDirection);
415 |
416 | if(this.isOutOfBounds(currentScrollY)) { // Ignore bouncy scrolling in OSX
417 | return;
418 | }
419 |
420 | if (currentScrollY <= this.offset ) {
421 | this.top();
422 | } else {
423 | this.notTop();
424 | }
425 |
426 | if(currentScrollY + this.getViewportHeight() >= this.getScrollerHeight()) {
427 | this.bottom();
428 | }
429 | else {
430 | this.notBottom();
431 | }
432 |
433 | if(this.shouldUnpin(currentScrollY, toleranceExceeded)) {
434 | this.unpin();
435 | }
436 | else if(this.shouldPin(currentScrollY, toleranceExceeded)) {
437 | this.pin();
438 | }
439 |
440 | this.lastKnownScrollY = currentScrollY;
441 | }
442 | };
443 | /**
444 | * Default options
445 | * @type {Object}
446 | */
447 | Headroom.options = {
448 | tolerance : {
449 | up : 0,
450 | down : 0
451 | },
452 | offset : 0,
453 | scroller: window,
454 | classes : {
455 | pinned : 'headroom--pinned',
456 | unpinned : 'headroom--unpinned',
457 | top : 'headroom--top',
458 | notTop : 'headroom--not-top',
459 | bottom : 'headroom--bottom',
460 | notBottom : 'headroom--not-bottom',
461 | initial : 'headroom'
462 | }
463 | };
464 | Headroom.cutsTheMustard = typeof features !== 'undefined' && features.rAF && features.bind && features.classList;
465 |
466 | return Headroom;
467 | }));
--------------------------------------------------------------------------------
/assets/src/scripts/_external/lazyload.js:
--------------------------------------------------------------------------------
1 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
2 |
3 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
4 |
5 | (function (global, factory) {
6 | (typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.LazyLoad = factory();
7 | })(this, function () {
8 | 'use strict';
9 |
10 | var defaultSettings = {
11 | elements_selector: "img",
12 | container: document,
13 | threshold: 300,
14 | thresholds: null,
15 | data_src: "src",
16 | data_srcset: "srcset",
17 | data_sizes: "sizes",
18 | data_bg: "bg",
19 | class_loading: "loading",
20 | class_loaded: "loaded",
21 | class_error: "error",
22 | load_delay: 0,
23 | callback_load: null,
24 | callback_error: null,
25 | callback_set: null,
26 | callback_enter: null,
27 | to_webp: false
28 | };
29 |
30 | var getInstanceSettings = function getInstanceSettings(customSettings) {
31 | return _extends({}, defaultSettings, customSettings);
32 | };
33 |
34 | var dataPrefix = "data-";
35 | var processedDataName = "was-processed";
36 | var timeoutDataName = "ll-timeout";
37 | var trueString = "true";
38 |
39 | var getData = function getData(element, attribute) {
40 | return element.getAttribute(dataPrefix + attribute);
41 | };
42 |
43 | var setData = function setData(element, attribute, value) {
44 | var attrName = dataPrefix + attribute;
45 | if (value === null) {
46 | element.removeAttribute(attrName);
47 | return;
48 | }
49 | element.setAttribute(attrName, value);
50 | };
51 |
52 | var setWasProcessedData = function setWasProcessedData(element) {
53 | return setData(element, processedDataName, trueString);
54 | };
55 |
56 | var getWasProcessedData = function getWasProcessedData(element) {
57 | return getData(element, processedDataName) === trueString;
58 | };
59 |
60 | var setTimeoutData = function setTimeoutData(element, value) {
61 | return setData(element, timeoutDataName, value);
62 | };
63 |
64 | var getTimeoutData = function getTimeoutData(element) {
65 | return getData(element, timeoutDataName);
66 | };
67 |
68 | function purgeElements(elements) {
69 | return elements.filter(function (element) {
70 | return !getWasProcessedData(element);
71 | });
72 | }
73 |
74 | /* Creates instance and notifies it through the window element */
75 | var createInstance = function createInstance(classObj, options) {
76 | var event;
77 | var eventString = "LazyLoad::Initialized";
78 | var instance = new classObj(options);
79 | try {
80 | // Works in modern browsers
81 | event = new CustomEvent(eventString, { detail: { instance: instance } });
82 | } catch (err) {
83 | // Works in Internet Explorer (all versions)
84 | event = document.createEvent("CustomEvent");
85 | event.initCustomEvent(eventString, false, false, { instance: instance });
86 | }
87 | window.dispatchEvent(event);
88 | };
89 |
90 | /* Auto initialization of one or more instances of lazyload, depending on the
91 | options passed in (plain object or an array) */
92 | function autoInitialize(classObj, options) {
93 | if (!options) {
94 | return;
95 | }
96 | if (!options.length) {
97 | // Plain object
98 | createInstance(classObj, options);
99 | } else {
100 | // Array of objects
101 | for (var i = 0, optionsItem; optionsItem = options[i]; i += 1) {
102 | createInstance(classObj, optionsItem);
103 | }
104 | }
105 | }
106 |
107 | var replaceExtToWebp = function replaceExtToWebp(value, condition) {
108 | return condition ? value.replace(/\.(jpe?g|png)/gi, ".webp") : value;
109 | };
110 |
111 | var detectWebp = function detectWebp() {
112 | var webpString = "image/webp";
113 | var canvas = document.createElement("canvas");
114 |
115 | if (canvas.getContext && canvas.getContext("2d")) {
116 | return canvas.toDataURL(webpString).indexOf('data:' + webpString) === 0;
117 | }
118 |
119 | return false;
120 | };
121 |
122 | var runningOnBrowser = typeof window !== "undefined";
123 |
124 | var isBot = runningOnBrowser && !("onscroll" in window) || /(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent);
125 |
126 | var supportsIntersectionObserver = runningOnBrowser && "IntersectionObserver" in window;
127 |
128 | var supportsClassList = runningOnBrowser && "classList" in document.createElement("p");
129 |
130 | var supportsWebp = runningOnBrowser && detectWebp();
131 |
132 | var setSourcesInChildren = function setSourcesInChildren(parentTag, attrName, dataAttrName, toWebpFlag) {
133 | for (var i = 0, childTag; childTag = parentTag.children[i]; i += 1) {
134 | if (childTag.tagName === "SOURCE") {
135 | var attrValue = getData(childTag, dataAttrName);
136 | setAttributeIfValue(childTag, attrName, attrValue, toWebpFlag);
137 | }
138 | }
139 | };
140 |
141 | var setAttributeIfValue = function setAttributeIfValue(element, attrName, value, toWebpFlag) {
142 | if (!value) {
143 | return;
144 | }
145 | element.setAttribute(attrName, replaceExtToWebp(value, toWebpFlag));
146 | };
147 |
148 | var setSourcesImg = function setSourcesImg(element, settings) {
149 | var toWebpFlag = supportsWebp && settings.to_webp;
150 | var srcsetDataName = settings.data_srcset;
151 | var parent = element.parentNode;
152 |
153 | if (parent && parent.tagName === "PICTURE") {
154 | setSourcesInChildren(parent, "srcset", srcsetDataName, toWebpFlag);
155 | }
156 | var sizesDataValue = getData(element, settings.data_sizes);
157 | setAttributeIfValue(element, "sizes", sizesDataValue);
158 | var srcsetDataValue = getData(element, srcsetDataName);
159 | setAttributeIfValue(element, "srcset", srcsetDataValue, toWebpFlag);
160 | var srcDataValue = getData(element, settings.data_src);
161 | setAttributeIfValue(element, "src", srcDataValue, toWebpFlag);
162 | };
163 |
164 | var setSourcesIframe = function setSourcesIframe(element, settings) {
165 | var srcDataValue = getData(element, settings.data_src);
166 |
167 | setAttributeIfValue(element, "src", srcDataValue);
168 | };
169 |
170 | var setSourcesVideo = function setSourcesVideo(element, settings) {
171 | var srcDataName = settings.data_src;
172 | var srcDataValue = getData(element, srcDataName);
173 |
174 | setSourcesInChildren(element, "src", srcDataName);
175 | setAttributeIfValue(element, "src", srcDataValue);
176 | element.load();
177 | };
178 |
179 | var setSourcesBgImage = function setSourcesBgImage(element, settings) {
180 | var toWebpFlag = supportsWebp && settings.to_webp;
181 | var srcDataValue = getData(element, settings.data_src);
182 | var bgDataValue = getData(element, settings.data_bg);
183 |
184 | if (srcDataValue) {
185 | var setValue = replaceExtToWebp(srcDataValue, toWebpFlag);
186 | element.style.backgroundImage = 'url("' + setValue + '")';
187 | }
188 |
189 | if (bgDataValue) {
190 | var _setValue = replaceExtToWebp(bgDataValue, toWebpFlag);
191 | element.style.backgroundImage = _setValue;
192 | }
193 | };
194 |
195 | var setSourcesFunctions = {
196 | IMG: setSourcesImg,
197 | IFRAME: setSourcesIframe,
198 | VIDEO: setSourcesVideo
199 | };
200 |
201 | var setSources = function setSources(element, settings) {
202 | var tagName = element.tagName;
203 | var setSourcesFunction = setSourcesFunctions[tagName];
204 | if (setSourcesFunction) {
205 | setSourcesFunction(element, settings);
206 | return;
207 | }
208 | setSourcesBgImage(element, settings);
209 | };
210 |
211 | var addClass = function addClass(element, className) {
212 | if (supportsClassList) {
213 | element.classList.add(className);
214 | return;
215 | }
216 | element.className += (element.className ? " " : "") + className;
217 | };
218 |
219 | var removeClass = function removeClass(element, className) {
220 | if (supportsClassList) {
221 | element.classList.remove(className);
222 | return;
223 | }
224 | element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), " ").replace(/^\s+/, "").replace(/\s+$/, "");
225 | };
226 |
227 | var callbackIfSet = function callbackIfSet(callback, argument) {
228 | if (callback) {
229 | callback(argument);
230 | }
231 | };
232 |
233 | var genericLoadEventName = "load";
234 | var mediaLoadEventName = "loadeddata";
235 | var errorEventName = "error";
236 |
237 | var addEventListener = function addEventListener(element, eventName, handler) {
238 | element.addEventListener(eventName, handler);
239 | };
240 |
241 | var removeEventListener = function removeEventListener(element, eventName, handler) {
242 | element.removeEventListener(eventName, handler);
243 | };
244 |
245 | var addAllEventListeners = function addAllEventListeners(element, loadHandler, errorHandler) {
246 | addEventListener(element, genericLoadEventName, loadHandler);
247 | addEventListener(element, mediaLoadEventName, loadHandler);
248 | addEventListener(element, errorEventName, errorHandler);
249 | };
250 |
251 | var removeAllEventListeners = function removeAllEventListeners(element, loadHandler, errorHandler) {
252 | removeEventListener(element, genericLoadEventName, loadHandler);
253 | removeEventListener(element, mediaLoadEventName, loadHandler);
254 | removeEventListener(element, errorEventName, errorHandler);
255 | };
256 |
257 | var eventHandler = function eventHandler(event, success, settings) {
258 | var className = success ? settings.class_loaded : settings.class_error;
259 | var callback = success ? settings.callback_load : settings.callback_error;
260 | var element = event.target;
261 |
262 | removeClass(element, settings.class_loading);
263 | addClass(element, className);
264 | callbackIfSet(callback, element);
265 | };
266 |
267 | var addOneShotEventListeners = function addOneShotEventListeners(element, settings) {
268 | var loadHandler = function loadHandler(event) {
269 | eventHandler(event, true, settings);
270 | removeAllEventListeners(element, loadHandler, errorHandler);
271 | };
272 | var errorHandler = function errorHandler(event) {
273 | eventHandler(event, false, settings);
274 | removeAllEventListeners(element, loadHandler, errorHandler);
275 | };
276 | addAllEventListeners(element, loadHandler, errorHandler);
277 | };
278 |
279 | var managedTags = ["IMG", "IFRAME", "VIDEO"];
280 |
281 | var loadAndUnobserve = function loadAndUnobserve(element, observer, settings) {
282 | revealElement(element, settings);
283 | observer.unobserve(element);
284 | };
285 |
286 | var cancelDelayLoad = function cancelDelayLoad(element) {
287 | var timeoutId = getTimeoutData(element);
288 | if (!timeoutId) {
289 | return; // do nothing if timeout doesn't exist
290 | }
291 | clearTimeout(timeoutId);
292 | setTimeoutData(element, null);
293 | };
294 |
295 | var delayLoad = function delayLoad(element, observer, settings) {
296 | var loadDelay = settings.load_delay;
297 | var timeoutId = getTimeoutData(element);
298 | if (timeoutId) {
299 | return; // do nothing if timeout already set
300 | }
301 | timeoutId = setTimeout(function () {
302 | loadAndUnobserve(element, observer, settings);
303 | cancelDelayLoad(element);
304 | }, loadDelay);
305 | setTimeoutData(element, timeoutId);
306 | };
307 |
308 | function revealElement(element, settings, force) {
309 | if (!force && getWasProcessedData(element)) {
310 | return; // element has already been processed and force wasn't true
311 | }
312 | callbackIfSet(settings.callback_enter, element);
313 | if (managedTags.indexOf(element.tagName) > -1) {
314 | addOneShotEventListeners(element, settings);
315 | addClass(element, settings.class_loading);
316 | }
317 | setSources(element, settings);
318 | setWasProcessedData(element);
319 | callbackIfSet(settings.callback_set, element);
320 | }
321 |
322 | /* entry.isIntersecting needs fallback because is null on some versions of MS Edge, and
323 | entry.intersectionRatio is not enough alone because it could be 0 on some intersecting elements */
324 | var isIntersecting = function isIntersecting(entry) {
325 | return entry.isIntersecting || entry.intersectionRatio > 0;
326 | };
327 |
328 | var getObserverSettings = function getObserverSettings(settings) {
329 | return {
330 | root: settings.container === document ? null : settings.container,
331 | rootMargin: settings.thresholds || settings.threshold + "px"
332 | };
333 | };
334 |
335 | var LazyLoad = function LazyLoad(customSettings, elements) {
336 | this._settings = getInstanceSettings(customSettings);
337 | this._setObserver();
338 | this.update(elements);
339 | };
340 |
341 | LazyLoad.prototype = {
342 | _manageIntersection: function _manageIntersection(entry) {
343 | var observer = this._observer;
344 | var settings = this._settings;
345 | var loadDelay = this._settings.load_delay;
346 | var element = entry.target;
347 | if (isIntersecting(entry)) {
348 | if (!loadDelay) {
349 | loadAndUnobserve(element, observer, settings);
350 | } else {
351 | delayLoad(element, observer, settings);
352 | }
353 | }
354 |
355 | // Writes in and outs in a data-attribute
356 | if (!isIntersecting(entry)) {
357 | cancelDelayLoad(element);
358 | }
359 | },
360 | _onIntersection: function _onIntersection(entries) {
361 | entries.forEach(this._manageIntersection.bind(this));
362 | this._elements = purgeElements(this._elements);
363 | },
364 | _setObserver: function _setObserver() {
365 | if (!supportsIntersectionObserver) {
366 | return;
367 | }
368 | this._observer = new IntersectionObserver(this._onIntersection.bind(this), getObserverSettings(this._settings));
369 | },
370 |
371 | loadAll: function loadAll() {
372 | var _this = this;
373 |
374 | this._elements.forEach(function (element) {
375 | _this.load(element);
376 | });
377 | this._elements = purgeElements(this._elements);
378 | },
379 |
380 | update: function update(elements) {
381 | var _this2 = this;
382 |
383 | var settings = this._settings;
384 | var nodeSet = elements || settings.container.querySelectorAll(settings.elements_selector);
385 |
386 | this._elements = purgeElements(Array.prototype.slice.call(nodeSet)); // nodeset to array for IE compatibility
387 |
388 | if (isBot || !this._observer) {
389 | this.loadAll();
390 | return;
391 | }
392 |
393 | this._elements.forEach(function (element) {
394 | _this2._observer.observe(element);
395 | });
396 | },
397 |
398 | destroy: function destroy() {
399 | var _this3 = this;
400 |
401 | if (this._observer) {
402 | purgeElements(this._elements).forEach(function (element) {
403 | _this3._observer.unobserve(element);
404 | });
405 | this._observer = null;
406 | }
407 | this._elements = null;
408 | this._settings = null;
409 | },
410 |
411 | load: function load(element, force) {
412 | revealElement(element, this._settings, force);
413 | }
414 | };
415 |
416 | /* Automatic instances creation if required (useful for async script loading) */
417 | if (runningOnBrowser) {
418 | autoInitialize(LazyLoad, window.lazyLoadOptions);
419 | }
420 |
421 | return LazyLoad;
422 | });
--------------------------------------------------------------------------------
/assets/src/scripts/main.js:
--------------------------------------------------------------------------------
1 | document.addEventListener('DOMContentLoaded', function(event) {
2 | // LazdyLoad
3 | const myLazyLoad = new LazyLoad()
4 |
5 | // Lightbox
6 | baguetteBox.run('main', {})
7 |
8 | // Hide header
9 | const navbar = document.querySelector('nav')
10 | if (navbar) {
11 | const headroom = new Headroom(navbar, {
12 | 'offset': 205,
13 | 'tolerance': 5,
14 | 'classes': {
15 | 'initial': 'animated',
16 | 'pinned': 'slideDown',
17 | 'unpinned': 'slideUp'
18 | }
19 | })
20 | headroom.init()
21 | }
22 | })
23 |
--------------------------------------------------------------------------------
/assets/src/styles/_chroma_friendly.scss:
--------------------------------------------------------------------------------
1 | /* Background */ .chroma { background-color: #f0f0f0 }
2 | /* Error */ .chroma .err { }
3 | /* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
4 | /* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; }
5 | /* LineHighlight */ .chroma .hl { display: block; width: 100%;background-color: #ffffcc }
6 | /* LineNumbersTable */ .chroma .lnt { margin-right: 0.4em; padding: 0 0.4em 0 0.4em; }
7 | /* LineNumbers */ .chroma .ln { margin-right: 0.4em; padding: 0 0.4em 0 0.4em; }
8 | /* Keyword */ .chroma .k { color: #007020; font-weight: bold }
9 | /* KeywordConstant */ .chroma .kc { color: #007020; font-weight: bold }
10 | /* KeywordDeclaration */ .chroma .kd { color: #007020; font-weight: bold }
11 | /* KeywordNamespace */ .chroma .kn { color: #007020; font-weight: bold }
12 | /* KeywordPseudo */ .chroma .kp { color: #007020 }
13 | /* KeywordReserved */ .chroma .kr { color: #007020; font-weight: bold }
14 | /* KeywordType */ .chroma .kt { color: #902000 }
15 | /* NameAttribute */ .chroma .na { color: #4070a0 }
16 | /* NameBuiltin */ .chroma .nb { color: #007020 }
17 | /* NameClass */ .chroma .nc { color: #0e84b5; font-weight: bold }
18 | /* NameConstant */ .chroma .no { color: #60add5 }
19 | /* NameDecorator */ .chroma .nd { color: #555555; font-weight: bold }
20 | /* NameEntity */ .chroma .ni { color: #d55537; font-weight: bold }
21 | /* NameException */ .chroma .ne { color: #007020 }
22 | /* NameFunction */ .chroma .nf { color: #06287e }
23 | /* NameLabel */ .chroma .nl { color: #002070; font-weight: bold }
24 | /* NameNamespace */ .chroma .nn { color: #0e84b5; font-weight: bold }
25 | /* NameTag */ .chroma .nt { color: #062873; font-weight: bold }
26 | /* NameVariable */ .chroma .nv { color: #bb60d5 }
27 | /* LiteralString */ .chroma .s { color: #4070a0 }
28 | /* LiteralStringAffix */ .chroma .sa { color: #4070a0 }
29 | /* LiteralStringBacktick */ .chroma .sb { color: #4070a0 }
30 | /* LiteralStringChar */ .chroma .sc { color: #4070a0 }
31 | /* LiteralStringDelimiter */ .chroma .dl { color: #4070a0 }
32 | /* LiteralStringDoc */ .chroma .sd { color: #4070a0; font-style: italic }
33 | /* LiteralStringDouble */ .chroma .s2 { color: #4070a0 }
34 | /* LiteralStringEscape */ .chroma .se { color: #4070a0; font-weight: bold }
35 | /* LiteralStringHeredoc */ .chroma .sh { color: #4070a0 }
36 | /* LiteralStringInterpol */ .chroma .si { color: #70a0d0; font-style: italic }
37 | /* LiteralStringOther */ .chroma .sx { color: #c65d09 }
38 | /* LiteralStringRegex */ .chroma .sr { color: #235388 }
39 | /* LiteralStringSingle */ .chroma .s1 { color: #4070a0 }
40 | /* LiteralStringSymbol */ .chroma .ss { color: #517918 }
41 | /* LiteralNumber */ .chroma .m { color: #40a070 }
42 | /* LiteralNumberBin */ .chroma .mb { color: #40a070 }
43 | /* LiteralNumberFloat */ .chroma .mf { color: #40a070 }
44 | /* LiteralNumberHex */ .chroma .mh { color: #40a070 }
45 | /* LiteralNumberInteger */ .chroma .mi { color: #40a070 }
46 | /* LiteralNumberIntegerLong */ .chroma .il { color: #40a070 }
47 | /* LiteralNumberOct */ .chroma .mo { color: #40a070 }
48 | /* Operator */ .chroma .o { color: #666666 }
49 | /* OperatorWord */ .chroma .ow { color: #007020; font-weight: bold }
50 | /* Comment */ .chroma .c { color: #60a0b0; font-style: italic }
51 | /* CommentHashbang */ .chroma .ch { color: #60a0b0; font-style: italic }
52 | /* CommentMultiline */ .chroma .cm { color: #60a0b0; font-style: italic }
53 | /* CommentSingle */ .chroma .c1 { color: #60a0b0; font-style: italic }
54 | /* CommentSpecial */ .chroma .cs { color: #60a0b0; background-color: #fff0f0 }
55 | /* CommentPreproc */ .chroma .cp { color: #007020 }
56 | /* CommentPreprocFile */ .chroma .cpf { color: #007020 }
57 | /* GenericDeleted */ .chroma .gd { color: #a00000 }
58 | /* GenericEmph */ .chroma .ge { font-style: italic }
59 | /* GenericError */ .chroma .gr { color: #ff0000 }
60 | /* GenericHeading */ .chroma .gh { color: #000080; font-weight: bold }
61 | /* GenericInserted */ .chroma .gi { color: #00a000 }
62 | /* GenericOutput */ .chroma .go { color: #888888 }
63 | /* GenericPrompt */ .chroma .gp { color: #c65d09; font-weight: bold }
64 | /* GenericStrong */ .chroma .gs { font-weight: bold }
65 | /* GenericSubheading */ .chroma .gu { color: #800080; font-weight: bold }
66 | /* GenericTraceback */ .chroma .gt { color: #0044dd }
67 | /* GenericUnderline */ .chroma .gl { text-decoration: underline }
68 | /* TextWhitespace */ .chroma .w { color: #bbbbbb }
69 |
--------------------------------------------------------------------------------
/assets/src/styles/_components/base.scss:
--------------------------------------------------------------------------------
1 | html, body {
2 | background-color: $base-background-color;
3 | font-family: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
4 | height: 100%;
5 | margin: 0;
6 | text-rendering: optimizeLegibility;
7 | }
8 |
9 | body {
10 | display: grid;
11 | grid-gap: 1rem;
12 | grid-template-areas: "nav" "main" "footer";
13 | grid-template-columns: 1fr;
14 | height: 100%;
15 |
16 | grid-template-rows: $navbar-height 1fr 3rem;
17 | @media screen and (max-width: $breakpoint) {
18 | grid-template-rows: $navbar-height 1fr 5rem;
19 | }
20 |
21 | a {
22 | color: $links-color;
23 | text-decoration: none;
24 |
25 | &:hover, &:active, &:visited {
26 | text-decoration: underline;
27 | }
28 | }
29 |
30 | nav {
31 | grid-area: nav;
32 | }
33 |
34 | main {
35 | grid-area: main;
36 | justify-self: center;
37 | grid-column: 1 / -1;
38 | max-width: 80rem !important;
39 | padding-bottom: 3rem !important;
40 | padding-top: 3rem !important;
41 |
42 | &.home {
43 | align-items: center;
44 | display: flex;
45 | flex-direction: column;
46 | justify-content: center;
47 | text-align: center;
48 | }
49 | }
50 |
51 | footer {
52 | grid-area: footer;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/assets/src/styles/_components/content.scss:
--------------------------------------------------------------------------------
1 | body {
2 | main {
3 | article {
4 | header {
5 | margin-bottom: 5rem;
6 | text-align: center;
7 |
8 | time {
9 | color: $color-silver;
10 | }
11 | }
12 |
13 | section {
14 | ins.adsbygoogle,
15 | video {
16 | margin: 5rem auto;
17 | }
18 |
19 | figure {
20 | margin: $itemMargin 0;
21 |
22 | &.full {
23 | left: 50%;
24 | margin-left: -50vw;
25 | margin-right: -50vw;
26 | position: relative;
27 | right: 50%;
28 | width: 100vw;
29 | }
30 |
31 | img {
32 | display: block;
33 | height: auto;
34 | margin: 0 auto;
35 | max-width: 100%;
36 | padding: 0;
37 |
38 | &.full {
39 | left: 50%;
40 | margin-left: -50vw;
41 | margin-right: -50vw;
42 | position: relative;
43 | right: 50%;
44 | width: 100vw;
45 | }
46 | }
47 |
48 | figcaption {
49 | text-align: center;
50 | }
51 | }
52 |
53 | table {
54 | tbody {
55 | tr {
56 | td {
57 | &[align="left"] {
58 | text-align: left;
59 | }
60 | &[align="right"] {
61 | text-align: right;
62 | }
63 | &[align="center"] {
64 | text-align: center;
65 | }
66 | }
67 | }
68 | }
69 | }
70 |
71 | pre {
72 | border-left: 0.3rem solid $links-color;
73 | display: grid;
74 | // overflow: auto;
75 |
76 | code {
77 | background-color: transparent;
78 | min-width: 0;
79 | }
80 | }
81 |
82 | .gist {
83 | width: 100%;
84 |
85 | & table {
86 | table-layout: fixed;
87 | }
88 |
89 | & td.js-line-number{
90 | width: 50px;
91 | text-align: center;
92 | }
93 | }
94 |
95 | iframe.instagram-media {
96 | margin-left: auto !important;
97 | margin-right: auto !important;
98 | }
99 |
100 | img {
101 | display: block;
102 | height: auto;
103 | margin: $itemMargin auto;
104 | max-width: 100%;
105 | padding: 0;
106 |
107 | &.full {
108 | left: 50%;
109 | margin-left: -50vw;
110 | margin-right: -50vw;
111 | position: relative;
112 | right: 50%;
113 | width: 100vw;
114 | }
115 | }
116 |
117 | p {
118 | code {
119 | background-color: $color-zhen-zhu-bai-pearl;
120 | color: $color-bara-red;
121 | white-space: normal;
122 |
123 | /* These are technically the same, but use both */
124 | overflow-wrap: break-word;
125 | word-wrap: break-word;
126 |
127 | -ms-word-break: break-all;
128 | /* This is the dangerous one in WebKit, as it breaks things wherever */
129 | word-break: break-all;
130 | /* Instead use this non-standard one: */
131 | word-break: break-word;
132 |
133 | /* Adds a hyphen where the word breaks, if supported (No Blink) */
134 | -ms-hyphens: auto;
135 | -moz-hyphens: auto;
136 | -webkit-hyphens: auto;
137 | hyphens: auto;
138 | }
139 | }
140 |
141 | ul {
142 | &.task-list {
143 | list-style: none;
144 | padding: 0;
145 | }
146 | }
147 |
148 | ol {
149 | list-style: decimal;
150 | }
151 |
152 | video {
153 | display: block;
154 | width: 100%
155 | }
156 |
157 | .embed-container {
158 | height: 0;
159 | max-width: 100%;
160 | overflow: hidden;
161 | padding-bottom: 56.25%;
162 | position: relative;
163 |
164 | embed, iframe, object {
165 | height: 100%;
166 | left: 0;
167 | position: absolute;
168 | top: 0;
169 | width: 100%;
170 | }
171 | }
172 |
173 | .speakerdeck {
174 | margin-left: auto !important;
175 | margin-right: auto !important;
176 | }
177 |
178 | .twitter-tweet {
179 | @media (max-width: 550px) {
180 | width: 0 !important;
181 | }
182 |
183 | margin-left: auto !important;
184 | margin-right: auto !important;
185 | }
186 | }
187 |
188 | footer {
189 | text-align: center;
190 |
191 | .meta {
192 | .tags {
193 | a {
194 | span {
195 | color: $color-silver;
196 | }
197 | }
198 | }
199 | }
200 |
201 | #disqus_thread {
202 | margin-left: auto !important;
203 | margin-right: auto !important;
204 | }
205 | }
206 | }
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/assets/src/styles/_components/elements.scss:
--------------------------------------------------------------------------------
1 | ul.posts-list {
2 | list-style: none;
3 |
4 | li {
5 | .date {
6 | color: $color-silver;
7 | font-size: 0.8em;
8 | display: block;
9 | }
10 |
11 | .lang {
12 | color: $color-silver;
13 | font-size: 0.7em;
14 | text-transform: uppercase;
15 |
16 | a {
17 | color: $color-silver;
18 | text-decoration: none;
19 |
20 | &:hover, &:active, &:visited {
21 | text-decoration: underline;
22 | }
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/assets/src/styles/_components/footer.scss:
--------------------------------------------------------------------------------
1 | body {
2 | > footer {
3 | align-items: right;
4 | color: $navbar-text-color;
5 | display: flex;
6 | font-size: 0.8em;
7 | justify-content: space-between;
8 | padding: 0.5rem;
9 | text-align: center;
10 |
11 | p {
12 | margin-bottom: 0;
13 | }
14 |
15 | // height: 3rem;
16 | // @media screen and (max-width: $breakpoint) {
17 | // height: 5rem;
18 | // }
19 |
20 | @media screen and (max-width: $breakpoint) {
21 | flex-direction: column;
22 |
23 | p {
24 | &:first-of-type {
25 | margin-bottom: 0.1rem;
26 | }
27 | &:last-of-type {
28 | margin-top: 0.1rem;
29 | }
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/assets/src/styles/_components/homepage.scss:
--------------------------------------------------------------------------------
1 | body {
2 | main {
3 | .homepage-avatar {
4 | border-radius: 50%;
5 | margin-bottom: 2rem;
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/assets/src/styles/_components/navbar.scss:
--------------------------------------------------------------------------------
1 | body {
2 | nav {
3 | align-items: center;
4 | background-color: #f4f5f6;
5 | color: $navbar-text-color;
6 | display: flex;
7 | height: $navbar-height;
8 | justify-content: space-between;
9 | left: 0;
10 | padding: 0.1rem 1rem;
11 | position: fixed;
12 | right: 0;
13 | top: 0;
14 | z-index: 10;
15 | border-bottom: .1rem solid #d1d1d1;
16 |
17 | a {
18 | color: $navbar-text-color;
19 | text-decoration: none;
20 |
21 | &:hover, &:active, &:visited {
22 | text-decoration: none;
23 | }
24 | }
25 |
26 | &.animated {
27 | animation-duration: 0.5s;
28 | animation-fill-mode: both;
29 | will-change: transform, opacity;
30 |
31 | &.slideDown {
32 | animation-name: slideDown;
33 | }
34 |
35 | &.slideUp {
36 | animation-name: slideUp;
37 | }
38 | }
39 | }
40 | }
41 |
42 | @-webkit-keyframes slideUp {
43 | 0% {
44 | -webkit-transform: translateY(0);
45 | }
46 |
47 | 100% {
48 | -webkit-transform: translateY(-100%);
49 | }
50 | }
51 |
52 | @-moz-keyframes slideUp {
53 | 0% {
54 | -moz-transform: translateY(0);
55 | }
56 |
57 | 100% {
58 | -moz-transform: translateY(-100%);
59 | }
60 | }
61 |
62 | @-o-keyframes slideUp {
63 | 0% {
64 | -o-transform: translateY(0);
65 | }
66 |
67 | 100% {
68 | -o-transform: translateY(-100%);
69 | }
70 | }
71 |
72 | @keyframes slideUp {
73 | 0% {
74 | transform: translateY(0);
75 | }
76 |
77 | 100% {
78 | transform: translateY(-100%);
79 | }
80 | }
81 |
82 | @-webkit-keyframes slideDown {
83 | 0% {
84 | -webkit-transform: translateY(-100%);
85 | }
86 |
87 | 100% {
88 | -webkit-transform: translateY(0);
89 | }
90 | }
91 |
92 | @-moz-keyframes slideDown {
93 | 0% {
94 | -moz-transform: translateY(-100%);
95 | }
96 |
97 | 100% {
98 | -moz-transform: translateY(0);
99 | }
100 | }
101 |
102 | @-o-keyframes slideDown {
103 | 0% {
104 | -o-transform: translateY(-100%);
105 | }
106 |
107 | 100% {
108 | -o-transform: translateY(0);
109 | }
110 | }
111 |
112 | @keyframes slideDown {
113 | 0% {
114 | transform: translateY(-100%);
115 | }
116 |
117 | 100% {
118 | transform: translateY(0);
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/assets/src/styles/_external/baguetteBox.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * baguetteBox.js
3 | * @author feimosi
4 | * @version 1.11.0
5 | * @url https://github.com/feimosi/baguetteBox.js
6 | */
7 | #baguetteBox-overlay {
8 | display: none;
9 | opacity: 0;
10 | position: fixed;
11 | overflow: hidden;
12 | top: 0;
13 | left: 0;
14 | width: 100%;
15 | height: 100%;
16 | z-index: 1000000;
17 | background-color: #222;
18 | background-color: rgba(0, 0, 0, 0.8);
19 | -webkit-transition: opacity .5s ease;
20 | transition: opacity .5s ease; }
21 | #baguetteBox-overlay.visible {
22 | opacity: 1; }
23 | #baguetteBox-overlay .full-image {
24 | display: inline-block;
25 | position: relative;
26 | width: 100%;
27 | height: 100%;
28 | text-align: center; }
29 | #baguetteBox-overlay .full-image figure {
30 | display: inline;
31 | margin: 0;
32 | height: 100%; }
33 | #baguetteBox-overlay .full-image img {
34 | display: inline-block;
35 | width: auto;
36 | height: auto;
37 | max-height: 100%;
38 | max-width: 100%;
39 | vertical-align: middle;
40 | -webkit-box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
41 | -moz-box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
42 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); }
43 | #baguetteBox-overlay .full-image figcaption {
44 | display: block;
45 | position: absolute;
46 | bottom: 0;
47 | width: 100%;
48 | text-align: center;
49 | line-height: 1.8;
50 | white-space: normal;
51 | color: #ccc;
52 | background-color: #000;
53 | background-color: rgba(0, 0, 0, 0.6);
54 | font-family: sans-serif; }
55 | #baguetteBox-overlay .full-image:before {
56 | content: "";
57 | display: inline-block;
58 | height: 50%;
59 | width: 1px;
60 | margin-right: -1px; }
61 |
62 | #baguetteBox-slider {
63 | position: absolute;
64 | left: 0;
65 | top: 0;
66 | height: 100%;
67 | width: 100%;
68 | white-space: nowrap;
69 | -webkit-transition: left .4s ease, -webkit-transform .4s ease;
70 | transition: left .4s ease, -webkit-transform .4s ease;
71 | transition: left .4s ease, transform .4s ease;
72 | transition: left .4s ease, transform .4s ease, -webkit-transform .4s ease, -moz-transform .4s ease; }
73 | #baguetteBox-slider.bounce-from-right {
74 | -webkit-animation: bounceFromRight .4s ease-out;
75 | animation: bounceFromRight .4s ease-out; }
76 | #baguetteBox-slider.bounce-from-left {
77 | -webkit-animation: bounceFromLeft .4s ease-out;
78 | animation: bounceFromLeft .4s ease-out; }
79 |
80 | @-webkit-keyframes bounceFromRight {
81 | 0% {
82 | margin-left: 0; }
83 | 50% {
84 | margin-left: -30px; }
85 | 100% {
86 | margin-left: 0; } }
87 |
88 | @keyframes bounceFromRight {
89 | 0% {
90 | margin-left: 0; }
91 | 50% {
92 | margin-left: -30px; }
93 | 100% {
94 | margin-left: 0; } }
95 |
96 | @-webkit-keyframes bounceFromLeft {
97 | 0% {
98 | margin-left: 0; }
99 | 50% {
100 | margin-left: 30px; }
101 | 100% {
102 | margin-left: 0; } }
103 |
104 | @keyframes bounceFromLeft {
105 | 0% {
106 | margin-left: 0; }
107 | 50% {
108 | margin-left: 30px; }
109 | 100% {
110 | margin-left: 0; } }
111 |
112 | .baguetteBox-button#next-button, .baguetteBox-button#previous-button {
113 | top: 50%;
114 | top: calc(50% - 30px);
115 | width: 44px;
116 | height: 60px; }
117 |
118 | .baguetteBox-button {
119 | position: absolute;
120 | cursor: pointer;
121 | outline: none;
122 | padding: 0;
123 | margin: 0;
124 | border: 0;
125 | -moz-border-radius: 15%;
126 | border-radius: 15%;
127 | background-color: #323232;
128 | background-color: rgba(50, 50, 50, 0.5);
129 | color: #ddd;
130 | font: 1.6em sans-serif;
131 | -webkit-transition: background-color .4s ease;
132 | transition: background-color .4s ease; }
133 | .baguetteBox-button:focus, .baguetteBox-button:hover {
134 | background-color: rgba(50, 50, 50, 0.9); }
135 | .baguetteBox-button#next-button {
136 | right: 2%; }
137 | .baguetteBox-button#previous-button {
138 | left: 2%; }
139 | .baguetteBox-button#close-button {
140 | top: 20px;
141 | right: 2%;
142 | right: calc(2% + 6px);
143 | width: 30px;
144 | height: 30px; }
145 | .baguetteBox-button svg {
146 | position: absolute;
147 | left: 0;
148 | top: 0; }
149 |
150 | /*
151 | Preloader
152 | Borrowed from http://tobiasahlin.com/spinkit/
153 | */
154 | .baguetteBox-spinner {
155 | width: 40px;
156 | height: 40px;
157 | display: inline-block;
158 | position: absolute;
159 | top: 50%;
160 | left: 50%;
161 | margin-top: -20px;
162 | margin-left: -20px; }
163 |
164 | .baguetteBox-double-bounce1,
165 | .baguetteBox-double-bounce2 {
166 | width: 100%;
167 | height: 100%;
168 | -moz-border-radius: 50%;
169 | border-radius: 50%;
170 | background-color: #fff;
171 | opacity: .6;
172 | position: absolute;
173 | top: 0;
174 | left: 0;
175 | -webkit-animation: bounce 2s infinite ease-in-out;
176 | animation: bounce 2s infinite ease-in-out; }
177 |
178 | .baguetteBox-double-bounce2 {
179 | -webkit-animation-delay: -1s;
180 | animation-delay: -1s; }
181 |
182 | @-webkit-keyframes bounce {
183 | 0%, 100% {
184 | -webkit-transform: scale(0);
185 | transform: scale(0); }
186 | 50% {
187 | -webkit-transform: scale(1);
188 | transform: scale(1); } }
189 |
190 | @keyframes bounce {
191 | 0%, 100% {
192 | -webkit-transform: scale(0);
193 | -moz-transform: scale(0);
194 | transform: scale(0); }
195 | 50% {
196 | -webkit-transform: scale(1);
197 | -moz-transform: scale(1);
198 | transform: scale(1); } }
199 |
--------------------------------------------------------------------------------
/assets/src/styles/_external/milligram.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Milligram v1.3.0
3 | * https://milligram.github.io
4 | *
5 | * Copyright (c) 2017 CJ Patoilo
6 | * Licensed under the MIT license
7 | */
8 |
9 | *,
10 | *:after,
11 | *:before {
12 | box-sizing: inherit;
13 | }
14 |
15 | html {
16 | box-sizing: border-box;
17 | font-size: 62.5%;
18 | }
19 |
20 | body {
21 | color: #606c76;
22 | font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
23 | font-size: 1.6em;
24 | font-weight: 300;
25 | letter-spacing: .01em;
26 | line-height: 1.6;
27 | }
28 |
29 | blockquote {
30 | border-left: 0.3rem solid #d1d1d1;
31 | margin-left: 0;
32 | margin-right: 0;
33 | padding: 1rem 1.5rem;
34 | }
35 |
36 | blockquote *:last-child {
37 | margin-bottom: 0;
38 | }
39 |
40 | .button,
41 | button,
42 | input[type='button'],
43 | input[type='reset'],
44 | input[type='submit'] {
45 | background-color: #9b4dca;
46 | border: 0.1rem solid #9b4dca;
47 | border-radius: .4rem;
48 | color: #fff;
49 | cursor: pointer;
50 | display: inline-block;
51 | font-size: 1.1rem;
52 | font-weight: 700;
53 | height: 3.8rem;
54 | letter-spacing: .1rem;
55 | line-height: 3.8rem;
56 | padding: 0 3.0rem;
57 | text-align: center;
58 | text-decoration: none;
59 | text-transform: uppercase;
60 | white-space: nowrap;
61 | }
62 |
63 | .button:focus, .button:hover,
64 | button:focus,
65 | button:hover,
66 | input[type='button']:focus,
67 | input[type='button']:hover,
68 | input[type='reset']:focus,
69 | input[type='reset']:hover,
70 | input[type='submit']:focus,
71 | input[type='submit']:hover {
72 | background-color: #606c76;
73 | border-color: #606c76;
74 | color: #fff;
75 | outline: 0;
76 | }
77 |
78 | .button[disabled],
79 | button[disabled],
80 | input[type='button'][disabled],
81 | input[type='reset'][disabled],
82 | input[type='submit'][disabled] {
83 | cursor: default;
84 | opacity: .5;
85 | }
86 |
87 | .button[disabled]:focus, .button[disabled]:hover,
88 | button[disabled]:focus,
89 | button[disabled]:hover,
90 | input[type='button'][disabled]:focus,
91 | input[type='button'][disabled]:hover,
92 | input[type='reset'][disabled]:focus,
93 | input[type='reset'][disabled]:hover,
94 | input[type='submit'][disabled]:focus,
95 | input[type='submit'][disabled]:hover {
96 | background-color: #9b4dca;
97 | border-color: #9b4dca;
98 | }
99 |
100 | .button.button-outline,
101 | button.button-outline,
102 | input[type='button'].button-outline,
103 | input[type='reset'].button-outline,
104 | input[type='submit'].button-outline {
105 | background-color: transparent;
106 | color: #9b4dca;
107 | }
108 |
109 | .button.button-outline:focus, .button.button-outline:hover,
110 | button.button-outline:focus,
111 | button.button-outline:hover,
112 | input[type='button'].button-outline:focus,
113 | input[type='button'].button-outline:hover,
114 | input[type='reset'].button-outline:focus,
115 | input[type='reset'].button-outline:hover,
116 | input[type='submit'].button-outline:focus,
117 | input[type='submit'].button-outline:hover {
118 | background-color: transparent;
119 | border-color: #606c76;
120 | color: #606c76;
121 | }
122 |
123 | .button.button-outline[disabled]:focus, .button.button-outline[disabled]:hover,
124 | button.button-outline[disabled]:focus,
125 | button.button-outline[disabled]:hover,
126 | input[type='button'].button-outline[disabled]:focus,
127 | input[type='button'].button-outline[disabled]:hover,
128 | input[type='reset'].button-outline[disabled]:focus,
129 | input[type='reset'].button-outline[disabled]:hover,
130 | input[type='submit'].button-outline[disabled]:focus,
131 | input[type='submit'].button-outline[disabled]:hover {
132 | border-color: inherit;
133 | color: #9b4dca;
134 | }
135 |
136 | .button.button-clear,
137 | button.button-clear,
138 | input[type='button'].button-clear,
139 | input[type='reset'].button-clear,
140 | input[type='submit'].button-clear {
141 | background-color: transparent;
142 | border-color: transparent;
143 | color: #9b4dca;
144 | }
145 |
146 | .button.button-clear:focus, .button.button-clear:hover,
147 | button.button-clear:focus,
148 | button.button-clear:hover,
149 | input[type='button'].button-clear:focus,
150 | input[type='button'].button-clear:hover,
151 | input[type='reset'].button-clear:focus,
152 | input[type='reset'].button-clear:hover,
153 | input[type='submit'].button-clear:focus,
154 | input[type='submit'].button-clear:hover {
155 | background-color: transparent;
156 | border-color: transparent;
157 | color: #606c76;
158 | }
159 |
160 | .button.button-clear[disabled]:focus, .button.button-clear[disabled]:hover,
161 | button.button-clear[disabled]:focus,
162 | button.button-clear[disabled]:hover,
163 | input[type='button'].button-clear[disabled]:focus,
164 | input[type='button'].button-clear[disabled]:hover,
165 | input[type='reset'].button-clear[disabled]:focus,
166 | input[type='reset'].button-clear[disabled]:hover,
167 | input[type='submit'].button-clear[disabled]:focus,
168 | input[type='submit'].button-clear[disabled]:hover {
169 | color: #9b4dca;
170 | }
171 |
172 | code {
173 | background: #f4f5f6;
174 | border-radius: .4rem;
175 | font-size: 86%;
176 | margin: 0 .2rem;
177 | padding: .2rem .5rem;
178 | white-space: nowrap;
179 | }
180 |
181 | pre {
182 | background: #f4f5f6;
183 | border-left: 0.3rem solid #9b4dca;
184 | overflow-y: hidden;
185 | }
186 |
187 | pre > code {
188 | border-radius: 0;
189 | display: block;
190 | padding: 1rem 1.5rem;
191 | white-space: pre;
192 | }
193 |
194 | hr {
195 | border: 0;
196 | border-top: 0.1rem solid #f4f5f6;
197 | margin: 3.0rem 0;
198 | }
199 |
200 | input[type='email'],
201 | input[type='number'],
202 | input[type='password'],
203 | input[type='search'],
204 | input[type='tel'],
205 | input[type='text'],
206 | input[type='url'],
207 | textarea,
208 | select {
209 | -webkit-appearance: none;
210 | -moz-appearance: none;
211 | appearance: none;
212 | background-color: transparent;
213 | border: 0.1rem solid #d1d1d1;
214 | border-radius: .4rem;
215 | box-shadow: none;
216 | box-sizing: inherit;
217 | height: 3.8rem;
218 | padding: .6rem 1.0rem;
219 | width: 100%;
220 | }
221 |
222 | input[type='email']:focus,
223 | input[type='number']:focus,
224 | input[type='password']:focus,
225 | input[type='search']:focus,
226 | input[type='tel']:focus,
227 | input[type='text']:focus,
228 | input[type='url']:focus,
229 | textarea:focus,
230 | select:focus {
231 | border-color: #9b4dca;
232 | outline: 0;
233 | }
234 |
235 | select {
236 | background: url('data:image/svg+xml;utf8, ') center right no-repeat;
237 | padding-right: 3.0rem;
238 | }
239 |
240 | select:focus {
241 | background-image: url('data:image/svg+xml;utf8, ');
242 | }
243 |
244 | textarea {
245 | min-height: 6.5rem;
246 | }
247 |
248 | label,
249 | legend {
250 | display: block;
251 | font-size: 1.6rem;
252 | font-weight: 700;
253 | margin-bottom: .5rem;
254 | }
255 |
256 | fieldset {
257 | border-width: 0;
258 | padding: 0;
259 | }
260 |
261 | input[type='checkbox'],
262 | input[type='radio'] {
263 | display: inline;
264 | }
265 |
266 | .label-inline {
267 | display: inline-block;
268 | font-weight: normal;
269 | margin-left: .5rem;
270 | }
271 |
272 | .container {
273 | margin: 0 auto;
274 | max-width: 112.0rem;
275 | padding: 0 2.0rem;
276 | position: relative;
277 | width: 100%;
278 | }
279 |
280 | .row {
281 | display: flex;
282 | flex-direction: column;
283 | padding: 0;
284 | width: 100%;
285 | }
286 |
287 | .row.row-no-padding {
288 | padding: 0;
289 | }
290 |
291 | .row.row-no-padding > .column {
292 | padding: 0;
293 | }
294 |
295 | .row.row-wrap {
296 | flex-wrap: wrap;
297 | }
298 |
299 | .row.row-top {
300 | align-items: flex-start;
301 | }
302 |
303 | .row.row-bottom {
304 | align-items: flex-end;
305 | }
306 |
307 | .row.row-center {
308 | align-items: center;
309 | }
310 |
311 | .row.row-stretch {
312 | align-items: stretch;
313 | }
314 |
315 | .row.row-baseline {
316 | align-items: baseline;
317 | }
318 |
319 | .row .column {
320 | display: block;
321 | flex: 1 1 auto;
322 | margin-left: 0;
323 | max-width: 100%;
324 | width: 100%;
325 | }
326 |
327 | .row .column.column-offset-10 {
328 | margin-left: 10%;
329 | }
330 |
331 | .row .column.column-offset-20 {
332 | margin-left: 20%;
333 | }
334 |
335 | .row .column.column-offset-25 {
336 | margin-left: 25%;
337 | }
338 |
339 | .row .column.column-offset-33, .row .column.column-offset-34 {
340 | margin-left: 33.3333%;
341 | }
342 |
343 | .row .column.column-offset-50 {
344 | margin-left: 50%;
345 | }
346 |
347 | .row .column.column-offset-66, .row .column.column-offset-67 {
348 | margin-left: 66.6666%;
349 | }
350 |
351 | .row .column.column-offset-75 {
352 | margin-left: 75%;
353 | }
354 |
355 | .row .column.column-offset-80 {
356 | margin-left: 80%;
357 | }
358 |
359 | .row .column.column-offset-90 {
360 | margin-left: 90%;
361 | }
362 |
363 | .row .column.column-10 {
364 | flex: 0 0 10%;
365 | max-width: 10%;
366 | }
367 |
368 | .row .column.column-20 {
369 | flex: 0 0 20%;
370 | max-width: 20%;
371 | }
372 |
373 | .row .column.column-25 {
374 | flex: 0 0 25%;
375 | max-width: 25%;
376 | }
377 |
378 | .row .column.column-33, .row .column.column-34 {
379 | flex: 0 0 33.3333%;
380 | max-width: 33.3333%;
381 | }
382 |
383 | .row .column.column-40 {
384 | flex: 0 0 40%;
385 | max-width: 40%;
386 | }
387 |
388 | .row .column.column-50 {
389 | flex: 0 0 50%;
390 | max-width: 50%;
391 | }
392 |
393 | .row .column.column-60 {
394 | flex: 0 0 60%;
395 | max-width: 60%;
396 | }
397 |
398 | .row .column.column-66, .row .column.column-67 {
399 | flex: 0 0 66.6666%;
400 | max-width: 66.6666%;
401 | }
402 |
403 | .row .column.column-75 {
404 | flex: 0 0 75%;
405 | max-width: 75%;
406 | }
407 |
408 | .row .column.column-80 {
409 | flex: 0 0 80%;
410 | max-width: 80%;
411 | }
412 |
413 | .row .column.column-90 {
414 | flex: 0 0 90%;
415 | max-width: 90%;
416 | }
417 |
418 | .row .column .column-top {
419 | align-self: flex-start;
420 | }
421 |
422 | .row .column .column-bottom {
423 | align-self: flex-end;
424 | }
425 |
426 | .row .column .column-center {
427 | -ms-grid-row-align: center;
428 | align-self: center;
429 | }
430 |
431 | @media (min-width: 40rem) {
432 | .row {
433 | flex-direction: row;
434 | margin-left: -1.0rem;
435 | width: calc(100% + 2.0rem);
436 | }
437 | .row .column {
438 | margin-bottom: inherit;
439 | padding: 0 1.0rem;
440 | }
441 | }
442 |
443 | a {
444 | color: #9b4dca;
445 | text-decoration: none;
446 | }
447 |
448 | a:focus, a:hover {
449 | color: #606c76;
450 | }
451 |
452 | dl,
453 | ol,
454 | ul {
455 | list-style: none;
456 | margin-top: 0;
457 | padding-left: 0;
458 | }
459 |
460 | dl dl,
461 | dl ol,
462 | dl ul,
463 | ol dl,
464 | ol ol,
465 | ol ul,
466 | ul dl,
467 | ul ol,
468 | ul ul {
469 | font-size: 90%;
470 | margin: 1.5rem 0 1.5rem 3.0rem;
471 | }
472 |
473 | ol {
474 | list-style: decimal inside;
475 | }
476 |
477 | ul {
478 | list-style: circle inside;
479 | }
480 |
481 | .button,
482 | button,
483 | dd,
484 | dt,
485 | li {
486 | margin-bottom: 1.0rem;
487 | }
488 |
489 | fieldset,
490 | input,
491 | select,
492 | textarea {
493 | margin-bottom: 1.5rem;
494 | }
495 |
496 | blockquote,
497 | dl,
498 | figure,
499 | form,
500 | ol,
501 | p,
502 | pre,
503 | table,
504 | ul {
505 | margin-bottom: 2.5rem;
506 | }
507 |
508 | table {
509 | border-spacing: 0;
510 | width: 100%;
511 | }
512 |
513 | td,
514 | th {
515 | border-bottom: 0.1rem solid #e1e1e1;
516 | padding: 1.2rem 1.5rem;
517 | text-align: left;
518 | }
519 |
520 | td:first-child,
521 | th:first-child {
522 | padding-left: 0;
523 | }
524 |
525 | td:last-child,
526 | th:last-child {
527 | padding-right: 0;
528 | }
529 |
530 | b,
531 | strong {
532 | font-weight: bold;
533 | }
534 |
535 | p {
536 | margin-top: 0;
537 | }
538 |
539 | h1,
540 | h2,
541 | h3,
542 | h4,
543 | h5,
544 | h6 {
545 | font-weight: 300;
546 | letter-spacing: -.1rem;
547 | margin-bottom: 2.0rem;
548 | margin-top: 0;
549 | }
550 |
551 | h1 {
552 | font-size: 4.6rem;
553 | line-height: 1.2;
554 | }
555 |
556 | h2 {
557 | font-size: 3.6rem;
558 | line-height: 1.25;
559 | }
560 |
561 | h3 {
562 | font-size: 2.8rem;
563 | line-height: 1.3;
564 | }
565 |
566 | h4 {
567 | font-size: 2.2rem;
568 | letter-spacing: -.08rem;
569 | line-height: 1.35;
570 | }
571 |
572 | h5 {
573 | font-size: 1.8rem;
574 | letter-spacing: -.05rem;
575 | line-height: 1.5;
576 | }
577 |
578 | h6 {
579 | font-size: 1.6rem;
580 | letter-spacing: 0;
581 | line-height: 1.4;
582 | }
583 |
584 | img {
585 | max-width: 100%;
586 | }
587 |
588 | .clearfix:after {
589 | clear: both;
590 | content: ' ';
591 | display: table;
592 | }
593 |
594 | .float-left {
595 | float: left;
596 | }
597 |
598 | .float-right {
599 | float: right;
600 | }
601 |
602 | /*# sourceMappingURL=milligram.css.map */
--------------------------------------------------------------------------------
/assets/src/styles/_external/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
2 |
3 | /* Document
4 | ========================================================================== */
5 |
6 | /**
7 | * 1. Correct the line height in all browsers.
8 | * 2. Prevent adjustments of font size after orientation changes in iOS.
9 | */
10 |
11 | html {
12 | line-height: 1.15; /* 1 */
13 | -webkit-text-size-adjust: 100%; /* 2 */
14 | }
15 |
16 | /* Sections
17 | ========================================================================== */
18 |
19 | /**
20 | * Remove the margin in all browsers.
21 | */
22 |
23 | body {
24 | margin: 0;
25 | }
26 |
27 | /**
28 | * Correct the font size and margin on `h1` elements within `section` and
29 | * `article` contexts in Chrome, Firefox, and Safari.
30 | */
31 |
32 | h1 {
33 | font-size: 2em;
34 | margin: 0.67em 0;
35 | }
36 |
37 | /* Grouping content
38 | ========================================================================== */
39 |
40 | /**
41 | * 1. Add the correct box sizing in Firefox.
42 | * 2. Show the overflow in Edge and IE.
43 | */
44 |
45 | hr {
46 | box-sizing: content-box; /* 1 */
47 | height: 0; /* 1 */
48 | overflow: visible; /* 2 */
49 | }
50 |
51 | /**
52 | * 1. Correct the inheritance and scaling of font size in all browsers.
53 | * 2. Correct the odd `em` font sizing in all browsers.
54 | */
55 |
56 | pre {
57 | font-family: monospace, monospace; /* 1 */
58 | font-size: 1em; /* 2 */
59 | }
60 |
61 | /* Text-level semantics
62 | ========================================================================== */
63 |
64 | /**
65 | * Remove the gray background on active links in IE 10.
66 | */
67 |
68 | a {
69 | background-color: transparent;
70 | }
71 |
72 | /**
73 | * 1. Remove the bottom border in Chrome 57-
74 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
75 | */
76 |
77 | abbr[title] {
78 | border-bottom: none; /* 1 */
79 | text-decoration: underline; /* 2 */
80 | text-decoration: underline dotted; /* 2 */
81 | }
82 |
83 | /**
84 | * Add the correct font weight in Chrome, Edge, and Safari.
85 | */
86 |
87 | b,
88 | strong {
89 | font-weight: bolder;
90 | }
91 |
92 | /**
93 | * 1. Correct the inheritance and scaling of font size in all browsers.
94 | * 2. Correct the odd `em` font sizing in all browsers.
95 | */
96 |
97 | code,
98 | kbd,
99 | samp {
100 | font-family: monospace, monospace; /* 1 */
101 | font-size: 1em; /* 2 */
102 | }
103 |
104 | /**
105 | * Add the correct font size in all browsers.
106 | */
107 |
108 | small {
109 | font-size: 80%;
110 | }
111 |
112 | /**
113 | * Prevent `sub` and `sup` elements from affecting the line height in
114 | * all browsers.
115 | */
116 |
117 | sub,
118 | sup {
119 | font-size: 75%;
120 | line-height: 0;
121 | position: relative;
122 | vertical-align: baseline;
123 | }
124 |
125 | sub {
126 | bottom: -0.25em;
127 | }
128 |
129 | sup {
130 | top: -0.5em;
131 | }
132 |
133 | /* Embedded content
134 | ========================================================================== */
135 |
136 | /**
137 | * Remove the border on images inside links in IE 10.
138 | */
139 |
140 | img {
141 | border-style: none;
142 | }
143 |
144 | /* Forms
145 | ========================================================================== */
146 |
147 | /**
148 | * 1. Change the font styles in all browsers.
149 | * 2. Remove the margin in Firefox and Safari.
150 | */
151 |
152 | button,
153 | input,
154 | optgroup,
155 | select,
156 | textarea {
157 | font-family: inherit; /* 1 */
158 | font-size: 100%; /* 1 */
159 | line-height: 1.15; /* 1 */
160 | margin: 0; /* 2 */
161 | }
162 |
163 | /**
164 | * Show the overflow in IE.
165 | * 1. Show the overflow in Edge.
166 | */
167 |
168 | button,
169 | input { /* 1 */
170 | overflow: visible;
171 | }
172 |
173 | /**
174 | * Remove the inheritance of text transform in Edge, Firefox, and IE.
175 | * 1. Remove the inheritance of text transform in Firefox.
176 | */
177 |
178 | button,
179 | select { /* 1 */
180 | text-transform: none;
181 | }
182 |
183 | /**
184 | * Correct the inability to style clickable types in iOS and Safari.
185 | */
186 |
187 | button,
188 | [type="button"],
189 | [type="reset"],
190 | [type="submit"] {
191 | -webkit-appearance: button;
192 | }
193 |
194 | /**
195 | * Remove the inner border and padding in Firefox.
196 | */
197 |
198 | button::-moz-focus-inner,
199 | [type="button"]::-moz-focus-inner,
200 | [type="reset"]::-moz-focus-inner,
201 | [type="submit"]::-moz-focus-inner {
202 | border-style: none;
203 | padding: 0;
204 | }
205 |
206 | /**
207 | * Restore the focus styles unset by the previous rule.
208 | */
209 |
210 | button:-moz-focusring,
211 | [type="button"]:-moz-focusring,
212 | [type="reset"]:-moz-focusring,
213 | [type="submit"]:-moz-focusring {
214 | outline: 1px dotted ButtonText;
215 | }
216 |
217 | /**
218 | * Correct the padding in Firefox.
219 | */
220 |
221 | fieldset {
222 | padding: 0.35em 0.75em 0.625em;
223 | }
224 |
225 | /**
226 | * 1. Correct the text wrapping in Edge and IE.
227 | * 2. Correct the color inheritance from `fieldset` elements in IE.
228 | * 3. Remove the padding so developers are not caught out when they zero out
229 | * `fieldset` elements in all browsers.
230 | */
231 |
232 | legend {
233 | box-sizing: border-box; /* 1 */
234 | color: inherit; /* 2 */
235 | display: table; /* 1 */
236 | max-width: 100%; /* 1 */
237 | padding: 0; /* 3 */
238 | white-space: normal; /* 1 */
239 | }
240 |
241 | /**
242 | * Add the correct vertical alignment in Chrome, Firefox, and Opera.
243 | */
244 |
245 | progress {
246 | vertical-align: baseline;
247 | }
248 |
249 | /**
250 | * Remove the default vertical scrollbar in IE 10+.
251 | */
252 |
253 | textarea {
254 | overflow: auto;
255 | }
256 |
257 | /**
258 | * 1. Add the correct box sizing in IE 10.
259 | * 2. Remove the padding in IE 10.
260 | */
261 |
262 | [type="checkbox"],
263 | [type="radio"] {
264 | box-sizing: border-box; /* 1 */
265 | padding: 0; /* 2 */
266 | }
267 |
268 | /**
269 | * Correct the cursor style of increment and decrement buttons in Chrome.
270 | */
271 |
272 | [type="number"]::-webkit-inner-spin-button,
273 | [type="number"]::-webkit-outer-spin-button {
274 | height: auto;
275 | }
276 |
277 | /**
278 | * 1. Correct the odd appearance in Chrome and Safari.
279 | * 2. Correct the outline style in Safari.
280 | */
281 |
282 | [type="search"] {
283 | -webkit-appearance: textfield; /* 1 */
284 | outline-offset: -2px; /* 2 */
285 | }
286 |
287 | /**
288 | * Remove the inner padding in Chrome and Safari on macOS.
289 | */
290 |
291 | [type="search"]::-webkit-search-decoration {
292 | -webkit-appearance: none;
293 | }
294 |
295 | /**
296 | * 1. Correct the inability to style clickable types in iOS and Safari.
297 | * 2. Change font properties to `inherit` in Safari.
298 | */
299 |
300 | ::-webkit-file-upload-button {
301 | -webkit-appearance: button; /* 1 */
302 | font: inherit; /* 2 */
303 | }
304 |
305 | /* Interactive
306 | ========================================================================== */
307 |
308 | /*
309 | * Add the correct display in Edge, IE 10+, and Firefox.
310 | */
311 |
312 | details {
313 | display: block;
314 | }
315 |
316 | /*
317 | * Add the correct display in all browsers.
318 | */
319 |
320 | summary {
321 | display: list-item;
322 | }
323 |
324 | /* Misc
325 | ========================================================================== */
326 |
327 | /**
328 | * Add the correct display in IE 10+.
329 | */
330 |
331 | template {
332 | display: none;
333 | }
334 |
335 | /**
336 | * Add the correct display in IE 10.
337 | */
338 |
339 | [hidden] {
340 | display: none;
341 | }
342 |
--------------------------------------------------------------------------------
/assets/src/styles/_settings.scss:
--------------------------------------------------------------------------------
1 | $breakpoint: 800px;
2 | $itemMargin: 2.5rem;
3 |
4 | $color-brilliant-azure: #39f;
5 | $color-bara-red: #f0506e;
6 | $color-black: #000;
7 | $color-pale-grey: #fefefe;
8 | $color-silver: #c0c0c0;
9 | $color-zhen-zhu-bai-pearl: #f8f8f8;
10 |
11 | $base-background-color: $color-pale-grey;
12 |
13 | $navbar-background-color: $color-zhen-zhu-bai-pearl;
14 | $navbar-height: 5rem;
15 | $navbar-text-color: $color-black;
16 |
17 | $links-color: $color-brilliant-azure;
18 |
--------------------------------------------------------------------------------
/assets/src/styles/styles.scss:
--------------------------------------------------------------------------------
1 | @import "chroma_friendly";
2 | @import "settings";
3 | @import "_components/base";
4 | @import "_components/content";
5 | @import "_components/elements";
6 | @import "_components/footer";
7 | @import "_components/homepage";
8 | @import "_components/navbar";
9 |
--------------------------------------------------------------------------------
/exampleSite/config.toml:
--------------------------------------------------------------------------------
1 | baseURL = "https://example.com"
2 | defaultContentLanguage = "en"
3 | disqusShortname = "test"
4 | enableEmoji = true
5 | enableRobotsTXT = true
6 | googleAnalytics = ""
7 | languageCode = "en-us"
8 | pygmentsCodeFences = true
9 | pygmentsStyle = "native"
10 | pygmentsUseClasses = true
11 | theme = "simplicity"
12 | title = "Simplicity - Hugo theme"
13 | [author]
14 | gravatarEmail = "test@example.com"
15 | homepageText = "Simplicity"
16 | name = "Przemysław `eshlox` Kołodziejczyk"
17 | rss = "/posts/index.xml"
18 | [imaging]
19 | anchor = "smart"
20 | resampleFilter = "box"
21 | quality = 75
22 | [[menu.pages]]
23 | name = "Projects"
24 | weight = -100
25 | identifier = "projects"
26 | url = "/projects/"
27 | [[menu.pages]]
28 | name = "Photos"
29 | weight = -90
30 | identifier = "photos"
31 | url = "/photos/"
32 | [outputs]
33 | home = ["HTML"]
34 | page = ["HTML"]
35 | section = ["HTML", "RSS"]
36 | taxonomy = ["HTML", "RSS"]
37 | taxonomyTerm = ["HTML"]
38 | [params]
39 | adsenseClient = ''
40 | adsenseSlot = ''
41 | description = "A blog about everything."
42 | licence = "[Some Rights Reserved](http://creativecommons.org/licenses/by-sa/4.0/)."
43 | displayPostLanguage = true
44 | [permalinks]
45 | posts = "/:year/:month/:day/:slug/"
46 | [pygmentsOptions]
47 | linenos = false
48 |
--------------------------------------------------------------------------------
/exampleSite/content/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Homepage
3 | language: en
4 | slug: /
5 | ---
6 |
7 | # Simplicity, Hugo theme.
8 |
9 | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
10 |
11 | [Posts](/posts/) • [Categories](/categories/) • [Tags](/tags/)
12 |
13 | [Photos](/photos/) • [Projects](/projects/)
14 |
--------------------------------------------------------------------------------
/exampleSite/content/categories/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Categories
3 | language: en
4 | slug: /categories/
5 | ---
6 |
--------------------------------------------------------------------------------
/exampleSite/content/media/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Media Folder
3 | ---
4 |
--------------------------------------------------------------------------------
/exampleSite/content/media/image-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eshlox/simplicity/8696b3b61946d89bb0cd1fc1920940544f1758e9/exampleSite/content/media/image-1.jpg
--------------------------------------------------------------------------------
/exampleSite/content/media/video.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eshlox/simplicity/8696b3b61946d89bb0cd1fc1920940544f1758e9/exampleSite/content/media/video.mp4
--------------------------------------------------------------------------------
/exampleSite/content/photos.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Photos
3 | language: en
4 | slug: photos
5 | ---
6 |
7 | {{< image src="media/image-1.jpg" title="Photo by Ales Krivec on Unsplash" lightbox="true" >}}
8 |
9 | {{< image src="media/image-1.jpg" title="Photo by Ales Krivec on Unsplash" >}}
10 |
--------------------------------------------------------------------------------
/exampleSite/content/posts/2014/goisforlovers.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "(Hu)go Template Primer"
3 | description = ""
4 | tags = [
5 | "go",
6 | "golang",
7 | "templates",
8 | "themes",
9 | "development",
10 | ]
11 | date = "2014-04-02"
12 | categories = [
13 | "Development",
14 | "golang",
15 | ]
16 | menu = "main"
17 | +++
18 |
19 | Hugo uses the excellent [go][] [html/template][gohtmltemplate] library for
20 | its template engine. It is an extremely lightweight engine that provides a very
21 | small amount of logic. In our experience that it is just the right amount of
22 | logic to be able to create a good static website. If you have used other
23 | template systems from different languages or frameworks you will find a lot of
24 | similarities in go templates.
25 |
26 | This document is a brief primer on using go templates. The [go docs][gohtmltemplate]
27 | provide more details.
28 |
29 | ## Introduction to Go Templates
30 |
31 | Go templates provide an extremely simple template language. It adheres to the
32 | belief that only the most basic of logic belongs in the template or view layer.
33 | One consequence of this simplicity is that go templates parse very quickly.
34 |
35 | A unique characteristic of go templates is they are content aware. Variables and
36 | content will be sanitized depending on the context of where they are used. More
37 | details can be found in the [go docs][gohtmltemplate].
38 |
39 | ## Basic Syntax
40 |
41 | Go lang templates are html files with the addition of variables and
42 | functions.
43 |
44 | **Go variables and functions are accessible within {{ }}**
45 |
46 | Accessing a predefined variable "foo":
47 |
48 | {{ foo }}
49 |
50 | **Parameters are separated using spaces**
51 |
52 | Calling the add function with input of 1, 2:
53 |
54 | {{ add 1 2 }}
55 |
56 | **Methods and fields are accessed via dot notation**
57 |
58 | Accessing the Page Parameter "bar"
59 |
60 | {{ .Params.bar }}
61 |
62 | **Parentheses can be used to group items together**
63 |
64 | {{ if or (isset .Params "alt") (isset .Params "caption") }} Caption {{ end }}
65 |
66 |
67 | ## Variables
68 |
69 | Each go template has a struct (object) made available to it. In hugo each
70 | template is passed either a page or a node struct depending on which type of
71 | page you are rendering. More details are available on the
72 | [variables](/layout/variables) page.
73 |
74 | A variable is accessed by referencing the variable name.
75 |
76 | {{ .Title }}
77 |
78 | Variables can also be defined and referenced.
79 |
80 | {{ $address := "123 Main St."}}
81 | {{ $address }}
82 |
83 |
84 | ## Functions
85 |
86 | Go template ship with a few functions which provide basic functionality. The go
87 | template system also provides a mechanism for applications to extend the
88 | available functions with their own. [Hugo template
89 | functions](/layout/functions) provide some additional functionality we believe
90 | are useful for building websites. Functions are called by using their name
91 | followed by the required parameters separated by spaces. Template
92 | functions cannot be added without recompiling hugo.
93 |
94 | **Example:**
95 |
96 | {{ add 1 2 }}
97 |
98 | ## Includes
99 |
100 | When including another template you will pass to it the data it will be
101 | able to access. To pass along the current context please remember to
102 | include a trailing dot. The templates location will always be starting at
103 | the /layout/ directory within Hugo.
104 |
105 | **Example:**
106 |
107 | {{ template "chrome/header.html" . }}
108 |
109 |
110 | ## Logic
111 |
112 | Go templates provide the most basic iteration and conditional logic.
113 |
114 | ### Iteration
115 |
116 | Just like in go, the go templates make heavy use of range to iterate over
117 | a map, array or slice. The following are different examples of how to use
118 | range.
119 |
120 | **Example 1: Using Context**
121 |
122 | {{ range array }}
123 | {{ . }}
124 | {{ end }}
125 |
126 | **Example 2: Declaring value variable name**
127 |
128 | {{range $element := array}}
129 | {{ $element }}
130 | {{ end }}
131 |
132 | **Example 2: Declaring key and value variable name**
133 |
134 | {{range $index, $element := array}}
135 | {{ $index }}
136 | {{ $element }}
137 | {{ end }}
138 |
139 | ### Conditionals
140 |
141 | If, else, with, or, & and provide the framework for handling conditional
142 | logic in Go Templates. Like range, each statement is closed with `end`.
143 |
144 |
145 | Go Templates treat the following values as false:
146 |
147 | * false
148 | * 0
149 | * any array, slice, map, or string of length zero
150 |
151 | **Example 1: If**
152 |
153 | {{ if isset .Params "title" }}{{ index .Params "title" }} {{ end }}
154 |
155 | **Example 2: If -> Else**
156 |
157 | {{ if isset .Params "alt" }}
158 | {{ index .Params "alt" }}
159 | {{else}}
160 | {{ index .Params "caption" }}
161 | {{ end }}
162 |
163 | **Example 3: And & Or**
164 |
165 | {{ if and (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}}
166 |
167 | **Example 4: With**
168 |
169 | An alternative way of writing "if" and then referencing the same value
170 | is to use "with" instead. With rebinds the context `.` within its scope,
171 | and skips the block if the variable is absent.
172 |
173 | The first example above could be simplified as:
174 |
175 | {{ with .Params.title }}{{ . }} {{ end }}
176 |
177 | **Example 5: If -> Else If**
178 |
179 | {{ if isset .Params "alt" }}
180 | {{ index .Params "alt" }}
181 | {{ else if isset .Params "caption" }}
182 | {{ index .Params "caption" }}
183 | {{ end }}
184 |
185 | ## Pipes
186 |
187 | One of the most powerful components of go templates is the ability to
188 | stack actions one after another. This is done by using pipes. Borrowed
189 | from unix pipes, the concept is simple, each pipeline's output becomes the
190 | input of the following pipe.
191 |
192 | Because of the very simple syntax of go templates, the pipe is essential
193 | to being able to chain together function calls. One limitation of the
194 | pipes is that they only can work with a single value and that value
195 | becomes the last parameter of the next pipeline.
196 |
197 | A few simple examples should help convey how to use the pipe.
198 |
199 | **Example 1 :**
200 |
201 | {{ if eq 1 1 }} Same {{ end }}
202 |
203 | is the same as
204 |
205 | {{ eq 1 1 | if }} Same {{ end }}
206 |
207 | It does look odd to place the if at the end, but it does provide a good
208 | illustration of how to use the pipes.
209 |
210 | **Example 2 :**
211 |
212 | {{ index .Params "disqus_url" | html }}
213 |
214 | Access the page parameter called "disqus_url" and escape the HTML.
215 |
216 | **Example 3 :**
217 |
218 | {{ if or (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}}
219 | Stuff Here
220 | {{ end }}
221 |
222 | Could be rewritten as
223 |
224 | {{ isset .Params "caption" | or isset .Params "title" | or isset .Params "attr" | if }}
225 | Stuff Here
226 | {{ end }}
227 |
228 |
229 | ## Context (aka. the dot)
230 |
231 | The most easily overlooked concept to understand about go templates is that {{ . }}
232 | always refers to the current context. In the top level of your template this
233 | will be the data set made available to it. Inside of a iteration it will have
234 | the value of the current item. When inside of a loop the context has changed. .
235 | will no longer refer to the data available to the entire page. If you need to
236 | access this from within the loop you will likely want to set it to a variable
237 | instead of depending on the context.
238 |
239 | **Example:**
240 |
241 | {{ $title := .Site.Title }}
242 | {{ range .Params.tags }}
243 | {{ . }} - {{ $title }}
244 | {{ end }}
245 |
246 | Notice how once we have entered the loop the value of {{ . }} has changed. We
247 | have defined a variable outside of the loop so we have access to it from within
248 | the loop.
249 |
250 | # Hugo Parameters
251 |
252 | Hugo provides the option of passing values to the template language
253 | through the site configuration (for sitewide values), or through the meta
254 | data of each specific piece of content. You can define any values of any
255 | type (supported by your front matter/config format) and use them however
256 | you want to inside of your templates.
257 |
258 |
259 | ## Using Content (page) Parameters
260 |
261 | In each piece of content you can provide variables to be used by the
262 | templates. This happens in the [front matter](/content/front-matter).
263 |
264 | An example of this is used in this documentation site. Most of the pages
265 | benefit from having the table of contents provided. Sometimes the TOC just
266 | doesn't make a lot of sense. We've defined a variable in our front matter
267 | of some pages to turn off the TOC from being displayed.
268 |
269 | Here is the example front matter:
270 |
271 | ```
272 | ---
273 | title: "Permalinks"
274 | date: "2013-11-18"
275 | aliases:
276 | - "/doc/permalinks/"
277 | groups: ["extras"]
278 | groups_weight: 30
279 | notoc: true
280 | ---
281 | ```
282 |
283 | Here is the corresponding code inside of the template:
284 |
285 | {{ if not .Params.notoc }}
286 |
287 | {{ .TableOfContents }}
288 |
289 | {{ end }}
290 |
291 |
292 |
293 | ## Using Site (config) Parameters
294 | In your top-level configuration file (eg, `config.yaml`) you can define site
295 | parameters, which are values which will be available to you in chrome.
296 |
297 | For instance, you might declare:
298 |
299 | ```yaml
300 | params:
301 | CopyrightHTML: "Copyright © 2013 John Doe. All Rights Reserved."
302 | TwitterUser: "spf13"
303 | SidebarRecentLimit: 5
304 | ```
305 |
306 | Within a footer layout, you might then declare a `