Compare commits
90 Commits
Author | SHA1 | Date | |
---|---|---|---|
67e595741c | |||
7a88c88ea2 | |||
a0e42e0599 | |||
dc3bb316c7 | |||
7380ed0291 | |||
ecaf3d921f | |||
89ea6c5872 | |||
9d803067a4 | |||
0ea375643b | |||
f31957bd0d | |||
36841d4624 | |||
d41fcbbc8a | |||
5d318225f5 | |||
9b56779ca6 | |||
1bf2cdb52a | |||
f67caaba5c | |||
25d1e368d6 | |||
5c6cce1519 | |||
019842155a | |||
1860a8305b | |||
6417b4cf2a | |||
1c61bc5f16 | |||
7a7f04c716 | |||
fd56128f9b | |||
cd3b470c18 | |||
f3b44a7411 | |||
b83917060f | |||
4aaedf69d2 | |||
03ac0d91b8 | |||
b55d5e2b32 | |||
4fe2eac739 | |||
6e3399366d | |||
98e9c12018 | |||
986a954f33 | |||
636882bce4 | |||
79e113226c | |||
8e865b797b | |||
a655b59e69 | |||
b078dcb86e | |||
d5002f2c51 | |||
41bcbb7157 | |||
452776939c | |||
57c31ddacb | |||
21088b1d38 | |||
16f283e675 | |||
942054ba0d | |||
782aba3991 | |||
9df85fbbe5 | |||
1e10549ee2 | |||
a6eb6848de | |||
6788302f62 | |||
67e55abfed | |||
bfaae0f7ba | |||
edfafffd32 | |||
7798bf115f | |||
9395846fdf | |||
99fad4cbc4 | |||
990f712209 | |||
4ff4b4c7f8 | |||
de05d90fe9 | |||
978e54403c | |||
73bd9c630e | |||
9597a28320 | |||
461639886e | |||
7592ad182b | |||
97a522a037 | |||
25f12d760b | |||
4f78d99112 | |||
f5b7b45f2e | |||
d34ff1d32b | |||
73a1ab52da | |||
5ec77dfb31 | |||
269d2b5787 | |||
d1d0bca2d8 | |||
d92dda3523 | |||
ca325285bf | |||
aee9f69bb0 | |||
a7d5c885bd | |||
9bc5c92628 | |||
0f3651c23f | |||
d739bb52a4 | |||
8d17e9a452 | |||
e4e6bb9c5a | |||
d2375a3917 | |||
577b92811c | |||
2f385ba5f1 | |||
b024b544e4 | |||
9caeb2a2e7 | |||
12d139aa7d | |||
690e1bad1f |
17
.editorconfig
Normal file
@ -0,0 +1,17 @@
|
||||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.hbs]
|
||||
insert_final_newline = false
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
19
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Do you need help or have a question? Please come chat in our forum: https://forum.ghost.org 👫.
|
||||
|
||||
If you're filing a bug 🐛, please include the following information:
|
||||
|
||||
### Screenshot
|
||||
|
||||
![]()
|
||||
|
||||
### Steps to Reproduce
|
||||
|
||||
1. This is the first step
|
||||
2. This may be the post content used to cause an issue...
|
||||
|
||||
### Technical details
|
||||
|
||||
* Casper Version:
|
||||
* Ghost Version:
|
||||
* Browser Version:
|
||||
* OS Version:
|
5
.gitignore
vendored
@ -13,9 +13,12 @@ results
|
||||
|
||||
npm-debug.log
|
||||
node_modules
|
||||
package-lock.json
|
||||
|
||||
.idea/*
|
||||
*.iml
|
||||
projectFilesBackup
|
||||
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
|
||||
dist/
|
||||
|
6
.travis.yml
Normal file
@ -0,0 +1,6 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- "8"
|
||||
|
||||
|
2
LICENSE
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2013-2017 Ghost Foundation
|
||||
Copyright (c) 2013-2018 Ghost Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
14
README.md
@ -34,12 +34,18 @@ One really neat trick is that you can also create custom one-off templates just
|
||||
|
||||
Casper styles are compiled using Gulp/PostCSS to polyfill future CSS spec. You'll need Node and Gulp installed globally. After that, from the theme's root directory:
|
||||
|
||||
`$ npm install`
|
||||
|
||||
`$ gulp`
|
||||
```bash
|
||||
$ yarn install
|
||||
$ yarn dev
|
||||
```
|
||||
|
||||
Now you can edit `/assets/css/` files, which will be compiled to `/assets/built/` automatically.
|
||||
|
||||
The `zip` Gulp task packages the theme files into `dist/<theme-name>.zip`, which you can then upload to your site.
|
||||
|
||||
```bash
|
||||
$ yarn zip
|
||||
```
|
||||
|
||||
# PostCSS Features Used
|
||||
|
||||
@ -57,4 +63,4 @@ You can add your own SVG icons in the same manner.
|
||||
|
||||
# Copyright & License
|
||||
|
||||
Copyright (c) 2013-2017 Ghost Foundation - Released under the [MIT license](LICENSE).
|
||||
Copyright (c) 2013-2018 Ghost Foundation - Released under the [MIT license](LICENSE).
|
||||
|
@ -1,2 +1,2 @@
|
||||
a,abbr,acronym,address,applet,article,aside,audio,big,blockquote,body,canvas,caption,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,ul,var,video{margin:0;padding:0;border:0;font:inherit;font-size:100%;vertical-align:baseline}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:"";content:none}img{max-width:100%}html{box-sizing:border-box;font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}*,:after,:before{box-sizing:inherit}a{background-color:transparent}a:active,a:hover{outline:0}b,strong{font-weight:700}dfn,em,i{font-style:italic}h1{margin:.67em 0;font-size:2em}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}mark{background-color:#fdffb6}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;color:inherit;font:inherit}button{overflow:visible;border:none}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input:focus{outline:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}legend{padding:0;border:0}textarea{overflow:auto}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}html{overflow-y:scroll;font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body,html{overflow-x:hidden}body{color:#3c484e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;font-size:1.5rem;line-height:1.6em;font-weight:400;font-style:normal;letter-spacing:0;text-rendering:optimizeLegibility;background:#fff;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-moz-font-feature-settings:"liga" on}::-moz-selection{text-shadow:none;background:#cbeafb}::selection{text-shadow:none;background:#cbeafb}hr{position:relative;display:block;width:100%;margin:2.5em 0 3.5em;padding:0;height:1px;border:0;border-top:1px solid #e3e9ed}audio,canvas,iframe,img,svg,video{vertical-align:middle}fieldset{margin:0;padding:0;border:0}textarea{resize:vertical}blockquote,dl,ol,p,ul{margin:0 0 1.5em}ol,ul{padding-left:1em;padding-right:1.5em}ol ol,ol ul,ul ol,ul ul{margin:.5em 0 1em}ul{list-style:disc}ol{list-style:decimal}li{margin:.5em 0;padding-left:.5em;line-height:1.6em}dt{float:left;margin:0 20px 0 0;width:120px;color:#15171a;font-weight:500;text-align:right}dd{margin:0 0 5px;text-align:left}blockquote{margin:1.5em 0;padding:0 1.6em;border-left:.5em solid #e5eff5}blockquote p{margin:.8em 0;font-size:1.2em;font-weight:300}blockquote small{display:inline-block;margin:.8em 0 .8em 1.5em;font-size:.9em;opacity:.8}blockquote small:before{content:"\2014 \00A0"}blockquote cite{font-weight:700}blockquote cite a{font-weight:400}a{color:#26a8ed;text-decoration:none}a:hover{text-decoration:underline}h1,h2,h3,h4,h5,h6{margin-top:0;line-height:1.15;font-weight:700;text-rendering:optimizeLegibility}h1{margin:0 0 .5em;font-size:5rem;font-weight:700}@media (max-width:500px){h1{font-size:2.2rem}}h2{margin:1.5em 0 .5em;font-size:2rem}@media (max-width:500px){h2{font-size:1.8rem}}h3{margin:1.5em 0 .5em;font-size:1.8rem;font-weight:500}@media (max-width:500px){h3{font-size:1.7rem}}h4{margin:1.5em 0 .5em;font-size:1.6rem;font-weight:500}h5,h6{margin:1.5em 0 .5em;font-size:1.4rem;font-weight:500}
|
||||
a,abbr,acronym,address,applet,article,aside,audio,big,blockquote,body,canvas,caption,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,ul,var,video{margin:0;padding:0;border:0;font:inherit;font-size:100%;vertical-align:baseline}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:"";content:none}img{max-width:100%}html{box-sizing:border-box;font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}*,:after,:before{box-sizing:inherit}a{background-color:transparent}a:active,a:hover{outline:0}b,strong{font-weight:700}dfn,em,i{font-style:italic}h1{margin:.67em 0;font-size:2em}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}mark{background-color:#fdffb6}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;color:inherit;font:inherit}button{overflow:visible;border:none}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input:focus{outline:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}legend{padding:0;border:0}textarea{overflow:auto}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}html{overflow-y:scroll;font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body,html{overflow-x:hidden}body{color:#3c484e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;font-size:1.5rem;line-height:1.6em;font-weight:400;font-style:normal;letter-spacing:0;text-rendering:optimizeLegibility;background:#fff;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-moz-font-feature-settings:"liga" on}::-moz-selection{text-shadow:none;background:#cbeafb}::selection{text-shadow:none;background:#cbeafb}hr{position:relative;display:block;width:100%;margin:2.5em 0 3.5em;padding:0;height:1px;border:0;border-top:1px solid #e3e9ed}audio,canvas,iframe,img,svg,video{vertical-align:middle}fieldset{margin:0;padding:0;border:0}textarea{resize:vertical}blockquote,dl,ol,p,ul{margin:0 0 1.5em}ol,ul{padding-left:1.3em;padding-right:1.5em}ol ol,ol ul,ul ol,ul ul{margin:.5em 0 1em}ul{list-style:disc}ol{list-style:decimal}ol,ul{max-width:100%}li{margin:.5em 0;padding-left:.3em;line-height:1.6em}dt{float:left;margin:0 20px 0 0;width:120px;color:#15171a;font-weight:500;text-align:right}dd{margin:0 0 5px;text-align:left}blockquote{margin:1.5em 0;padding:0 1.6em;border-left:.5em solid #e5eff5}blockquote p{margin:.8em 0;font-size:1.2em;font-weight:300}blockquote small{display:inline-block;margin:.8em 0 .8em 1.5em;font-size:.9em;opacity:.8}blockquote small:before{content:"\2014 \00A0"}blockquote cite{font-weight:700}blockquote cite a{font-weight:400}a{color:#26a8ed;text-decoration:none}a:hover{text-decoration:underline}h1,h2,h3,h4,h5,h6{margin-top:0;line-height:1.15;font-weight:700;text-rendering:optimizeLegibility}h1{margin:0 0 .5em;font-size:5rem;font-weight:700}@media (max-width:500px){h1{font-size:2.2rem}}h2{margin:1.5em 0 .5em;font-size:2rem}@media (max-width:500px){h2{font-size:1.8rem}}h3{margin:1.5em 0 .5em;font-size:1.8rem;font-weight:500}@media (max-width:500px){h3{font-size:1.7rem}}h4{margin:1.5em 0 .5em;font-size:1.6rem;font-weight:500}h5,h6{margin:1.5em 0 .5em;font-size:1.4rem;font-weight:500}
|
||||
/*# sourceMappingURL=global.css.map */
|
||||
|
@ -267,7 +267,6 @@ th {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/* ==========================================================================
|
||||
Base styles: opinionated defaults
|
||||
========================================================================== */
|
||||
@ -341,7 +340,7 @@ blockquote {
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-left: 1em;
|
||||
padding-left: 1.3em;
|
||||
padding-right: 1.5em;
|
||||
}
|
||||
|
||||
@ -360,9 +359,14 @@ ol {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0.5em 0;
|
||||
padding-left: 0.5em;
|
||||
padding-left: 0.3em;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
@ -383,7 +387,7 @@ dd {
|
||||
blockquote {
|
||||
margin: 1.5em 0;
|
||||
padding: 0 1.6em 0 1.6em;
|
||||
border-left: var(--whitegrey) 0.5em solid;;
|
||||
border-left: var(--whitegrey) 0.5em solid;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
|
@ -1,10 +1,12 @@
|
||||
/* global maxPages */
|
||||
|
||||
// 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 = 100;
|
||||
var buffer = 300;
|
||||
|
||||
var ticking = false;
|
||||
var isLoading = false;
|
||||
@ -13,9 +15,6 @@ $(function ($) {
|
||||
var lastWindowHeight = window.innerHeight;
|
||||
var lastDocumentHeight = $document.height();
|
||||
|
||||
// remove hash params from pathname
|
||||
pathname = pathname.replace(/#(.*)$/g, '').replace('/\//g', '/');
|
||||
|
||||
function onScroll() {
|
||||
lastScrollY = window.scrollY;
|
||||
requestTick();
|
||||
@ -29,12 +28,34 @@ $(function ($) {
|
||||
|
||||
function requestTick() {
|
||||
if (!ticking) {
|
||||
requestAnimationFrame(infiniteScroll)
|
||||
requestAnimationFrame(infiniteScroll);
|
||||
}
|
||||
ticking = true;
|
||||
}
|
||||
|
||||
function infiniteScroll () {
|
||||
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;
|
||||
@ -46,29 +67,40 @@ $(function ($) {
|
||||
return;
|
||||
}
|
||||
|
||||
// return if currentPage is the last page already
|
||||
if (currentPage === maxPages) {
|
||||
/**
|
||||
* 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++;
|
||||
currentPage += 1;
|
||||
|
||||
// Load more
|
||||
var nextPage = pathname + 'page/' + currentPage + '/';
|
||||
|
||||
$.get(nextPage, function (content) {
|
||||
$result.append($(content).find('.post').hide().fadeIn(100));
|
||||
|
||||
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;
|
||||
|
0
assets/screenshot-desktop.jpg
Executable file → Normal file
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
0
assets/screenshot-mobile.jpg
Executable file → Normal file
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
10
author.hbs
@ -22,15 +22,15 @@
|
||||
{{plural ../pagination.total empty='No posts' singular='% post' plural='% posts'}} <span class="bull">•</span>
|
||||
</div>
|
||||
{{#if website}}
|
||||
<a class="social-link social-link-wb" href="{{website}}" target="_blank">{{> "icons/website"}}</a>
|
||||
<a class="social-link social-link-wb" href="{{website}}" target="_blank" rel="noopener">{{> "icons/website"}}</a>
|
||||
{{/if}}
|
||||
{{#if twitter}}
|
||||
<a class="social-link social-link-tw" href="{{twitter_url}}" target="_blank">{{> "icons/twitter"}}</a>
|
||||
<a class="social-link social-link-tw" href="{{twitter_url}}" target="_blank" rel="noopener">{{> "icons/twitter"}}</a>
|
||||
{{/if}}
|
||||
{{#if facebook}}
|
||||
<a class="social-link social-link-fb" href="{{facebook_url}}" target="_blank">{{> "icons/facebook"}}</a>
|
||||
<a class="social-link social-link-fb" href="{{facebook_url}}" target="_blank" rel="noopener">{{> "icons/facebook"}}</a>
|
||||
{{/if}}
|
||||
<a class="social-link social-link-rss" href="http://cloud.feedly.com/#subscription/feed/{{url absolute="true"}}/rss/" target="_blank">{{> "icons/rss"}}</a>
|
||||
<a class="social-link social-link-rss" href="https://feedly.com/i/subscription/feed/{{url absolute="true"}}rss/" target="_blank" rel="noopener">{{> "icons/rss"}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -38,7 +38,7 @@
|
||||
{{/author}}
|
||||
|
||||
{{!-- The main content area --}}
|
||||
<main id="site-main" class="site-main outer" role="main">
|
||||
<main id="site-main" class="site-main outer">
|
||||
<div class="inner">
|
||||
|
||||
<div class="post-feed">
|
||||
|
25
default.hbs
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="{{lang}}">
|
||||
<head>
|
||||
|
||||
{{!-- Document Settings --}}
|
||||
@ -14,7 +14,7 @@
|
||||
{{!-- Styles'n'Scripts --}}
|
||||
<link rel="stylesheet" type="text/css" href="{{asset "built/screen.css"}}" />
|
||||
|
||||
{{!-- This tag outputes SEO meta+structured data and other important settings --}}
|
||||
{{!-- This tag outputs SEO meta+structured data and other important settings --}}
|
||||
{{ghost_head}}
|
||||
|
||||
</head>
|
||||
@ -31,9 +31,9 @@
|
||||
<section class="copyright"><a href="{{@blog.url}}">{{@blog.title}}</a> © {{date format="YYYY"}}</section>
|
||||
<nav class="site-footer-nav">
|
||||
<a href="{{@blog.url}}">Latest Posts</a>
|
||||
{{#if @blog.facebook}}<a href="{{facebook_url @blog.facebook}}" target="_blank">Facebook</a>{{/if}}
|
||||
{{#if @blog.twitter}}<a href="{{twitter_url @blog.twitter}}" target="_blank">Twitter</a>{{/if}}
|
||||
<a href="https://ghost.org" target="_blank">Ghost</a>
|
||||
{{#if @blog.facebook}}<a href="{{facebook_url @blog.facebook}}" target="_blank" rel="noopener">Facebook</a>{{/if}}
|
||||
{{#if @blog.twitter}}<a href="{{twitter_url @blog.twitter}}" target="_blank" rel="noopener">Twitter</a>{{/if}}
|
||||
<a href="https://ghost.org" target="_blank" rel="noopener">Ghost</a>
|
||||
</nav>
|
||||
</div>
|
||||
</footer>
|
||||
@ -55,6 +55,18 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<script>
|
||||
var images = document.querySelectorAll('.kg-gallery-image img');
|
||||
images.forEach(function (image) {
|
||||
var container = image.closest('.kg-gallery-image');
|
||||
var width = image.attributes.width.value;
|
||||
var height = image.attributes.height.value;
|
||||
var ratio = width / height;
|
||||
container.style.flex = ratio + ' 1 0%';
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
{{!-- jQuery + Fitvids, which makes all video embeds responsive --}}
|
||||
<script
|
||||
src="https://code.jquery.com/jquery-3.2.1.min.js"
|
||||
@ -65,6 +77,9 @@
|
||||
|
||||
{{#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>
|
||||
|
@ -28,7 +28,7 @@ It's a good idea to keep this template as minimal as possible in terms of both f
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="site-main" class="site-main outer" role="main">
|
||||
<main id="site-main" class="site-main outer">
|
||||
<div class="inner">
|
||||
|
||||
<section class="error-message">
|
||||
|
@ -29,7 +29,7 @@ You'll notice that we *don't* use any JavsScript, or ghost_head / ghost_foot in
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="site-main" class="site-main outer" role="main">
|
||||
<main id="site-main" class="site-main outer">
|
||||
<div class="inner">
|
||||
|
||||
<section class="error-message">
|
||||
|
19
gulpfile.js
@ -3,9 +3,9 @@ var gulp = require('gulp');
|
||||
// gulp plugins and utils
|
||||
var gutil = require('gulp-util');
|
||||
var livereload = require('gulp-livereload');
|
||||
var nodemon = require('gulp-nodemon');
|
||||
var postcss = require('gulp-postcss');
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
var zip = require('gulp-zip');
|
||||
|
||||
// postcss plugins
|
||||
var autoprefixer = require('autoprefixer');
|
||||
@ -36,7 +36,8 @@ gulp.task('css', function () {
|
||||
autoprefixer({browsers: ['last 2 versions']}),
|
||||
cssnano()
|
||||
];
|
||||
gulp.src('assets/css/*.css')
|
||||
|
||||
return gulp.src('assets/css/*.css')
|
||||
.on('error', swallowError)
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(postcss(processors))
|
||||
@ -49,6 +50,20 @@ gulp.task('watch', function () {
|
||||
gulp.watch('assets/css/**', ['css']);
|
||||
});
|
||||
|
||||
gulp.task('zip', ['css'], function () {
|
||||
var targetDir = 'dist/';
|
||||
var themeName = require('./package.json').name;
|
||||
var filename = themeName + '.zip';
|
||||
|
||||
return gulp.src([
|
||||
'**',
|
||||
'!node_modules', '!node_modules/**',
|
||||
'!dist', '!dist/**'
|
||||
])
|
||||
.pipe(zip(filename))
|
||||
.pipe(gulp.dest(targetDir));
|
||||
});
|
||||
|
||||
gulp.task('default', ['build'], function () {
|
||||
gulp.start('watch');
|
||||
});
|
||||
|
@ -20,7 +20,7 @@ into the {body} of the default.hbs template --}}
|
||||
</header>
|
||||
|
||||
{{!-- The main content area --}}
|
||||
<main id="site-main" class="site-main outer" role="main">
|
||||
<main id="site-main" class="site-main outer">
|
||||
<div class="inner">
|
||||
|
||||
<div class="post-feed">
|
||||
|
15
package.json
@ -2,15 +2,20 @@
|
||||
"name": "casper",
|
||||
"description": "The default personal blogging theme for Ghost. Beautiful, minimal and responsive.",
|
||||
"demo": "https://demo.ghost.io",
|
||||
"version": "2.0.3",
|
||||
"version": "2.6.0",
|
||||
"engines": {
|
||||
"ghost": ">=1.2.0"
|
||||
"ghost": ">=2.0.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"screenshots": {
|
||||
"desktop": "assets/screenshot-desktop.jpg",
|
||||
"mobile": "assets/screenshot-mobile.jpg"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "gulp",
|
||||
"zip": "gulp zip",
|
||||
"test": "gscan ."
|
||||
},
|
||||
"author": {
|
||||
"name": "Ghost Foundation",
|
||||
"email": "hello@ghost.org",
|
||||
@ -25,7 +30,8 @@
|
||||
},
|
||||
"keywords": [
|
||||
"ghost",
|
||||
"theme"
|
||||
"theme",
|
||||
"ghost-theme"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -36,13 +42,14 @@
|
||||
"devDependencies": {
|
||||
"autoprefixer": "6.3.6",
|
||||
"cssnano": "3.7.1",
|
||||
"gscan": "^2.0.0",
|
||||
"gulp": "3.9.1",
|
||||
"gulp-livereload": "3.8.1",
|
||||
"gulp-nodemon": "2.1.0",
|
||||
"gulp-postcss": "6.1.1",
|
||||
"gulp-sourcemaps": "1.6.0",
|
||||
"gulp-util": "3.0.7",
|
||||
"gulp-watch": "4.3.8",
|
||||
"gulp-zip": "4.0.0",
|
||||
"postcss-color-function": "2.0.1",
|
||||
"postcss-custom-properties": "5.0.1",
|
||||
"postcss-easy-import": "1.0.1"
|
||||
|
6
page.hbs
@ -12,7 +12,7 @@ into the {body} of the default.hbs template --}}
|
||||
{{!-- Everything inside the #post tags pulls data from the post --}}
|
||||
{{#post}}
|
||||
|
||||
<main id="site-main" class="site-main outer" role="main">
|
||||
<main id="site-main" class="site-main outer">
|
||||
<div class="inner">
|
||||
|
||||
<article class="post-full {{post_class}} {{#unless feature_image}}no-image{{/unless}}">
|
||||
@ -27,7 +27,9 @@ into the {body} of the default.hbs template --}}
|
||||
{{/if}}
|
||||
|
||||
<section class="post-full-content">
|
||||
{{content}}
|
||||
<div class="post-content">
|
||||
{{content}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</article>
|
||||
|
72
partials/byline-multiple.hbs
Normal file
@ -0,0 +1,72 @@
|
||||
<section class="post-full-authors">
|
||||
|
||||
<div class="post-full-authors-content">
|
||||
<p>This post was a collaboration between</p>
|
||||
<p>{{authors}}</p>
|
||||
</div>
|
||||
|
||||
<ul class="author-list">
|
||||
{{#foreach authors}}
|
||||
<li class="author-list-item">
|
||||
|
||||
<div class="author-card">
|
||||
<div class="basic-info">
|
||||
{{#if profile_image}}
|
||||
<img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" />
|
||||
{{else}}
|
||||
<div class="author-profile-image">{{> "icons/avatar"}}</div>
|
||||
{{/if}}
|
||||
<h2>{{name}}</h2>
|
||||
</div>
|
||||
<div class="bio">
|
||||
{{#if bio}}
|
||||
<p>{{bio}}</p>
|
||||
<p><a href="{{url}}">More posts</a> by {{name}}.</p>
|
||||
{{else}}
|
||||
<p>Read <a href="{{url}}">more posts</a> by this author.</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if profile_image}}
|
||||
<a href="{{url}}" class="moving-avatar"><img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" /></a>
|
||||
{{else}}
|
||||
<a href="{{url}}" class="moving-avatar author-profile-image">{{> "icons/avatar"}}</a>
|
||||
{{/if}}
|
||||
|
||||
</li>
|
||||
{{/foreach}}
|
||||
|
||||
</ul>
|
||||
|
||||
</section>
|
||||
|
||||
{{#contentFor "scripts"}}
|
||||
<script>
|
||||
// Adds delay to author card dropups to disappear. This gives enough
|
||||
// time for the user to interact with the author card while they move
|
||||
// the mouse from the avatar to the card. Also makes space for the
|
||||
// interacted avatar.
|
||||
$(document).ready(function () {
|
||||
|
||||
var hoverTimeout;
|
||||
|
||||
$('.author-list-item').hover(function(){
|
||||
var $this = $(this);
|
||||
|
||||
clearTimeout(hoverTimeout);
|
||||
|
||||
$('.author-card').removeClass('hovered');
|
||||
$(this).children('.author-card').addClass('hovered');
|
||||
|
||||
}, function() {
|
||||
var $this = $(this);
|
||||
|
||||
hoverTimeout = setTimeout(function() {
|
||||
$this.children('.author-card').removeClass('hovered');
|
||||
}, 800);
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
{{/contentFor}}
|
23
partials/byline-single.hbs
Normal file
@ -0,0 +1,23 @@
|
||||
{{!-- Everything inside the #author tags pulls data from the author --}}
|
||||
{{#primary_author}}
|
||||
|
||||
<section class="author-card">
|
||||
{{#if profile_image}}
|
||||
<img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" />
|
||||
{{else}}
|
||||
<span class="avatar-wrapper">{{> "icons/avatar"}}</span>
|
||||
{{/if}}
|
||||
<section class="author-card-content">
|
||||
<h4 class="author-card-name"><a href="{{url}}">{{name}}</a></h4>
|
||||
{{#if bio}}
|
||||
<p>{{bio}}</p>
|
||||
{{else}}
|
||||
<p>Read <a href="{{url}}">more posts</a> by this author.</p>
|
||||
{{/if}}
|
||||
</section>
|
||||
</section>
|
||||
<div class="post-full-footer-right">
|
||||
<a class="author-card-button" href="{{url}}">Read More</a>
|
||||
</div>
|
||||
|
||||
{{/primary_author}}
|
@ -20,7 +20,7 @@
|
||||
{{> "icons/facebook"}}
|
||||
</a>
|
||||
</div>
|
||||
<progress class="progress" value="0">
|
||||
<progress id="reading-progress" class="progress" value="0">
|
||||
<div class="progress-container">
|
||||
<span class="progress-bar"></span>
|
||||
</div>
|
||||
|
1
partials/icons/avatar.hbs
Normal file
@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M3.513 18.998C4.749 15.504 8.082 13 12 13s7.251 2.504 8.487 5.998C18.47 21.442 15.417 23 12 23s-6.47-1.558-8.487-4.002zM12 12c2.21 0 4-2.79 4-5s-1.79-4-4-4-4 1.79-4 4 1.79 5 4 5z" fill="#FFF"/></g></svg>
|
After Width: | Height: | Size: 308 B |
0
partials/icons/facebook.hbs
Executable file → Normal file
Before Width: | Height: | Size: 155 B After Width: | Height: | Size: 155 B |
@ -17,10 +17,26 @@
|
||||
</section>
|
||||
</a>
|
||||
<footer class="post-card-meta">
|
||||
{{#if author.profile_image}}
|
||||
<img class="author-profile-image" src="{{author.profile_image}}" alt="{{author.name}}" />
|
||||
{{/if}}
|
||||
<span class="post-card-author">{{author}}</span>
|
||||
|
||||
<ul class="author-list">
|
||||
{{#foreach authors}}
|
||||
<li class="author-list-item">
|
||||
|
||||
<div class="author-name-tooltip">
|
||||
{{name}}
|
||||
</div>
|
||||
|
||||
{{#if profile_image}}
|
||||
<a href="{{url}}" class="static-avatar"><img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" /></a>
|
||||
{{else}}
|
||||
<a href="{{url}}" class="static-avatar author-profile-image">{{> "icons/avatar"}}</a>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/foreach}}
|
||||
</ul>
|
||||
|
||||
<span class="reading-time">{{reading_time}}</span>
|
||||
|
||||
</footer>
|
||||
</div>
|
||||
</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">{{> "icons/facebook"}}</a>
|
||||
<a class="social-link social-link-fb" href="{{facebook_url @blog.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">{{> "icons/twitter"}}</a>
|
||||
<a class="social-link social-link-tw" href="{{twitter_url @blog.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="http://cloud.feedly.com/#subscription/feed/{{@blog.url}}/rss/" target="_blank">{{> "icons/rss"}}</a>
|
||||
<a class="rss-button" href="https://feedly.com/i/subscription/feed/{{@blog.url}}/rss/" target="_blank" rel="noopener">{{> "icons/rss"}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</nav>
|
||||
|
60
post.hbs
@ -12,7 +12,7 @@ into the {body} of the default.hbs template --}}
|
||||
{{!-- Everything inside the #post tags pulls data from the post --}}
|
||||
{{#post}}
|
||||
|
||||
<main id="site-main" class="site-main outer" role="main">
|
||||
<main id="site-main" class="site-main outer">
|
||||
<div class="inner">
|
||||
|
||||
<article class="post-full {{post_class}} {{#unless feature_image}}no-image{{/unless}}">
|
||||
@ -33,7 +33,9 @@ into the {body} of the default.hbs template --}}
|
||||
{{/if}}
|
||||
|
||||
<section class="post-full-content">
|
||||
{{content}}
|
||||
<div class="post-content">
|
||||
{{content}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{!-- Email subscribe form at the bottom of the page --}}
|
||||
@ -46,49 +48,23 @@ into the {body} of the default.hbs template --}}
|
||||
{{/if}}
|
||||
|
||||
<footer class="post-full-footer">
|
||||
{{!-- Everything inside the #author tags pulls data from the author --}}
|
||||
{{#author}}
|
||||
|
||||
<section class="author-card">
|
||||
{{#if profile_image}}
|
||||
<img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" />
|
||||
{{/if}}
|
||||
<section class="author-card-content">
|
||||
<h4 class="author-card-name"><a href="{{url}}">{{name}}</a></h4>
|
||||
{{#if bio}}
|
||||
<p>{{bio}}</p>
|
||||
{{else}}
|
||||
<p>Read <a href="{{url}}">more posts</a> by this author.</p>
|
||||
{{/if}}
|
||||
</section>
|
||||
</section>
|
||||
<div class="post-full-footer-right">
|
||||
<a class="author-card-button" href="{{url}}">Read More</a>
|
||||
</div>
|
||||
{{!-- There are two options for how we display the byline/author-info.
|
||||
If the post has more than one author, we load a specific template
|
||||
from includes/byline-multiple.hbs, otherwise, we just use the
|
||||
default byline. --}}
|
||||
|
||||
{{#has author="count:>1"}}
|
||||
{{> "byline-multiple"}}
|
||||
{{else}}
|
||||
{{> "byline-single"}}
|
||||
{{/has}}
|
||||
|
||||
{{/author}}
|
||||
</footer>
|
||||
|
||||
{{!--
|
||||
|
||||
If you use Disqus comments, just uncomment this block.
|
||||
The only thing you need to change is "test-apkdzgmqhj" - which
|
||||
should be replaced with your own Disqus site-id.
|
||||
|
||||
<section class="post-full-comments">
|
||||
<div id="disqus_thread"></div>
|
||||
<script>
|
||||
var disqus_config = function () {
|
||||
this.page.url = '{{url absolute="true"}}';
|
||||
this.page.identifier = 'ghost-{{comment_id}}';
|
||||
};
|
||||
(function() {
|
||||
var d = document, s = d.createElement('script');
|
||||
s.src = 'https://test-apkdzgmqhj.disqus.com/embed.js';
|
||||
s.setAttribute('data-timestamp', +new Date());
|
||||
(d.head || d.body).appendChild(s);
|
||||
})();
|
||||
</script>
|
||||
If you want to embed comments, this is a good place to do it!
|
||||
</section>
|
||||
--}}
|
||||
|
||||
@ -101,7 +77,7 @@ into the {body} of the default.hbs template --}}
|
||||
<aside class="read-next outer">
|
||||
<div class="inner">
|
||||
<div class="read-next-feed">
|
||||
|
||||
{{#if primary_tag}}
|
||||
{{#get "posts" filter="tags:{{primary_tag.slug}}+id:-{{id}}" limit="3" as |related_posts|}}
|
||||
{{#if related_posts}}
|
||||
<article class="read-next-card"
|
||||
@ -132,6 +108,7 @@ into the {body} of the default.hbs template --}}
|
||||
</article>
|
||||
{{/if}}
|
||||
{{/get}}
|
||||
{{/if}}
|
||||
|
||||
{{!-- If there's a next post, display it using the same markup included from - partials/post-card.hbs --}}
|
||||
{{#next_post}}
|
||||
@ -166,7 +143,7 @@ $(document).ready(function () {
|
||||
$postContent.fitVids();
|
||||
// End fitVids
|
||||
|
||||
var progressBar = document.querySelector('progress');
|
||||
var progressBar = document.querySelector('#reading-progress');
|
||||
var header = document.querySelector('.floating-header');
|
||||
var title = document.querySelector('.post-full-title');
|
||||
|
||||
@ -215,6 +192,7 @@ $(document).ready(function () {
|
||||
window.addEventListener('resize', onResize, false);
|
||||
|
||||
update();
|
||||
|
||||
});
|
||||
</script>
|
||||
{{/contentFor}}
|
||||
|
2
tag.hbs
@ -21,7 +21,7 @@
|
||||
{{/tag}}
|
||||
|
||||
{{!-- The main content area --}}
|
||||
<main id="site-main" class="site-main outer" role="main">
|
||||
<main id="site-main" class="site-main outer">
|
||||
<div class="inner">
|
||||
<div class="post-feed">
|
||||
{{#foreach posts}}
|
||||
|