mirror of
https://github.com/GenZmeY/casper-i18n.git
synced 2024-11-10 02:28:02 +00:00
Merge branch 'main' of https://github.com/TryGhost/Casper into master-upstream
This commit is contained in:
commit
fdce6d76ce
@ -1,17 +0,0 @@
|
|||||||
# 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
19
.github/ISSUE_TEMPLATE.md
vendored
@ -1,19 +0,0 @@
|
|||||||
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:
|
|
15
.github/workflows/test.yml
vendored
15
.github/workflows/test.yml
vendored
@ -1,15 +0,0 @@
|
|||||||
name: Test
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- 'renovate/*'
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push' || (github.event_name == 'pull_request' && !startsWith(github.head_ref, 'renovate/'))
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: yarn test:ci
|
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2013-2020 Ghost Foundation
|
Copyright (c) 2013-2022 Ghost Foundation
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation
|
obtaining a copy of this software and associated documentation
|
||||||
|
@ -34,4 +34,4 @@ If your contribution is not related to translation - contribute it to the origin
|
|||||||
|
|
||||||
# Copyright & License
|
# Copyright & License
|
||||||
|
|
||||||
Copyright (c) 2013-2020 Ghost Foundation - Released under the [MIT license](LICENSE).
|
Copyright (c) 2013-2022 Ghost Foundation - Released under the [MIT license](LICENSE).
|
@ -1,9 +0,0 @@
|
|||||||
# Reporting Security Vulnerabilities
|
|
||||||
|
|
||||||
Potential security vulnerabilities can be reported directly us at `security@ghost.org`. The Ghost Security Team communicates privately and works in a secured, isolated repository for tracking, testing, and resolving security-related issues.
|
|
||||||
|
|
||||||
The full, up-to-date details of our security policy and procedure can always be found in our documentation:
|
|
||||||
|
|
||||||
https://ghost.org/docs/concepts/security/
|
|
||||||
|
|
||||||
Please refer to this before emailing us. Thanks for helping make Ghost safe for everyone 🙏.
|
|
@ -1,2 +1,2 @@
|
|||||||
!function(o){"use strict";o.fn.fitVids=function(e){var t,i,n={customSelector:null,ignore:null};return document.getElementById("fit-vids-style")||(t=document.head||document.getElementsByTagName("head")[0],(i=document.createElement("div")).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>',t.appendChild(i.childNodes[1])),e&&o.extend(n,e),this.each(function(){var e=['iframe[src*="player.vimeo.com"]','iframe[src*="youtube.com"]','iframe[src*="youtube-nocookie.com"]','iframe[src*="kickstarter.com"][src*="video.html"]',"object","embed"];n.customSelector&&e.push(n.customSelector);var r=".fitvidsignore";n.ignore&&(r=r+", "+n.ignore);e=o(this).find(e.join(","));(e=(e=e.not("object object")).not(r)).each(function(){var e,t,i=o(this);0<i.parents(r).length||"embed"===this.tagName.toLowerCase()&&i.parent("object").length||i.parent(".fluid-width-video-wrapper").length||(i.css("height")||i.css("width")||!isNaN(i.attr("height"))&&!isNaN(i.attr("width"))||(i.attr("height",9),i.attr("width",16)),e=("object"===this.tagName.toLowerCase()||i.attr("height")&&!isNaN(parseInt(i.attr("height"),10))?parseInt(i.attr("height"),10):i.height())/(isNaN(parseInt(i.attr("width"),10))?i.width():parseInt(i.attr("width"),10)),i.attr("name")||(t="fitvid"+o.fn.fitVids._count,i.attr("name",t),o.fn.fitVids._count++),i.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+"%"),i.removeAttr("height").removeAttr("width"))})})},o.fn.fitVids._count=0}(window.jQuery||window.Zepto),function(e){e.addEventListener("DOMContentLoaded",function(){e.querySelectorAll(".kg-gallery-image img").forEach(function(e){var t=e.closest(".kg-gallery-image"),e=e.attributes.width.value/e.attributes.height.value;t.style.flex=e+" 1 0%"})})}((window,document)),function(t,i){var r,n,o,s,a,d,l,c=i.querySelector("link[rel=next]");function u(){if(404===this.status)return t.removeEventListener("scroll",f),void t.removeEventListener("resize",v);this.response.querySelectorAll(".post-card").forEach(function(e){r.appendChild(i.importNode(e,!0))});var e=this.response.querySelector("link[rel=next]");e?c.href=e.href:(t.removeEventListener("scroll",f),t.removeEventListener("resize",v)),l=i.documentElement.scrollHeight,s=o=!1}function e(){var e;s||(a+d<=l-n?o=!1:(s=!0,(e=new t.XMLHttpRequest).responseType="document",e.addEventListener("load",u),e.open("GET",c.href),e.send(null)))}function h(){o||t.requestAnimationFrame(e),o=!0}function f(){a=t.scrollY,h()}function v(){d=t.innerHeight,l=i.documentElement.scrollHeight,h()}!c||(r=i.querySelector(".post-feed"))&&(s=o=!(n=300),a=t.scrollY,d=t.innerHeight,l=i.documentElement.scrollHeight,t.addEventListener("scroll",f,{passive:!0}),t.addEventListener("resize",v),h())}(window,document),function(s,a){s.Casper||(s.Casper={}),s.Casper.stickyNavTitle=function(e){var t=a.querySelector(e.navSelector),i=a.querySelector(e.titleSelector),r=s.scrollY,n=!1;function o(){i.getBoundingClientRect().top+s.scrollY+(i.offsetHeight+35)<=r?t.classList.add(e.activeClass):t.classList.remove(e.activeClass),n=!1}s.addEventListener("scroll",function(){r=s.scrollY,function(){n||requestAnimationFrame(o);n=!0}()},{passive:!0}),o()}}(window,document);
|
!function(o){"use strict";o.fn.fitVids=function(e){var t,i,n={customSelector:null,ignore:null};return document.getElementById("fit-vids-style")||(t=document.head||document.getElementsByTagName("head")[0],(i=document.createElement("div")).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>',t.appendChild(i.childNodes[1])),e&&o.extend(n,e),this.each(function(){var e=['iframe[src*="player.vimeo.com"]','iframe[src*="youtube.com"]','iframe[src*="youtube-nocookie.com"]','iframe[src*="kickstarter.com"][src*="video.html"]',"object","embed"];n.customSelector&&e.push(n.customSelector);var r=".fitvidsignore";n.ignore&&(r=r+", "+n.ignore);e=o(this).find(e.join(","));(e=(e=e.not("object object")).not(r)).each(function(){var e,t,i=o(this);0<i.parents(r).length||"embed"===this.tagName.toLowerCase()&&i.parent("object").length||i.parent(".fluid-width-video-wrapper").length||(i.css("height")||i.css("width")||!isNaN(i.attr("height"))&&!isNaN(i.attr("width"))||(i.attr("height",9),i.attr("width",16)),e=("object"===this.tagName.toLowerCase()||i.attr("height")&&!isNaN(parseInt(i.attr("height"),10))?parseInt(i.attr("height"),10):i.height())/(isNaN(parseInt(i.attr("width"),10))?i.width():parseInt(i.attr("width"),10)),i.attr("name")||(t="fitvid"+o.fn.fitVids._count,i.attr("name",t),o.fn.fitVids._count++),i.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+"%"),i.removeAttr("height").removeAttr("width"))})})},o.fn.fitVids._count=0}(window.jQuery||window.Zepto),function(t,i){var r,n,o,d,s,a,c,l=i.querySelector("link[rel=next]");function h(){if(404===this.status)return t.removeEventListener("scroll",p),void t.removeEventListener("resize",f);this.response.querySelectorAll("article.post-card").forEach(function(e){r.appendChild(i.importNode(e,!0))});var e=this.response.querySelector("link[rel=next]");e?l.href=e.href:(t.removeEventListener("scroll",p),t.removeEventListener("resize",f)),c=i.documentElement.scrollHeight,d=o=!1}function e(){var e;d||(s+a<=c-n?o=!1:(d=!0,(e=new t.XMLHttpRequest).responseType="document",e.addEventListener("load",h),e.open("GET",l.href),e.send(null)))}function u(){o||t.requestAnimationFrame(e),o=!0}function p(){s=t.scrollY,u()}function f(){a=t.innerHeight,c=i.documentElement.scrollHeight,u()}!l||(r=i.querySelector(".post-feed"))&&(d=o=!(n=300),s=t.scrollY,a=t.innerHeight,c=i.documentElement.scrollHeight,t.addEventListener("scroll",p,{passive:!0}),t.addEventListener("resize",f),u())}(window,document);
|
||||||
//# sourceMappingURL=casper.js.map
|
//# sourceMappingURL=casper.js.map
|
File diff suppressed because one or more lines are too long
@ -1,2 +1,2 @@
|
|||||||
:root{--blue:#3eb0ef;--green:#a4d037;--purple:#ad26b4;--yellow:#fecd35;--red:#f05230;--darkgrey:#15171a;--midgrey:#738a94;--lightgrey:#c5d2d9;--whitegrey:#e5eff5;--pink:#fa3a57;--brown:#a3821a;--darkmode:#1a1c20}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:#303a3e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;font-size:1.6rem;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 #e4eaed}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:var(--darkgrey);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 var(--whitegrey)}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:#26a6ed;text-decoration:none}a:hover{text-decoration:underline}h1,h2,h3,h4,h5,h6{margin-top:0;line-height:1.15;font-weight:600;text-rendering:optimizeLegibility}h1{margin:0 0 .5em;font-size:5.5rem;font-weight:600}@media (max-width:500px){h1{font-size:2.2rem}}h2{margin:1.5em 0 .5em;font-size:2.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{display:block;max-width:100%;height:auto}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}kbd{padding:3px 5px;font-family:var(--font-mono);font-size:1.5rem;background:#f6f8fa;border:1px solid rgba(124,139,154,.25);border-radius:6px;box-shadow:inset 0 -1px 0 rgba(124,139,154,.25)}@media (max-width:600px){kbd{font-size:1.3rem}}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{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{color:#35373a;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;font-size:1.6rem;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:#daf2fd}::selection{text-shadow:none;background:#daf2fd}hr{position:relative;display:block;width:100%;margin:2.5em 0 3.5em;padding:0;height:1px;border:0;border-top:1px solid #f0f0f0}audio,canvas,iframe,img,svg,video{vertical-align:middle}fieldset{margin:0;padding:0;border:0}textarea{resize:vertical}::not(.gh-content) blockquote,::not(.gh-content) dl,::not(.gh-content) ol,::not(.gh-content) p,::not(.gh-content) 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{padding-left:.3em;line-height:1.6em}li+li{margin-top:.5em}dt{float:left;margin:0 20px 0 0;width:120px;color:#daf2fd;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:#daf2fd}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:#15171a;text-decoration:none}h1,h2,h3,h4,h5,h6{margin-top:0;line-height:1.15;font-weight:600;text-rendering:optimizeLegibility;letter-spacing:-.01em}h1{margin:0 0 .5em;font-size:4.8rem;font-weight:700;letter-spacing:-.015em}@media (max-width:600px){h1{font-size:2.8rem}}h2{margin:1.5em 0 .5em;font-size:2.8rem;font-weight:700}@media (max-width:600px){h2{font-size:2.3rem}}h3{margin:1.5em 0 .5em;font-size:2.4rem;font-weight:600}@media (max-width:600px){h3{font-size:1.7rem}}h4{margin:1.5em 0 .5em;font-size:2rem}@media (max-width:600px){h4{font-size:1.7rem}}h5{font-size:2rem}h5,h6{margin:1.5em 0 .5em}h6{font-size:1.8rem}
|
||||||
/*# sourceMappingURL=global.css.map */
|
/*# sourceMappingURL=global.css.map */
|
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
@ -1,22 +1,3 @@
|
|||||||
/* Variables
|
|
||||||
/* ---------------------------------------------------------- */
|
|
||||||
|
|
||||||
:root {
|
|
||||||
/* Colours */
|
|
||||||
--blue: #3eb0ef;
|
|
||||||
--green: #a4d037;
|
|
||||||
--purple: #ad26b4;
|
|
||||||
--yellow: #fecd35;
|
|
||||||
--red: #f05230;
|
|
||||||
--darkgrey: #15171A;
|
|
||||||
--midgrey: #738a94;
|
|
||||||
--lightgrey: #c5d2d9;
|
|
||||||
--whitegrey: #e5eff5;
|
|
||||||
--pink: #fa3a57;
|
|
||||||
--brown: #a3821a;
|
|
||||||
--darkmode: color-mod(var(--darkgrey) l(+2%));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset
|
/* Reset
|
||||||
/* ---------------------------------------------------------- */
|
/* ---------------------------------------------------------- */
|
||||||
|
|
||||||
@ -127,7 +108,9 @@ table {
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
|
display: block;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
html {
|
html {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -193,6 +176,20 @@ samp {
|
|||||||
font-family: monospace, monospace;
|
font-family: monospace, monospace;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
kbd {
|
||||||
|
padding: 3px 5px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
background: #f6f8fa;
|
||||||
|
border: 1px solid rgba(124, 139, 154, 0.25);
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: inset 0 -1px 0 rgba(124, 139, 154, 0.25);
|
||||||
|
}
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
kbd {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
button,
|
button,
|
||||||
input,
|
input,
|
||||||
optgroup,
|
optgroup,
|
||||||
@ -273,15 +270,12 @@ th {
|
|||||||
========================================================================== */
|
========================================================================== */
|
||||||
|
|
||||||
html {
|
html {
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: scroll;
|
|
||||||
font-size: 62.5%;
|
font-size: 62.5%;
|
||||||
|
|
||||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
overflow-x: hidden;
|
color: #35373A;
|
||||||
color: color-mod(var(--midgrey) l(-30%));
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
line-height: 1.6em;
|
line-height: 1.6em;
|
||||||
@ -298,7 +292,7 @@ body {
|
|||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
background: color-mod(var(--blue) lightness(+30%));
|
background: #daf2fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
@ -309,7 +303,7 @@ hr {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-top: 1px solid color-mod(var(--lightgrey) l(+10%));
|
border-top: 1px solid #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
audio,
|
audio,
|
||||||
@ -331,11 +325,11 @@ textarea {
|
|||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
p,
|
::not(.gh-content) p,
|
||||||
ul,
|
::not(.gh-content) ul,
|
||||||
ol,
|
::not(.gh-content) ol,
|
||||||
dl,
|
::not(.gh-content) dl,
|
||||||
blockquote {
|
::not(.gh-content) blockquote {
|
||||||
margin: 0 0 1.5em 0;
|
margin: 0 0 1.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,16 +360,19 @@ ol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
margin: 0.5em 0;
|
|
||||||
padding-left: 0.3em;
|
padding-left: 0.3em;
|
||||||
line-height: 1.6em;
|
line-height: 1.6em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li + li {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
dt {
|
dt {
|
||||||
float: left;
|
float: left;
|
||||||
margin: 0 20px 0 0;
|
margin: 0 20px 0 0;
|
||||||
width: 120px;
|
width: 120px;
|
||||||
color: var(--darkgrey);
|
color: #daf2fd;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
@ -388,13 +385,7 @@ dd {
|
|||||||
blockquote {
|
blockquote {
|
||||||
margin: 1.5em 0;
|
margin: 1.5em 0;
|
||||||
padding: 0 1.6em 0 1.6em;
|
padding: 0 1.6em 0 1.6em;
|
||||||
border-left: var(--whitegrey) 0.5em solid;
|
border-left: #daf2fd;
|
||||||
}
|
|
||||||
|
|
||||||
blockquote p {
|
|
||||||
margin: 0.8em 0;
|
|
||||||
font-size: 1.2em;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote small {
|
blockquote small {
|
||||||
@ -416,14 +407,10 @@ blockquote cite a {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: color-mod(var(--blue) l(-5%));
|
color: #15171A;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -434,35 +421,38 @@ h6 {
|
|||||||
line-height: 1.15;
|
line-height: 1.15;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
margin: 0 0 0.5em 0;
|
margin: 0 0 0.5em 0;
|
||||||
font-size: 5.5rem;
|
font-size: 4.8rem;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.015em;
|
||||||
}
|
}
|
||||||
@media (max-width: 500px) {
|
@media (max-width: 600px) {
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 2.2rem;
|
font-size: 2.8rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
margin: 1.5em 0 0.5em 0;
|
margin: 1.5em 0 0.5em 0;
|
||||||
font-size: 2.2rem;
|
font-size: 2.8rem;
|
||||||
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@media (max-width: 500px) {
|
@media (max-width: 600px) {
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 1.8rem;
|
font-size: 2.3rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
margin: 1.5em 0 0.5em 0;
|
margin: 1.5em 0 0.5em 0;
|
||||||
font-size: 1.8rem;
|
font-size: 2.4rem;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
@media (max-width: 500px) {
|
@media (max-width: 600px) {
|
||||||
h3 {
|
h3 {
|
||||||
font-size: 1.7rem;
|
font-size: 1.7rem;
|
||||||
}
|
}
|
||||||
@ -470,18 +460,20 @@ h3 {
|
|||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
margin: 1.5em 0 0.5em 0;
|
margin: 1.5em 0 0.5em 0;
|
||||||
font-size: 1.6rem;
|
font-size: 2rem;
|
||||||
font-weight: 500;
|
}
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
h4 {
|
||||||
|
font-size: 1.7rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h5 {
|
h5 {
|
||||||
margin: 1.5em 0 0.5em 0;
|
margin: 1.5em 0 0.5em 0;
|
||||||
font-size: 1.4rem;
|
font-size: 2rem;
|
||||||
font-weight: 500;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h6 {
|
h6 {
|
||||||
margin: 1.5em 0 0.5em 0;
|
margin: 1.5em 0 0.5em 0;
|
||||||
font-size: 1.4rem;
|
font-size: 1.8rem;
|
||||||
font-weight: 500;
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,24 +0,0 @@
|
|||||||
/* eslint-env browser */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gallery card support
|
|
||||||
* Used on any individual post/page
|
|
||||||
*
|
|
||||||
* Detects when a gallery card has been used and applies sizing to make sure
|
|
||||||
* the display matches what is seen in the editor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function (window, document) {
|
|
||||||
var resizeImagesInGalleries = function resizeImagesInGalleries() {
|
|
||||||
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%';
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', resizeImagesInGalleries);
|
|
||||||
})(window, document);
|
|
@ -43,7 +43,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// append contents
|
// append contents
|
||||||
var postElements = this.response.querySelectorAll('.post-card');
|
var postElements = this.response.querySelectorAll('article.post-card');
|
||||||
postElements.forEach(function (item) {
|
postElements.forEach(function (item) {
|
||||||
// document.importNode is important, without it the item's owner
|
// document.importNode is important, without it the item's owner
|
||||||
// document will be different which can break resizing of
|
// document will be different which can break resizing of
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
/* eslint-env browser */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Nav/Title replacement
|
|
||||||
* Used on invividual post pages, displays the post title in place of the nav
|
|
||||||
* bar when scrolling past the title
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* ```
|
|
||||||
* Casper.stickyTitle({
|
|
||||||
* navSelector: '.site-nav-main',
|
|
||||||
* titleSelector: '.post-full-title',
|
|
||||||
* activeClass: 'nav-post-title-active'
|
|
||||||
* });
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function (window, document) {
|
|
||||||
// set up Casper as a global object
|
|
||||||
if (!window.Casper) {
|
|
||||||
window.Casper = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
window.Casper.stickyNavTitle = function stickyNavTitle(options) {
|
|
||||||
var nav = document.querySelector(options.navSelector);
|
|
||||||
var title = document.querySelector(options.titleSelector);
|
|
||||||
|
|
||||||
var lastScrollY = window.scrollY;
|
|
||||||
var ticking = false;
|
|
||||||
|
|
||||||
function onScroll() {
|
|
||||||
lastScrollY = window.scrollY;
|
|
||||||
requestTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
function requestTick() {
|
|
||||||
if (!ticking) {
|
|
||||||
requestAnimationFrame(update);
|
|
||||||
}
|
|
||||||
ticking = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function update() {
|
|
||||||
var trigger = title.getBoundingClientRect().top + window.scrollY;
|
|
||||||
var triggerOffset = title.offsetHeight + 35;
|
|
||||||
|
|
||||||
// show/hide post title
|
|
||||||
if (lastScrollY >= trigger + triggerOffset) {
|
|
||||||
nav.classList.add(options.activeClass);
|
|
||||||
} else {
|
|
||||||
nav.classList.remove(options.activeClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
ticking = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('scroll', onScroll, {passive: true});
|
|
||||||
|
|
||||||
update();
|
|
||||||
};
|
|
||||||
})(window, document);
|
|
90
author.hbs
90
author.hbs
@ -1,61 +1,57 @@
|
|||||||
{{!< default}}
|
{{!< default}}
|
||||||
{{!-- The tag above means - insert everything in this file into the {body} of the default.hbs template --}}
|
{{!-- The tag above means - insert everything in this file into the {body} of the default.hbs template --}}
|
||||||
|
|
||||||
{{#author}}
|
|
||||||
{{!-- Everything inside the #author tags pulls data from the author --}}
|
|
||||||
|
|
||||||
|
<section class="outer">
|
||||||
<header class="site-archive-header">
|
|
||||||
{{> site-header}}
|
|
||||||
{{> header-background background=cover_image}} {{!--Special header-image.hbs partial to generate the background image--}}
|
|
||||||
<div class="inner">
|
|
||||||
<div class="site-header-content author-header">
|
|
||||||
{{#if profile_image}}
|
|
||||||
<img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" />
|
|
||||||
{{else}}
|
|
||||||
<span class="author-profile-image">{{> "icons/avatar"}}</span>
|
|
||||||
{{/if}}
|
|
||||||
<div class="author-header-content">
|
|
||||||
<h1 class="site-title">{{name}}</h1>
|
|
||||||
{{#if bio}}
|
|
||||||
<h2 class="author-bio">{{bio}}</h2>
|
|
||||||
{{/if}}
|
|
||||||
<div class="author-meta">
|
|
||||||
{{#if location}}
|
|
||||||
<div class="author-location">{{location}}</div>
|
|
||||||
{{/if}}
|
|
||||||
<div class="author-stats">
|
|
||||||
{{plural ../pagination.total empty=(t "No posts") singular=(t "1 post") plural=(t "% posts")}}
|
|
||||||
</div>
|
|
||||||
{{#if website}}
|
|
||||||
<span class="author-social-link"><a href="{{website}}" target="_blank" rel="noopener">Website</a></span>
|
|
||||||
{{/if}}
|
|
||||||
{{#if twitter}}
|
|
||||||
<span class="author-social-link"><a href="{{twitter_url}}" target="_blank" rel="noopener">Twitter</a></span>
|
|
||||||
{{/if}}
|
|
||||||
{{#if facebook}}
|
|
||||||
<span class="author-social-link"><a href="{{facebook_url}}" target="_blank" rel="noopener">Facebook</a></span>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
{{/author}}
|
|
||||||
|
|
||||||
{{!-- The main content area --}}
|
|
||||||
<main id="site-main" class="site-main outer">
|
|
||||||
<div class="inner posts">
|
<div class="inner posts">
|
||||||
|
|
||||||
|
<header class="author-profile">
|
||||||
|
{{#author}}
|
||||||
|
{{!-- Everything inside the #author tags pulls data from the author --}}
|
||||||
|
|
||||||
|
<div class="author-profile-content">
|
||||||
|
|
||||||
|
{{#if profile_image}}
|
||||||
|
<img class="author-profile-pic" src="{{profile_image}}" alt="{{name}}" />
|
||||||
|
{{else}}
|
||||||
|
<span class="author-profile-pic">{{> "icons/avatar"}}</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<h1>{{name}}</h1>
|
||||||
|
<p>
|
||||||
|
{{#if bio}}
|
||||||
|
{{bio}}
|
||||||
|
{{else}}
|
||||||
|
{{plural ../pagination.total empty='No posts' singular='% post' plural='% posts'}} published
|
||||||
|
{{/if}}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="author-profile-meta">
|
||||||
|
{{#if location}}
|
||||||
|
<div class="author-profile-location">📍 {{location}}</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#if website}}
|
||||||
|
<span><a class="author-profile-social-link" href="{{website}}" target="_blank" rel="noopener">{{website}}</a></span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if twitter}}
|
||||||
|
<span><a class="author-profile-social-link" href="{{twitter_url}}" target="_blank" rel="noopener">{{twitter_url}}</a></span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if facebook}}
|
||||||
|
<span><a class="author-profile-social-link" href="{{facebook_url}}" target="_blank" rel="noopener">{{facebook_url}}</a></span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{/author}}
|
||||||
|
</header>
|
||||||
|
|
||||||
<div class="post-feed">
|
<div class="post-feed">
|
||||||
{{#foreach posts}}
|
{{#foreach posts}}
|
||||||
|
|
||||||
{{!-- The tag below includes the markup for each post - partials/post-card.hbs --}}
|
{{!-- The tag below includes the markup for each post - partials/post-card.hbs --}}
|
||||||
{{> "post-card"}}
|
{{> "post-card"}}
|
||||||
|
|
||||||
{{/foreach}}
|
{{/foreach}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</section>
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"github": {
|
|
||||||
"token": "<gh-personal-access-token>"
|
|
||||||
}
|
|
||||||
}
|
|
202
default.hbs
202
default.hbs
@ -1,139 +1,115 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{@site.lang}}">
|
<html lang="{{@site.locale}}"{{#match @custom.color_scheme "Dark"}} class="dark-mode"{{/match}}{{#match @custom.color_scheme "Auto"}} class="auto-color"{{/match}}>
|
||||||
<head>
|
<head>
|
||||||
|
|
||||||
{{!-- Document Settings --}}
|
{{!-- Basic meta - advanced meta is output with {ghost_head} below --}}
|
||||||
|
<title>{{meta_title}}</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
|
||||||
{{!-- Base Meta --}}
|
|
||||||
<title>{{meta_title}}</title>
|
|
||||||
<meta name="HandheldFriendly" content="True" />
|
<meta name="HandheldFriendly" content="True" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|
||||||
{{!-- Styles'n'Scripts --}}
|
<style>
|
||||||
|
:root {
|
||||||
|
{{#if @custom.header_button_background}}
|
||||||
|
--button-bg-color: {{@custom.header_button_background}};
|
||||||
|
{{/if}}
|
||||||
|
--button-text-color: {{#match @custom.header_button_text_color "Light"}}#fff{{else}}var(--color-darkgrey){{/match}};
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{{!-- Theme assets - use the {asset} helper to reference styles & scripts,
|
||||||
|
this will take care of caching and cache-busting automatically --}}
|
||||||
<link rel="stylesheet" type="text/css" href="{{asset "built/screen.css"}}" />
|
<link rel="stylesheet" type="text/css" href="{{asset "built/screen.css"}}" />
|
||||||
|
|
||||||
{{!-- This tag outputs SEO meta+structured data and other important settings --}}
|
{{!-- This tag outputs all your advanced SEO meta, structured data, and other important settings,
|
||||||
|
it should always be the last tag before the closing head tag --}}
|
||||||
{{ghost_head}}
|
{{ghost_head}}
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="{{body_class}}">
|
|
||||||
|
|
||||||
<div class="site-wrapper">
|
<body class="{{body_class}}{{#match @custom.title_font "=" "Elegant serif"}} has-serif-title{{/match}}{{#match @custom.body_font "=" "Modern sans-serif"}} has-sans-body{{/match}}">
|
||||||
|
<div class="viewport">
|
||||||
|
|
||||||
{{!-- All the main content gets inserted here, index.hbs, post.hbs, etc --}}
|
<header id="gh-head" class="gh-head{{#match @custom.publication_cover_style "!=" "None"}} has-cover{{/match}}">
|
||||||
|
<nav class="gh-head-inner inner gh-container">
|
||||||
|
|
||||||
|
<div class="gh-head-brand">
|
||||||
|
<a class="gh-head-logo" href="{{@site.url}}">
|
||||||
|
{{#if @site.logo}}
|
||||||
|
<img src="{{@site.logo}}" alt="{{@site.title}}" />
|
||||||
|
{{else}}
|
||||||
|
{{@site.title}}
|
||||||
|
{{/if}}
|
||||||
|
</a>
|
||||||
|
<a class="gh-burger" role="button">
|
||||||
|
<div class="gh-burger-box">
|
||||||
|
<div class="gh-burger-inner"></div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="gh-head-menu">
|
||||||
|
{{navigation}}
|
||||||
|
</div>
|
||||||
|
<div class="gh-head-actions">
|
||||||
|
<div class="gh-social">
|
||||||
|
{{#if @site.facebook}}
|
||||||
|
<a class="gh-social-facebook" href="{{facebook_url @site.facebook}}" title="Facebook" target="_blank" rel="noopener">{{> "icons/facebook"}}</a>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @site.twitter}}
|
||||||
|
<a class="gh-social-twitter" href="{{twitter_url @site.twitter}}" title="Twitter" target="_blank" rel="noopener">{{> "icons/twitter"}}</a>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#unless @member}}
|
||||||
|
<a class="gh-head-button" href="#/portal/signup" data-portal="signup">Subscribe</a>
|
||||||
|
{{else}}
|
||||||
|
<a class="gh-head-button" href="#/portal/account" data-portal="account">Account</a>
|
||||||
|
{{/unless}}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="site-content">
|
||||||
|
{{!-- All other templates get inserted here, index.hbs, post.hbs, etc --}}
|
||||||
{{{body}}}
|
{{{body}}}
|
||||||
|
|
||||||
{{!-- The footer at the very bottom of the screen --}}
|
|
||||||
<footer class="site-footer outer">
|
|
||||||
<div class="site-footer-content inner">
|
|
||||||
<section class="copyright"><a href="{{@site.url}}">{{@site.title}}</a> © {{date format="YYYY"}}</section>
|
|
||||||
<nav class="site-footer-nav">
|
|
||||||
<a href="{{@site.url}}">{{t "Latest Posts"}}</a>
|
|
||||||
{{#if @site.facebook}}<a href="{{facebook_url @site.facebook}}" target="_blank" rel="noopener">Facebook</a>{{/if}}
|
|
||||||
{{#if @site.twitter}}<a href="{{twitter_url @site.twitter}}" target="_blank" rel="noopener">Twitter</a>{{/if}}
|
|
||||||
<a href="https://ghost.org" target="_blank" rel="noopener">Ghost</a>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{!-- The big email subscribe modal content --}}
|
{{!-- The global footer at the very bottom of the screen --}}
|
||||||
{{#if @labs.members}}
|
<footer class="site-footer outer">
|
||||||
<div class="subscribe-notification subscribe-success-message">
|
<div class="inner">
|
||||||
<a class="subscribe-close-button" href="javascript:;"></a>
|
<section class="copyright"><a href="{{@site.url}}">{{@site.title}}</a> © {{date format="YYYY"}}</section>
|
||||||
{{t "You’ve successfully subscribed to"}} {{@site.title}}!
|
<nav class="site-footer-nav">
|
||||||
</div>
|
{{navigation type="secondary"}}
|
||||||
<div class="subscribe-notification subscribe-failure-message">
|
</nav>
|
||||||
<a class="subscribe-close-button" href="javascript:;"></a>
|
<div><a href="https://ghost.org/" target="_blank" rel="noopener">Powered by Ghost</a></div>
|
||||||
{{t "Could not sign up! Invalid sign up link."}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="subscribe" class="subscribe-overlay">
|
|
||||||
<a class="subscribe-close-overlay" href="#"></a>
|
|
||||||
<a class="subscribe-close-button" href="#"></a>
|
|
||||||
<div class="subscribe-overlay-content">
|
|
||||||
{{#if @site.logo}}
|
|
||||||
<img class="subscribe-overlay-logo" src="{{@site.logo}}" alt="{{@site.title}}" />
|
|
||||||
{{/if}}
|
|
||||||
<div class="subscribe-form">
|
|
||||||
<h1 class="subscribe-overlay-title">{{t "Subscribe to"}} {{@site.title}}</h1>
|
|
||||||
<p class="subscribe-overlay-description">{{t "Stay up to date! Get all the latest & greatest posts delivered straight to your inbox"}}</p>
|
|
||||||
<form data-members-form="subscribe">
|
|
||||||
<div class="form-group">
|
|
||||||
<input class="subscribe-email" data-members-email placeholder="youremail@example.com"
|
|
||||||
autocomplete="false" />
|
|
||||||
<button class="button primary" type="submit">
|
|
||||||
<span class="button-content">{{t "Subscribe"}}</span>
|
|
||||||
<span class="button-loader">{{> "icons/loader"}}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="message-success">
|
|
||||||
{{t "<strong>Great!</strong> Check your inbox and click the link to confirm your subscription."}}
|
|
||||||
</div>
|
|
||||||
<div class="message-error">
|
|
||||||
{{t "Please enter a valid email address!"}}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{!-- jQuery, required for fitvids --}}
|
</div>
|
||||||
<script
|
{{!-- /.viewport --}}
|
||||||
src="https://code.jquery.com/jquery-3.5.1.min.js"
|
|
||||||
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
|
|
||||||
crossorigin="anonymous">
|
|
||||||
</script>
|
|
||||||
{{!-- Fitvids (for responsive video embeds), infinite scroll, floating header, and gallery card support --}}
|
|
||||||
<script src="{{asset "built/casper.js"}}"></script>
|
|
||||||
|
|
||||||
{{!-- Scripts for Members subscription --}}
|
|
||||||
<script>
|
|
||||||
// Parse the URL parameter
|
|
||||||
function getParameterByName(name, url) {
|
|
||||||
if (!url) url = window.location.href;
|
|
||||||
name = name.replace(/[\[\]]/g, "\\$&");
|
|
||||||
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
|
|
||||||
results = regex.exec(url);
|
|
||||||
if (!results) return null;
|
|
||||||
if (!results[2]) return '';
|
|
||||||
return decodeURIComponent(results[2].replace(/\+/g, " "));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give the parameter a variable name
|
{{!-- Scripts - handle member signups, responsive videos, infinite scroll, floating headers, and galleries --}}
|
||||||
var action = getParameterByName('action');
|
<script
|
||||||
var success = getParameterByName('success');
|
src="https://code.jquery.com/jquery-3.5.1.min.js"
|
||||||
|
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
|
||||||
|
crossorigin="anonymous">
|
||||||
|
</script>
|
||||||
|
<script src="{{asset "built/casper.js"}}"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
// Mobile Menu Trigger
|
||||||
|
$('.gh-burger').click(function () {
|
||||||
|
$('body').toggleClass('gh-head-open');
|
||||||
|
});
|
||||||
|
// FitVids - Makes video embeds responsive
|
||||||
|
$(".gh-content").fitVids();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
$(document).ready(function () {
|
{{!-- Ghost outputs required functional scripts with this tag - it should always be the last thing before the closing body tag --}}
|
||||||
if (action == 'subscribe' && (success === null || success === 'true')) {
|
{{ghost_foot}}
|
||||||
$('body').addClass('subscribe-success');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action == 'subscribe' && success === 'false') {
|
|
||||||
$('body').addClass('subscribe-failure');
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.subscribe-notification .subscribe-close-button').click(function () {
|
|
||||||
$('.subscribe-notification').addClass('close');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Reset form on opening subscrion overlay
|
|
||||||
$('.subscribe-button').click(function() {
|
|
||||||
$('.subscribe-overlay form').removeClass();
|
|
||||||
$('.subscribe-email').val('');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{!-- 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. --}}
|
|
||||||
{{{block "scripts"}}}
|
|
||||||
|
|
||||||
{{!-- Ghost outputs important scripts and data with this tag - it should always be the very last thing before the closing body tag --}}
|
|
||||||
{{ghost_foot}}
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,30 +1,37 @@
|
|||||||
|
{{!< default}}
|
||||||
|
|
||||||
{{!--
|
{{!--
|
||||||
This error template is used for all 404 errors, which might occur on your site.
|
|
||||||
It's a good idea to keep this template as minimal as possible in terms of both file size and complexity.
|
There are two error files in this theme, one for 404s and one for all other errors.
|
||||||
|
This file is the former, and handles all 404 Page Not Found errors.
|
||||||
|
|
||||||
|
The 404 error is the most common error that a visitor might see, for example when
|
||||||
|
following a broken link
|
||||||
|
|
||||||
|
Keep this template as lightweight as you can!
|
||||||
|
|
||||||
--}}
|
--}}
|
||||||
|
|
||||||
{{!< default}}
|
<section class="outer error-content">
|
||||||
{{!-- The tag above means: insert everything in this file
|
|
||||||
into the {body} of the default.hbs template --}}
|
|
||||||
|
|
||||||
<header class="site-header">
|
|
||||||
{{> site-header}}
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main id="site-main" class="site-main outer error-content">
|
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<section class="error-message">
|
<section class="error-message">
|
||||||
<h1 class="error-code">{{statusCode}}</h1>
|
<h1 class="error-code">{{statusCode}}</h1>
|
||||||
<p class="error-description">{{message}}</p>
|
<p class="error-description">{{message}}</p>
|
||||||
<a class="error-link" href="{{@site.url}}">{{t "Go to the front page"}} →</a>
|
<a class="error-link" href="{{@site.url}}">{{t "Go to the front page"}} →</a>
|
||||||
</section>
|
</section>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
{{#get "posts" limit="3" include="authors,tags"}}
|
{{!-- Given that people landing on this page didn't find what they
|
||||||
<div class="post-feed">
|
were looking for, let's give them some alternative stuff to read. --}}
|
||||||
{{#foreach posts}}
|
<aside class="read-more-wrap">
|
||||||
{{> "post-card"}}
|
<div class="read-more inner">
|
||||||
|
{{#get "posts" include="authors" limit="3" as |more_posts|}}
|
||||||
|
{{#if more_posts}}
|
||||||
|
{{#foreach more_posts}}
|
||||||
|
{{> "post-card"}}
|
||||||
{{/foreach}}
|
{{/foreach}}
|
||||||
</div>
|
{{/if}}
|
||||||
{{/get}}
|
{{/get}}
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</aside>
|
16
error.hbs
16
error.hbs
@ -1,7 +1,15 @@
|
|||||||
{{!--
|
{{!--
|
||||||
This error template is used for all 400/500 errors, except 404, which might occur on your site.
|
|
||||||
It's a good idea to keep this template as minimal as possible in terms of both file size and complexity.
|
There are two error files in this theme, one for 404s and one for all other errors.
|
||||||
You'll notice that we *don't* use any JavaScript, or ghost_head / ghost_foot in this file.
|
This file is the latter, and handle all 400/500 errors that might occur.
|
||||||
|
|
||||||
|
Because 500 errors in particular usuall happen when a server is struggling, this
|
||||||
|
template is as simple as possible. No template dependencies, no JS, no API calls.
|
||||||
|
This is to prevent rendering the error-page itself compounding the issue causing
|
||||||
|
the error in the first place.
|
||||||
|
|
||||||
|
Keep this template as lightweight as you can!
|
||||||
|
|
||||||
--}}
|
--}}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@ -32,7 +40,7 @@ You'll notice that we *don't* use any JavaScript, or ghost_head / ghost_foot in
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main id="site-main" class="site-main outer error-content">
|
<main class="outer error-content">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
|
|
||||||
<section class="error-message">
|
<section class="error-message">
|
||||||
|
94
gulpfile.js
94
gulpfile.js
@ -80,7 +80,9 @@ function zipper(done) {
|
|||||||
'**',
|
'**',
|
||||||
'!node_modules', '!node_modules/**',
|
'!node_modules', '!node_modules/**',
|
||||||
'!dist', '!dist/**',
|
'!dist', '!dist/**',
|
||||||
'!yarn-error.log'
|
'!yarn-error.log',
|
||||||
|
'!yarn.lock',
|
||||||
|
'!gulpfile.js'
|
||||||
]),
|
]),
|
||||||
zip(filename),
|
zip(filename),
|
||||||
dest('dist/')
|
dest('dist/')
|
||||||
@ -96,10 +98,10 @@ exports.build = build;
|
|||||||
exports.zip = series(build, zipper);
|
exports.zip = series(build, zipper);
|
||||||
exports.default = series(build, serve, watcher);
|
exports.default = series(build, serve, watcher);
|
||||||
|
|
||||||
exports.release = () => {
|
exports.release = async () => {
|
||||||
// @NOTE: https://yarnpkg.com/lang/en/docs/cli/version/
|
// @NOTE: https://yarnpkg.com/lang/en/docs/cli/version/
|
||||||
// require(./package.json) can run into caching issues, this re-reads from file everytime on release
|
// require(./package.json) can run into caching issues, this re-reads from file everytime on release
|
||||||
var packageJSON = JSON.parse(fs.readFileSync('./package.json'));
|
let packageJSON = JSON.parse(fs.readFileSync('./package.json'));
|
||||||
const newVersion = packageJSON.version;
|
const newVersion = packageJSON.version;
|
||||||
|
|
||||||
if (!newVersion || newVersion === '') {
|
if (!newVersion || newVersion === '') {
|
||||||
@ -109,45 +111,36 @@ exports.release = () => {
|
|||||||
|
|
||||||
console.log(`\nCreating release for ${newVersion}...`);
|
console.log(`\nCreating release for ${newVersion}...`);
|
||||||
|
|
||||||
let config;
|
const githubToken = process.env.GST_TOKEN;
|
||||||
try {
|
|
||||||
config = require('./config');
|
|
||||||
} catch (err) {
|
|
||||||
config = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config || !config.github || !config.github.token) {
|
if (!githubToken) {
|
||||||
console.log('Please copy config.example.json and configure Github token.');
|
console.log('Please configure your environment with a GitHub token located in GST_TOKEN');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let compatibleWithGhost;
|
try {
|
||||||
|
const result = await inquirer.prompt([{
|
||||||
|
type: 'input',
|
||||||
|
name: 'compatibleWithGhost',
|
||||||
|
message: 'Which version of Ghost is it compatible with?',
|
||||||
|
default: '4.0.0'
|
||||||
|
}]);
|
||||||
|
|
||||||
return inquirer.prompt([{
|
const compatibleWithGhost = result.compatibleWithGhost;
|
||||||
type: 'input',
|
|
||||||
name: 'compatibleWithGhost',
|
const releasesResponse = await releaseUtils.releases.get({
|
||||||
message: 'Which version of Ghost is it compatible with?',
|
userAgent: 'Casper',
|
||||||
default: '3.0.0'
|
uri: `https://api.github.com/repos/${REPO_READONLY}/releases`
|
||||||
}])
|
});
|
||||||
.then(result => {
|
|
||||||
compatibleWithGhost = result.compatibleWithGhost;
|
if (!releasesResponse || !releasesResponse) {
|
||||||
return Promise.resolve();
|
|
||||||
})
|
|
||||||
.then(() => releaseUtils.releases.get({
|
|
||||||
userAgent: 'Casper',
|
|
||||||
uri: `https://api.github.com/repos/${REPO_READONLY}/releases`
|
|
||||||
}))
|
|
||||||
.then((response) => {
|
|
||||||
if (!response || !response.length) {
|
|
||||||
console.log('No releases found. Skipping...');
|
console.log('No releases found. Skipping...');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let previousVersion = response[0].tag_name || response[0].name;
|
let previousVersion = releasesResponse[0].tag_name || releasesResponse[0].name;
|
||||||
console.log(`Previous version: ${previousVersion}`);
|
console.log(`Previous version: ${previousVersion}`);
|
||||||
return Promise.resolve(previousVersion);
|
|
||||||
})
|
|
||||||
.then((previousVersion) => {
|
|
||||||
const changelog = new releaseUtils.Changelog({
|
const changelog = new releaseUtils.Changelog({
|
||||||
changelogPath: CHANGELOG_PATH,
|
changelogPath: CHANGELOG_PATH,
|
||||||
folder: path.join(process.cwd(), '.')
|
folder: path.join(process.cwd(), '.')
|
||||||
@ -161,27 +154,22 @@ exports.release = () => {
|
|||||||
.sort()
|
.sort()
|
||||||
.clean();
|
.clean();
|
||||||
|
|
||||||
return Promise.resolve();
|
const newReleaseResponse = await releaseUtils.releases.create({
|
||||||
})
|
draft: true,
|
||||||
.then(() => releaseUtils.releases.create({
|
preRelease: false,
|
||||||
draft: true,
|
tagName: 'v' + newVersion,
|
||||||
preRelease: false,
|
releaseName: newVersion,
|
||||||
tagName: newVersion,
|
userAgent: 'Casper',
|
||||||
releaseName: newVersion,
|
uri: `https://api.github.com/repos/${REPO}/releases`,
|
||||||
userAgent: 'Casper',
|
github: {
|
||||||
uri: `https://api.github.com/repos/${REPO}/releases`,
|
token: githubToken
|
||||||
github: {
|
},
|
||||||
token: config.github.token
|
content: [`**Compatible with Ghost ≥ ${compatibleWithGhost}**\n\n`],
|
||||||
},
|
changelogPath: CHANGELOG_PATH
|
||||||
content: [`**Compatible with Ghost ≥ ${compatibleWithGhost}**\n\n`],
|
});
|
||||||
changelogPath: CHANGELOG_PATH
|
console.log(`\nRelease draft generated: ${newReleaseResponse.releaseUrl}\n`);
|
||||||
}))
|
} catch (err) {
|
||||||
.then((response) => {
|
|
||||||
console.log(`\nRelease draft generated: ${response.releaseUrl}\n`);
|
|
||||||
return Promise.resolve();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error(err);
|
console.error(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
103
index.hbs
103
index.hbs
@ -2,29 +2,37 @@
|
|||||||
{{!-- The tag above means: insert everything in this file
|
{{!-- The tag above means: insert everything in this file
|
||||||
into the {body} of the default.hbs template --}}
|
into the {body} of the default.hbs template --}}
|
||||||
|
|
||||||
<header class="site-home-header">
|
{{#match @custom.publication_cover_style "!=" "None"}}
|
||||||
{{> header-background background=@site.cover_image}} {{!--Special header-image.hbs partial to generate the background image--}}
|
<div class="site-header-content{{#match @custom.publication_cover_style "Large"}} large{{/match}}">
|
||||||
<div class="inner">
|
{{#if @site.cover_image}}
|
||||||
{{> "site-nav"}}
|
{{!-- This is a responsive image, it loads different sizes depending on device
|
||||||
<div class="site-header-content">
|
https://medium.freecodecamp.org/a-guide-to-responsive-images-with-ready-to-use-templates-c400bd65c433 --}}
|
||||||
<h1 class="site-title">
|
<img class="site-header-cover"
|
||||||
{{#if @site.logo}}
|
srcset="{{img_url @site.cover_image size="s"}} 300w,
|
||||||
<img class="site-logo" src="{{img_url @site.logo size="l"}}" alt="{{@site.title}}" />
|
{{img_url @site.cover_image size="m"}} 600w,
|
||||||
{{else}}
|
{{img_url @site.cover_image size="l"}} 1000w,
|
||||||
{{@site.title}}
|
{{img_url @site.cover_image size="xl"}} 2000w"
|
||||||
{{/if}}
|
sizes="100vw"
|
||||||
</h1>
|
src="{{img_url @site.cover_image size="xl"}}"
|
||||||
<h2 class="site-description">{{@site.description}}</h2>
|
alt=""
|
||||||
</div>
|
/>
|
||||||
</div>
|
{{/if}}
|
||||||
|
<h1 class="site-title">
|
||||||
|
{{#if @site.logo}}
|
||||||
|
<img class="site-logo" src="{{img_url @site.logo size="m"}}" alt="{{@site.title}}" />
|
||||||
|
{{else}}
|
||||||
|
{{@site.title}}
|
||||||
|
{{/if}}
|
||||||
|
</h1>
|
||||||
|
<p>{{@site.description}}</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
{{/match}}
|
||||||
|
|
||||||
{{!-- The main content area --}}
|
{{!-- The main content area --}}
|
||||||
<main id="site-main" class="site-main outer">
|
<main id="site-main" class="site-main outer">
|
||||||
<div class="inner posts">
|
<div class="inner posts">
|
||||||
|
|
||||||
<div class="post-feed">
|
<div class="post-feed{{#match @custom.feed_layout "List"}} list{{/match}}">
|
||||||
{{#foreach posts}}
|
{{#foreach posts}}
|
||||||
|
|
||||||
{{!-- The tag below includes the markup for each post - partials/post-card.hbs --}}
|
{{!-- The tag below includes the markup for each post - partials/post-card.hbs --}}
|
||||||
@ -35,64 +43,3 @@ into the {body} of the default.hbs template --}}
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{{> site-header}}
|
|
||||||
|
|
||||||
{{!-- The #contentFor helper here will send everything inside it up to the matching #block helper found in default.hbs --}}
|
|
||||||
{{#contentFor "scripts"}}
|
|
||||||
<script>
|
|
||||||
|
|
||||||
// NOTE: Scroll performance is poor in Safari
|
|
||||||
// - this appears to be due to the events firing much more slowly in Safari.
|
|
||||||
// Dropping the scroll event and using only a raf loop results in smoother
|
|
||||||
// scrolling but continuous processing even when not scrolling
|
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
var nav = document.querySelector('.site-nav-main .site-nav');
|
|
||||||
var feed = document.querySelector('.post-feed');
|
|
||||||
|
|
||||||
var lastScrollY = window.scrollY;
|
|
||||||
var lastWindowHeight = window.innerHeight;
|
|
||||||
var lastDocumentHeight = $(document).height();
|
|
||||||
var ticking = false;
|
|
||||||
|
|
||||||
function onScroll() {
|
|
||||||
lastScrollY = window.scrollY;
|
|
||||||
requestTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onResize() {
|
|
||||||
lastWindowHeight = window.innerHeight;
|
|
||||||
lastDocumentHeight = $(document).height();
|
|
||||||
requestTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
function requestTick() {
|
|
||||||
if (!ticking) {
|
|
||||||
requestAnimationFrame(update);
|
|
||||||
}
|
|
||||||
ticking = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function update() {
|
|
||||||
var trigger = feed.getBoundingClientRect().top + window.scrollY;
|
|
||||||
var progressMax = lastDocumentHeight - lastWindowHeight;
|
|
||||||
|
|
||||||
// show/hide nav
|
|
||||||
if (lastScrollY >= trigger - 20) {
|
|
||||||
nav.classList.add('fixed-nav-active');
|
|
||||||
} else {
|
|
||||||
nav.classList.remove('fixed-nav-active');
|
|
||||||
}
|
|
||||||
|
|
||||||
ticking = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('scroll', onScroll, { passive: true });
|
|
||||||
window.addEventListener('resize', onResize, false);
|
|
||||||
|
|
||||||
update();
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{{/contentFor}}
|
|
117
package.json
117
package.json
@ -2,10 +2,10 @@
|
|||||||
"name": "casper-i18n",
|
"name": "casper-i18n",
|
||||||
"description": "The same casper theme, but with localization support",
|
"description": "The same casper theme, but with localization support",
|
||||||
"demo": "https://demo.ghost.io",
|
"demo": "https://demo.ghost.io",
|
||||||
"version": "3.1.2",
|
"version": "4.7.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"ghost": ">=3.0.0",
|
"ghost": ">=4.0.0",
|
||||||
"ghost-api": "v3"
|
"ghost-api": "v4"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"screenshots": {
|
"screenshots": {
|
||||||
@ -25,7 +25,7 @@
|
|||||||
"author": {
|
"author": {
|
||||||
"name": "Ghost Foundation",
|
"name": "Ghost Foundation",
|
||||||
"email": "hello@ghost.org",
|
"email": "hello@ghost.org",
|
||||||
"url": "https://ghost.org"
|
"url": "https://ghost.org/"
|
||||||
},
|
},
|
||||||
"gpm": {
|
"gpm": {
|
||||||
"type": "theme",
|
"type": "theme",
|
||||||
@ -46,19 +46,19 @@
|
|||||||
"bugs": "https://github.com/TryGhost/Casper/issues",
|
"bugs": "https://github.com/TryGhost/Casper/issues",
|
||||||
"contributors": "https://github.com/TryGhost/Casper/graphs/contributors",
|
"contributors": "https://github.com/TryGhost/Casper/graphs/contributors",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tryghost/release-utils": "0.6.8",
|
"@tryghost/release-utils": "0.6.12",
|
||||||
"autoprefixer": "10.0.4",
|
"autoprefixer": "10.2.5",
|
||||||
"beeper": "2.0.0",
|
"beeper": "2.1.0",
|
||||||
"cssnano": "4.1.10",
|
"cssnano": "4.1.10",
|
||||||
"gscan": "3.6.0",
|
"gscan": "4.22.0",
|
||||||
"gulp": "4.0.2",
|
"gulp": "4.0.2",
|
||||||
"gulp-concat": "2.6.1",
|
"gulp-concat": "2.6.1",
|
||||||
"gulp-livereload": "4.0.2",
|
"gulp-livereload": "4.0.2",
|
||||||
"gulp-postcss": "9.0.0",
|
"gulp-postcss": "9.0.0",
|
||||||
"gulp-uglify": "3.0.2",
|
"gulp-uglify": "3.0.2",
|
||||||
"gulp-zip": "5.0.2",
|
"gulp-zip": "5.1.0",
|
||||||
"inquirer": "7.3.3",
|
"inquirer": "8.0.0",
|
||||||
"postcss": "8.1.10",
|
"postcss": "8.2.8",
|
||||||
"postcss-color-mod-function": "3.0.3",
|
"postcss-color-mod-function": "3.0.3",
|
||||||
"postcss-easy-import": "3.0.0",
|
"postcss-easy-import": "3.0.0",
|
||||||
"pump": "3.0.0"
|
"pump": "3.0.0"
|
||||||
@ -87,6 +87,101 @@
|
|||||||
"xl": {
|
"xl": {
|
||||||
"width": 2000
|
"width": 2000
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"card_assets": true,
|
||||||
|
"custom": {
|
||||||
|
"title_font": {
|
||||||
|
"type": "select",
|
||||||
|
"options": [
|
||||||
|
"Modern sans-serif",
|
||||||
|
"Elegant serif"
|
||||||
|
],
|
||||||
|
"default": "Modern sans-serif"
|
||||||
|
},
|
||||||
|
"body_font": {
|
||||||
|
"type": "select",
|
||||||
|
"options": [
|
||||||
|
"Modern sans-serif",
|
||||||
|
"Elegant serif"
|
||||||
|
],
|
||||||
|
"default": "Elegant serif"
|
||||||
|
},
|
||||||
|
"publication_cover_style": {
|
||||||
|
"type": "select",
|
||||||
|
"options": [
|
||||||
|
"None",
|
||||||
|
"Medium",
|
||||||
|
"Large"
|
||||||
|
],
|
||||||
|
"default": "Medium",
|
||||||
|
"group": "homepage"
|
||||||
|
},
|
||||||
|
"feed_layout": {
|
||||||
|
"type": "select",
|
||||||
|
"options": [
|
||||||
|
"Dynamic grid",
|
||||||
|
"Simple grid",
|
||||||
|
"List"
|
||||||
|
],
|
||||||
|
"default": "Dynamic grid",
|
||||||
|
"group": "homepage"
|
||||||
|
},
|
||||||
|
"color_scheme": {
|
||||||
|
"type": "select",
|
||||||
|
"options": [
|
||||||
|
"Light",
|
||||||
|
"Dark",
|
||||||
|
"Auto"
|
||||||
|
],
|
||||||
|
"default": "Light"
|
||||||
|
},
|
||||||
|
"header_button_background": {
|
||||||
|
"type": "color",
|
||||||
|
"default": "#ffffff"
|
||||||
|
},
|
||||||
|
"header_button_text_color": {
|
||||||
|
"type": "select",
|
||||||
|
"options": [
|
||||||
|
"Light",
|
||||||
|
"Dark"
|
||||||
|
],
|
||||||
|
"default": "Dark"
|
||||||
|
},
|
||||||
|
"post_image_width": {
|
||||||
|
"type": "select",
|
||||||
|
"options": [
|
||||||
|
"Wide",
|
||||||
|
"Full",
|
||||||
|
"Small"
|
||||||
|
],
|
||||||
|
"default": "Wide",
|
||||||
|
"group": "post"
|
||||||
|
},
|
||||||
|
"email_signup_for_logged_out_visitors": {
|
||||||
|
"type": "select",
|
||||||
|
"options": [
|
||||||
|
"Footer",
|
||||||
|
"Bottom of post",
|
||||||
|
"None"
|
||||||
|
],
|
||||||
|
"default": "Footer",
|
||||||
|
"group": "post"
|
||||||
|
},
|
||||||
|
"email_signup_text": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "Sign up for more like this.",
|
||||||
|
"group": "post"
|
||||||
|
},
|
||||||
|
"show_recent_posts": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"group": "post"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"renovate": {
|
||||||
|
"extends": [
|
||||||
|
"@tryghost:theme"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
62
page.hbs
62
page.hbs
@ -1,30 +1,18 @@
|
|||||||
{{!< default}}
|
{{!< default}}
|
||||||
|
|
||||||
{{!-- The tag above means: insert everything in this file
|
{{!-- The tag above means: insert everything in this file
|
||||||
into the {body} of the default.hbs template --}}
|
into the {body} tag of the default.hbs template --}}
|
||||||
|
|
||||||
{{!-- The big featured header, it uses blog cover image as a BG if available --}}
|
|
||||||
<header class="site-header">
|
|
||||||
<div class="outer site-nav-main">
|
|
||||||
<div class="inner">
|
|
||||||
{{> "site-nav"}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{{!-- Everything inside the #post tags pulls data from the post --}}
|
|
||||||
{{#post}}
|
{{#post}}
|
||||||
|
{{!-- Everything inside the #post block pulls data from the page --}}
|
||||||
|
|
||||||
<main id="site-main" class="site-main outer">
|
<main id="site-main" class="site-main">
|
||||||
<div class="inner">
|
<article class="article {{post_class}}">
|
||||||
|
|
||||||
<article class="post-full {{post_class}} {{#unless feature_image}}no-image{{/unless}}">
|
|
||||||
|
|
||||||
<header class="post-full-header">
|
|
||||||
<h1 class="post-full-title">{{title}}</h1>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
|
<header class="article-header gh-canvas">
|
||||||
{{#if feature_image}}
|
{{#if feature_image}}
|
||||||
<figure class="post-full-image">
|
<figure class="article-image">
|
||||||
{{!-- This is a responsive image, it loads different sizes depending on device
|
{{!-- 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 --}}
|
https://medium.freecodecamp.org/a-guide-to-responsive-images-with-ready-to-use-templates-c400bd65c433 --}}
|
||||||
<img
|
<img
|
||||||
@ -32,34 +20,26 @@ into the {body} of the default.hbs template --}}
|
|||||||
{{img_url feature_image size="m"}} 600w,
|
{{img_url feature_image size="m"}} 600w,
|
||||||
{{img_url feature_image size="l"}} 1000w,
|
{{img_url feature_image size="l"}} 1000w,
|
||||||
{{img_url feature_image size="xl"}} 2000w"
|
{{img_url feature_image size="xl"}} 2000w"
|
||||||
sizes="(max-width: 800px) 400px,
|
sizes="(min-width: 1400px) 1400px, 92vw"
|
||||||
(max-width: 1170px) 1170px,
|
|
||||||
2000px"
|
|
||||||
src="{{img_url feature_image size="xl"}}"
|
src="{{img_url feature_image size="xl"}}"
|
||||||
alt="{{title}}"
|
alt="{{#if feature_image_alt}}{{feature_image_alt}}{{else}}{{title}}{{/if}}"
|
||||||
/>
|
/>
|
||||||
|
{{#if feature_image_caption}}
|
||||||
|
<figcaption>{{feature_image_caption}}</figcaption>
|
||||||
|
{{/if}}
|
||||||
</figure>
|
</figure>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="post-full-content">
|
<section class="gh-content gh-canvas">
|
||||||
<div class="post-content">
|
|
||||||
{{content}}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</article>
|
<h1 class="article-title">{{title}}</h1>
|
||||||
|
|
||||||
</div>
|
{{content}}
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</article>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{{/post}}
|
{{/post}}
|
||||||
|
|
||||||
{{!-- The #contentFor helper here will send everything inside it up to the matching #block helper found in default.hbs --}}
|
|
||||||
{{#contentFor "scripts"}}
|
|
||||||
<script>
|
|
||||||
$(function() {
|
|
||||||
var $postContent = $(".post-full-content");
|
|
||||||
$postContent.fitVids();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{{/contentFor}}
|
|
@ -1,47 +0,0 @@
|
|||||||
{{!--
|
|
||||||
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>
|
|
||||||
<div class="outer site-header-background responsive-header-img">
|
|
||||||
|
|
||||||
{{else}}
|
|
||||||
|
|
||||||
<div class="outer site-header-background no-image">
|
|
||||||
|
|
||||||
{{/if}}
|
|
@ -1,4 +1,7 @@
|
|||||||
<article class="post-card {{post_class}} {{#unless feature_image}}no-image{{else}}{{#is "home"}}{{#has index="nth:6"}}post-card-large{{/has}}{{/is}}{{/unless}}">
|
{{!-- This is a partial file used to generate a post "card"
|
||||||
|
which templates loop over to generate a list of posts. --}}
|
||||||
|
|
||||||
|
<article class="post-card {{post_class}} {{#match @custom.feed_layout "!=" "Simple grid"}}{{#is "home"}}{{#match @custom.feed_layout "Dynamic grid"}}{{#has index="0"}}{{#if feature_image}}post-card-large{{/if}}{{/has}}{{else}}post-card-large{{/match}}{{/is}}{{/match}}">
|
||||||
|
|
||||||
{{#if feature_image}}
|
{{#if feature_image}}
|
||||||
<a class="post-card-image-link" href="{{url}}">
|
<a class="post-card-image-link" href="{{url}}">
|
||||||
@ -9,10 +12,10 @@
|
|||||||
{{img_url feature_image size="m"}} 600w,
|
{{img_url feature_image size="m"}} 600w,
|
||||||
{{img_url feature_image size="l"}} 1000w,
|
{{img_url feature_image size="l"}} 1000w,
|
||||||
{{img_url feature_image size="xl"}} 2000w"
|
{{img_url feature_image size="xl"}} 2000w"
|
||||||
sizes="(max-width: 1000px) 400px, 700px"
|
sizes="(max-width: 1000px) 400px, 800px"
|
||||||
loading="lazy"
|
|
||||||
src="{{img_url feature_image size="m"}}"
|
src="{{img_url feature_image size="m"}}"
|
||||||
alt="{{title}}"
|
alt="{{#if feature_image_alt}}{{feature_image_alt}}{{else}}{{title}}{{/if}}"
|
||||||
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -20,7 +23,6 @@
|
|||||||
<div class="post-card-content">
|
<div class="post-card-content">
|
||||||
|
|
||||||
<a class="post-card-content-link" href="{{url}}">
|
<a class="post-card-content-link" href="{{url}}">
|
||||||
|
|
||||||
<header class="post-card-header">
|
<header class="post-card-header">
|
||||||
{{#if primary_tag}}
|
{{#if primary_tag}}
|
||||||
{{#primary_tag}}
|
{{#primary_tag}}
|
||||||
@ -29,29 +31,18 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
<h2 class="post-card-title">{{title}}</h2>
|
<h2 class="post-card-title">{{title}}</h2>
|
||||||
</header>
|
</header>
|
||||||
|
<div class="post-card-excerpt">
|
||||||
<section class="post-card-excerpt">
|
<p>{{excerpt}}</p>
|
||||||
{{#if feature_image}}
|
</div>
|
||||||
<p>{{excerpt words="30"}}</p>
|
|
||||||
{{else}}
|
|
||||||
<p>{{excerpt words="44"}}</p>
|
|
||||||
{{/if}}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<footer class="post-card-meta">
|
<footer class="post-card-meta">
|
||||||
<ul class="author-list">
|
<ul class="author-list">
|
||||||
{{#foreach authors}}
|
{{#foreach authors}}
|
||||||
<li class="author-list-item">
|
<li class="author-list-item">
|
||||||
|
|
||||||
<div class="author-name-tooltip">
|
|
||||||
{{name}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#if profile_image}}
|
{{#if profile_image}}
|
||||||
<a href="{{url}}" class="static-avatar">
|
<a href="{{url}}" class="static-avatar">
|
||||||
<img class="author-profile-image" src="{{img_url profile_image size="xs"}}" alt="{{name}}" />
|
<img class="author-profile-image" src="{{img_url profile_image size="xs"}}" alt="{{name}}" loading="lazy" />
|
||||||
</a>
|
</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a href="{{url}}" class="static-avatar author-profile-image">{{> "icons/avatar"}}</a>
|
<a href="{{url}}" class="static-avatar author-profile-image">{{> "icons/avatar"}}</a>
|
||||||
@ -60,8 +51,8 @@
|
|||||||
{{/foreach}}
|
{{/foreach}}
|
||||||
</ul>
|
</ul>
|
||||||
<div class="post-card-byline-content">
|
<div class="post-card-byline-content">
|
||||||
<span>{{#has author="count:>2"}}Multiple authors{{else}}{{authors}}{{/has}}</span>
|
<span class="post-card-byline-author">{{#has author="count:>2"}}Multiple authors{{else}}{{authors}}{{/has}}</span>
|
||||||
<span class="post-card-byline-date"><time datetime="{{date format="YYYY-MM-DD"}}">{{date format="D MMM YYYY"}}</time> <span class="bull">•</span> {{reading_time minute=(t "1 min read") minutes=(t "% min read")}}</span>
|
<span class="post-card-byline-date"><time datetime="{{date format="YYYY-MM-DD"}}">{{date}}</time> <span class="bull">•</span> {{reading_time}}</span>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
<div class="outer site-nav-main">
|
|
||||||
<div class="inner">
|
|
||||||
{{> "site-nav"}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
268
post.hbs
268
post.hbs
@ -1,92 +1,56 @@
|
|||||||
{{!< default}}
|
{{!< default}}
|
||||||
|
|
||||||
{{!-- The tag above means: insert everything in this file
|
{{!-- The tag above means: insert everything in this file
|
||||||
into the {body} of the default.hbs template --}}
|
into the {body} tag of the default.hbs template --}}
|
||||||
|
|
||||||
<header class="site-header">
|
|
||||||
{{> site-header}}
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{{!-- Everything inside the #post tags pulls data from the post --}}
|
|
||||||
{{#post}}
|
{{#post}}
|
||||||
|
{{!-- Everything inside the #post block pulls data from the post --}}
|
||||||
|
|
||||||
<main id="site-main" class="site-main outer">
|
<main id="site-main" class="site-main">
|
||||||
<div class="inner">
|
<article class="article {{post_class}} {{#match @custom.post_image_width "Full"}}image-full{{else match @custom.post_image_width "=" "Small"}}image-small{{/match}}">
|
||||||
|
|
||||||
<article class="post-full {{post_class}} {{#unless feature_image}}no-image{{/unless}}">
|
<header class="article-header gh-canvas">
|
||||||
|
|
||||||
<header class="post-full-header">
|
{{#if primary_tag}}
|
||||||
|
<section class="article-tag">
|
||||||
|
<a href="{{primary_tag.url}}">{{primary_tag.name}}</a>
|
||||||
|
</section>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if primary_tag}}
|
<h1 class="article-title">{{title}}</h1>
|
||||||
<section class="post-full-tags">
|
|
||||||
{{#primary_tag}}
|
{{#if custom_excerpt}}
|
||||||
<a href="{{url}}">{{name}}</a>
|
<p class="article-excerpt">{{custom_excerpt}}</p>
|
||||||
{{/primary_tag}}
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="article-byline">
|
||||||
|
<section class="article-byline-content">
|
||||||
|
<ul class="author-list">
|
||||||
|
{{#foreach authors}}
|
||||||
|
<li class="author-list-item">
|
||||||
|
{{#if profile_image}}
|
||||||
|
<a href="{{url}}" class="author-avatar">
|
||||||
|
<img class="author-profile-image" src="{{img_url profile_image size="xs"}}" alt="{{name}}" />
|
||||||
|
</a>
|
||||||
|
{{else}}
|
||||||
|
<a href="{{url}}" class="author-avatar author-profile-image">{{> "icons/avatar"}}</a>
|
||||||
|
{{/if}}
|
||||||
|
</li>
|
||||||
|
{{/foreach}}
|
||||||
|
</ul>
|
||||||
|
<div class="article-byline-meta">
|
||||||
|
<h4 class="author-name">{{authors}}</h4>
|
||||||
|
<div class="byline-meta-content">
|
||||||
|
<time class="byline-meta-date" datetime="{{date format="YYYY-MM-DD"}}">{{date}}</time>
|
||||||
|
<span class="byline-reading-time"><span class="bull">•</span> {{reading_time}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{{/if}}
|
</div>
|
||||||
|
|
||||||
<h1 class="post-full-title">{{title}}</h1>
|
|
||||||
|
|
||||||
{{#if custom_excerpt}}
|
|
||||||
<p class="post-full-custom-excerpt">{{custom_excerpt}}</p>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<div class="post-full-byline">
|
|
||||||
|
|
||||||
<section class="post-full-byline-content">
|
|
||||||
|
|
||||||
<ul class="author-list">
|
|
||||||
{{#foreach authors}}
|
|
||||||
<li class="author-list-item">
|
|
||||||
|
|
||||||
<div class="author-card">
|
|
||||||
{{#if profile_image}}
|
|
||||||
<img class="author-profile-image" src="{{img_url profile_image size="xs"}}" alt="{{name}}" />
|
|
||||||
{{else}}
|
|
||||||
<div class="author-profile-image">{{> "icons/avatar"}}</div>
|
|
||||||
{{/if}}
|
|
||||||
<div class="author-info">
|
|
||||||
{{#if bio}}
|
|
||||||
<div class="bio">
|
|
||||||
<h2>{{name}}</h2>
|
|
||||||
<p>{{bio}}</p>
|
|
||||||
<p>{{{t "<a href='{url}'>More posts</a> by {name}" url=(url) name=name}}}.</p>
|
|
||||||
</div>
|
|
||||||
{{else}}
|
|
||||||
<h2>{{name}}</h2>
|
|
||||||
<p>{{{t "Read <a href='{url}'>more posts</a> by this author" url=(url)}}}.</p>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#if profile_image}}
|
|
||||||
<a href="{{url}}" class="author-avatar">
|
|
||||||
<img class="author-profile-image" src="{{img_url profile_image size="xs"}}" alt="{{name}}" />
|
|
||||||
</a>
|
|
||||||
{{else}}
|
|
||||||
<a href="{{url}}" class="author-avatar author-profile-image">{{> "icons/avatar"}}</a>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
</li>
|
|
||||||
{{/foreach}}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<section class="post-full-byline-meta">
|
|
||||||
<h4 class="author-name">{{authors}}</h4>
|
|
||||||
<div class="byline-meta-content">
|
|
||||||
<time class="byline-meta-date" datetime="{{date format="YYYY-MM-DD"}}">{{date format="D MMM YYYY"}}</time>
|
|
||||||
<span class="byline-reading-time"><span class="bull">•</span> {{reading_time minute=(t "1 min read") minutes=(t "% min read")}}</span>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{{#if feature_image}}
|
{{#if feature_image}}
|
||||||
<figure class="post-full-image">
|
<figure class="article-image">
|
||||||
{{!-- This is a responsive image, it loads different sizes depending on device
|
{{!-- 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 --}}
|
https://medium.freecodecamp.org/a-guide-to-responsive-images-with-ready-to-use-templates-c400bd65c433 --}}
|
||||||
<img
|
<img
|
||||||
@ -94,121 +58,67 @@ into the {body} of the default.hbs template --}}
|
|||||||
{{img_url feature_image size="m"}} 600w,
|
{{img_url feature_image size="m"}} 600w,
|
||||||
{{img_url feature_image size="l"}} 1000w,
|
{{img_url feature_image size="l"}} 1000w,
|
||||||
{{img_url feature_image size="xl"}} 2000w"
|
{{img_url feature_image size="xl"}} 2000w"
|
||||||
sizes="(max-width: 800px) 400px,
|
sizes="(min-width: 1400px) 1400px, 92vw"
|
||||||
(max-width: 1170px) 1170px,
|
|
||||||
2000px"
|
|
||||||
src="{{img_url feature_image size="xl"}}"
|
src="{{img_url feature_image size="xl"}}"
|
||||||
alt="{{title}}"
|
alt="{{#if feature_image_alt}}{{feature_image_alt}}{{else}}{{title}}{{/if}}"
|
||||||
/>
|
/>
|
||||||
|
{{#if feature_image_caption}}
|
||||||
|
<figcaption>{{feature_image_caption}}</figcaption>
|
||||||
|
{{/if}}
|
||||||
</figure>
|
</figure>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="post-full-content">
|
<section class="gh-content gh-canvas">
|
||||||
<div class="post-content">
|
{{content}}
|
||||||
{{content}}
|
</section>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{{!-- Email subscribe form at the bottom of the page --}}
|
{{!--
|
||||||
{{#if @labs.members}}
|
<section class="article-comments gh-canvas">
|
||||||
{{> subscribe-form}}
|
If you want to embed comments, this is a good place to paste your code!
|
||||||
{{/if}}
|
</section>
|
||||||
|
--}}
|
||||||
|
|
||||||
{{!--
|
</article>
|
||||||
<section class="post-full-comments">
|
|
||||||
If you want to embed comments, this is a good place to do it!
|
|
||||||
</section>
|
|
||||||
--}}
|
|
||||||
|
|
||||||
</article>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{{!-- Links to Previous/Next posts --}}
|
{{!-- A signup call to action is displayed here, unless viewed as a logged-in member --}}
|
||||||
<aside class="read-next outer">
|
{{#match @custom.email_signup_for_logged_out_visitors "!=" "None"}}
|
||||||
<div class="inner">
|
{{#unless @member}}{{#if access}}
|
||||||
<div class="read-next-feed">
|
<section class="footer-cta {{#match @custom.email_signup_for_logged_out_visitors "Bottom of post"}}cta-alt{{/match}}">
|
||||||
{{#if primary_tag}}
|
<div class="inner">
|
||||||
{{#get "posts" filter="tags:{{primary_tag.slug}}+id:-{{id}}" limit="3" as |related_posts|}}
|
{{#if @custom.email_signup_text}}<h2>{{@custom.email_signup_text}}</h2>{{/if}}
|
||||||
{{#if related_posts}}
|
<a class="footer-cta-button" href="#/portal" data-portal>
|
||||||
<article class="read-next-card">
|
<div class="footer-cta-input">Enter your email</div>
|
||||||
<header class="read-next-card-header">
|
<span>Subscribe</span>
|
||||||
{{#../primary_tag}}
|
</a>
|
||||||
<h3><span>More in</span> <a href="{{url}}">{{name}}</a></h3>
|
{{!-- ^ This looks like a form element, but it's just a link to Portal,
|
||||||
{{/../primary_tag}}
|
making the form validation and submission much simpler. --}}
|
||||||
</header>
|
|
||||||
<div class="read-next-card-content">
|
|
||||||
<ul>
|
|
||||||
{{#foreach related_posts}}
|
|
||||||
<li>
|
|
||||||
<h4><a href="{{url}}">{{title}}</a></h4>
|
|
||||||
<div class="read-next-card-meta">
|
|
||||||
<p><time datetime="{{date format="YYYY-MM-DD"}}">{{date format="D MMM YYYY"}}</time> –
|
|
||||||
{{reading_time minute=(t "1 min read") minutes=(t "% min read")}}</p>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
{{/foreach}}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<footer class="read-next-card-footer">
|
|
||||||
<a href="{{#../primary_tag}}{{url}}{{/../primary_tag}}">{{plural meta.pagination.total empty=(t "No posts") singular=(t "1 post") plural=(t "See all % posts")}}
|
|
||||||
→</a>
|
|
||||||
</footer>
|
|
||||||
</article>
|
|
||||||
{{/if}}
|
|
||||||
{{/get}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{!-- If there's a next post, display it using the same markup included from - partials/post-card.hbs --}}
|
|
||||||
{{#next_post}}
|
|
||||||
{{> "post-card"}}
|
|
||||||
{{/next_post}}
|
|
||||||
|
|
||||||
{{!-- If there's a previous post, display it using the same markup included from - partials/post-card.hbs --}}
|
|
||||||
{{#prev_post}}
|
|
||||||
{{> "post-card"}}
|
|
||||||
{{/prev_post}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</aside>
|
{{/if}}{{/unless}}
|
||||||
|
{{/match}}
|
||||||
|
|
||||||
{{/post}}
|
|
||||||
|
|
||||||
{{!-- The #contentFor helper here will send everything inside it up to the matching #block helper found in default.hbs --}}
|
{{!-- Read more links, just above the footer --}}
|
||||||
{{#contentFor "scripts"}}
|
{{#if @custom.show_recent_posts}}
|
||||||
<script>
|
{{!-- The {#get} helper below fetches some of the latest posts here
|
||||||
$(document).ready(function () {
|
so that people have something else to read when they finish this one.
|
||||||
// FitVids - start
|
|
||||||
var $postContent = $(".post-full-content");
|
|
||||||
$postContent.fitVids();
|
|
||||||
// FitVids - end
|
|
||||||
|
|
||||||
// Replace nav with title on scroll - start
|
This query gets the latest 3 posts on the site, but adds a filter to
|
||||||
Casper.stickyNavTitle({
|
exclude the post we're currently on from being included. --}}
|
||||||
navSelector: '.site-nav-main',
|
{{#get "posts" filter="id:-{{id}}" include="authors" limit="3" as |more_posts|}}
|
||||||
titleSelector: '.post-full-title',
|
|
||||||
activeClass: 'nav-post-title-active'
|
|
||||||
});
|
|
||||||
// Replace nav with title on scroll - end
|
|
||||||
|
|
||||||
// Hover on avatar
|
{{#if more_posts}}
|
||||||
var hoverTimeout;
|
<aside class="read-more-wrap">
|
||||||
$('.author-list-item').hover(function () {
|
<div class="read-more inner">
|
||||||
var $this = $(this);
|
{{#foreach more_posts}}
|
||||||
|
{{> "post-card"}}
|
||||||
|
{{/foreach}}
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
{{/if}}
|
||||||
|
{{/get}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
clearTimeout(hoverTimeout);
|
{{/post}}
|
||||||
|
|
||||||
$('.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}}
|
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": [
|
|
||||||
"@tryghost:theme"
|
|
||||||
]
|
|
||||||
}
|
|
61
tag.hbs
61
tag.hbs
@ -1,32 +1,57 @@
|
|||||||
{{!< default}}
|
{{!< default}}
|
||||||
{{!-- The tag above means - insert everything in this file into the {body} of the default.hbs template --}}
|
{{!-- The tag above means - insert everything in this file into the {body} of the default.hbs template --}}
|
||||||
|
|
||||||
{{#tag}}
|
|
||||||
<header class="site-archive-header">
|
|
||||||
{{> site-header}}
|
|
||||||
{{> header-background background=feature_image}} {{!--Special header-image.hbs partial to generate the background image--}}
|
|
||||||
<div class="inner site-header-content">
|
|
||||||
<h1 class="site-title">{{name}}</h1>
|
|
||||||
<h2 class="site-description">
|
|
||||||
{{#if description}}
|
|
||||||
{{description}}
|
|
||||||
{{else}}
|
|
||||||
{{plural ../pagination.total empty=(t "A collection of posts") singular=(t "A collection of 1 post") plural=(t "A collection of % posts")}}
|
|
||||||
{{/if}}
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
{{/tag}}
|
|
||||||
|
|
||||||
{{!-- The main content area --}}
|
|
||||||
<main id="site-main" class="site-main outer">
|
<main id="site-main" class="site-main outer">
|
||||||
<div class="inner posts">
|
<div class="inner posts">
|
||||||
<div class="post-feed">
|
<div class="post-feed">
|
||||||
|
|
||||||
|
{{#tag}}
|
||||||
|
<section class="post-card post-card-large">
|
||||||
|
{{#if feature_image}}
|
||||||
|
<div class="post-card-image-link">
|
||||||
|
{{!-- 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, 800px"
|
||||||
|
src="{{img_url feature_image size="m"}}"
|
||||||
|
alt="{{title}}"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
<div class="post-card-content">
|
||||||
|
<div class="post-card-content-link">
|
||||||
|
<header class="post-card-header">
|
||||||
|
<div class="post-card-primary-tag">Tagged</div>
|
||||||
|
<h2 class="post-card-title">{{name}}</h2>
|
||||||
|
</header>
|
||||||
|
<div class="post-card-excerpt">
|
||||||
|
<p>
|
||||||
|
{{#if description}}
|
||||||
|
{{description}}
|
||||||
|
{{else}}
|
||||||
|
A collection of {{plural ../pagination.total empty='zero posts' singular='% post' plural='% posts'}}
|
||||||
|
{{/if}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>{{!--/.post-card-content--}}
|
||||||
|
|
||||||
|
</section>
|
||||||
|
{{/tag}}
|
||||||
|
|
||||||
{{#foreach posts}}
|
{{#foreach posts}}
|
||||||
|
|
||||||
{{!-- The tag below includes the markup for each post - partials/post-card.hbs --}}
|
{{!-- The tag below includes the markup for each post - partials/post-card.hbs --}}
|
||||||
{{> "post-card"}}
|
{{> "post-card"}}
|
||||||
|
|
||||||
{{/foreach}}
|
{{/foreach}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
Loading…
Reference in New Issue
Block a user