mirror of
https://github.com/GenZmeY/casper-i18n.git
synced 2025-07-12 16:56:06 +00:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
475c015fa2 | |||
79ebbd50a3 | |||
a22dda9694 | |||
3c2347c7f9 | |||
f695d69aeb | |||
d53b25bf5d | |||
bef56a2294 | |||
5ad6e1ed1f |
2
assets/built/infinitescroll.js
Normal file
2
assets/built/infinitescroll.js
Normal file
@ -0,0 +1,2 @@
|
||||
!function(n,t){var r=t.querySelector("link[rel=next]");if(r){var i=t.querySelector(".post-feed");if(i){var o=300,s=!1,l=!1,c=n.scrollY,u=n.innerHeight,d=t.documentElement.scrollHeight;n.addEventListener("scroll",a,{passive:!0}),n.addEventListener("resize",m),f()}}function v(){if(404===this.status)return n.removeEventListener("scroll",a),void n.removeEventListener("resize",m);this.response.querySelectorAll(".post-card").forEach(function(e){i.appendChild(e)});var e=this.response.querySelector("link[rel=next]");e?r.href=e.href:(n.removeEventListener("scroll",a),n.removeEventListener("resize",m)),d=t.documentElement.scrollHeight,l=s=!1}function e(){if(!l)if(c+u<=d-o)s=!1;else{l=!0;var e=new n.XMLHttpRequest;e.responseType="document",e.addEventListener("load",v),e.open("GET",r.href),e.send(null)}}function f(){s||n.requestAnimationFrame(e),s=!0}function a(){c=n.scrollY,f()}function m(){u=n.innerHeight,d=t.documentElement.scrollHeight,f()}}(window,document);
|
||||
//# sourceMappingURL=infinitescroll.js.map
|
1
assets/built/infinitescroll.js.map
Normal file
1
assets/built/infinitescroll.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"sources":["infinitescroll.js"],"names":["window","document","nextElement","querySelector","feedElement","buffer","ticking","loading","lastScrollY","scrollY","lastWindowHeight","innerHeight","lastDocumentHeight","documentElement","scrollHeight","addEventListener","onScroll","passive","onResize","requestTick","onPageLoad","this","status","removeEventListener","response","querySelectorAll","forEach","item","appendChild","resNextElement","href","onUpdate","xhr","XMLHttpRequest","responseType","open","send","requestAnimationFrame"],"mappings":"CAIA,SAAUA,EAAQC,GAEd,IAAIC,EAAcD,EAASE,cAAc,kBACzC,GAAKD,EAAL,CAGA,IAAIE,EAAcH,EAASE,cAAc,cACzC,GAAKC,EAAL,CAEA,IAAIC,EAAS,IAETC,GAAU,EACVC,GAAU,EAEVC,EAAcR,EAAOS,QACrBC,EAAmBV,EAAOW,YAC1BC,EAAqBX,EAASY,gBAAgBC,aAmElDd,EAAOe,iBAAiB,SAAUC,EAAU,CAAEC,SAAS,IACvDjB,EAAOe,iBAAiB,SAAUG,GAElCC,KApEA,SAASC,IACL,GAAoB,MAAhBC,KAAKC,OAGL,OAFAtB,EAAOuB,oBAAoB,SAAUP,QACrChB,EAAOuB,oBAAoB,SAAUL,GAKtBG,KAAKG,SAASC,iBAAiB,cACrCC,QAAQ,SAAUC,GAC3BvB,EAAYwB,YAAYD,KAI5B,IAAIE,EAAiBR,KAAKG,SAASrB,cAAc,kBAC7C0B,EACA3B,EAAY4B,KAAOD,EAAeC,MAElC9B,EAAOuB,oBAAoB,SAAUP,GACrChB,EAAOuB,oBAAoB,SAAUL,IAIzCN,EAAqBX,EAASY,gBAAgBC,aAE9CP,EADAD,GAAU,EAId,SAASyB,IAEL,IAAIxB,EAGJ,GAAIC,EAAcE,GAAoBE,EAAqBP,EACvDC,GAAU,MADd,CAKAC,GAAU,EAEV,IAAIyB,EAAM,IAAIhC,EAAOiC,eACrBD,EAAIE,aAAe,WAEnBF,EAAIjB,iBAAiB,OAAQK,GAE7BY,EAAIG,KAAK,MAAOjC,EAAY4B,MAC5BE,EAAII,KAAK,OAGb,SAASjB,IACLb,GAAWN,EAAOqC,sBAAsBN,GACxCzB,GAAU,EAGd,SAASU,IACLR,EAAcR,EAAOS,QACrBU,IAGJ,SAASD,IACLR,EAAmBV,EAAOW,YAC1BC,EAAqBX,EAASY,gBAAgBC,aAC9CK,KAhFR,CAuFGnB,OAAQC","file":"infinitescroll.js","sourcesContent":["/**\n * Infinite Scroll\n */\n\n(function(window, document) {\n // next link element\n var nextElement = document.querySelector('link[rel=next]');\n if (!nextElement) return;\n\n // post feed element\n var feedElement = document.querySelector('.post-feed');\n if (!feedElement) return;\n\n var buffer = 300;\n\n var ticking = false;\n var loading = false;\n\n var lastScrollY = window.scrollY;\n var lastWindowHeight = window.innerHeight;\n var lastDocumentHeight = document.documentElement.scrollHeight;\n\n function onPageLoad() {\n if (this.status === 404) {\n window.removeEventListener('scroll', onScroll);\n window.removeEventListener('resize', onResize);\n return;\n }\n\n // append contents\n var postElements = this.response.querySelectorAll('.post-card');\n postElements.forEach(function (item) {\n feedElement.appendChild(item);\n });\n\n // set next link\n var resNextElement = this.response.querySelector('link[rel=next]');\n if (resNextElement) {\n nextElement.href = resNextElement.href;\n } else {\n window.removeEventListener('scroll', onScroll);\n window.removeEventListener('resize', onResize);\n }\n\n // sync status\n lastDocumentHeight = document.documentElement.scrollHeight;\n ticking = false;\n loading = false;\n }\n\n function onUpdate() {\n // return if already loading\n if (loading) return;\n\n // return if not scroll to the bottom\n if (lastScrollY + lastWindowHeight <= lastDocumentHeight - buffer) {\n ticking = false;\n return;\n }\n\n loading = true;\n\n var xhr = new window.XMLHttpRequest();\n xhr.responseType = 'document';\n\n xhr.addEventListener('load', onPageLoad);\n\n xhr.open('GET', nextElement.href);\n xhr.send(null);\n }\n\n function requestTick() {\n ticking || window.requestAnimationFrame(onUpdate);\n ticking = true;\n }\n\n function onScroll() {\n lastScrollY = window.scrollY;\n requestTick();\n }\n\n function onResize() {\n lastWindowHeight = window.innerHeight;\n lastDocumentHeight = document.documentElement.scrollHeight;\n requestTick();\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n window.addEventListener('resize', onResize);\n\n requestTick();\n})(window, document);\n"],"sourceRoot":"/source/"}
|
2
assets/built/jquery.fitvids.js
Normal file
2
assets/built/jquery.fitvids.js
Normal file
@ -0,0 +1,2 @@
|
||||
!function(d){"use strict";d.fn.fitVids=function(t){var i={customSelector:null,ignore:null};if(!document.getElementById("fit-vids-style")){var e=document.head||document.getElementsByTagName("head")[0],r=document.createElement("div");r.innerHTML='<p>x</p><style id="fit-vids-style">.fluid-width-video-container{flex-grow: 1;width:100%;}.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}</style>',e.appendChild(r.childNodes[1])}return t&&d.extend(i,t),this.each(function(){var t=['iframe[src*="player.vimeo.com"]','iframe[src*="youtube.com"]','iframe[src*="youtube-nocookie.com"]','iframe[src*="kickstarter.com"][src*="video.html"]',"object","embed"];i.customSelector&&t.push(i.customSelector);var r=".fitvidsignore";i.ignore&&(r=r+", "+i.ignore);var e=d(this).find(t.join(","));(e=(e=e.not("object object")).not(r)).each(function(){var t=d(this);if(!(0<t.parents(r).length||"embed"===this.tagName.toLowerCase()&&t.parent("object").length||t.parent(".fluid-width-video-wrapper").length)){t.css("height")||t.css("width")||!isNaN(t.attr("height"))&&!isNaN(t.attr("width"))||(t.attr("height",9),t.attr("width",16));var e=("object"===this.tagName.toLowerCase()||t.attr("height")&&!isNaN(parseInt(t.attr("height"),10))?parseInt(t.attr("height"),10):t.height())/(isNaN(parseInt(t.attr("width"),10))?t.width():parseInt(t.attr("width"),10));if(!t.attr("name")){var i="fitvid"+d.fn.fitVids._count;t.attr("name",i),d.fn.fitVids._count++}t.wrap('<div class="fluid-width-video-container"><div class="fluid-width-video-wrapper"></div></div>').parent(".fluid-width-video-wrapper").css("padding-top",100*e+"%"),t.removeAttr("height").removeAttr("width")}})})},d.fn.fitVids._count=0}(window.jQuery||window.Zepto);
|
||||
//# sourceMappingURL=jquery.fitvids.js.map
|
1
assets/built/jquery.fitvids.js.map
Normal file
1
assets/built/jquery.fitvids.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -411,10 +411,10 @@ The knock-on effect of this is ugly browser-scroll bars at the bottom, so 80px o
|
||||
}
|
||||
|
||||
.post-card-image {
|
||||
width: auto;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background: var(--lightgrey) no-repeat center center;
|
||||
background-size: cover;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.post-card-content-link {
|
||||
@ -595,46 +595,48 @@ The knock-on effect of this is ugly browser-scroll bars at the bottom, so 80px o
|
||||
|
||||
/* Special Styling for home page grid (below):
|
||||
|
||||
The first (most recent) post in the list is styled to be bigger than the others and take over the full width of the grid to give it more emphasis. Wrapped in a media query to make sure this only happens on large viewports / desktop-ish devices.
|
||||
The first post in the list is styled to be bigger than the others and take over
|
||||
the full width of the grid to give it more emphasis. Wrapped in a media query to
|
||||
make sure this only happens on large viewports / desktop-ish devices.
|
||||
|
||||
*/
|
||||
|
||||
@media (min-width: 795px) {
|
||||
.home-template .post-feed .post-card:nth-child(6n+1):not(.no-image) {
|
||||
.post-card-large {
|
||||
flex: 1 1 100%;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.home-template .post-feed .post-card:nth-child(6n+1):not(.no-image) .post-card-image-link {
|
||||
.post-card-large .post-card-image-link {
|
||||
position: relative;
|
||||
flex: 1 1 auto;
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
|
||||
.home-template .post-feed .post-card:nth-child(6n+1):not(.no-image) .post-card-image {
|
||||
.post-card-large .post-card-image {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.home-template .post-feed .post-card:nth-child(6n+1):not(.no-image) .post-card-content {
|
||||
.post-card-large .post-card-content {
|
||||
flex: 0 1 357px;
|
||||
}
|
||||
|
||||
.home-template .post-feed .post-card:nth-child(6n+1):not(.no-image) h2 {
|
||||
.post-card-large h2 {
|
||||
font-size: 2.6rem;
|
||||
}
|
||||
|
||||
.home-template .post-feed .post-card:nth-child(6n+1):not(.no-image) p {
|
||||
.post-card-large p {
|
||||
font-size: 1.8rem;
|
||||
line-height: 1.55em;
|
||||
}
|
||||
|
||||
.home-template .post-feed .post-card:nth-child(6n+1):not(.no-image) .post-card-content-link {
|
||||
.post-card-large .post-card-content-link {
|
||||
padding: 30px 40px 0;
|
||||
}
|
||||
|
||||
.home-template .post-feed .post-card:nth-child(6n+1):not(.no-image) .post-card-meta {
|
||||
.post-card-large .post-card-meta {
|
||||
padding: 0 40px 30px;
|
||||
}
|
||||
}
|
||||
@ -709,22 +711,29 @@ The first (most recent) post in the list is styled to be bigger than the others
|
||||
|
||||
.post-full-image {
|
||||
margin: 0 -10vw -165px;
|
||||
height: 800px;
|
||||
background: var(--lightgrey) center center;
|
||||
background-size: cover;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.post-full-image img {
|
||||
width: 100%;
|
||||
height: 800px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
@media (max-width: 1170px) {
|
||||
.post-full-image {
|
||||
margin: 0 -4vw -100px;
|
||||
height: 600px;
|
||||
border-radius: 0;
|
||||
}
|
||||
.post-full-image img {
|
||||
height: 600px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.post-full-image {
|
||||
.post-full-image img {
|
||||
height: 400px;
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,78 @@
|
||||
/* global maxPages */
|
||||
/**
|
||||
* Infinite Scroll
|
||||
*/
|
||||
|
||||
(function(window, document) {
|
||||
// next link element
|
||||
var nextElement = document.querySelector('link[rel=next]');
|
||||
if (!nextElement) return;
|
||||
|
||||
// post feed element
|
||||
var feedElement = document.querySelector('.post-feed');
|
||||
if (!feedElement) return;
|
||||
|
||||
// Code snippet inspired by https://github.com/douglasrodrigues5/ghost-blog-infinite-scroll
|
||||
$(function ($) {
|
||||
var currentPage = 1;
|
||||
var pathname = window.location.pathname;
|
||||
var $document = $(document);
|
||||
var $result = $('.post-feed');
|
||||
var buffer = 300;
|
||||
|
||||
var ticking = false;
|
||||
var isLoading = false;
|
||||
var loading = false;
|
||||
|
||||
var lastScrollY = window.scrollY;
|
||||
var lastWindowHeight = window.innerHeight;
|
||||
var lastDocumentHeight = $document.height();
|
||||
var lastDocumentHeight = document.documentElement.scrollHeight;
|
||||
|
||||
function onPageLoad() {
|
||||
if (this.status === 404) {
|
||||
window.removeEventListener('scroll', onScroll);
|
||||
window.removeEventListener('resize', onResize);
|
||||
return;
|
||||
}
|
||||
|
||||
// append contents
|
||||
var postElements = this.response.querySelectorAll('.post-card');
|
||||
postElements.forEach(function (item) {
|
||||
feedElement.appendChild(item);
|
||||
});
|
||||
|
||||
// set next link
|
||||
var resNextElement = this.response.querySelector('link[rel=next]');
|
||||
if (resNextElement) {
|
||||
nextElement.href = resNextElement.href;
|
||||
} else {
|
||||
window.removeEventListener('scroll', onScroll);
|
||||
window.removeEventListener('resize', onResize);
|
||||
}
|
||||
|
||||
// sync status
|
||||
lastDocumentHeight = document.documentElement.scrollHeight;
|
||||
ticking = false;
|
||||
loading = false;
|
||||
}
|
||||
|
||||
function onUpdate() {
|
||||
// return if already loading
|
||||
if (loading) return;
|
||||
|
||||
// return if not scroll to the bottom
|
||||
if (lastScrollY + lastWindowHeight <= lastDocumentHeight - buffer) {
|
||||
ticking = false;
|
||||
return;
|
||||
}
|
||||
|
||||
loading = true;
|
||||
|
||||
var xhr = new window.XMLHttpRequest();
|
||||
xhr.responseType = 'document';
|
||||
|
||||
xhr.addEventListener('load', onPageLoad);
|
||||
|
||||
xhr.open('GET', nextElement.href);
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
function requestTick() {
|
||||
ticking || window.requestAnimationFrame(onUpdate);
|
||||
ticking = true;
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
lastScrollY = window.scrollY;
|
||||
@ -22,94 +81,12 @@ $(function ($) {
|
||||
|
||||
function onResize() {
|
||||
lastWindowHeight = window.innerHeight;
|
||||
lastDocumentHeight = $document.height();
|
||||
lastDocumentHeight = document.documentElement.scrollHeight;
|
||||
requestTick();
|
||||
}
|
||||
|
||||
function requestTick() {
|
||||
if (!ticking) {
|
||||
requestAnimationFrame(infiniteScroll);
|
||||
}
|
||||
ticking = true;
|
||||
}
|
||||
|
||||
function sanitizePathname(path) {
|
||||
var paginationRegex = /(?:page\/)(\d)(?:\/)$/i;
|
||||
|
||||
// remove hash params from path
|
||||
path = path.replace(/#(.*)$/g, '').replace('////g', '/');
|
||||
|
||||
// remove pagination from the path and replace the current pages
|
||||
// with the actual requested page. E. g. `/page/3/` indicates that
|
||||
// the user actually requested page 3, so we should request page 4
|
||||
// next, unless it's the last page already.
|
||||
if (path.match(paginationRegex)) {
|
||||
currentPage = parseInt(path.match(paginationRegex)[1]);
|
||||
|
||||
path = path.replace(paginationRegex, '');
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
function infiniteScroll() {
|
||||
// sanitize the pathname from possible pagination or hash params
|
||||
pathname = sanitizePathname(pathname);
|
||||
|
||||
// return if already loading
|
||||
if (isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
// return if not scroll to the bottom
|
||||
if (lastScrollY + lastWindowHeight <= lastDocumentHeight - buffer) {
|
||||
ticking = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* maxPages is defined in default.hbs and is the value
|
||||
* of the amount of pagination pages.
|
||||
* If we reached the last page or are past it,
|
||||
* we return and disable the listeners.
|
||||
*/
|
||||
if (currentPage >= maxPages) {
|
||||
window.removeEventListener('scroll', onScroll, {passive: true});
|
||||
window.removeEventListener('resize', onResize);
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
|
||||
// next page
|
||||
currentPage += 1;
|
||||
|
||||
// Load more
|
||||
var nextPage = pathname + 'page/' + currentPage + '/';
|
||||
|
||||
$.get(nextPage, function (content) {
|
||||
var parse = document.createRange().createContextualFragment(content);
|
||||
var posts = parse.querySelectorAll('.post');
|
||||
if (posts.length) {
|
||||
[].forEach.call(posts, function (post) {
|
||||
$result[0].appendChild(post);
|
||||
});
|
||||
}
|
||||
}).fail(function (xhr) {
|
||||
// 404 indicates we've run out of pages
|
||||
if (xhr.status === 404) {
|
||||
window.removeEventListener('scroll', onScroll, {passive: true});
|
||||
window.removeEventListener('resize', onResize);
|
||||
}
|
||||
}).always(function () {
|
||||
lastDocumentHeight = $document.height();
|
||||
isLoading = false;
|
||||
ticking = false;
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', onScroll, {passive: true});
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
window.addEventListener('resize', onResize);
|
||||
|
||||
infiniteScroll();
|
||||
});
|
||||
requestTick();
|
||||
})(window, document);
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
{{#author}}
|
||||
{{!-- Everything inside the #author tags pulls data from the author --}}
|
||||
<header class="site-header outer {{#if cover_image}}" style="background-image: url({{cover_image}}){{else}}no-cover{{/if}}">
|
||||
|
||||
|
||||
{{> header background=feature_image}} {{!--Special header.hbs partial to generate the <header> tag--}}
|
||||
<div class="inner">
|
||||
{{> "site-nav"}}
|
||||
<div class="site-header-content">
|
||||
|
10
default.hbs
10
default.hbs
@ -73,16 +73,10 @@
|
||||
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
|
||||
crossorigin="anonymous">
|
||||
</script>
|
||||
<script type="text/javascript" src="{{asset "js/jquery.fitvids.js"}}"></script>
|
||||
<script type="text/javascript" src="{{asset "built/jquery.fitvids.js"}}"></script>
|
||||
|
||||
{{#if pagination.pages}}
|
||||
<script>
|
||||
// maxPages is a global variable that is needed to determine
|
||||
// if we need to load more pages for the infinitescroll, or if
|
||||
// we reached the last page already.
|
||||
var maxPages = parseInt('{{pagination.pages}}');
|
||||
</script>
|
||||
<script src="{{asset "js/infinitescroll.js"}}"></script>
|
||||
<script src="{{asset "built/infinitescroll.js"}}"></script>
|
||||
{{/if}}
|
||||
|
||||
{{!-- The #block helper will pull in data from the #contentFor other template files. In this case, there's some JavaScript which we only want to use in post.hbs, but it needs to be included down here, after jQuery has already loaded. --}}
|
||||
|
@ -20,7 +20,7 @@ It's a good idea to keep this template as minimal as possible in terms of both f
|
||||
<div class="inner">
|
||||
<nav class="site-nav-center">
|
||||
{{#if @blog.logo}}
|
||||
<a class="site-nav-logo" href="{{@blog.url}}"><img src="{{@blog.logo}}" alt="{{@blog.title}}" /></a>
|
||||
<a class="site-nav-logo" href="{{@blog.url}}"><img src="{{img_url @blog.logo size="xs"}}" alt="{{@blog.title}}" /></a>
|
||||
{{else}}
|
||||
<a class="site-nav-logo" href="{{@blog.url}}">{{@blog.title}}</a>
|
||||
{{/if}}
|
||||
|
@ -21,7 +21,7 @@ You'll notice that we *don't* use any JavsScript, or ghost_head / ghost_foot in
|
||||
<div class="inner">
|
||||
<nav class="site-nav-center">
|
||||
{{#if @blog.logo}}
|
||||
<a class="site-nav-logo" href="{{@blog.url}}"><img src="{{@blog.logo}}" alt="{{@blog.title}}" /></a>
|
||||
<a class="site-nav-logo" href="{{@blog.url}}"><img src="{{img_url @blog.logo size="xs"}}" alt="{{@blog.title}}" /></a>
|
||||
{{else}}
|
||||
<a class="site-nav-logo" href="{{@blog.url}}">{{@blog.title}}</a>
|
||||
{{/if}}
|
||||
|
25
gulpfile.js
25
gulpfile.js
@ -26,10 +26,12 @@ var nodemonServerInit = function () {
|
||||
livereload.listen(1234);
|
||||
};
|
||||
|
||||
gulp.task('build', ['css'], function (/* cb */) {
|
||||
gulp.task('build', ['css', 'js'], function (/* cb */) {
|
||||
return nodemonServerInit();
|
||||
});
|
||||
|
||||
gulp.task('generate', ['css', 'js']);
|
||||
|
||||
gulp.task('css', function () {
|
||||
var processors = [
|
||||
easyimport,
|
||||
@ -48,25 +50,34 @@ gulp.task('css', function () {
|
||||
.pipe(livereload());
|
||||
});
|
||||
|
||||
gulp.task('js', function () {
|
||||
var jsFilter = filter(['**/*.js'], {restore: true});
|
||||
|
||||
return gulp.src('assets/js/*.js')
|
||||
.on('error', swallowError)
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(jsFilter)
|
||||
.pipe(uglify())
|
||||
.pipe(jsFilter.restore)
|
||||
.pipe(sourcemaps.write('.'))
|
||||
.pipe(gulp.dest('assets/built/'))
|
||||
.pipe(livereload());
|
||||
});
|
||||
|
||||
gulp.task('watch', function () {
|
||||
gulp.watch('assets/css/**', ['css']);
|
||||
});
|
||||
|
||||
gulp.task('zip', ['css'], function () {
|
||||
gulp.task('zip', ['css', 'js'], function () {
|
||||
var targetDir = 'dist/';
|
||||
var themeName = require('./package.json').name;
|
||||
var filename = themeName + '.zip';
|
||||
|
||||
var jsFilter = filter(['**/*.js'], {restore: true});
|
||||
|
||||
return gulp.src([
|
||||
'**',
|
||||
'!node_modules', '!node_modules/**',
|
||||
'!dist', '!dist/**'
|
||||
])
|
||||
.pipe(jsFilter)
|
||||
.pipe(uglify())
|
||||
.pipe(jsFilter.restore)
|
||||
.pipe(zip(filename))
|
||||
.pipe(gulp.dest(targetDir));
|
||||
});
|
||||
|
@ -2,13 +2,12 @@
|
||||
{{!-- The tag above means: insert everything in this file
|
||||
into the {body} of the default.hbs template --}}
|
||||
|
||||
{{!-- The big featured header, it uses blog cover image as a BG if available --}}
|
||||
<header class="site-header outer {{#if @blog.cover_image}}" style="background-image: url({{@blog.cover_image}}){{else}}no-cover{{/if}}">
|
||||
{{> header background=@blog.cover_image}} {{!--Special header.hbs partial to generate the <header> tag--}}
|
||||
<div class="inner">
|
||||
<div class="site-header-content">
|
||||
<h1 class="site-title">
|
||||
{{#if @blog.logo}}
|
||||
<img class="site-logo" src="{{@blog.logo}}" alt="{{@blog.title}}" />
|
||||
<img class="site-logo" src="{{img_url @blog.logo size="s"}}" alt="{{@blog.title}}" />
|
||||
{{else}}
|
||||
{{@blog.title}}
|
||||
{{/if}}
|
||||
|
24
package.json
24
package.json
@ -2,7 +2,7 @@
|
||||
"name": "casper",
|
||||
"description": "The default personal blogging theme for Ghost. Beautiful, minimal and responsive.",
|
||||
"demo": "https://demo.ghost.io",
|
||||
"version": "2.6.4",
|
||||
"version": "2.8.0",
|
||||
"engines": {
|
||||
"ghost": ">=2.0.0"
|
||||
},
|
||||
@ -57,6 +57,26 @@
|
||||
"gulp-uglify": "3.0.1"
|
||||
},
|
||||
"config": {
|
||||
"posts_per_page": 25
|
||||
"posts_per_page": 25,
|
||||
"image_sizes": {
|
||||
"xxs": {
|
||||
"width": 30
|
||||
},
|
||||
"xs": {
|
||||
"width": 100
|
||||
},
|
||||
"s": {
|
||||
"width": 300
|
||||
},
|
||||
"m": {
|
||||
"width": 600
|
||||
},
|
||||
"l": {
|
||||
"width": 1000
|
||||
},
|
||||
"xl": {
|
||||
"width": 2000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
15
page.hbs
15
page.hbs
@ -22,7 +22,20 @@ into the {body} of the default.hbs template --}}
|
||||
</header>
|
||||
|
||||
{{#if feature_image}}
|
||||
<figure class="post-full-image" style="background-image: url({{feature_image}})">
|
||||
<figure class="post-full-image">
|
||||
{{!-- This is a responsive image, it loads different sizes depending on device
|
||||
https://medium.freecodecamp.org/a-guide-to-responsive-images-with-ready-to-use-templates-c400bd65c433 --}}
|
||||
<img
|
||||
srcset="{{img_url feature_image size="s"}} 300w,
|
||||
{{img_url feature_image size="m"}} 600w,
|
||||
{{img_url feature_image size="l"}} 1000w,
|
||||
{{img_url feature_image size="xl"}} 2000w"
|
||||
sizes="(max-width: 800px) 400px,
|
||||
(max-width: 1170px) 700px,
|
||||
1400px"
|
||||
src="{{img_url feature_image size="xl"}}"
|
||||
alt="{{title}}"
|
||||
/>
|
||||
</figure>
|
||||
{{/if}}
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
<div class="author-card">
|
||||
<div class="basic-info">
|
||||
{{#if profile_image}}
|
||||
<img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" />
|
||||
<img class="author-profile-image" src="{{img_url profile_image size="xs"}}" alt="{{name}}" />
|
||||
{{else}}
|
||||
<div class="author-profile-image">{{> "icons/avatar"}}</div>
|
||||
{{/if}}
|
||||
@ -29,7 +29,9 @@
|
||||
</div>
|
||||
|
||||
{{#if profile_image}}
|
||||
<a href="{{url}}" class="moving-avatar"><img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" /></a>
|
||||
<a href="{{url}}" class="moving-avatar">
|
||||
<img class="author-profile-image" src="{{img_url profile_image size="xs"}}" alt="{{name}}" />
|
||||
</a>
|
||||
{{else}}
|
||||
<a href="{{url}}" class="moving-avatar author-profile-image">{{> "icons/avatar"}}</a>
|
||||
{{/if}}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
<section class="author-card">
|
||||
{{#if profile_image}}
|
||||
<img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" />
|
||||
<img class="author-profile-image" src="{{img_url profile_image size="xs"}}" alt="{{name}}" />
|
||||
{{else}}
|
||||
<span class="avatar-wrapper">{{> "icons/avatar"}}</span>
|
||||
{{/if}}
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="floating-header-logo">
|
||||
<a href="{{@blog.url}}">
|
||||
{{#if @blog.icon}}
|
||||
<img src="{{@blog.icon}}" alt="{{@blog.title}} icon" />
|
||||
<img src="{{img_url @blog.icon size="xxs"}}" alt="{{@blog.title}} icon" />
|
||||
{{/if}}
|
||||
<span>{{@blog.title}}</span>
|
||||
</a>
|
||||
|
51
partials/header.hbs
Normal file
51
partials/header.hbs
Normal file
@ -0,0 +1,51 @@
|
||||
{{!--
|
||||
Wow what the hell is going on in here even?
|
||||
|
||||
Ok so, several templates use this big header with a giant BG image. Nice idea, but big images
|
||||
have a heavy impact on performance, so it's a good idea to make them responsive. Because we
|
||||
can only get the image dynamically using Handlebars, and we can only set the image to properly
|
||||
be a background image using CSS, we end up with a handful of inline styles.
|
||||
|
||||
If the template in question has a background image, then we render responsive image styles
|
||||
for it, and apply those styles to the <header> tag. Else, we just output a <header> tag
|
||||
with a `no-image` class so we can style it accordingly.
|
||||
--}}
|
||||
|
||||
{{#if background}}
|
||||
|
||||
<style type="text/css">
|
||||
.responsive-header-img {
|
||||
background-image: url({{img_url background size='xl'}});
|
||||
}
|
||||
@media(max-width: 1000px) {
|
||||
.responsive-header-img {
|
||||
background-image: url({{img_url background size='l'}});
|
||||
background-image: -webkit-image-set(
|
||||
url({{img_url background size='l'}}) 1x,
|
||||
url({{img_url background size='xl'}}) 2x
|
||||
);
|
||||
background-image: image-set(
|
||||
url({{img_url background size='l'}}) 1x,
|
||||
url({{img_url background size='xl'}}) 2x
|
||||
);
|
||||
}
|
||||
@media(max-width: 600px) {
|
||||
.responsive-header-img {
|
||||
background-image: url({{img_url background size='m'}});
|
||||
background-image: -webkit-image-set(
|
||||
url({{img_url background size='m'}}) 1x,
|
||||
url({{img_url background size='l'}}) 2x
|
||||
);
|
||||
background-image: image-set(
|
||||
url({{img_url background size='m'}}) 1x,
|
||||
url({{img_url background size='l'}}) 2x
|
||||
);
|
||||
}
|
||||
</style>
|
||||
<header class="site-header outer responsive-header-img">
|
||||
|
||||
{{else}}
|
||||
|
||||
<header class="site-header outer no-image">
|
||||
|
||||
{{/if}}
|
@ -1,21 +1,38 @@
|
||||
<article class="post-card {{post_class}}{{#unless feature_image}} no-image{{/unless}}">
|
||||
<article class="post-card {{post_class}} {{#unless feature_image}}no-image{{else}}{{#is "home"}}{{#has index="nth:6"}}post-card-large{{/has}}{{/is}}{{/unless}}">
|
||||
|
||||
{{#if feature_image}}
|
||||
<a class="post-card-image-link" href="{{url}}">
|
||||
<div class="post-card-image" style="background-image: url({{feature_image}})"></div>
|
||||
</a>
|
||||
<a class="post-card-image-link" href="{{url}}">
|
||||
{{!-- This is a responsive image, it loads different sizes depending on device
|
||||
https://medium.freecodecamp.org/a-guide-to-responsive-images-with-ready-to-use-templates-c400bd65c433 --}}
|
||||
<img class="post-card-image"
|
||||
srcset="{{img_url feature_image size="s"}} 300w,
|
||||
{{img_url feature_image size="m"}} 600w,
|
||||
{{img_url feature_image size="l"}} 1000w,
|
||||
{{img_url feature_image size="xl"}} 2000w"
|
||||
sizes="(max-width: 1000px) 400px, 700px"
|
||||
src="{{img_url feature_image size="m"}}"
|
||||
alt="{{title}}"
|
||||
/>
|
||||
</a>
|
||||
{{/if}}
|
||||
|
||||
<div class="post-card-content">
|
||||
|
||||
<a class="post-card-content-link" href="{{url}}">
|
||||
|
||||
<header class="post-card-header">
|
||||
{{#if primary_tag}}
|
||||
<span class="post-card-tags">{{primary_tag.name}}</span>
|
||||
{{/if}}
|
||||
<h2 class="post-card-title">{{title}}</h2>
|
||||
</header>
|
||||
|
||||
<section class="post-card-excerpt">
|
||||
<p>{{excerpt words="33"}}</p>
|
||||
</section>
|
||||
|
||||
</a>
|
||||
|
||||
<footer class="post-card-meta">
|
||||
|
||||
<ul class="author-list">
|
||||
@ -27,7 +44,9 @@
|
||||
</div>
|
||||
|
||||
{{#if profile_image}}
|
||||
<a href="{{url}}" class="static-avatar"><img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" /></a>
|
||||
<a href="{{url}}" class="static-avatar">
|
||||
<img class="author-profile-image" src="{{img_url profile_image size="xs"}}" alt="{{name}}" />
|
||||
</a>
|
||||
{{else}}
|
||||
<a href="{{url}}" class="static-avatar author-profile-image">{{> "icons/avatar"}}</a>
|
||||
{{/if}}
|
||||
@ -38,5 +57,7 @@
|
||||
<span class="reading-time">{{reading_time}}</span>
|
||||
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
</div>{{!--/.post-card-content--}}
|
||||
|
||||
</article>
|
||||
|
@ -14,16 +14,16 @@
|
||||
<div class="site-nav-right">
|
||||
<div class="social-links">
|
||||
{{#if @blog.facebook}}
|
||||
<a class="social-link social-link-fb" href="{{facebook_url @blog.facebook}}" target="_blank" rel="noopener">{{> "icons/facebook"}}</a>
|
||||
<a class="social-link social-link-fb" href="{{facebook_url @blog.facebook}}" title="Facebook" target="_blank" rel="noopener">{{> "icons/facebook"}}</a>
|
||||
{{/if}}
|
||||
{{#if @blog.twitter}}
|
||||
<a class="social-link social-link-tw" href="{{twitter_url @blog.twitter}}" target="_blank" rel="noopener">{{> "icons/twitter"}}</a>
|
||||
<a class="social-link social-link-tw" href="{{twitter_url @blog.twitter}}" title="Twitter" target="_blank" rel="noopener">{{> "icons/twitter"}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if @labs.subscribers}}
|
||||
<a class="subscribe-button" href="#subscribe">Subscribe</a>
|
||||
{{else}}
|
||||
<a class="rss-button" href="https://feedly.com/i/subscription/feed/{{@blog.url}}/rss/" target="_blank" rel="noopener">{{> "icons/rss"}}</a>
|
||||
<a class="rss-button" href="https://feedly.com/i/subscription/feed/{{@blog.url}}/rss/" title="RSS" target="_blank" rel="noopener">{{> "icons/rss"}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</nav>
|
||||
|
19
post.hbs
19
post.hbs
@ -28,7 +28,20 @@ into the {body} of the default.hbs template --}}
|
||||
</header>
|
||||
|
||||
{{#if feature_image}}
|
||||
<figure class="post-full-image" style="background-image: url({{feature_image}})">
|
||||
<figure class="post-full-image">
|
||||
{{!-- This is a responsive image, it loads different sizes depending on device
|
||||
https://medium.freecodecamp.org/a-guide-to-responsive-images-with-ready-to-use-templates-c400bd65c433 --}}
|
||||
<img
|
||||
srcset="{{img_url feature_image size="s"}} 300w,
|
||||
{{img_url feature_image size="m"}} 600w,
|
||||
{{img_url feature_image size="l"}} 1000w,
|
||||
{{img_url feature_image size="xl"}} 2000w"
|
||||
sizes="(max-width: 800px) 400px,
|
||||
(max-width: 1170px) 700px,
|
||||
1400px"
|
||||
src="{{img_url feature_image size="xl"}}"
|
||||
alt="{{title}}"
|
||||
/>
|
||||
</figure>
|
||||
{{/if}}
|
||||
|
||||
@ -82,10 +95,10 @@ into the {body} of the default.hbs template --}}
|
||||
{{#if related_posts}}
|
||||
<article class="read-next-card"
|
||||
{{#if ../primary_tag.feature_image}}
|
||||
style="background-image: url({{../primary_tag.feature_image}})"
|
||||
style="background-image: url({{img_url ../primary_tag.feature_image size="m"}})"
|
||||
{{else}}
|
||||
{{#if @blog.cover_image}}
|
||||
style="background-image: url({{@blog.cover_image}})"{{/if}}
|
||||
style="background-image: url({{img_url @blog.cover_image size="m"}})"{{/if}}
|
||||
{{/if}}
|
||||
>
|
||||
<header class="read-next-card-header">
|
||||
|
3
tag.hbs
3
tag.hbs
@ -1,9 +1,8 @@
|
||||
{{!< default}}
|
||||
{{!-- The tag above means - insert everything in this file into the {body} of the default.hbs template --}}
|
||||
|
||||
{{!-- The big featured header, it uses blog cover image as a BG if available --}}
|
||||
{{#tag}}
|
||||
<header class="site-header outer {{#if feature_image}}" style="background-image: url({{feature_image}}){{else}}no-cover{{/if}}">
|
||||
{{> header background=feature_image}} {{!--Special header.hbs partial to generate the <header> tag--}}
|
||||
<div class="inner">
|
||||
{{> "site-nav"}}
|
||||
<div class="site-header-content">
|
||||
|
Reference in New Issue
Block a user