mirror of
https://github.com/ViViDboarder/Vivid-Casper.git
synced 2024-12-22 19:47:38 +00:00
Merge branch 'master' of github.com:TryGhost/Casper
This commit is contained in:
commit
6be42f38cc
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@ -1,4 +1,4 @@
|
||||
Do you need help or have a question? Please come chat in Slack: https://ghost.org/slack 👫.
|
||||
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:
|
||||
|
||||
|
6
.travis.yml
Normal file
6
.travis.yml
Normal file
@ -0,0 +1,6 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- "8"
|
||||
|
||||
|
@ -32,11 +32,11 @@ One really neat trick is that you can also create custom one-off templates just
|
||||
|
||||
# Development
|
||||
|
||||
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:
|
||||
Casper styles are compiled using Gulp/PostCSS to polyfill future CSS spec. You'll need [Node](https://nodejs.org/), [Yarn](https://yarnpkg.com/) and [Gulp](https://gulpjs.com) installed globally. After that, from the theme's root directory:
|
||||
|
||||
```bash
|
||||
$ npm install
|
||||
$ gulp
|
||||
$ yarn install
|
||||
$ yarn dev
|
||||
```
|
||||
|
||||
Now you can edit `/assets/css/` files, which will be compiled to `/assets/built/` automatically.
|
||||
@ -44,7 +44,7 @@ Now you can edit `/assets/css/` files, which will be compiled to `/assets/built/
|
||||
The `zip` Gulp task packages the theme files into `dist/<theme-name>.zip`, which you can then upload to your site.
|
||||
|
||||
```bash
|
||||
$ gulp zip
|
||||
$ yarn zip
|
||||
```
|
||||
|
||||
# PostCSS Features Used
|
||||
|
2
assets/built/infinitescroll.js
Normal file
2
assets/built/infinitescroll.js
Normal file
@ -0,0 +1,2 @@
|
||||
$(function(t){var o=1,r=window.location.pathname,a=t(document),s=t(".post-feed"),c=300,l=!1,w=!1,d=window.scrollY,v=window.innerHeight,u=a.height();function f(){d=window.scrollY,e()}function g(){v=window.innerHeight,u=a.height(),e()}function e(){l||requestAnimationFrame(n),l=!0}function n(){var e,n;if(n=/(?:page\/)(\d)(?:\/)$/i,(e=(e=r).replace(/#(.*)$/g,"").replace("////g","/")).match(n)&&(o=parseInt(e.match(n)[1]),e=e.replace(n,"")),r=e,!w)if(d+v<=u-c)l=!1;else{if(o>=maxPages)return window.removeEventListener("scroll",f,{passive:!0}),void window.removeEventListener("resize",g);w=!0;var i=r+"page/"+(o+=1)+"/";t.get(i,function(e){var n=document.createRange().createContextualFragment(e).querySelectorAll(".post");n.length&&[].forEach.call(n,function(e){s[0].appendChild(e)})}).fail(function(e){404===e.status&&(window.removeEventListener("scroll",f,{passive:!0}),window.removeEventListener("resize",g))}).always(function(){u=a.height(),l=w=!1})}}window.addEventListener("scroll",f,{passive:!0}),window.addEventListener("resize",g),n()});
|
||||
//# sourceMappingURL=infinitescroll.js.map
|
1
assets/built/infinitescroll.js.map
Normal file
1
assets/built/infinitescroll.js.map
Normal file
File diff suppressed because one or more lines are too long
2
assets/built/jquery.fitvids.js
Normal file
2
assets/built/jquery.fitvids.js
Normal file
@ -0,0 +1,2 @@
|
||||
!function(d){"use strict";d.fn.fitVids=function(t){var i={customSelector:null,ignore:null};if(!document.getElementById("fit-vids-style")){var e=document.head||document.getElementsByTagName("head")[0],r=document.createElement("div");r.innerHTML='<p>x</p><style id="fit-vids-style">.fluid-width-video-container{flex-grow: 1;width:100%;}.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}</style>',e.appendChild(r.childNodes[1])}return t&&d.extend(i,t),this.each(function(){var t=['iframe[src*="player.vimeo.com"]','iframe[src*="youtube.com"]','iframe[src*="youtube-nocookie.com"]','iframe[src*="kickstarter.com"][src*="video.html"]',"object","embed"];i.customSelector&&t.push(i.customSelector);var r=".fitvidsignore";i.ignore&&(r=r+", "+i.ignore);var e=d(this).find(t.join(","));(e=(e=e.not("object object")).not(r)).each(function(){var t=d(this);if(!(0<t.parents(r).length||"embed"===this.tagName.toLowerCase()&&t.parent("object").length||t.parent(".fluid-width-video-wrapper").length)){t.css("height")||t.css("width")||!isNaN(t.attr("height"))&&!isNaN(t.attr("width"))||(t.attr("height",9),t.attr("width",16));var e=("object"===this.tagName.toLowerCase()||t.attr("height")&&!isNaN(parseInt(t.attr("height"),10))?parseInt(t.attr("height"),10):t.height())/(isNaN(parseInt(t.attr("width"),10))?t.width():parseInt(t.attr("width"),10));if(!t.attr("name")){var i="fitvid"+d.fn.fitVids._count;t.attr("name",i),d.fn.fitVids._count++}t.wrap('<div class="fluid-width-video-container"><div class="fluid-width-video-wrapper"></div></div>').parent(".fluid-width-video-wrapper").css("padding-top",100*e+"%"),t.removeAttr("height").removeAttr("width")}})})},d.fn.fitVids._count=0}(window.jQuery||window.Zepto);
|
||||
//# sourceMappingURL=jquery.fitvids.js.map
|
1
assets/built/jquery.fitvids.js.map
Normal file
1
assets/built/jquery.fitvids.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -13,9 +13,12 @@ production stylesheet in assets/built/screen.css
|
||||
7. Single Post
|
||||
7.1. Subscribe Form
|
||||
7.2. Post Footer
|
||||
7.2.1 Single Author Byline
|
||||
7.2.2 Multiple Author Byline
|
||||
7.3. Comments
|
||||
7.4. Related Posts
|
||||
7.5. Floating Header
|
||||
7.6. Koenig Styles
|
||||
8. Author Template
|
||||
9. Error Template
|
||||
10. Subscribe Overlay
|
||||
@ -395,9 +398,9 @@ The knock-on effect of this is ugly browser-scroll bars at the bottom, so 80px o
|
||||
}
|
||||
|
||||
.post-card:hover {
|
||||
box-shadow: 0 0 1px rgba(39,44,49,0.10), 0 3px 16px rgba(39, 44, 49,0.07);
|
||||
transition: all 0.3s ease;
|
||||
transform: translate3D(0, -1px, 0);
|
||||
box-shadow: rgba(39,44,49,0.07) 8px 28px 50px, rgba(39, 44, 49, 0.04) 1px 6px 12px;
|
||||
transition: all 0.4s ease;
|
||||
transform: translate3D(0, -1px, 0) scale(1.02);
|
||||
}
|
||||
|
||||
.post-card-image-link {
|
||||
@ -416,6 +419,7 @@ The knock-on effect of this is ugly browser-scroll bars at the bottom, so 80px o
|
||||
|
||||
.post-card-content-link {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
display: block;
|
||||
padding: 25px 25px 0;
|
||||
color: var(--darkgrey);
|
||||
@ -452,20 +456,138 @@ The knock-on effect of this is ugly browser-scroll bars at the bottom, so 80px o
|
||||
}
|
||||
|
||||
.post-card-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
padding: 0 25px 25px;
|
||||
}
|
||||
|
||||
.author-profile-image {
|
||||
margin-right: 5px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
.author-profile-image,
|
||||
.avatar-wrapper {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: color(var(--lightgrey) l(+10%));
|
||||
border-radius: 100%;
|
||||
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.post-card-author {
|
||||
font-size: 1.3rem;
|
||||
.post-card-meta .profile-image-wrapper,
|
||||
.post-card-meta .avatar-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.author-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap-reverse;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.author-list-item {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.author-list-item:nth-child(1) {
|
||||
z-index: 10;
|
||||
}
|
||||
.author-list-item:nth-child(2) {
|
||||
z-index: 9;
|
||||
}
|
||||
.author-list-item:nth-child(3) {
|
||||
z-index: 8;
|
||||
}
|
||||
.author-list-item:nth-child(4) {
|
||||
z-index: 7;
|
||||
}
|
||||
.author-list-item:nth-child(5) {
|
||||
z-index: 6;
|
||||
}
|
||||
.author-list-item:nth-child(6) {
|
||||
z-index: 5;
|
||||
}
|
||||
.author-list-item:nth-child(7) {
|
||||
z-index: 4;
|
||||
}
|
||||
.author-list-item:nth-child(8) {
|
||||
z-index: 3;
|
||||
}
|
||||
.author-list-item:nth-child(9) {
|
||||
z-index: 2;
|
||||
}
|
||||
.author-list-item:nth-child(10) {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.static-avatar {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 0 -5px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border: #fff 2px solid;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.moving-avatar {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 0 -6px;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
border: #fff 2px solid;
|
||||
border-radius: 100%;
|
||||
transition: all 0.5s cubic-bezier(0.4, 0.01, 0.165, 0.99) 0.7s;
|
||||
}
|
||||
|
||||
@media (min-width: 800px) {
|
||||
.author-list:hover .moving-avatar {
|
||||
margin: 0;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0.01, 0.165, 0.99);
|
||||
}
|
||||
}
|
||||
|
||||
.author-name-tooltip {
|
||||
position: absolute;
|
||||
bottom: 105%;
|
||||
z-index: 999;
|
||||
display: block;
|
||||
padding: 2px 8px;
|
||||
color: white;
|
||||
font-size: 1.2rem;
|
||||
letter-spacing: 0.2px;
|
||||
white-space: nowrap;
|
||||
background: var(--darkgrey);
|
||||
border-radius: 3px;
|
||||
box-shadow: rgba(39,44,49,0.08) 0 12px 26px, rgba(39, 44, 49, 0.03) 1px 3px 8px;
|
||||
opacity: 0;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0.01, 0.165, 0.99);
|
||||
transform: translateY(6px);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.author-list-item:hover .author-name-tooltip {
|
||||
opacity: 1.0;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
|
||||
@media (max-width: 650px) {
|
||||
.author-name-tooltip {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.reading-time {
|
||||
flex-shrink: 0;
|
||||
margin-left: 20px;
|
||||
color: var(--midgrey);
|
||||
font-size: 1.2rem;
|
||||
line-height: 33px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
@ -666,13 +788,6 @@ The first (most recent) post in the list is styled to be bigger than the others
|
||||
display: none;
|
||||
}
|
||||
|
||||
.kg-card-markdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
max-width: 920px;
|
||||
}
|
||||
|
||||
.post-full-content h1,
|
||||
.post-full-content h2,
|
||||
.post-full-content h3,
|
||||
@ -698,13 +813,9 @@ The first (most recent) post in the list is styled to be bigger than the others
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.post-template .kg-card-markdown > p:first-child {
|
||||
font-size: 1.25em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.post-full-content a {
|
||||
color: #000;
|
||||
word-break: break-word;
|
||||
box-shadow: var(--blue) 0 -1px 0 inset;
|
||||
}
|
||||
|
||||
@ -732,6 +843,7 @@ The first (most recent) post in the list is styled to be bigger than the others
|
||||
display: block;
|
||||
margin: 1.5em auto;
|
||||
max-width: 1040px;
|
||||
height: auto;
|
||||
}
|
||||
@media (max-width: 1040px) {
|
||||
.post-full-content img,
|
||||
@ -767,11 +879,13 @@ Usage (In Ghost editor):
|
||||
display: block;
|
||||
margin-top: -3em;
|
||||
margin-bottom: 1.5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* Override third party iframe styles */
|
||||
.post-full-content iframe {
|
||||
margin: 0 auto;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
.post-full-content blockquote {
|
||||
@ -801,6 +915,10 @@ Usage (In Ghost editor):
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.post-full-content p code {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.post-full-content pre {
|
||||
overflow-x: auto;
|
||||
margin: 1.5em 0 3em;
|
||||
@ -821,7 +939,7 @@ Usage (In Ghost editor):
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.post-full-content pre code * {
|
||||
.post-full-content pre code :not(span) {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
@ -1157,19 +1275,22 @@ Usage (In Ghost editor):
|
||||
max-width: 840px;
|
||||
}
|
||||
|
||||
/* 7.2.1 Single Author Byline
|
||||
/* ---------------------------------------------------------- */
|
||||
|
||||
.author-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.author-card .author-profile-image {
|
||||
.author-card .author-profile-image,
|
||||
.author-card .avatar-wrapper {
|
||||
margin-right: 15px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.author-card-name {
|
||||
margin: 0 0 2px 0;
|
||||
margin: 8px 0 2px 0;
|
||||
padding: 0;
|
||||
font-size: 2rem;
|
||||
}
|
||||
@ -1212,6 +1333,137 @@ Usage (In Ghost editor):
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 7.2.2 Multiple Author Byline
|
||||
/* ---------------------------------------------------------- */
|
||||
|
||||
.post-full-authors {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
padding-top: 40px;
|
||||
border-top: color(var(--lightgrey) l(+10%)) 1px solid;
|
||||
}
|
||||
|
||||
.post-full-authors-content {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.post-full-authors-content p {
|
||||
margin-bottom: 0;
|
||||
color: var(--midgrey);
|
||||
font-size: 1.4rem;
|
||||
letter-spacing: 0.2px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.post-full-authors-content a {
|
||||
display: inline-block;
|
||||
color: color(var(--darkgrey) l(+20%));
|
||||
font-size: 1.4rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.post-full-footer .author-list {
|
||||
justify-content: center;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.author-card .author-profile-image,
|
||||
.author-card .avatar-wrapper {
|
||||
position: relative;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.author-list-item .author-card {
|
||||
position: absolute;
|
||||
bottom: 130%;
|
||||
left: 50%;
|
||||
z-index: 300;
|
||||
display: block;
|
||||
margin-left: -160px;
|
||||
width: 320px;
|
||||
font-size: 1.4rem;
|
||||
letter-spacing: 0.2px;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
box-shadow: rgba(39,44,49,0.08) 0 12px 26px, rgba(39, 44, 49, 0.03) 1px 3px 8px;
|
||||
opacity: 0;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0.01, 0.165, 0.99);
|
||||
transform: scale(0.98) translateY(15px);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.author-list-item .author-card:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
display: block;
|
||||
margin-left: -12px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 12px solid #fff;
|
||||
border-right: 12px solid transparent;
|
||||
border-left: 12px solid transparent;
|
||||
}
|
||||
|
||||
.author-list-item .author-card.hovered {
|
||||
opacity: 1.0;
|
||||
transform: scale(1) translateY(0px);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.author-card .basic-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 30px 20px 20px 20px;
|
||||
color: #fff;
|
||||
background: var(--darkgrey);
|
||||
border-radius: 6px 6px 0 0;
|
||||
}
|
||||
|
||||
.author-card .basic-info h2 {
|
||||
margin: 1em 0 0.5em;
|
||||
}
|
||||
|
||||
.author-card .bio {
|
||||
padding: 20px 20px 0;
|
||||
}
|
||||
|
||||
@media (max-width: 650px) {
|
||||
.author-list-item .author-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.basic-info .author-profile-image {
|
||||
margin: 0;
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.basic-info .avatar-wrapper {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
border: none;
|
||||
background: rgba(229, 239, 245, 0.1);
|
||||
}
|
||||
|
||||
.basic-info .avatar-wrapper svg {
|
||||
margin: 0;
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
opacity: 0.15;
|
||||
}
|
||||
|
||||
|
||||
/* 7.3. Comments
|
||||
/* ---------------------------------------------------------- */
|
||||
@ -1571,6 +1823,110 @@ Usage (In Ghost editor):
|
||||
}
|
||||
|
||||
|
||||
/* 7.6. Koenig Styles
|
||||
/* ---------------------------------------------------------- */
|
||||
|
||||
.post-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
max-width: 920px;
|
||||
}
|
||||
|
||||
.post-template .post-content > p:first-child {
|
||||
font-size: 1.25em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.post-full-content .kg-image {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Preventing full-width image overlap with post image. */
|
||||
.post-full-image + .post-full-content .kg-content *:first-child .kg-image {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.post-full-content .kg-width-wide .kg-image {
|
||||
max-width: 1040px;
|
||||
}
|
||||
|
||||
.post-full-content .kg-width-full .kg-image {
|
||||
max-width: 100vw;
|
||||
}
|
||||
|
||||
.post-full-content figure {
|
||||
margin: 1.5em 0 3em;
|
||||
}
|
||||
|
||||
.post-full-content figure img {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.post-full-content figcaption {
|
||||
margin: 1.0em 0 0;
|
||||
font-size: 80%;
|
||||
line-height: 1.6em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.kg-width-full figcaption {
|
||||
padding: 0 1.5em;
|
||||
}
|
||||
|
||||
.kg-embed-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.kg-embed-card .fluid-width-video-wrapper {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 1040px) {
|
||||
.post-full-content .kg-width-full .kg-image {
|
||||
width: 100vw;
|
||||
}
|
||||
}
|
||||
|
||||
.kg-gallery-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 1040px;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.kg-gallery-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.kg-gallery-image img {
|
||||
display: block;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.kg-gallery-row:not(:first-of-type) {
|
||||
margin: 0.75em 0 0 0;
|
||||
}
|
||||
|
||||
.kg-gallery-image:not(:first-of-type) {
|
||||
margin: 0 0 0 0.75em;
|
||||
}
|
||||
|
||||
.kg-gallery-card + .kg-image-card.kg-width-wide,
|
||||
.kg-gallery-card + .kg-gallery-card,
|
||||
.kg-image-card.kg-width-wide + .kg-gallery-card,
|
||||
.kg-image-card.kg-width-wide + .kg-image-card.kg-width-wide {
|
||||
margin: -2.25em 0 3em;
|
||||
}
|
||||
|
||||
/* 8. Author Template
|
||||
/* ---------------------------------------------------------- */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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">
|
||||
|
21
default.hbs
21
default.hbs
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="{{lang}}">
|
||||
<head>
|
||||
|
||||
{{!-- Document Settings --}}
|
||||
@ -62,19 +62,34 @@
|
||||
</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"
|
||||
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
|
||||
crossorigin="anonymous">
|
||||
</script>
|
||||
<script type="text/javascript" src="{{asset "js/jquery.fitvids.js"}}"></script>
|
||||
<script type="text/javascript" src="{{asset "built/jquery.fitvids.js"}}"></script>
|
||||
|
||||
{{#if pagination.pages}}
|
||||
<script>
|
||||
// maxPages is a global variable that is needed to determine
|
||||
// if we need to load more pages for the infinitescroll, or if
|
||||
// we reached the last page already.
|
||||
var maxPages = parseInt('{{pagination.pages}}');
|
||||
</script>
|
||||
<script src="{{asset "js/infinitescroll.js"}}"></script>
|
||||
<script src="{{asset "built/infinitescroll.js"}}"></script>
|
||||
{{/if}}
|
||||
|
||||
{{!-- The #block helper will pull in data from the #contentFor other template files. In this case, there's some JavaScript which we only want to use in post.hbs, but it needs to be included down here, after jQuery has already loaded. --}}
|
||||
|
@ -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">
|
||||
|
22
gulpfile.js
22
gulpfile.js
@ -6,6 +6,8 @@ var livereload = require('gulp-livereload');
|
||||
var postcss = require('gulp-postcss');
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
var zip = require('gulp-zip');
|
||||
var uglify = require('gulp-uglify');
|
||||
var filter = require('gulp-filter');
|
||||
|
||||
// postcss plugins
|
||||
var autoprefixer = require('autoprefixer');
|
||||
@ -24,10 +26,12 @@ var nodemonServerInit = function () {
|
||||
livereload.listen(1234);
|
||||
};
|
||||
|
||||
gulp.task('build', ['css'], function (/* cb */) {
|
||||
gulp.task('build', ['css', 'js'], function (/* cb */) {
|
||||
return nodemonServerInit();
|
||||
});
|
||||
|
||||
gulp.task('generate', ['css', 'js']);
|
||||
|
||||
gulp.task('css', function () {
|
||||
var processors = [
|
||||
easyimport,
|
||||
@ -46,11 +50,25 @@ gulp.task('css', function () {
|
||||
.pipe(livereload());
|
||||
});
|
||||
|
||||
gulp.task('js', function () {
|
||||
var jsFilter = filter(['**/*.js'], {restore: true});
|
||||
|
||||
return gulp.src('assets/js/*.js')
|
||||
.on('error', swallowError)
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(jsFilter)
|
||||
.pipe(uglify())
|
||||
.pipe(jsFilter.restore)
|
||||
.pipe(sourcemaps.write('.'))
|
||||
.pipe(gulp.dest('assets/built/'))
|
||||
.pipe(livereload());
|
||||
});
|
||||
|
||||
gulp.task('watch', function () {
|
||||
gulp.watch('assets/css/**', ['css']);
|
||||
});
|
||||
|
||||
gulp.task('zip', ['css'], function () {
|
||||
gulp.task('zip', ['css', 'js'], function () {
|
||||
var targetDir = 'dist/';
|
||||
var themeName = require('./package.json').name;
|
||||
var filename = themeName + '.zip';
|
||||
|
@ -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">
|
||||
|
17
package.json
17
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.1.9",
|
||||
"version": "2.7.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,6 +42,7 @@
|
||||
"devDependencies": {
|
||||
"autoprefixer": "6.3.6",
|
||||
"cssnano": "3.7.1",
|
||||
"gscan": "^2.0.0",
|
||||
"gulp": "3.9.1",
|
||||
"gulp-livereload": "3.8.1",
|
||||
"gulp-postcss": "6.1.1",
|
||||
@ -45,7 +52,9 @@
|
||||
"gulp-zip": "4.0.0",
|
||||
"postcss-color-function": "2.0.1",
|
||||
"postcss-custom-properties": "5.0.1",
|
||||
"postcss-easy-import": "1.0.1"
|
||||
"postcss-easy-import": "1.0.1",
|
||||
"gulp-filter": "5.1.0",
|
||||
"gulp-uglify": "3.0.1"
|
||||
},
|
||||
"config": {
|
||||
"posts_per_page": 25
|
||||
|
4
page.hbs
4
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">
|
||||
<div class="post-content">
|
||||
{{content}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</article>
|
||||
|
72
partials/byline-multiple.hbs
Normal file
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
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
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 |
@ -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}}" />
|
||||
|
||||
<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}}
|
||||
<span class="post-card-author">{{author}}</span>
|
||||
</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" rel="noopener">{{> "icons/facebook"}}</a>
|
||||
<a class="social-link social-link-fb" href="{{facebook_url @blog.facebook}}" title="Facebook" target="_blank" rel="noopener">{{> "icons/facebook"}}</a>
|
||||
{{/if}}
|
||||
{{#if @blog.twitter}}
|
||||
<a class="social-link social-link-tw" href="{{twitter_url @blog.twitter}}" target="_blank" rel="noopener">{{> "icons/twitter"}}</a>
|
||||
<a class="social-link social-link-tw" href="{{twitter_url @blog.twitter}}" title="Twitter" target="_blank" rel="noopener">{{> "icons/twitter"}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if @labs.subscribers}}
|
||||
<a class="subscribe-button" href="#subscribe">Subscribe</a>
|
||||
{{else}}
|
||||
<a class="rss-button" href="https://feedly.com/i/subscription/feed/{{@blog.url}}/rss/" target="_blank" rel="noopener">{{> "icons/rss"}}</a>
|
||||
<a class="rss-button" href="https://feedly.com/i/subscription/feed/{{@blog.url}}/rss/" title="RSS" target="_blank" rel="noopener">{{> "icons/rss"}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</nav>
|
||||
|
53
post.hbs
53
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">
|
||||
<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>
|
||||
{{!-- 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}}
|
||||
<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>
|
||||
{{> "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>
|
||||
--}}
|
||||
|
||||
@ -167,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');
|
||||
|
||||
@ -216,6 +192,7 @@ $(document).ready(function () {
|
||||
window.addEventListener('resize', onResize, false);
|
||||
|
||||
update();
|
||||
|
||||
});
|
||||
</script>
|
||||
{{/contentFor}}
|
||||
|
2
tag.hbs
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}}
|
||||
|
Loading…
Reference in New Issue
Block a user